2 * Copyright (c) 2011-2013, Ingo Weinhold <ingo_weinhold@gmx.de>
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
8 #include <package/PackageInfo.h>
9 #include <package/PackageInfoSet.h>
10 #include <package/PackageRoster.h>
11 #include <package/PackageVersion.h>
12 #include <package/RepositoryCache.h>
13 #include <package/RepositoryConfig.h>
15 #include "repo_haiku.h"
17 using namespace BPackageKit;
18 using namespace BPackageKit::BHPKG;
20 static BString haiku_version_to_string(const BPackageVersion &version)
22 if (version.InitCheck() != B_OK)
25 // compose ":<major>.<minor>.<micro>" (empty epoch)
27 string << version.Major();
28 if (!version.Minor().IsEmpty())
30 string << '.' << version.Minor();
31 if (!version.Micro().IsEmpty())
32 string << '.' << version.Micro();
36 if (!version.PreRelease().IsEmpty())
37 string << '-' << version.PreRelease();
40 if (version.Revision() != 0)
41 string << '-' << version.Revision();
46 static void add_dependency(Repo *repo, Offset &dependencies, const char *name,
47 const char *version, int flags, const char* compatVersion = NULL)
49 Pool *pool = repo->pool;
51 Id dependency = pool_str2id(pool, name, 1);
53 if (version && version[0] != '\0')
55 Id versionId = pool_str2id(pool, version, 1);
57 if (compatVersion && compatVersion[0] != '\0')
59 versionId = pool_rel2id(pool, pool_str2id(pool, compatVersion, 1),
60 versionId, REL_COMPAT, 1);
63 dependency = pool_rel2id(pool, dependency, versionId, flags, 1);
66 dependencies = repo_addid_dep(repo, dependencies, dependency, 0);
69 static void add_dependency(Repo *repo, Offset &dependencies, const char *name,
70 const BPackageVersion &version, int flags)
72 add_dependency(repo, dependencies, name, haiku_version_to_string(version),
76 static void add_resolvables(Repo *repo, Offset &dependencies,
77 const BObjectList<BPackageResolvable> &resolvables)
79 for (int32 i = 0; BPackageResolvable *resolvable = resolvables.ItemAt(i); i++)
81 add_dependency(repo, dependencies, resolvable->Name(),
82 haiku_version_to_string(resolvable->Version()), REL_EQ,
83 haiku_version_to_string(resolvable->CompatibleVersion()));
87 static void add_resolvable_expressions(Repo *repo, Offset &dependencies,
88 const BObjectList<BPackageResolvableExpression> &expressions)
91 BPackageResolvableExpression *expression = expressions.ItemAt(i); i++)
93 // It is possible that no version is specified. In that case any version
95 if (expression->Version().InitCheck() != B_OK)
97 BPackageVersion version;
98 add_dependency(repo, dependencies, expression->Name(), NULL, 0);
103 switch (expression->Operator())
105 case B_PACKAGE_RESOLVABLE_OP_LESS:
108 case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL:
109 flags |= REL_LT | REL_EQ;
111 case B_PACKAGE_RESOLVABLE_OP_EQUAL:
114 case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL:
116 case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL:
117 flags |= REL_GT | REL_EQ;
119 case B_PACKAGE_RESOLVABLE_OP_GREATER:
124 add_dependency(repo, dependencies, expression->Name(),
125 expression->Version(), flags);
129 static void add_replaces_list(Repo *repo, Offset &dependencies,
130 const BStringList &packageNames)
132 int32 count = packageNames.CountStrings();
133 for (int32 i = 0; i < count; i++)
135 const BString &packageName = packageNames.StringAt(i);
136 add_dependency(repo, dependencies, packageName, BPackageVersion(), 0);
140 static Id add_package_info_to_repo(Repo *repo, Repodata *repoData,
141 const BPackageInfo &packageInfo)
143 Pool *pool = repo->pool;
145 Id solvableId = repo_add_solvable(repo);
146 Solvable *solvable = pool_id2solvable(pool, solvableId);
147 // Prepend "pkg:" to package name, so "provides" don't match unless explicitly
148 // specified this way.
149 BString name("pkg:");
150 name << packageInfo.Name();
151 solvable->name = pool_str2id(pool, name, 1);
152 if (packageInfo.Architecture() == B_PACKAGE_ARCHITECTURE_ANY)
153 solvable->arch = ARCH_ANY;
155 solvable->arch = pool_str2id(pool,
156 BPackageInfo::kArchitectureNames[packageInfo.Architecture()], 1);
157 solvable->evr = pool_str2id(pool,
158 haiku_version_to_string(packageInfo.Version()), 1);
159 solvable->vendor = pool_str2id(pool, packageInfo.Vendor(), 1);
160 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_SUMMARY,
161 packageInfo.Summary());
162 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_DESCRIPTION,
163 packageInfo.Description());
164 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_PACKAGER,
165 packageInfo.Packager());
167 if (!packageInfo.Checksum().IsEmpty())
168 repodata_set_checksum(repoData, solvable - pool->solvables,
169 SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, packageInfo.Checksum());
171 solvable->provides = repo_addid_dep(repo, solvable->provides,
172 pool_rel2id(pool, solvable->name, solvable->evr, REL_EQ, 1), 0);
174 add_resolvables(repo, solvable->provides, packageInfo.ProvidesList());
175 add_resolvable_expressions(repo, solvable->requires,
176 packageInfo.RequiresList());
177 add_resolvable_expressions(repo, solvable->supplements,
178 packageInfo.SupplementsList());
179 add_resolvable_expressions(repo, solvable->conflicts,
180 packageInfo.ConflictsList());
181 add_resolvable_expressions(repo, solvable->enhances,
182 packageInfo.FreshensList());
183 add_replaces_list(repo, solvable->obsoletes, packageInfo.ReplacesList());
184 // TODO: Check whether freshens and replaces does indeed work as intended
187 // TODO: copyrights, licenses, URLs, source URLs
192 static void add_installed_packages(Repo *repo, Repodata *repoData,
193 BPackageInstallationLocation location)
195 BPackageRoster roster;
196 BPackageInfoSet packageInfos;
197 if (roster.GetActivePackages(location, packageInfos) == B_OK)
199 BRepositoryCache::Iterator it = packageInfos.GetIterator();
200 while (const BPackageInfo *packageInfo = it.Next())
201 add_package_info_to_repo(repo, repoData, *packageInfo);
205 int repo_add_haiku_installed_packages(Repo *repo, const char *rootdir,
208 Repodata *repoData = repo_add_repodata(repo, flags);
210 add_installed_packages(repo, repoData,
211 B_PACKAGE_INSTALLATION_LOCATION_SYSTEM);
212 add_installed_packages(repo, repoData,
213 B_PACKAGE_INSTALLATION_LOCATION_COMMON);
214 add_installed_packages(repo, repoData, B_PACKAGE_INSTALLATION_LOCATION_HOME);
216 if (!(flags & REPO_NO_INTERNALIZE))
217 repodata_internalize(repoData);
222 Id repo_add_haiku_package(Repo *repo, const char *hpkgPath, int flags)
224 BPackageInfo packageInfo;
225 if (packageInfo.ReadFromPackageFile(hpkgPath) != B_OK)
228 return repo_add_haiku_package_info(repo, packageInfo, flags);
231 int repo_add_haiku_packages(Repo *repo, const char *repoName, int flags)
233 BPackageRoster roster;
234 BRepositoryCache cache;
235 if (roster.GetRepositoryCache(repoName, &cache) != B_OK)
238 Repodata *repoData = repo_add_repodata(repo, flags);
240 BRepositoryCache::Iterator it = cache.GetIterator();
241 while (const BPackageInfo *packageInfo = it.Next())
242 add_package_info_to_repo(repo, repoData, *packageInfo);
244 if (!(flags & REPO_NO_INTERNALIZE))
245 repodata_internalize(repoData);
250 Id repo_add_haiku_package_info(Repo *repo,
251 const BPackageKit::BPackageInfo &packageInfo, int flags)
253 if (packageInfo.InitCheck() != B_OK)
256 Repodata *repoData = repo_add_repodata(repo, flags);
258 Id id = add_package_info_to_repo(repo, repoData, packageInfo);
260 if (!(flags & REPO_NO_INTERNALIZE))
261 repodata_internalize(repoData);