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)
26 BString string(version.Major());
27 if (!version.Minor().IsEmpty())
29 string << '.' << version.Minor();
30 if (!version.Micro().IsEmpty())
31 string << '.' << version.Micro();
35 if (!version.PreRelease().IsEmpty())
36 string << '-' << version.PreRelease();
39 if (version.Revision() != 0)
40 string << '-' << version.Revision();
45 static void add_dependency(Repo *repo, Offset &dependencies, const char *name,
46 const char *version, int flags, const char* compatVersion = NULL)
48 Pool *pool = repo->pool;
50 Id dependency = pool_str2id(pool, name, 1);
52 if (version && version[0] != '\0')
54 Id versionId = pool_str2id(pool, version, 1);
56 if (compatVersion && compatVersion[0] != '\0')
58 versionId = pool_rel2id(pool, versionId, pool_str2id(pool, compatVersion, 1),
62 dependency = pool_rel2id(pool, dependency, versionId, flags, 1);
65 dependencies = repo_addid_dep(repo, dependencies, dependency, 0);
68 static void add_dependency(Repo *repo, Offset &dependencies, const char *name,
69 const BPackageVersion &version, int flags)
71 add_dependency(repo, dependencies, name, haiku_version_to_string(version),
75 static void add_resolvables(Repo *repo, Offset &dependencies,
76 const BObjectList<BPackageResolvable> &resolvables)
78 for (int32 i = 0; BPackageResolvable *resolvable = resolvables.ItemAt(i); i++)
80 add_dependency(repo, dependencies, resolvable->Name(),
81 haiku_version_to_string(resolvable->Version()), REL_EQ,
82 haiku_version_to_string(resolvable->CompatibleVersion()));
86 static void add_resolvable_expressions(Repo *repo, Offset &dependencies,
87 const BObjectList<BPackageResolvableExpression> &expressions)
90 BPackageResolvableExpression *expression = expressions.ItemAt(i); i++)
92 // It is possible that no version is specified. In that case any version
94 if (expression->Version().InitCheck() != B_OK)
96 BPackageVersion version;
97 add_dependency(repo, dependencies, expression->Name(), NULL, 0);
102 switch (expression->Operator())
104 case B_PACKAGE_RESOLVABLE_OP_LESS:
107 case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL:
108 flags |= REL_LT | REL_EQ;
110 case B_PACKAGE_RESOLVABLE_OP_EQUAL:
113 case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL:
115 case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL:
116 flags |= REL_GT | REL_EQ;
118 case B_PACKAGE_RESOLVABLE_OP_GREATER:
123 add_dependency(repo, dependencies, expression->Name(),
124 expression->Version(), flags);
128 static void add_replaces_list(Repo *repo, Offset &dependencies,
129 const BStringList &packageNames)
131 int32 count = packageNames.CountStrings();
132 for (int32 i = 0; i < count; i++)
134 const BString &packageName = packageNames.StringAt(i);
135 add_dependency(repo, dependencies, packageName, BPackageVersion(), 0);
139 static Id add_package_info_to_repo(Repo *repo, Repodata *repoData,
140 const BPackageInfo &packageInfo)
142 Pool *pool = repo->pool;
144 Id solvableId = repo_add_solvable(repo);
145 Solvable *solvable = pool_id2solvable(pool, solvableId);
146 // Prepend "pkg:" to package name, so "provides" don't match unless explicitly
147 // specified this way.
148 BString name("pkg:");
149 name << packageInfo.Name();
150 solvable->name = pool_str2id(pool, name, 1);
151 if (packageInfo.Architecture() == B_PACKAGE_ARCHITECTURE_ANY)
152 solvable->arch = ARCH_ANY;
154 solvable->arch = pool_str2id(pool,
155 BPackageInfo::kArchitectureNames[packageInfo.Architecture()], 1);
156 solvable->evr = pool_str2id(pool,
157 haiku_version_to_string(packageInfo.Version()), 1);
158 solvable->vendor = pool_str2id(pool, packageInfo.Vendor(), 1);
159 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_SUMMARY,
160 packageInfo.Summary());
161 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_DESCRIPTION,
162 packageInfo.Description());
163 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_PACKAGER,
164 packageInfo.Packager());
166 if (!packageInfo.Checksum().IsEmpty())
167 repodata_set_checksum(repoData, solvable - pool->solvables,
168 SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, packageInfo.Checksum());
170 solvable->provides = repo_addid_dep(repo, solvable->provides,
171 pool_rel2id(pool, solvable->name, solvable->evr, REL_EQ, 1), 0);
173 add_resolvables(repo, solvable->provides, packageInfo.ProvidesList());
174 add_resolvable_expressions(repo, solvable->requires,
175 packageInfo.RequiresList());
176 add_resolvable_expressions(repo, solvable->supplements,
177 packageInfo.SupplementsList());
178 add_resolvable_expressions(repo, solvable->conflicts,
179 packageInfo.ConflictsList());
180 add_resolvable_expressions(repo, solvable->enhances,
181 packageInfo.FreshensList());
182 add_replaces_list(repo, solvable->obsoletes, packageInfo.ReplacesList());
183 // TODO: Check whether freshens and replaces does indeed work as intended
186 // TODO: copyrights, licenses, URLs, source URLs
191 static void add_installed_packages(Repo *repo, Repodata *repoData,
192 BPackageInstallationLocation location)
194 BPackageRoster roster;
195 BPackageInfoSet packageInfos;
196 if (roster.GetActivePackages(location, packageInfos) == B_OK)
198 BRepositoryCache::Iterator it = packageInfos.GetIterator();
199 while (const BPackageInfo *packageInfo = it.Next())
200 add_package_info_to_repo(repo, repoData, *packageInfo);
204 int repo_add_haiku_installed_packages(Repo *repo, const char *rootdir,
207 Repodata *repoData = repo_add_repodata(repo, flags);
209 add_installed_packages(repo, repoData,
210 B_PACKAGE_INSTALLATION_LOCATION_SYSTEM);
211 add_installed_packages(repo, repoData,
212 B_PACKAGE_INSTALLATION_LOCATION_COMMON);
213 add_installed_packages(repo, repoData, B_PACKAGE_INSTALLATION_LOCATION_HOME);
215 if (!(flags & REPO_NO_INTERNALIZE))
216 repodata_internalize(repoData);
221 Id repo_add_haiku_package(Repo *repo, const char *hpkgPath, int flags)
223 BPackageInfo packageInfo;
224 if (packageInfo.ReadFromPackageFile(hpkgPath) != B_OK)
227 return repo_add_haiku_package_info(repo, packageInfo, flags);
230 int repo_add_haiku_packages(Repo *repo, const char *repoName, int flags)
232 BPackageRoster roster;
233 BRepositoryCache cache;
234 if (roster.GetRepositoryCache(repoName, &cache) != B_OK)
237 Repodata *repoData = repo_add_repodata(repo, flags);
239 BRepositoryCache::Iterator it = cache.GetIterator();
240 while (const BPackageInfo *packageInfo = it.Next())
241 add_package_info_to_repo(repo, repoData, *packageInfo);
243 if (!(flags & REPO_NO_INTERNALIZE))
244 repodata_internalize(repoData);
249 Id repo_add_haiku_package_info(Repo *repo,
250 const BPackageKit::BPackageInfo &packageInfo, int flags)
252 if (packageInfo.InitCheck() != B_OK)
255 Repodata *repoData = repo_add_repodata(repo, flags);
257 Id id = add_package_info_to_repo(repo, repoData, packageInfo);
259 if (!(flags & REPO_NO_INTERNALIZE))
260 repodata_internalize(repoData);