Add Haiku repository support to libsolvext
authorIngo Weinhold <ingo_weinhold@gmx.de>
Sat, 30 Mar 2013 14:48:12 +0000 (14:48 +0000)
committerMichael Schroeder <mls@suse.de>
Tue, 16 Apr 2013 09:09:49 +0000 (11:09 +0200)
ext/CMakeLists.txt
ext/libsolvext.ver
ext/repo_haiku.cpp [new file with mode: 0644]
ext/repo_haiku.h [new file with mode: 0644]

index bcd4f81..63e0dee 100644 (file)
@@ -78,6 +78,13 @@ IF (ENABLE_CUDFREPO)
        repo_cudf.h)
 ENDIF (ENABLE_CUDFREPO)
 
+IF (ENABLE_HAIKU)
+    SET (libsolvext_SRCS ${libsolvext_SRCS}
+       repo_haiku.cpp)
+    SET (libsolvext_HEADERS ${libsolvext_HEADERS}
+       repo_haiku.h)
+ENDIF (ENABLE_HAIKU)
+
 SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
 SET (CMAKE_SHARED_LINKER_FLAGS "${LINK_FLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/ext/libsolvext.ver")
 
index 9817339..bb0270a 100644 (file)
@@ -12,6 +12,10 @@ SOLV_1.0 {
                repo_add_debdb;
                repo_add_debpackages;
                repo_add_deltainfoxml;
+               repo_add_haiku_installed_packages;
+               repo_add_haiku_package;
+               repo_add_haiku_package_info;
+               repo_add_haiku_packages;
                repo_add_helix;
                repo_add_mdk;
                repo_add_mdk_info;
diff --git a/ext/repo_haiku.cpp b/ext/repo_haiku.cpp
new file mode 100644 (file)
index 0000000..139bf50
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2011-2013, Ingo Weinhold <ingo_weinhold@gmx.de>
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include <package/PackageInfo.h>
+#include <package/PackageInfoSet.h>
+#include <package/PackageRoster.h>
+#include <package/PackageVersion.h>
+#include <package/RepositoryCache.h>
+#include <package/RepositoryConfig.h>
+
+#include "repo_haiku.h"
+
+using namespace BPackageKit;
+using namespace BPackageKit::BHPKG;
+
+static BString haiku_version_to_string(const BPackageVersion &version)
+{
+  if (version.InitCheck() != B_OK)
+    return BString();
+
+  // compose ":<major>.<minor>.<micro>" (empty epoch)
+  BString string(":");
+  string << version.Major();
+  if (!version.Minor().IsEmpty())
+    {
+      string << '.' << version.Minor();
+      if (!version.Micro().IsEmpty())
+        string << '.' << version.Micro();
+    }
+
+  // append pre-release -- separate it with '/' to keep pool_evrcmp_str() happy
+  // (it expects only the release to be separated by '-')
+  if (!version.PreRelease().IsEmpty())
+    string << '/' << version.PreRelease();
+
+  // append revision
+  if (version.Revision() != 0)
+    string << '-' << version.Revision();
+
+  return string;
+}
+
+static void add_dependency(Repo *repo, Offset &dependencies, const char *name,
+  const char *version, int flags, const char* compatVersion = NULL)
+{
+  Pool *pool = repo->pool;
+
+  Id dependency = pool_str2id(pool, name, 1);
+
+  if (version && version[0] != '\0')
+  {
+    Id versionId = pool_str2id(pool, version, 1);
+
+    if (compatVersion && compatVersion[0] != '\0')
+      {
+        versionId = pool_rel2id(pool, pool_str2id(pool, compatVersion, 1),
+          versionId, REL_COMPAT, 1);
+        versionId = MAKERELDEP(versionId);
+      }
+
+    dependency = pool_rel2id(pool, dependency, versionId, flags, 1);
+  }
+
+  dependencies = repo_addid_dep(repo, dependencies, dependency, 0);
+}
+
+static void add_dependency(Repo *repo, Offset &dependencies, const char *name,
+  const BPackageVersion &version, int flags)
+{
+  add_dependency(repo, dependencies, name, haiku_version_to_string(version),
+    flags);
+}
+
+static void add_resolvables(Repo *repo, Offset &dependencies,
+  const BObjectList<BPackageResolvable> &resolvables)
+{
+  for (int32 i = 0; BPackageResolvable *resolvable = resolvables.ItemAt(i); i++)
+    {
+      add_dependency(repo, dependencies, resolvable->Name(),
+        haiku_version_to_string(resolvable->Version()), REL_EQ,
+        haiku_version_to_string(resolvable->CompatibleVersion()));
+    }
+}
+
+static void add_resolvable_expressions(Repo *repo, Offset &dependencies,
+  const BObjectList<BPackageResolvableExpression> &expressions)
+{
+  for (int32 i = 0;
+    BPackageResolvableExpression *expression = expressions.ItemAt(i); i++)
+    {
+      // It is possible that no version is specified. In that case any version
+      // is acceptable.
+      if (expression->Version().InitCheck() != B_OK)
+        {
+          BPackageVersion version;
+          add_dependency(repo, dependencies, expression->Name(), NULL, 0);
+          continue;
+        }
+
+      int flags = 0;
+      switch (expression->Operator())
+        {
+          case B_PACKAGE_RESOLVABLE_OP_LESS:
+            flags |= REL_LT;
+            break;
+          case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL:
+            flags |= REL_LT | REL_EQ;
+            break;
+          case B_PACKAGE_RESOLVABLE_OP_EQUAL:
+            flags |= REL_EQ;
+            break;
+          case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL:
+            break;
+          case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL:
+            flags |= REL_GT | REL_EQ;
+            break;
+          case B_PACKAGE_RESOLVABLE_OP_GREATER:
+              flags |= REL_GT;
+            break;
+        }
+
+      add_dependency(repo, dependencies, expression->Name(),
+        expression->Version(), flags);
+    }
+}
+
+static void add_replaces_list(Repo *repo, Offset &dependencies,
+  const BStringList &packageNames)
+{
+  int32 count = packageNames.CountStrings();
+  for (int32 i = 0; i < count; i++)
+    {
+      const BString &packageName = packageNames.StringAt(i);
+      add_dependency(repo, dependencies, packageName, BPackageVersion(), 0);
+    }
+}
+
+static Id add_package_info_to_repo(Repo *repo, Repodata *repoData,
+  const BPackageInfo &packageInfo)
+{
+  Pool *pool = repo->pool;
+
+  Id solvableId = repo_add_solvable(repo);
+  Solvable *solvable = pool_id2solvable(pool, solvableId);
+  // Prepend "pkg:" to package name, so "provides" don't match unless explicitly
+  // specified this way.
+  BString name("pkg:");
+  name << packageInfo.Name();
+  solvable->name = pool_str2id(pool, name, 1);
+  if (packageInfo.Architecture() == B_PACKAGE_ARCHITECTURE_ANY)
+    solvable->arch = ARCH_NOARCH;
+  else
+    solvable->arch = pool_str2id(pool,
+      BPackageInfo::kArchitectureNames[packageInfo.Architecture()], 1);
+  solvable->evr = pool_str2id(pool,
+    haiku_version_to_string(packageInfo.Version()), 1);
+  solvable->vendor = pool_str2id(pool, packageInfo.Vendor(), 1);
+  repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_SUMMARY,
+    packageInfo.Summary());
+  repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_DESCRIPTION,
+    packageInfo.Description());
+  repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_PACKAGER,
+    packageInfo.Packager());
+
+  if (!packageInfo.Checksum().IsEmpty())
+    repodata_set_checksum(repoData, solvable - pool->solvables,
+      SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, packageInfo.Checksum());
+
+  solvable->provides = repo_addid_dep(repo, solvable->provides,
+    pool_rel2id(pool, solvable->name, solvable->evr, REL_EQ, 1), 0);
+
+  add_resolvables(repo, solvable->provides, packageInfo.ProvidesList());
+  add_resolvable_expressions(repo, solvable->requires,
+    packageInfo.RequiresList());
+  add_resolvable_expressions(repo, solvable->supplements,
+    packageInfo.SupplementsList());
+  add_resolvable_expressions(repo, solvable->conflicts,
+    packageInfo.ConflictsList());
+  add_resolvable_expressions(repo, solvable->enhances,
+    packageInfo.FreshensList());
+  add_replaces_list(repo, solvable->obsoletes, packageInfo.ReplacesList());
+  // TODO: Check whether freshens and replaces does indeed work as intended
+  // here.
+
+  // TODO: copyrights, licenses, URLs, source URLs
+
+  return solvableId;
+}
+
+static void add_installed_packages(Repo *repo, Repodata *repoData,
+  BPackageInstallationLocation location)
+{
+  BPackageRoster roster;
+  BPackageInfoSet packageInfos;
+  if (roster.GetActivePackages(location, packageInfos) == B_OK)
+    {
+      BRepositoryCache::Iterator it = packageInfos.GetIterator();
+      while (const BPackageInfo *packageInfo = it.Next())
+        add_package_info_to_repo(repo, repoData, *packageInfo);
+    }
+}
+
+int repo_add_haiku_installed_packages(Repo *repo, const char *rootdir,
+  int flags)
+{
+  Repodata *repoData = repo_add_repodata(repo, flags);
+
+  add_installed_packages(repo, repoData,
+    B_PACKAGE_INSTALLATION_LOCATION_SYSTEM);
+  add_installed_packages(repo, repoData,
+    B_PACKAGE_INSTALLATION_LOCATION_COMMON);
+  add_installed_packages(repo, repoData, B_PACKAGE_INSTALLATION_LOCATION_HOME);
+
+  if (!(flags & REPO_NO_INTERNALIZE))
+    repodata_internalize(repoData);
+
+  return 0;
+}
+
+Id repo_add_haiku_package(Repo *repo, const char *hpkgPath, int flags)
+{
+  BPackageInfo packageInfo;
+  if (packageInfo.ReadFromPackageFile(hpkgPath) != B_OK)
+    return 0;
+
+  return repo_add_haiku_package_info(repo, packageInfo, flags);
+}
+
+int repo_add_haiku_packages(Repo *repo, const char *repoName, int flags)
+{
+  BPackageRoster roster;
+  BRepositoryCache cache;
+  if (roster.GetRepositoryCache(repoName, &cache) != B_OK)
+    return 0;
+
+  Repodata *repoData = repo_add_repodata(repo, flags);
+
+  BRepositoryCache::Iterator it = cache.GetIterator();
+  while (const BPackageInfo *packageInfo = it.Next())
+    add_package_info_to_repo(repo, repoData, *packageInfo);
+
+  if (!(flags & REPO_NO_INTERNALIZE))
+    repodata_internalize(repoData);
+
+  return 0;
+}
+
+Id repo_add_haiku_package_info(Repo *repo,
+  const BPackageKit::BPackageInfo &packageInfo, int flags)
+{
+  if (packageInfo.InitCheck() != B_OK)
+    return 0;
+  
+  Repodata *repoData = repo_add_repodata(repo, flags);
+
+  Id id = add_package_info_to_repo(repo, repoData, packageInfo);
+
+  if (!(flags & REPO_NO_INTERNALIZE))
+    repodata_internalize(repoData);
+
+  return id;
+}
diff --git a/ext/repo_haiku.h b/ext/repo_haiku.h
new file mode 100644 (file)
index 0000000..6770666
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011-2013, Ingo Weinhold <ingo_weinhold@gmx.de>
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+#ifndef REPO_HAIKU_H
+#define REPO_HAIKU_H
+
+#include "repo.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int repo_add_haiku_installed_packages(Repo *repo, const char *rootdir,
+  int flags);
+Id repo_add_haiku_package(Repo *repo, const char *hpkgPath, int flags);
+int repo_add_haiku_packages(Repo *repo, const char *repoName, int flags);
+
+#ifdef __cplusplus
+
+namespace BPackageKit {
+  class BPackageInfo;
+}
+
+Id repo_add_haiku_package_info(Repo *repo,
+  const BPackageKit::BPackageInfo &packageInfo, int flags);
+
+} /* extern "C" */
+
+#endif /*__cplusplus*/
+
+#endif /* REPO_HAIKU_H */