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();
35 // append pre-release -- separate it with '/' to keep pool_evrcmp_str() happy
36 // (it expects only the release to be separated by '-')
37 if (!version.PreRelease().IsEmpty())
38 string << '/' << version.PreRelease();
41 if (version.Revision() != 0)
42 string << '-' << version.Revision();
47 static void add_dependency(Repo *repo, Offset &dependencies, const char *name,
48 const char *version, int flags, const char* compatVersion = NULL)
50 Pool *pool = repo->pool;
52 Id dependency = pool_str2id(pool, name, 1);
54 if (version && version[0] != '\0')
56 Id versionId = pool_str2id(pool, version, 1);
58 if (compatVersion && compatVersion[0] != '\0')
60 versionId = pool_rel2id(pool, pool_str2id(pool, compatVersion, 1),
61 versionId, REL_COMPAT, 1);
62 versionId = MAKERELDEP(versionId);
65 dependency = pool_rel2id(pool, dependency, versionId, flags, 1);
68 dependencies = repo_addid_dep(repo, dependencies, dependency, 0);
71 static void add_dependency(Repo *repo, Offset &dependencies, const char *name,
72 const BPackageVersion &version, int flags)
74 add_dependency(repo, dependencies, name, haiku_version_to_string(version),
78 static void add_resolvables(Repo *repo, Offset &dependencies,
79 const BObjectList<BPackageResolvable> &resolvables)
81 for (int32 i = 0; BPackageResolvable *resolvable = resolvables.ItemAt(i); i++)
83 add_dependency(repo, dependencies, resolvable->Name(),
84 haiku_version_to_string(resolvable->Version()), REL_EQ,
85 haiku_version_to_string(resolvable->CompatibleVersion()));
89 static void add_resolvable_expressions(Repo *repo, Offset &dependencies,
90 const BObjectList<BPackageResolvableExpression> &expressions)
93 BPackageResolvableExpression *expression = expressions.ItemAt(i); i++)
95 // It is possible that no version is specified. In that case any version
97 if (expression->Version().InitCheck() != B_OK)
99 BPackageVersion version;
100 add_dependency(repo, dependencies, expression->Name(), NULL, 0);
105 switch (expression->Operator())
107 case B_PACKAGE_RESOLVABLE_OP_LESS:
110 case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL:
111 flags |= REL_LT | REL_EQ;
113 case B_PACKAGE_RESOLVABLE_OP_EQUAL:
116 case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL:
118 case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL:
119 flags |= REL_GT | REL_EQ;
121 case B_PACKAGE_RESOLVABLE_OP_GREATER:
126 add_dependency(repo, dependencies, expression->Name(),
127 expression->Version(), flags);
131 static void add_replaces_list(Repo *repo, Offset &dependencies,
132 const BStringList &packageNames)
134 int32 count = packageNames.CountStrings();
135 for (int32 i = 0; i < count; i++)
137 const BString &packageName = packageNames.StringAt(i);
138 add_dependency(repo, dependencies, packageName, BPackageVersion(), 0);
142 static Id add_package_info_to_repo(Repo *repo, Repodata *repoData,
143 const BPackageInfo &packageInfo)
145 Pool *pool = repo->pool;
147 Id solvableId = repo_add_solvable(repo);
148 Solvable *solvable = pool_id2solvable(pool, solvableId);
149 // Prepend "pkg:" to package name, so "provides" don't match unless explicitly
150 // specified this way.
151 BString name("pkg:");
152 name << packageInfo.Name();
153 solvable->name = pool_str2id(pool, name, 1);
154 if (packageInfo.Architecture() == B_PACKAGE_ARCHITECTURE_ANY)
155 solvable->arch = ARCH_NOARCH;
157 solvable->arch = pool_str2id(pool,
158 BPackageInfo::kArchitectureNames[packageInfo.Architecture()], 1);
159 solvable->evr = pool_str2id(pool,
160 haiku_version_to_string(packageInfo.Version()), 1);
161 solvable->vendor = pool_str2id(pool, packageInfo.Vendor(), 1);
162 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_SUMMARY,
163 packageInfo.Summary());
164 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_DESCRIPTION,
165 packageInfo.Description());
166 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_PACKAGER,
167 packageInfo.Packager());
169 if (!packageInfo.Checksum().IsEmpty())
170 repodata_set_checksum(repoData, solvable - pool->solvables,
171 SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, packageInfo.Checksum());
173 solvable->provides = repo_addid_dep(repo, solvable->provides,
174 pool_rel2id(pool, solvable->name, solvable->evr, REL_EQ, 1), 0);
176 add_resolvables(repo, solvable->provides, packageInfo.ProvidesList());
177 add_resolvable_expressions(repo, solvable->requires,
178 packageInfo.RequiresList());
179 add_resolvable_expressions(repo, solvable->supplements,
180 packageInfo.SupplementsList());
181 add_resolvable_expressions(repo, solvable->conflicts,
182 packageInfo.ConflictsList());
183 add_resolvable_expressions(repo, solvable->enhances,
184 packageInfo.FreshensList());
185 add_replaces_list(repo, solvable->obsoletes, packageInfo.ReplacesList());
186 // TODO: Check whether freshens and replaces does indeed work as intended
189 // TODO: copyrights, licenses, URLs, source URLs
194 static void add_installed_packages(Repo *repo, Repodata *repoData,
195 BPackageInstallationLocation location)
197 BPackageRoster roster;
198 BPackageInfoSet packageInfos;
199 if (roster.GetActivePackages(location, packageInfos) == B_OK)
201 BRepositoryCache::Iterator it = packageInfos.GetIterator();
202 while (const BPackageInfo *packageInfo = it.Next())
203 add_package_info_to_repo(repo, repoData, *packageInfo);
207 int repo_add_haiku_installed_packages(Repo *repo, const char *rootdir,
210 Repodata *repoData = repo_add_repodata(repo, flags);
212 add_installed_packages(repo, repoData,
213 B_PACKAGE_INSTALLATION_LOCATION_SYSTEM);
214 add_installed_packages(repo, repoData,
215 B_PACKAGE_INSTALLATION_LOCATION_COMMON);
216 add_installed_packages(repo, repoData, B_PACKAGE_INSTALLATION_LOCATION_HOME);
218 if (!(flags & REPO_NO_INTERNALIZE))
219 repodata_internalize(repoData);
224 Id repo_add_haiku_package(Repo *repo, const char *hpkgPath, int flags)
226 BPackageInfo packageInfo;
227 if (packageInfo.ReadFromPackageFile(hpkgPath) != B_OK)
230 return repo_add_haiku_package_info(repo, packageInfo, flags);
233 int repo_add_haiku_packages(Repo *repo, const char *repoName, int flags)
235 BPackageRoster roster;
236 BRepositoryCache cache;
237 if (roster.GetRepositoryCache(repoName, &cache) != B_OK)
240 Repodata *repoData = repo_add_repodata(repo, flags);
242 BRepositoryCache::Iterator it = cache.GetIterator();
243 while (const BPackageInfo *packageInfo = it.Next())
244 add_package_info_to_repo(repo, repoData, *packageInfo);
246 if (!(flags & REPO_NO_INTERNALIZE))
247 repodata_internalize(repoData);
252 Id repo_add_haiku_package_info(Repo *repo,
253 const BPackageKit::BPackageInfo &packageInfo, int flags)
255 if (packageInfo.InitCheck() != B_OK)
258 Repodata *repoData = repo_add_repodata(repo, flags);
260 Id id = add_package_info_to_repo(repo, repoData, packageInfo);
262 if (!(flags & REPO_NO_INTERNALIZE))
263 repodata_internalize(repoData);