also simplify solvable_copy_cb's checksum handling
[platform/upstream/libsolv.git] / ext / repo_haiku.cpp
1 /*
2  * Copyright (c) 2011-2013, Ingo Weinhold <ingo_weinhold@gmx.de>
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
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>
14
15 #include "repo_haiku.h"
16
17 using namespace BPackageKit;
18 using namespace BPackageKit::BHPKG;
19
20 static void add_dependency(Repo *repo, Offset &dependencies, const char *name,
21   const char *version, int flags, const char* compatVersion = NULL)
22 {
23   Pool *pool = repo->pool;
24
25   Id dependency = pool_str2id(pool, name, 1);
26
27   if (version && version[0] != '\0')
28   {
29     Id versionId = pool_str2id(pool, version, 1);
30
31     if (compatVersion && compatVersion[0] != '\0')
32       {
33         versionId = pool_rel2id(pool, versionId, pool_str2id(pool, compatVersion, 1),
34           REL_COMPAT, 1);
35       }
36
37     dependency = pool_rel2id(pool, dependency, versionId, flags, 1);
38   }
39
40   dependencies = repo_addid_dep(repo, dependencies, dependency, 0);
41 }
42
43 static void add_dependency(Repo *repo, Offset &dependencies, const char *name,
44   const BPackageVersion &version, int flags)
45 {
46   add_dependency(repo, dependencies, name, version.ToString(),
47     flags);
48 }
49
50 static void add_resolvables(Repo *repo, Offset &dependencies,
51   const BObjectList<BPackageResolvable> &resolvables)
52 {
53   for (int32 i = 0; BPackageResolvable *resolvable = resolvables.ItemAt(i); i++)
54     {
55       add_dependency(repo, dependencies, resolvable->Name(),
56         resolvable->Version().ToString(), REL_EQ,
57         resolvable->CompatibleVersion().ToString());
58     }
59 }
60
61 static void add_resolvable_expressions(Repo *repo, Offset &dependencies,
62   const BObjectList<BPackageResolvableExpression> &expressions)
63 {
64   for (int32 i = 0;
65     BPackageResolvableExpression *expression = expressions.ItemAt(i); i++)
66     {
67       // It is possible that no version is specified. In that case any version
68       // is acceptable.
69       if (expression->Version().InitCheck() != B_OK)
70         {
71           BPackageVersion version;
72           add_dependency(repo, dependencies, expression->Name(), NULL, 0);
73           continue;
74         }
75
76       int flags = 0;
77       switch (expression->Operator())
78         {
79           case B_PACKAGE_RESOLVABLE_OP_LESS:
80             flags |= REL_LT;
81             break;
82           case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL:
83             flags |= REL_LT | REL_EQ;
84             break;
85           case B_PACKAGE_RESOLVABLE_OP_EQUAL:
86             flags |= REL_EQ;
87             break;
88           case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL:
89             break;
90           case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL:
91             flags |= REL_GT | REL_EQ;
92             break;
93           case B_PACKAGE_RESOLVABLE_OP_GREATER:
94               flags |= REL_GT;
95             break;
96         }
97
98       add_dependency(repo, dependencies, expression->Name(),
99         expression->Version(), flags);
100     }
101 }
102
103 static void add_replaces_list(Repo *repo, Offset &dependencies,
104   const BStringList &packageNames)
105 {
106   int32 count = packageNames.CountStrings();
107   for (int32 i = 0; i < count; i++)
108     {
109       const BString &packageName = packageNames.StringAt(i);
110       add_dependency(repo, dependencies, packageName, BPackageVersion(), 0);
111     }
112 }
113
114 static Id add_package_info_to_repo(Repo *repo, Repodata *repoData,
115   const BPackageInfo &packageInfo)
116 {
117   Pool *pool = repo->pool;
118
119   Id solvableId = repo_add_solvable(repo);
120   Solvable *solvable = pool_id2solvable(pool, solvableId);
121   // Prepend "pkg:" to package name, so "provides" don't match unless explicitly
122   // specified this way.
123   BString name("pkg:");
124   name << packageInfo.Name();
125   solvable->name = pool_str2id(pool, name, 1);
126   if (packageInfo.Architecture() == B_PACKAGE_ARCHITECTURE_ANY)
127     solvable->arch = ARCH_ANY;
128   else if (packageInfo.Architecture() == B_PACKAGE_ARCHITECTURE_SOURCE)
129     solvable->arch = ARCH_SRC;
130   else
131     solvable->arch = pool_str2id(pool,
132       BPackageInfo::kArchitectureNames[packageInfo.Architecture()], 1);
133   solvable->evr = pool_str2id(pool, packageInfo.Version().ToString(), 1);
134   solvable->vendor = pool_str2id(pool, packageInfo.Vendor(), 1);
135   repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_SUMMARY,
136     packageInfo.Summary());
137   repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_DESCRIPTION,
138     packageInfo.Description());
139   repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_PACKAGER,
140     packageInfo.Packager());
141
142   if (!packageInfo.Checksum().IsEmpty())
143     repodata_set_checksum(repoData, solvable - pool->solvables,
144       SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, packageInfo.Checksum());
145
146   solvable->provides = repo_addid_dep(repo, solvable->provides,
147     pool_rel2id(pool, solvable->name, solvable->evr, REL_EQ, 1), 0);
148
149   add_resolvables(repo, solvable->provides, packageInfo.ProvidesList());
150   add_resolvable_expressions(repo, solvable->requires,
151     packageInfo.RequiresList());
152   add_resolvable_expressions(repo, solvable->supplements,
153     packageInfo.SupplementsList());
154   add_resolvable_expressions(repo, solvable->conflicts,
155     packageInfo.ConflictsList());
156   add_resolvable_expressions(repo, solvable->enhances,
157     packageInfo.FreshensList());
158   add_replaces_list(repo, solvable->obsoletes, packageInfo.ReplacesList());
159   // TODO: Check whether freshens and replaces does indeed work as intended
160   // here.
161
162   // TODO: copyrights, licenses, URLs, source URLs
163
164   return solvableId;
165 }
166
167 static void add_installed_packages(Repo *repo, Repodata *repoData,
168   BPackageInstallationLocation location)
169 {
170   BPackageRoster roster;
171   BPackageInfoSet packageInfos;
172   if (roster.GetActivePackages(location, packageInfos) == B_OK)
173     {
174       BRepositoryCache::Iterator it = packageInfos.GetIterator();
175       while (const BPackageInfo *packageInfo = it.Next())
176         add_package_info_to_repo(repo, repoData, *packageInfo);
177     }
178 }
179
180 int repo_add_haiku_installed_packages(Repo *repo, const char *rootdir,
181   int flags)
182 {
183   Repodata *repoData = repo_add_repodata(repo, flags);
184
185   add_installed_packages(repo, repoData,
186     B_PACKAGE_INSTALLATION_LOCATION_SYSTEM);
187   add_installed_packages(repo, repoData, B_PACKAGE_INSTALLATION_LOCATION_HOME);
188
189   if (!(flags & REPO_NO_INTERNALIZE))
190     repodata_internalize(repoData);
191
192   return 0;
193 }
194
195 Id repo_add_haiku_package(Repo *repo, const char *hpkgPath, int flags)
196 {
197   BPackageInfo packageInfo;
198   if (packageInfo.ReadFromPackageFile(hpkgPath) != B_OK)
199     return 0;
200
201   return repo_add_haiku_package_info(repo, packageInfo, flags);
202 }
203
204 int repo_add_haiku_packages(Repo *repo, const char *repoName, int flags)
205 {
206   BPackageRoster roster;
207   BRepositoryCache cache;
208   if (roster.GetRepositoryCache(repoName, &cache) != B_OK)
209     return 0;
210
211   Repodata *repoData = repo_add_repodata(repo, flags);
212
213   BRepositoryCache::Iterator it = cache.GetIterator();
214   while (const BPackageInfo *packageInfo = it.Next())
215     add_package_info_to_repo(repo, repoData, *packageInfo);
216
217   if (!(flags & REPO_NO_INTERNALIZE))
218     repodata_internalize(repoData);
219
220   return 0;
221 }
222
223 Id repo_add_haiku_package_info(Repo *repo,
224   const BPackageKit::BPackageInfo &packageInfo, int flags)
225 {
226   if (packageInfo.InitCheck() != B_OK)
227     return 0;
228   
229   Repodata *repoData = repo_add_repodata(repo, flags);
230
231   Id id = add_package_info_to_repo(repo, repoData, packageInfo);
232
233   if (!(flags & REPO_NO_INTERNALIZE))
234     repodata_internalize(repoData);
235
236   return id;
237 }