]> git.ipfire.org Git - pakfire.git/blob - src/libpakfire/package.c
libpakfire: Implement reference counting to packages
[pakfire.git] / src / libpakfire / package.c
1 /*#############################################################################
2 # #
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2013 Pakfire development team #
5 # #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
18 # #
19 #############################################################################*/
20
21 #include <assert.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25
26 #include <solv/evr.h>
27 #include <solv/pool.h>
28 #include <solv/pooltypes.h>
29 #include <solv/repo.h>
30 #include <solv/solvable.h>
31
32 #include <pakfire/cache.h>
33 #include <pakfire/constants.h>
34 #include <pakfire/file.h>
35 #include <pakfire/i18n.h>
36 #include <pakfire/package.h>
37 #include <pakfire/packagecache.h>
38 #include <pakfire/pool.h>
39 #include <pakfire/private.h>
40 #include <pakfire/relation.h>
41 #include <pakfire/relationlist.h>
42 #include <pakfire/repo.h>
43 #include <pakfire/repocache.h>
44 #include <pakfire/util.h>
45
46 static Pool* pakfire_package_get_solv_pool(PakfirePackage pkg) {
47 return pakfire_pool_get_solv_pool(pkg->pool);
48 }
49
50 static void pakfire_package_add_self_provides(PakfirePool pool, PakfirePackage pkg, const char* name, const char* evr) {
51 PakfireRelation relation = pakfire_relation_create(pool, name, PAKFIRE_EQ, evr);
52 pakfire_package_add_provides(pkg, relation);
53
54 pakfire_relation_free(relation);
55 }
56
57 PAKFIRE_EXPORT PakfirePackage pakfire_package_create(PakfirePool pool, Id id) {
58 PakfirePackage pkg = pakfire_calloc(1, sizeof(*pkg));
59 if (pkg) {
60 pkg->pool = pakfire_pool_ref(pool);
61 pkg->id = id;
62
63 // Initialize reference counter
64 pkg->nrefs = 1;
65 }
66
67 return pkg;
68 }
69
70 PAKFIRE_EXPORT PakfirePackage pakfire_package_create2(PakfirePool pool, PakfireRepo repo, const char* name, const char* evr, const char* arch) {
71 PakfirePackage pkg = pakfire_repo_add_package(repo);
72
73 pakfire_package_set_name(pkg, name);
74 pakfire_package_set_evr(pkg, evr);
75 pakfire_package_set_arch(pkg, arch);
76
77 pakfire_package_add_self_provides(pool, pkg, name, evr);
78
79 return pkg;
80 }
81
82 static void pakfire_package_free(PakfirePackage pkg) {
83 pakfire_pool_unref(pkg->pool);
84 pakfire_package_filelist_remove(pkg);
85 pakfire_free(pkg);
86 }
87
88 PAKFIRE_EXPORT PakfirePackage pakfire_package_ref(PakfirePackage pkg) {
89 pkg->nrefs++;
90
91 return pkg;
92 }
93
94 PAKFIRE_EXPORT PakfirePackage pakfire_package_unref(PakfirePackage pkg) {
95 if (!pkg)
96 return NULL;
97
98 if (--pkg->nrefs > 0)
99 return pkg;
100
101 pakfire_package_free(pkg);
102 return NULL;
103 }
104
105 static Solvable* get_solvable(PakfirePackage pkg) {
106 Pool* pool = pakfire_package_get_solv_pool(pkg);
107
108 return pool_id2solvable(pool, pkg->id);
109 }
110
111 static Repo* pakfire_package_solv_repo(PakfirePackage pkg) {
112 Solvable* s = get_solvable(pkg);
113
114 return s->repo;
115 }
116
117 static Id pakfire_package_get_handle(PakfirePackage pkg) {
118 Pool* pool = pakfire_package_get_solv_pool(pkg);
119 Solvable* s = get_solvable(pkg);
120
121 return s - pool->solvables;
122 }
123
124 PAKFIRE_EXPORT int pakfire_package_identical(PakfirePackage pkg1, PakfirePackage pkg2) {
125 return pkg1->id == pkg2->id;
126 }
127
128 PAKFIRE_EXPORT int pakfire_package_cmp(PakfirePackage pkg1, PakfirePackage pkg2) {
129 Pool* pool = pakfire_package_get_solv_pool(pkg1);
130
131 Solvable* s1 = get_solvable(pkg1);
132 Solvable* s2 = get_solvable(pkg2);
133
134 // Check names
135 const char* str1 = pool_id2str(pool, s1->name);
136 const char* str2 = pool_id2str(pool, s2->name);
137
138 int ret = strcmp(str1, str2);
139 if (ret)
140 return ret;
141
142 // Check the version string
143 ret = pakfire_package_evr_cmp(pkg1, pkg2);
144 if (ret)
145 return ret;
146
147 // Check repositories
148 PakfireRepo repo1 = pakfire_package_get_repo(pkg1);
149 PakfireRepo repo2 = pakfire_package_get_repo(pkg2);
150
151 if (repo1 && repo2) {
152 ret = pakfire_repo_cmp(repo1, repo2);
153
154 pakfire_repo_free(repo1);
155 pakfire_repo_free(repo2);
156
157 if (ret)
158 return ret;
159 }
160
161 // Check package architectures
162 str1 = pool_id2str(pool, s1->arch);
163 str2 = pool_id2str(pool, s2->arch);
164
165 return strcmp(str1, str2);
166 }
167
168 PAKFIRE_EXPORT int pakfire_package_evr_cmp(PakfirePackage pkg1, PakfirePackage pkg2) {
169 Pool* pool = pakfire_package_get_solv_pool(pkg1);
170
171 Solvable* s1 = get_solvable(pkg1);
172 Solvable* s2 = get_solvable(pkg2);
173
174 return pool_evrcmp(pool, s1->evr, s2->evr, EVRCMP_COMPARE);
175 }
176
177 PAKFIRE_EXPORT Id pakfire_package_id(PakfirePackage pkg) {
178 return pkg->id;
179 }
180
181 PAKFIRE_EXPORT char* pakfire_package_get_nevra(PakfirePackage pkg) {
182 Pool* pool = pakfire_package_get_solv_pool(pkg);
183 Solvable* s = get_solvable(pkg);
184
185 const char* nevra = pool_solvable2str(pool, s);
186
187 return pakfire_strdup(nevra);
188 }
189
190 PAKFIRE_EXPORT const char* pakfire_package_get_name(PakfirePackage pkg) {
191 Pool* pool = pakfire_package_get_solv_pool(pkg);
192 Solvable* s = get_solvable(pkg);
193
194 return pool_id2str(pool, s->name);
195 }
196
197 PAKFIRE_EXPORT void pakfire_package_set_name(PakfirePackage pkg, const char* name) {
198 Pool* pool = pakfire_package_get_solv_pool(pkg);
199 Solvable* s = get_solvable(pkg);
200
201 s->name = pool_str2id(pool, name, 1);
202 }
203
204 PAKFIRE_EXPORT const char* pakfire_package_get_evr(PakfirePackage pkg) {
205 Pool* pool = pakfire_package_get_solv_pool(pkg);
206 Solvable* s = get_solvable(pkg);
207
208 return pool_id2str(pool, s->evr);
209 }
210
211 PAKFIRE_EXPORT void pakfire_package_set_evr(PakfirePackage pkg, const char* evr) {
212 Pool* pool = pakfire_package_get_solv_pool(pkg);
213 Solvable* s = get_solvable(pkg);
214
215 s->evr = pool_str2id(pool, evr, 1);
216 }
217
218 static void split_evr(Pool* pool, const char* evr_c, char** epoch, char** version, char** release) {
219 char* evr = pakfire_pool_tmpdup(pool, evr_c);
220 char *e, *v, *r;
221
222 for (e = evr + 1; *e != ':' && *e != '-'; ++e)
223 ;
224
225 if (*e == '-') {
226 *e = '\0';
227 v = evr;
228 r = e + 1;
229 e = NULL;
230 } else { /* *e == ':' */
231 *e = '\0';
232 v = e + 1;
233 e = evr;
234 for (r = v + 1; *r != '-'; ++r)
235 ;
236 *r = '\0';
237 r++;
238 }
239
240 *epoch = e;
241 *version = v;
242 *release = r;
243 }
244
245 PAKFIRE_EXPORT unsigned long pakfire_package_get_epoch(PakfirePackage pkg) {
246 Pool* pool = pakfire_package_get_solv_pool(pkg);
247 char *e, *v, *r, *endptr;
248
249 unsigned long epoch = 0;
250
251 split_evr(pool, pakfire_package_get_evr(pkg), &e, &v, &r);
252
253 if (e) {
254 long int converted = strtol(e, &endptr, 10);
255 assert(converted > 0);
256 assert(*endptr == '\0');
257 epoch = converted;
258 }
259
260 return epoch;
261 }
262
263 PAKFIRE_EXPORT const char* pakfire_package_get_version(PakfirePackage pkg) {
264 Pool* pool = pakfire_package_get_solv_pool(pkg);
265 char *e, *v, *r;
266
267 split_evr(pool, pakfire_package_get_evr(pkg), &e, &v, &r);
268 return pakfire_strdup(v);
269 }
270
271 PAKFIRE_EXPORT const char* pakfire_package_get_release(PakfirePackage pkg) {
272 Pool* pool = pakfire_package_get_solv_pool(pkg);
273 char *e, *v, *r;
274
275 split_evr(pool, pakfire_package_get_evr(pkg), &e, &v, &r);
276 return pakfire_strdup(r);
277 }
278
279 PAKFIRE_EXPORT const char* pakfire_package_get_arch(PakfirePackage pkg) {
280 Pool* pool = pakfire_package_get_solv_pool(pkg);
281 Solvable* s = get_solvable(pkg);
282
283 return pool_id2str(pool, s->arch);
284 }
285
286 PAKFIRE_EXPORT void pakfire_package_set_arch(PakfirePackage pkg, const char* arch) {
287 Pool* pool = pakfire_package_get_solv_pool(pkg);
288 Solvable* s = get_solvable(pkg);
289
290 s->arch = pool_str2id(pool, arch, 1);
291 }
292
293 static void pakfire_package_internalize_repo(PakfirePackage pkg) {
294 PakfireRepo repo = pakfire_package_get_repo(pkg);
295 if (repo) {
296 pakfire_repo_internalize(repo);
297 pakfire_repo_free(repo);
298 }
299 }
300
301 static const char* pakfire_package_get_string(PakfirePackage pkg, int key) {
302 pakfire_package_internalize_repo(pkg);
303
304 Solvable* s = get_solvable(pkg);
305 const char* str = solvable_lookup_str(s, key);
306
307 if (!str)
308 return NULL;
309
310 if (strlen(str) == 0)
311 return NULL;
312
313 return str;
314 }
315
316 static void pakfire_package_set_string(PakfirePackage pkg, int key, const char* value) {
317 Solvable* s = get_solvable(pkg);
318
319 if (!value)
320 value = "";
321
322 solvable_set_str(s, key, value);
323 }
324
325 PAKFIRE_EXPORT const char* pakfire_package_get_uuid(PakfirePackage pkg) {
326 return pakfire_package_get_string(pkg, SOLVABLE_PKGID);
327 }
328
329 PAKFIRE_EXPORT void pakfire_package_set_uuid(PakfirePackage pkg, const char* uuid) {
330 pakfire_package_set_string(pkg, SOLVABLE_PKGID, uuid);
331 }
332
333 PAKFIRE_EXPORT const char* pakfire_package_get_checksum(PakfirePackage pkg) {
334 return pakfire_package_get_string(pkg, SOLVABLE_CHECKSUM);
335 }
336
337 PAKFIRE_EXPORT void pakfire_package_set_checksum(PakfirePackage pkg, const char* checksum) {
338 pakfire_package_set_string(pkg, SOLVABLE_CHECKSUM, checksum);
339 }
340
341 PAKFIRE_EXPORT const char* pakfire_package_get_summary(PakfirePackage pkg) {
342 return pakfire_package_get_string(pkg, SOLVABLE_SUMMARY);
343 }
344
345 PAKFIRE_EXPORT void pakfire_package_set_summary(PakfirePackage pkg, const char* summary) {
346 pakfire_package_set_string(pkg, SOLVABLE_SUMMARY, summary);
347 }
348
349 PAKFIRE_EXPORT const char* pakfire_package_get_description(PakfirePackage pkg) {
350 return pakfire_package_get_string(pkg, SOLVABLE_DESCRIPTION);
351 }
352
353 PAKFIRE_EXPORT void pakfire_package_set_description(PakfirePackage pkg, const char* description) {
354 pakfire_package_set_string(pkg, SOLVABLE_DESCRIPTION, description);
355 }
356
357 PAKFIRE_EXPORT const char* pakfire_package_get_license(PakfirePackage pkg) {
358 return pakfire_package_get_string(pkg, SOLVABLE_LICENSE);
359 }
360
361 PAKFIRE_EXPORT void pakfire_package_set_license(PakfirePackage pkg, const char* license) {
362 pakfire_package_set_string(pkg, SOLVABLE_LICENSE, license);
363 }
364
365 PAKFIRE_EXPORT const char* pakfire_package_get_url(PakfirePackage pkg) {
366 return pakfire_package_get_string(pkg, SOLVABLE_URL);
367 }
368
369 PAKFIRE_EXPORT void pakfire_package_set_url(PakfirePackage pkg, const char* url) {
370 pakfire_package_set_string(pkg, SOLVABLE_URL, url);
371 }
372
373 #warning the groups functions need to be refactored
374
375 PAKFIRE_EXPORT const char** pakfire_package_get_groups(PakfirePackage pkg) {
376 const char* groups = pakfire_package_get_string(pkg, SOLVABLE_GROUP);
377
378 const char** grouplist = NULL;
379 char* group = strtok((char *)groups, " ");
380
381 int i = 0;
382 while (group != NULL) {
383 grouplist = realloc(grouplist, sizeof(char *) * ++i);
384 assert(grouplist);
385 grouplist[i - 1] = group;
386
387 group = strtok(NULL, " ");
388 }
389 grouplist[i] = NULL;
390
391 return grouplist;
392 }
393
394 PAKFIRE_EXPORT void pakfire_package_set_groups(PakfirePackage pkg, const char** grouplist) {
395 char groups[2048] = "";
396
397 if (grouplist) {
398 const char* group;
399 while ((group = *grouplist++) != NULL) {
400 if (groups[0])
401 strcat(groups, " ");
402
403 strcat(groups, group);
404 }
405 groups[sizeof(groups) - 1] = '\0';
406 } else
407 groups[0] = '\0';
408
409 pakfire_package_set_string(pkg, SOLVABLE_GROUP, (const char *)&groups);
410 }
411
412 PAKFIRE_EXPORT const char* pakfire_package_get_vendor(PakfirePackage pkg) {
413 return pakfire_package_get_string(pkg, SOLVABLE_VENDOR);
414 }
415
416 PAKFIRE_EXPORT void pakfire_package_set_vendor(PakfirePackage pkg, const char* vendor) {
417 pakfire_package_set_string(pkg, SOLVABLE_VENDOR, vendor);
418 }
419
420 PAKFIRE_EXPORT const char* pakfire_package_get_maintainer(PakfirePackage pkg) {
421 return pakfire_package_get_string(pkg, SOLVABLE_PACKAGER);
422 }
423
424 PAKFIRE_EXPORT void pakfire_package_set_maintainer(PakfirePackage pkg, const char* maintainer) {
425 pakfire_package_set_string(pkg, SOLVABLE_PACKAGER, maintainer);
426 }
427
428 PAKFIRE_EXPORT const char* pakfire_package_get_filename(PakfirePackage pkg) {
429 return pakfire_package_get_string(pkg, SOLVABLE_MEDIAFILE);
430 }
431
432 PAKFIRE_EXPORT void pakfire_package_set_filename(PakfirePackage pkg, const char* filename) {
433 pakfire_package_set_string(pkg, SOLVABLE_MEDIAFILE, filename);
434 }
435
436 PAKFIRE_EXPORT int pakfire_package_is_installed(PakfirePackage pkg) {
437 Pool* pool = pakfire_package_get_solv_pool(pkg);
438 Solvable* s = get_solvable(pkg);
439
440 return pool->installed == s->repo;
441 }
442
443 static unsigned long long pakfire_package_get_num(PakfirePackage pkg, Id type) {
444 pakfire_package_internalize_repo(pkg);
445
446 Solvable* s = get_solvable(pkg);
447 return solvable_lookup_num(s, type, 0);
448 }
449
450 static void pakfire_package_set_num(PakfirePackage pkg, Id type, unsigned long long value) {
451 Solvable* s = get_solvable(pkg);
452
453 solvable_set_num(s, type, value);
454 }
455
456 PAKFIRE_EXPORT unsigned long long pakfire_package_get_downloadsize(PakfirePackage pkg) {
457 return pakfire_package_get_num(pkg, SOLVABLE_DOWNLOADSIZE);
458 }
459
460 PAKFIRE_EXPORT void pakfire_package_set_downloadsize(PakfirePackage pkg, unsigned long long downloadsize) {
461 return pakfire_package_set_num(pkg, SOLVABLE_DOWNLOADSIZE, downloadsize);
462 }
463
464 PAKFIRE_EXPORT unsigned long long pakfire_package_get_installsize(PakfirePackage pkg) {
465 return pakfire_package_get_num(pkg, SOLVABLE_INSTALLSIZE);
466 }
467
468 PAKFIRE_EXPORT void pakfire_package_set_installsize(PakfirePackage pkg, unsigned long long installsize) {
469 return pakfire_package_set_num(pkg, SOLVABLE_INSTALLSIZE, installsize);
470 }
471
472 PAKFIRE_EXPORT unsigned long long pakfire_package_get_size(PakfirePackage pkg) {
473 if (pakfire_package_is_installed(pkg))
474 return pakfire_package_get_installsize(pkg);
475
476 return pakfire_package_get_downloadsize(pkg);
477 }
478
479 PAKFIRE_EXPORT const char* pakfire_package_get_buildhost(PakfirePackage pkg) {
480 return pakfire_package_get_string(pkg, SOLVABLE_BUILDHOST);
481 }
482
483 PAKFIRE_EXPORT void pakfire_package_set_buildhost(PakfirePackage pkg, const char* buildhost) {
484 pakfire_package_set_string(pkg, SOLVABLE_BUILDHOST, buildhost);
485 }
486
487 PAKFIRE_EXPORT unsigned long long pakfire_package_get_buildtime(PakfirePackage pkg) {
488 return pakfire_package_get_num(pkg, SOLVABLE_BUILDTIME);
489 }
490
491 PAKFIRE_EXPORT void pakfire_package_set_buildtime(PakfirePackage pkg, unsigned long long buildtime) {
492 pakfire_package_set_num(pkg, SOLVABLE_BUILDTIME, buildtime);
493 }
494
495 PAKFIRE_EXPORT unsigned long long pakfire_package_get_installtime(PakfirePackage pkg) {
496 return pakfire_package_get_num(pkg, SOLVABLE_INSTALLTIME);
497 }
498
499 static PakfireRelationList pakfire_package_get_relationlist(PakfirePackage pkg, Id type) {
500 Queue q;
501 queue_init(&q);
502
503 Solvable* s = get_solvable(pkg);
504 solvable_lookup_idarray(s, type, &q);
505
506 PakfireRelationList relationlist = pakfire_relationlist_from_queue(pkg->pool, q);
507
508 queue_free(&q);
509
510 return relationlist;
511 }
512
513 static void pakfire_package_set_relationlist(PakfirePackage pkg, Id type, PakfireRelationList relationlist) {
514 #if 0
515 // This implemention should be the fastest, but unfortunately does not work.
516 Queue q;
517 pakfire_relationlist_clone_to_queue(relationlist, &q);
518
519 Solvable* s = get_solvable(pkg);
520 solvable_set_idarray(s, type, &q);
521
522 queue_free(&q);
523 #endif
524
525 Solvable* s = get_solvable(pkg);
526 solvable_unset(s, type);
527
528 int count = pakfire_relationlist_count(relationlist);
529 for (int i = 0; i < count; i++) {
530 PakfireRelation relation = pakfire_relationlist_get_clone(relationlist, i);
531 solvable_add_idarray(s, type, relation->id);
532
533 pakfire_relation_free(relation);
534 }
535 }
536
537 static void pakfire_package_add_relation(PakfirePackage pkg, Id type, PakfireRelation relation) {
538 Solvable* s = get_solvable(pkg);
539
540 solvable_add_idarray(s, type, relation->id);
541 }
542
543 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_provides(PakfirePackage pkg) {
544 return pakfire_package_get_relationlist(pkg, SOLVABLE_PROVIDES);
545 }
546
547 PAKFIRE_EXPORT void pakfire_package_set_provides(PakfirePackage pkg, PakfireRelationList relationlist) {
548 pakfire_package_set_relationlist(pkg, SOLVABLE_PROVIDES, relationlist);
549 }
550
551 PAKFIRE_EXPORT void pakfire_package_add_provides(PakfirePackage pkg, PakfireRelation relation) {
552 pakfire_package_add_relation(pkg, SOLVABLE_PROVIDES, relation);
553 }
554
555 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_prerequires(PakfirePackage pkg) {
556 #warning TODO
557 return NULL;
558 }
559
560 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_requires(PakfirePackage pkg) {
561 return pakfire_package_get_relationlist(pkg, SOLVABLE_REQUIRES);
562 }
563
564 PAKFIRE_EXPORT void pakfire_package_set_requires(PakfirePackage pkg, PakfireRelationList relationlist) {
565 pakfire_package_set_relationlist(pkg, SOLVABLE_REQUIRES, relationlist);
566 }
567
568 PAKFIRE_EXPORT void pakfire_package_add_requires(PakfirePackage pkg, PakfireRelation relation) {
569 pakfire_package_add_relation(pkg, SOLVABLE_REQUIRES, relation);
570 }
571
572 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_conflicts(PakfirePackage pkg) {
573 return pakfire_package_get_relationlist(pkg, SOLVABLE_CONFLICTS);
574 }
575
576 PAKFIRE_EXPORT void pakfire_package_set_conflicts(PakfirePackage pkg, PakfireRelationList relationlist) {
577 pakfire_package_set_relationlist(pkg, SOLVABLE_CONFLICTS, relationlist);
578 }
579
580 PAKFIRE_EXPORT void pakfire_package_add_conflicts(PakfirePackage pkg, PakfireRelation relation) {
581 pakfire_package_add_relation(pkg, SOLVABLE_CONFLICTS, relation);
582 }
583
584 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_obsoletes(PakfirePackage pkg) {
585 return pakfire_package_get_relationlist(pkg, SOLVABLE_OBSOLETES);
586 }
587
588 PAKFIRE_EXPORT void pakfire_package_set_obsoletes(PakfirePackage pkg, PakfireRelationList relationlist) {
589 pakfire_package_set_relationlist(pkg, SOLVABLE_OBSOLETES, relationlist);
590 }
591
592 PAKFIRE_EXPORT void pakfire_package_add_obsoletes(PakfirePackage pkg, PakfireRelation relation) {
593 pakfire_package_add_relation(pkg, SOLVABLE_OBSOLETES, relation);
594 }
595
596 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_recommends(PakfirePackage pkg) {
597 return pakfire_package_get_relationlist(pkg, SOLVABLE_RECOMMENDS);
598 }
599
600 PAKFIRE_EXPORT void pakfire_package_set_recommends(PakfirePackage pkg, PakfireRelationList relationlist) {
601 pakfire_package_set_relationlist(pkg, SOLVABLE_RECOMMENDS, relationlist);
602 }
603
604 PAKFIRE_EXPORT void pakfire_package_add_recommends(PakfirePackage pkg, PakfireRelation relation) {
605 pakfire_package_add_relation(pkg, SOLVABLE_RECOMMENDS, relation);
606 }
607
608 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_suggests(PakfirePackage pkg) {
609 return pakfire_package_get_relationlist(pkg, SOLVABLE_SUGGESTS);
610 }
611
612 PAKFIRE_EXPORT void pakfire_package_set_suggests(PakfirePackage pkg, PakfireRelationList relationlist) {
613 pakfire_package_set_relationlist(pkg, SOLVABLE_SUGGESTS, relationlist);
614 }
615
616 PAKFIRE_EXPORT void pakfire_package_add_suggests(PakfirePackage pkg, PakfireRelation relation) {
617 pakfire_package_add_relation(pkg, SOLVABLE_SUGGESTS, relation);
618 }
619
620 PAKFIRE_EXPORT PakfireRepo pakfire_package_get_repo(PakfirePackage pkg) {
621 Solvable* s = get_solvable(pkg);
622
623 return pakfire_repo_create_from_repo(pkg->pool, s->repo);
624 }
625
626 PAKFIRE_EXPORT void pakfire_package_set_repo(PakfirePackage pkg, PakfireRepo repo) {
627 Solvable* s = get_solvable(pkg);
628
629 s->repo = pakfire_repo_get_solv_repo(repo);
630 }
631
632 PAKFIRE_EXPORT char* pakfire_package_get_location(PakfirePackage pkg) {
633 pakfire_package_internalize_repo(pkg);
634
635 Solvable* s = get_solvable(pkg);
636
637 const char* location = solvable_get_location(s, NULL);
638 return pakfire_strdup(location);
639 }
640
641 static void pakfire_package_dump_add_line(char** str, const char* key, const char* val) {
642 if (val)
643 asprintf(str, "%s%-15s: %s\n", *str, key ? key : "", val);
644 }
645
646 static void pakfire_package_dump_add_lines(char** str, const char* key, const char* val) {
647 const char* string = val;
648
649 while (*string) {
650 char line[STRING_SIZE];
651 int counter = 0;
652
653 while (*string) {
654 if (*string == '\n') {
655 string++;
656 break;
657 }
658
659 line[counter++] = *string++;
660 }
661 line[counter] = '\0';
662
663 if (*line) {
664 pakfire_package_dump_add_line(str, key, line);
665 key = NULL;
666 }
667 }
668 }
669
670 static void pakfire_package_dump_add_line_date(char** str, const char* key, unsigned long long date) {
671 // Convert from integer to tm struct.
672 struct tm* timer = gmtime((time_t *)&date);
673
674 char val[STRING_SIZE];
675 strftime(val, STRING_SIZE, "%a, %d %b %Y %T %z", timer);
676
677 pakfire_package_dump_add_line(str, key, val);
678 }
679
680 static void pakfire_package_dump_add_line_relations(char** str, const char* key, PakfireRelationList deps) {
681 int count = pakfire_relationlist_count(deps);
682 for (int i = 0; i < count; i++) {
683 PakfireRelation relation = pakfire_relationlist_get_clone(deps, i);
684
685 if (relation) {
686 char* dep = pakfire_relation_str(relation);
687 pakfire_relation_free(relation);
688
689 // Stop here and don't list any files.
690 if (strcmp(PAKFIRE_SOLVABLE_FILEMARKER, dep) == 0)
691 break;
692
693 if (dep) {
694 pakfire_package_dump_add_line(str, (i == 0) ? key : "", dep);
695 pakfire_free(dep);
696 }
697 }
698 }
699 }
700
701 static void pakfire_package_dump_add_line_size(char** str, const char* key, unsigned long long size) {
702 char* val = pakfire_format_size(size);
703
704 if (val) {
705 pakfire_package_dump_add_line(str, key, val);
706 pakfire_free(val);
707 }
708 }
709
710 PAKFIRE_EXPORT char* pakfire_package_dump(PakfirePackage pkg, int flags) {
711 char* string = "";
712
713 // Name
714 const char* name = pakfire_package_get_name(pkg);
715 pakfire_package_dump_add_line(&string, _("Name"), name);
716
717 // Version
718 const char* version = pakfire_package_get_version(pkg);
719 pakfire_package_dump_add_line(&string, _("Version"), version);
720
721 // Release
722 const char* release = pakfire_package_get_release(pkg);
723 pakfire_package_dump_add_line(&string, _("Release"), release);
724
725 // Size
726 unsigned long long size = pakfire_package_get_size(pkg);
727 pakfire_package_dump_add_line_size(&string, _("Size"), size);
728
729 // Installed size
730 if (pakfire_package_is_installed(pkg)) {
731 unsigned long long installsize = pakfire_package_get_installsize(pkg);
732 pakfire_package_dump_add_line_size(&string, _("Installed size"), installsize);
733
734 // Downloadsize
735 } else {
736 unsigned long long downloadsize = pakfire_package_get_downloadsize(pkg);
737 pakfire_package_dump_add_line_size(&string, _("Download size"), downloadsize);
738 }
739
740 PakfireRepo repo = pakfire_package_get_repo(pkg);
741 if (repo) {
742 const char* repo_name = pakfire_repo_get_name(repo);
743 pakfire_package_dump_add_line(&string, _("Repo"), repo_name);
744
745 pakfire_repo_free(repo);
746 }
747
748 // Summary
749 const char* summary = pakfire_package_get_summary(pkg);
750 pakfire_package_dump_add_line(&string, _("Summary"), summary);
751
752 // Description
753 const char* description = pakfire_package_get_description(pkg);
754 pakfire_package_dump_add_lines(&string, _("Description"), description);
755
756 // Groups
757 #warning TODO groups
758
759 // URL
760 const char* url = pakfire_package_get_url(pkg);
761 pakfire_package_dump_add_line(&string, _("URL"), url);
762
763 // License
764 const char* license = pakfire_package_get_license(pkg);
765 pakfire_package_dump_add_line(&string, _("License"), license);
766
767 if (flags & PAKFIRE_PKG_DUMP_LONG) {
768 // Maintainer
769 const char* maintainer = pakfire_package_get_maintainer(pkg);
770 pakfire_package_dump_add_line(&string, _("Maintainer"), maintainer);
771
772 // Vendor
773 const char* vendor = pakfire_package_get_vendor(pkg);
774 pakfire_package_dump_add_line(&string, _("Vendor"), vendor);
775
776 // UUID
777 const char* uuid = pakfire_package_get_uuid(pkg);
778 pakfire_package_dump_add_line(&string, _("UUID"), uuid);
779
780 // Build time
781 unsigned long long buildtime = pakfire_package_get_buildtime(pkg);
782 pakfire_package_dump_add_line_date(&string, _("Build date"), buildtime);
783
784 // Build host
785 const char* buildhost = pakfire_package_get_buildhost(pkg);
786 pakfire_package_dump_add_line(&string, _("Build host"), buildhost);
787
788 PakfireRelationList provides = pakfire_package_get_provides(pkg);
789 if (provides) {
790 pakfire_package_dump_add_line_relations(&string, _("Provides"), provides);
791 pakfire_relationlist_free(provides);
792 }
793
794 PakfireRelationList requires = pakfire_package_get_requires(pkg);
795 if (requires) {
796 pakfire_package_dump_add_line_relations(&string, _("Requires"), requires);
797 pakfire_relationlist_free(requires);
798 }
799
800 PakfireRelationList conflicts = pakfire_package_get_conflicts(pkg);
801 if (conflicts) {
802 pakfire_package_dump_add_line_relations(&string, _("Conflicts"), conflicts);
803 pakfire_relationlist_free(conflicts);
804 }
805
806 PakfireRelationList obsoletes = pakfire_package_get_obsoletes(pkg);
807 if (obsoletes) {
808 pakfire_package_dump_add_line_relations(&string, _("Obsoletes"), obsoletes);
809 pakfire_relationlist_free(obsoletes);
810 }
811
812 PakfireRelationList recommends = pakfire_package_get_recommends(pkg);
813 if (recommends) {
814 pakfire_package_dump_add_line_relations(&string, _("Recommends"), recommends);
815 pakfire_relationlist_free(recommends);
816 }
817
818 PakfireRelationList suggests = pakfire_package_get_suggests(pkg);
819 if (suggests) {
820 pakfire_package_dump_add_line_relations(&string, _("Suggests"), suggests);
821 pakfire_relationlist_free(suggests);
822 }
823 }
824
825 if (flags & PAKFIRE_PKG_DUMP_FILELIST) {
826 PakfireFile file = pakfire_package_get_filelist(pkg);
827
828 char* prefix = _("Filelist");
829 while (file) {
830 const char* name = pakfire_file_get_name(file);
831 pakfire_package_dump_add_line(&string, prefix, name);
832
833 file = pakfire_file_get_next(file);
834
835 // Only prefix the first line.
836 prefix = NULL;
837 }
838 }
839
840 return string;
841 }
842
843 PAKFIRE_EXPORT int pakfire_package_is_cached(PakfirePackage pkg) {
844 PakfireCache cache = pakfire_pool_get_cache(pkg->pool);
845 if (!cache)
846 return 1;
847
848 return pakfire_cache_has_package(cache, pkg);
849 }
850
851 PAKFIRE_EXPORT char* pakfire_package_get_cache_path(PakfirePackage pkg) {
852 PakfireCache cache = pakfire_pool_get_cache(pkg->pool);
853 if (!cache)
854 return NULL;
855
856 return pakfire_cache_get_package_path(cache, pkg);
857 }
858
859 PAKFIRE_EXPORT char* pakfire_package_get_cache_full_path(PakfirePackage pkg) {
860 char* cache_path = NULL;
861
862 char* pkg_cache_path = pakfire_package_get_cache_path(pkg);
863 if (!pkg_cache_path)
864 return NULL;
865
866 PakfireRepo repo = pakfire_package_get_repo(pkg);
867 if (!repo)
868 goto out;
869
870 PakfireRepoCache repo_cache = pakfire_repo_get_cache(repo);
871 if (!repo_cache) {
872 goto out;
873 }
874
875 cache_path = pakfire_repocache_get_full_path(repo_cache, pkg_cache_path);
876
877 out:
878 if (repo)
879 pakfire_repo_free(repo);
880
881 return cache_path;
882 }
883
884 static PakfireFile pakfire_package_fetch_legacy_filelist(PakfirePackage pkg) {
885 pakfire_package_internalize_repo(pkg);
886
887 PakfireFile file = NULL;
888 PakfireRepo repo = pakfire_package_get_repo(pkg);
889 Solvable* s = get_solvable(pkg);
890 Pool* p = pakfire_package_get_solv_pool(pkg);
891 Repo* r = pakfire_repo_get_solv_repo(repo);
892
893 int found_marker = 0;
894
895 Id id, *ids;
896 ids = r->idarraydata + s->provides;
897 while((id = *ids++) != 0) {
898 const char* filename = pool_dep2str(p, id);
899
900 if (found_marker) {
901 if (file) {
902 file = pakfire_file_append(file);
903 } else {
904 file = pakfire_file_create();
905 }
906
907 pakfire_file_set_name(file, filename);
908 continue;
909 }
910
911 if (strcmp(filename, PAKFIRE_SOLVABLE_FILEMARKER) == 0)
912 ++found_marker;
913 }
914
915 if (file) {
916 file = pakfire_file_get_first(file);
917
918 // Sort the output
919 file = pakfire_file_sort(file);
920 }
921
922 return file;
923 }
924
925 static PakfireFile pakfire_package_fetch_filelist(PakfirePackage pkg) {
926 pakfire_package_internalize_repo(pkg);
927
928 PakfireFile file = NULL;
929 Pool* pool = pakfire_package_get_solv_pool(pkg);
930 Repo* repo = pakfire_package_solv_repo(pkg);
931 Id handle = pakfire_package_get_handle(pkg);
932
933 Dataiterator di;
934 dataiterator_init(&di, pool, repo, handle,
935 SOLVABLE_FILELIST, NULL, SEARCH_FILES | SEARCH_COMPLETE_FILELIST);
936 while (dataiterator_step(&di)) {
937 if (file) {
938 file = pakfire_file_append(file);
939 } else {
940 file = pakfire_file_create();
941 }
942
943 pakfire_file_set_name(file, di.kv.str);
944 }
945 dataiterator_free(&di);
946
947 if (file) {
948 file = pakfire_file_get_first(file);
949
950 // Sort the result.
951 file = pakfire_file_sort(file);
952 }
953
954 // If the file list is empty, we fall back to read files
955 // in the older format.
956 if (!file)
957 file = pakfire_package_fetch_legacy_filelist(pkg);
958
959 return file;
960 }
961
962 PAKFIRE_EXPORT PakfireFile pakfire_package_get_filelist(PakfirePackage pkg) {
963 if (!pkg->filelist) {
964 pkg->filelist = pakfire_package_fetch_filelist(pkg);
965 }
966
967 return pkg->filelist;
968 }
969
970 PAKFIRE_EXPORT PakfireFile pakfire_package_filelist_append(PakfirePackage pkg, const char* filename) {
971 PakfireRepo repo = pakfire_package_get_repo(pkg);
972
973 Id handle = pakfire_package_get_handle(pkg);
974
975 char* dirname = pakfire_dirname(filename);
976 char* basename = pakfire_basename(filename);
977
978 Id did = repodata_str2dir(repo->filelist, dirname, 1);
979 if (!did)
980 did = repodata_str2dir(repo->filelist, "/", 1);
981
982 repodata_add_dirstr(repo->filelist, handle,
983 SOLVABLE_FILELIST, did, basename);
984
985 return NULL;
986 }
987
988 #if 0
989 PakfireFile pakfire_package_filelist_append(PakfirePackage pkg) {
990 if (pkg->filelist) {
991 return pakfire_file_append(pkg->filelist);
992 }
993
994 PakfireFile file = pakfire_file_create();
995 pkg->filelist = file;
996
997 return file;
998 }
999 #endif
1000
1001 PAKFIRE_EXPORT void pakfire_package_filelist_remove(PakfirePackage pkg) {
1002 if (pkg->filelist)
1003 pakfire_file_free_all(pkg->filelist);
1004 }