pkg_hash: remove accidentally committed stuff
[project/opkg-lede.git] / libopkg / pkg_hash.c
1 /* opkg_hash.c - the opkg package management system
2
3 Steven M. Ayer
4
5 Copyright (C) 2002 Compaq Computer Corporation
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16 */
17
18 #include <stdio.h>
19
20 #include "hash_table.h"
21 #include "pkg.h"
22 #include "opkg_message.h"
23 #include "pkg_depends.h"
24 #include "pkg_vec.h"
25 #include "pkg_hash.h"
26 #include "parse_util.h"
27 #include "pkg_parse.h"
28 #include "opkg_utils.h"
29 #include "sprintf_alloc.h"
30 #include "file_util.h"
31 #include "libbb/libbb.h"
32 #include "libbb/gzip.h"
33
34 void pkg_hash_init(void)
35 {
36 hash_table_init("pkg-hash", &conf->pkg_hash,
37 OPKG_CONF_DEFAULT_HASH_LEN);
38 }
39
40 static void free_pkgs(const char *key, void *entry, void *data)
41 {
42 int i;
43 abstract_pkg_t *ab_pkg;
44
45 /* Each entry in the hash table is an abstract package, which contains
46 * a list of packages that provide the abstract package.
47 */
48
49 ab_pkg = (abstract_pkg_t *) entry;
50
51 if (ab_pkg->pkgs) {
52 for (i = 0; i < ab_pkg->pkgs->len; i++) {
53 pkg_deinit(ab_pkg->pkgs->pkgs[i]);
54 free(ab_pkg->pkgs->pkgs[i]);
55 }
56 }
57
58 abstract_pkg_vec_free(ab_pkg->provided_by);
59 abstract_pkg_vec_free(ab_pkg->replaced_by);
60 pkg_vec_free(ab_pkg->pkgs);
61 free(ab_pkg->depended_upon_by);
62 free(ab_pkg->name);
63 free(ab_pkg);
64 }
65
66 void pkg_hash_deinit(void)
67 {
68 hash_table_foreach(&conf->pkg_hash, free_pkgs, NULL);
69 hash_table_deinit(&conf->pkg_hash);
70 }
71
72 int dist_hash_add_from_file(const char *lists_dir, pkg_src_t * dist)
73 {
74 nv_pair_list_elt_t *l;
75 char *list_file, *subname;
76
77 list_for_each_entry(l, &conf->arch_list.head, node) {
78 nv_pair_t *nv = (nv_pair_t *) l->data;
79 sprintf_alloc(&subname, "%s-%s", dist->name, nv->name);
80 sprintf_alloc(&list_file, "%s/%s", lists_dir, subname);
81
82 if (file_exists(list_file)) {
83 if (pkg_hash_add_from_file(list_file, dist, NULL, 0, 0, NULL, NULL)) {
84 free(list_file);
85 return -1;
86 }
87 pkg_src_list_append(&conf->pkg_src_list, subname,
88 dist->value, "__dummy__", 0);
89 }
90
91 free(list_file);
92 }
93
94 return 0;
95 }
96
97 int
98 pkg_hash_add_from_file(const char *file_name,
99 pkg_src_t * src, pkg_dest_t * dest, int is_status_file, int state_flags,
100 void (*cb)(pkg_t *, void *), void *priv)
101 {
102 pkg_t *pkg;
103 FILE *fp;
104 char *buf;
105 const size_t len = 4096;
106 int ret = 0;
107 struct gzip_handle zh;
108
109 if (src && src->gzip) {
110 fp = gzip_fdopen(&zh, file_name);
111 } else {
112 fp = fopen(file_name, "r");
113 }
114
115 if (fp == NULL) {
116 opkg_perror(ERROR, "Failed to open %s", file_name);
117 return -1;
118 }
119
120 buf = xmalloc(len);
121
122 do {
123 pkg = pkg_new();
124 pkg->src = src;
125 pkg->dest = dest;
126 pkg->state_flag |= state_flags;
127
128 ret = parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, 0,
129 &buf, len);
130
131 if (pkg->name == NULL) {
132 /* probably just a blank line */
133 ret = 1;
134 }
135
136 if (ret) {
137 pkg_deinit(pkg);
138 free(pkg);
139 if (ret == -1)
140 break;
141 if (ret == 1)
142 /* Probably a blank line, continue parsing. */
143 ret = 0;
144 continue;
145 }
146
147 if (!(pkg->state_flag & SF_NEED_DETAIL)) {
148 //opkg_msg(DEBUG, "Package %s is unrelated, ignoring.\n", pkg->name);
149 pkg_deinit(pkg);
150 free(pkg);
151 continue;
152 }
153
154 if (!pkg_get_architecture(pkg) || !pkg_get_arch_priority(pkg)) {
155 char *version_str = pkg_version_str_alloc(pkg);
156 opkg_msg(NOTICE, "Package %s version %s has no "
157 "valid architecture, ignoring.\n",
158 pkg->name, version_str);
159 free(version_str);
160 continue;
161 }
162
163 if (cb)
164 cb(pkg, priv);
165 else
166 hash_insert_pkg(pkg, is_status_file);
167
168 } while (!feof(fp));
169
170 free(buf);
171 fclose(fp);
172
173 if (src && src->gzip)
174 gzip_close(&zh);
175
176 return ret;
177 }
178
179 /*
180 * Load in feed files from the cached "src" and/or "src/gz" locations.
181 */
182 int pkg_hash_load_feeds(int state_flags, void (*cb)(pkg_t *, void *), void *priv)
183 {
184 pkg_src_list_elt_t *iter;
185 pkg_src_t *src;
186 char *list_file, *lists_dir;
187
188 opkg_msg(INFO, "\n");
189
190 lists_dir = conf->restrict_to_default_dest ?
191 conf->default_dest->lists_dir : conf->lists_dir;
192
193 for (iter = void_list_first(&conf->pkg_src_list); iter;
194 iter = void_list_next(&conf->pkg_src_list, iter)) {
195
196 src = (pkg_src_t *) iter->data;
197
198 sprintf_alloc(&list_file, "%s/%s", lists_dir, src->name);
199
200 if (file_exists(list_file)) {
201 if (pkg_hash_add_from_file(list_file, src, NULL, 0, state_flags, cb, priv)) {
202 free(list_file);
203 return -1;
204 }
205 }
206 free(list_file);
207 }
208
209 return 0;
210 }
211
212 /*
213 * Load in status files from the configured "dest"s.
214 */
215 int pkg_hash_load_status_files(void (*cb)(pkg_t *, void *), void *priv)
216 {
217 pkg_dest_list_elt_t *iter;
218 pkg_dest_t *dest;
219
220 opkg_msg(INFO, "\n");
221
222 for (iter = void_list_first(&conf->pkg_dest_list); iter;
223 iter = void_list_next(&conf->pkg_dest_list, iter)) {
224
225 dest = (pkg_dest_t *) iter->data;
226
227 if (file_exists(dest->status_file_name)) {
228 if (pkg_hash_add_from_file
229 (dest->status_file_name, NULL, dest, 1, SF_NEED_DETAIL, cb, priv))
230 return -1;
231 }
232 }
233
234 return 0;
235 }
236
237 static void
238 pkg_hash_load_package_details_helper(const char *pkg_name, void *entry, void *data)
239 {
240 int *count = data;
241 abstract_pkg_t *ab_pkg = (abstract_pkg_t *) entry;
242
243 if (ab_pkg->state_flag & SF_NEED_DETAIL) {
244 if (ab_pkg->state_flag & SF_MARKED) {
245 opkg_msg(DEBUG, "skipping already seen flagged abpkg %s\n",
246 ab_pkg->name);
247 return;
248 }
249
250 opkg_msg(DEBUG, "found yet incomplete flagged abpkg %s\n",
251 ab_pkg->name);
252
253 (*count)++;
254 ab_pkg->state_flag |= SF_MARKED;
255 }
256 }
257
258 int pkg_hash_load_package_details(void)
259 {
260 int n_need_detail;
261
262 while (1) {
263 pkg_hash_load_feeds(0, NULL, NULL);
264
265 n_need_detail = 0;
266 hash_table_foreach(&conf->pkg_hash, pkg_hash_load_package_details_helper, &n_need_detail);
267
268 if (n_need_detail > 0)
269 opkg_msg(DEBUG, "Found %d packages requiring details, reloading feeds\n", n_need_detail);
270 else
271 break;
272 }
273
274 return 0;
275 }
276
277 static int
278 pkg_hash_check_unresolved(pkg_t *maybe)
279 {
280 char **unresolved = NULL;
281 char **tmp;
282 pkg_vec_t *depends, *all;
283 int i, res = 0;
284
285 depends = pkg_vec_alloc();
286 pkg_hash_fetch_unsatisfied_dependencies(maybe, depends, &unresolved);
287
288 if (unresolved) {
289 res = 1;
290 tmp = unresolved;
291 while (tmp)
292 free(*(tmp++));
293 free(unresolved);
294 }
295 pkg_vec_free(depends);
296
297 /* clear depenacy checked marks, left by pkg_hash_fetch_unsatisfied_dependencies */
298 all = pkg_vec_alloc();
299 pkg_hash_fetch_available(all);
300 for (i = 0; i < all->len; i++) {
301 all->pkgs[i]->parent->dependencies_checked = 0;
302 }
303 pkg_vec_free(all);
304
305 return res;
306 }
307
308 pkg_t *pkg_hash_fetch_best_installation_candidate(abstract_pkg_t * apkg,
309 int (*constraint_fcn) (pkg_t *
310 pkg,
311 void
312 *cdata),
313 void *cdata, int quiet)
314 {
315 int i, j;
316 int nprovides = 0;
317 int nmatching = 0;
318 int wrong_arch_found = 0;
319 int arch_priority;
320 pkg_vec_t *matching_pkgs;
321 abstract_pkg_vec_t *matching_apkgs;
322 abstract_pkg_vec_t *provided_apkg_vec;
323 abstract_pkg_t **provided_apkgs;
324 abstract_pkg_vec_t *providers;
325 pkg_t *latest_installed_parent = NULL;
326 pkg_t *latest_matching = NULL;
327 pkg_t *priorized_matching = NULL;
328 pkg_t *held_pkg = NULL;
329 pkg_t *good_pkg_by_name = NULL;
330
331 if (apkg == NULL || apkg->provided_by == NULL
332 || (apkg->provided_by->len == 0))
333 return NULL;
334
335 matching_pkgs = pkg_vec_alloc();
336 matching_apkgs = abstract_pkg_vec_alloc();
337 providers = abstract_pkg_vec_alloc();
338
339 opkg_msg(DEBUG, "Best installation candidate for %s:\n", apkg->name);
340
341 provided_apkg_vec = apkg->provided_by;
342 nprovides = provided_apkg_vec->len;
343 provided_apkgs = provided_apkg_vec->pkgs;
344 if (nprovides > 1)
345 opkg_msg(DEBUG, "apkg=%s nprovides=%d.\n", apkg->name,
346 nprovides);
347
348 /* accumulate all the providers */
349 for (i = 0; i < nprovides; i++) {
350 abstract_pkg_t *provider_apkg = provided_apkgs[i];
351 opkg_msg(DEBUG, "Adding %s to providers.\n",
352 provider_apkg->name);
353 abstract_pkg_vec_insert(providers, provider_apkg);
354 }
355 nprovides = providers->len;
356
357 for (i = 0; i < nprovides; i++) {
358 abstract_pkg_t *provider_apkg =
359 abstract_pkg_vec_get(providers, i);
360 abstract_pkg_t *replacement_apkg = NULL;
361 pkg_vec_t *vec;
362
363 if (provider_apkg->replaced_by
364 && provider_apkg->replaced_by->len) {
365 replacement_apkg = provider_apkg->replaced_by->pkgs[0];
366 if (provider_apkg->replaced_by->len > 1) {
367 opkg_msg(NOTICE, "Multiple replacers for %s, "
368 "using first one (%s).\n",
369 provider_apkg->name,
370 replacement_apkg->name);
371 }
372 }
373
374 if (replacement_apkg)
375 opkg_msg(DEBUG,
376 "replacement_apkg=%s for provider_apkg=%s.\n",
377 replacement_apkg->name, provider_apkg->name);
378
379 if (replacement_apkg && (replacement_apkg != provider_apkg)) {
380 if (abstract_pkg_vec_contains
381 (providers, replacement_apkg))
382 continue;
383 else
384 provider_apkg = replacement_apkg;
385 }
386
387 if (!(vec = provider_apkg->pkgs)) {
388 opkg_msg(DEBUG, "No pkgs for provider_apkg %s.\n",
389 provider_apkg->name);
390 continue;
391 }
392
393 /* now check for supported architecture */
394 {
395 int max_count = 0;
396
397 /* count packages matching max arch priority and keep track of last one */
398 for (j = 0; j < vec->len; j++) {
399 pkg_t *maybe = vec->pkgs[j];
400 arch_priority = pkg_get_arch_priority(maybe);
401
402 opkg_msg(DEBUG,
403 "%s arch=%s arch_priority=%d version=%s.\n",
404 maybe->name, pkg_get_architecture(maybe),
405 arch_priority, pkg_get_string(maybe, PKG_VERSION));
406 /* We make sure not to add the same package twice. Need to search for the reason why
407 they show up twice sometimes. */
408 if ((arch_priority > 0)
409 &&
410 (!pkg_vec_contains(matching_pkgs, maybe))
411 &&
412 (!pkg_hash_check_unresolved(maybe))) {
413 max_count++;
414 abstract_pkg_vec_insert(matching_apkgs,
415 maybe->parent);
416 pkg_vec_insert(matching_pkgs, maybe);
417 }
418 }
419
420 if (vec->len > 0 && matching_pkgs->len < 1)
421 wrong_arch_found = 1;
422 }
423 }
424
425 if (matching_pkgs->len < 1) {
426 if (wrong_arch_found)
427 opkg_msg(ERROR, "Packages for %s found, but"
428 " incompatible with the architectures configured\n",
429 apkg->name);
430 pkg_vec_free(matching_pkgs);
431 abstract_pkg_vec_free(matching_apkgs);
432 abstract_pkg_vec_free(providers);
433 return NULL;
434 }
435
436 if (matching_pkgs->len > 1)
437 pkg_vec_sort(matching_pkgs,
438 pkg_name_version_and_architecture_compare);
439 if (matching_apkgs->len > 1)
440 abstract_pkg_vec_sort(matching_apkgs, abstract_pkg_name_compare);
441
442 for (i = 0; i < matching_pkgs->len; i++) {
443 pkg_t *matching = matching_pkgs->pkgs[i];
444 if (constraint_fcn(matching, cdata)) {
445 opkg_msg(DEBUG, "Candidate: %s %s.\n",
446 matching->name, pkg_get_string(matching, PKG_VERSION));
447 good_pkg_by_name = matching;
448 /* It has been provided by hand, so it is what user want */
449 if (matching->provided_by_hand == 1)
450 break;
451 }
452 }
453
454 for (i = 0; i < matching_pkgs->len; i++) {
455 pkg_t *matching = matching_pkgs->pkgs[i];
456 latest_matching = matching;
457 if (matching->parent->state_status == SS_INSTALLED
458 || matching->parent->state_status == SS_UNPACKED)
459 latest_installed_parent = matching;
460 if (matching->state_flag & (SF_HOLD | SF_PREFER)) {
461 if (held_pkg)
462 opkg_msg(NOTICE,
463 "Multiple packages (%s and %s) providing"
464 " same name marked HOLD or PREFER. "
465 "Using latest.\n", held_pkg->name,
466 matching->name);
467 held_pkg = matching;
468 }
469 }
470
471 if (!good_pkg_by_name && !held_pkg && !latest_installed_parent
472 && matching_apkgs->len > 1 && !quiet) {
473 int prio = 0;
474 for (i = 0; i < matching_pkgs->len; i++) {
475 pkg_t *matching = matching_pkgs->pkgs[i];
476 arch_priority = pkg_get_arch_priority(matching);
477 if (arch_priority > prio) {
478 priorized_matching = matching;
479 prio = arch_priority;
480 opkg_msg(DEBUG, "Match %s with priority %i.\n",
481 matching->name, prio);
482 }
483 }
484
485 }
486
487 if (conf->verbosity >= INFO && matching_apkgs->len > 1) {
488 opkg_msg(INFO, "%d matching pkgs for apkg=%s:\n",
489 matching_pkgs->len, apkg->name);
490 for (i = 0; i < matching_pkgs->len; i++) {
491 pkg_t *matching = matching_pkgs->pkgs[i];
492 opkg_msg(INFO, "%s %s %s\n",
493 matching->name, pkg_get_string(matching, PKG_VERSION),
494 pkg_get_architecture(matching));
495 }
496 }
497
498 nmatching = matching_apkgs->len;
499
500 pkg_vec_free(matching_pkgs);
501 abstract_pkg_vec_free(matching_apkgs);
502 abstract_pkg_vec_free(providers);
503
504 if (good_pkg_by_name) { /* We found a good candidate, we will install it */
505 return good_pkg_by_name;
506 }
507 if (held_pkg) {
508 opkg_msg(INFO, "Using held package %s.\n", held_pkg->name);
509 return held_pkg;
510 }
511 if (latest_installed_parent) {
512 opkg_msg(INFO,
513 "Using latest version of installed package %s.\n",
514 latest_installed_parent->name);
515 return latest_installed_parent;
516 }
517 if (priorized_matching) {
518 opkg_msg(INFO, "Using priorized matching %s %s %s.\n",
519 priorized_matching->name, pkg_get_string(priorized_matching, PKG_VERSION),
520 pkg_get_architecture(priorized_matching));
521 return priorized_matching;
522 }
523 if (nmatching > 1) {
524 opkg_msg(INFO, "No matching pkg out of %d matching_apkgs.\n",
525 nmatching);
526 return NULL;
527 }
528 if (latest_matching) {
529 opkg_msg(INFO, "Using latest matching %s %s %s.\n",
530 latest_matching->name, pkg_get_string(latest_matching, PKG_VERSION),
531 pkg_get_architecture(latest_matching));
532 return latest_matching;
533 }
534 return NULL;
535 }
536
537 static int pkg_name_constraint_fcn(pkg_t * pkg, void *cdata)
538 {
539 const char *name = (const char *)cdata;
540
541 if (strcmp(pkg->name, name) == 0)
542 return 1;
543 else
544 return 0;
545 }
546
547 static pkg_vec_t *pkg_vec_fetch_by_name(const char *pkg_name)
548 {
549 abstract_pkg_t *ab_pkg;
550
551 if (!(ab_pkg = abstract_pkg_fetch_by_name(pkg_name)))
552 return NULL;
553
554 if (ab_pkg->pkgs)
555 return ab_pkg->pkgs;
556
557 if (ab_pkg->provided_by) {
558 abstract_pkg_t *abpkg =
559 abstract_pkg_vec_get(ab_pkg->provided_by, 0);
560 if (abpkg != NULL)
561 return abpkg->pkgs;
562 else
563 return ab_pkg->pkgs;
564 }
565
566 return NULL;
567 }
568
569 pkg_t *pkg_hash_fetch_best_installation_candidate_by_name(const char *name)
570 {
571 abstract_pkg_t *apkg = NULL;
572
573 if (!(apkg = abstract_pkg_fetch_by_name(name)))
574 return NULL;
575
576 return pkg_hash_fetch_best_installation_candidate(apkg,
577 pkg_name_constraint_fcn,
578 apkg->name, 0);
579 }
580
581 pkg_t *pkg_hash_fetch_by_name_version(const char *pkg_name, const char *version)
582 {
583 pkg_vec_t *vec;
584 int i;
585 char *version_str = NULL;
586
587 if (!(vec = pkg_vec_fetch_by_name(pkg_name)))
588 return NULL;
589
590 for (i = 0; i < vec->len; i++) {
591 version_str = pkg_version_str_alloc(vec->pkgs[i]);
592 if (!strcmp(version_str, version)) {
593 free(version_str);
594 break;
595 }
596 free(version_str);
597 }
598
599 if (i == vec->len)
600 return NULL;
601
602 return vec->pkgs[i];
603 }
604
605 pkg_t *pkg_hash_fetch_installed_by_name_dest(const char *pkg_name,
606 pkg_dest_t * dest)
607 {
608 pkg_vec_t *vec;
609 int i;
610
611 if (!(vec = pkg_vec_fetch_by_name(pkg_name))) {
612 return NULL;
613 }
614
615 for (i = 0; i < vec->len; i++)
616 if ((vec->pkgs[i]->state_status == SS_INSTALLED
617 || vec->pkgs[i]->state_status == SS_UNPACKED)
618 && vec->pkgs[i]->dest == dest) {
619 return vec->pkgs[i];
620 }
621
622 return NULL;
623 }
624
625 pkg_t *pkg_hash_fetch_installed_by_name(const char *pkg_name)
626 {
627 pkg_vec_t *vec;
628 int i;
629
630 if (!(vec = pkg_vec_fetch_by_name(pkg_name))) {
631 return NULL;
632 }
633
634 for (i = 0; i < vec->len; i++) {
635 if (vec->pkgs[i]->state_status == SS_INSTALLED
636 || vec->pkgs[i]->state_status == SS_UNPACKED) {
637 return vec->pkgs[i];
638 }
639 }
640
641 return NULL;
642 }
643
644 static void
645 pkg_hash_fetch_available_helper(const char *pkg_name, void *entry, void *data)
646 {
647 int j;
648 abstract_pkg_t *ab_pkg = (abstract_pkg_t *) entry;
649 pkg_vec_t *all = (pkg_vec_t *) data;
650 pkg_vec_t *pkg_vec = ab_pkg->pkgs;
651
652 if (!pkg_vec)
653 return;
654
655 for (j = 0; j < pkg_vec->len; j++) {
656 pkg_t *pkg = pkg_vec->pkgs[j];
657 pkg_vec_insert(all, pkg);
658 }
659 }
660
661 void pkg_hash_fetch_available(pkg_vec_t * all)
662 {
663 hash_table_foreach(&conf->pkg_hash, pkg_hash_fetch_available_helper,
664 all);
665 }
666
667 static void
668 pkg_hash_fetch_all_installed_helper(const char *pkg_name, void *entry,
669 void *data)
670 {
671 abstract_pkg_t *ab_pkg = (abstract_pkg_t *) entry;
672 pkg_vec_t *all = (pkg_vec_t *) data;
673 pkg_vec_t *pkg_vec = ab_pkg->pkgs;
674 int j;
675
676 if (!pkg_vec)
677 return;
678
679 for (j = 0; j < pkg_vec->len; j++) {
680 pkg_t *pkg = pkg_vec->pkgs[j];
681 if (pkg->state_status == SS_INSTALLED
682 || pkg->state_status == SS_UNPACKED)
683 pkg_vec_insert(all, pkg);
684 }
685 }
686
687 void pkg_hash_fetch_all_installed(pkg_vec_t * all)
688 {
689 hash_table_foreach(&conf->pkg_hash, pkg_hash_fetch_all_installed_helper,
690 all);
691 }
692
693 /*
694 * This assumes that the abstract pkg doesn't exist.
695 */
696 static abstract_pkg_t *add_new_abstract_pkg_by_name(const char *pkg_name)
697 {
698 abstract_pkg_t *ab_pkg;
699
700 ab_pkg = abstract_pkg_new();
701
702 ab_pkg->name = xstrdup(pkg_name);
703 hash_table_insert(&conf->pkg_hash, pkg_name, ab_pkg);
704
705 return ab_pkg;
706 }
707
708 abstract_pkg_t *ensure_abstract_pkg_by_name(const char *pkg_name)
709 {
710 abstract_pkg_t *ab_pkg;
711
712 if (!(ab_pkg = abstract_pkg_fetch_by_name(pkg_name)))
713 ab_pkg = add_new_abstract_pkg_by_name(pkg_name);
714
715 return ab_pkg;
716 }
717
718 void hash_insert_pkg(pkg_t * pkg, int set_status)
719 {
720 abstract_pkg_t *ab_pkg;
721
722 ab_pkg = ensure_abstract_pkg_by_name(pkg->name);
723 if (!ab_pkg->pkgs)
724 ab_pkg->pkgs = pkg_vec_alloc();
725
726 if (pkg->state_status == SS_INSTALLED) {
727 ab_pkg->state_status = SS_INSTALLED;
728 } else if (pkg->state_status == SS_UNPACKED) {
729 ab_pkg->state_status = SS_UNPACKED;
730 }
731
732 buildDepends(pkg);
733
734 buildProvides(ab_pkg, pkg);
735
736 init_providelist(pkg, NULL);
737
738 /* Need to build the conflicts graph before replaces for correct
739 * calculation of replaced_by relation.
740 */
741 buildConflicts(pkg);
742
743 buildReplaces(ab_pkg, pkg);
744
745 buildDependedUponBy(pkg, ab_pkg);
746
747 pkg_vec_insert_merge(ab_pkg->pkgs, pkg, set_status);
748 pkg->parent = ab_pkg;
749 }
750
751 static const char *strip_offline_root(const char *file_name)
752 {
753 unsigned int len;
754
755 if (conf->offline_root) {
756 len = strlen(conf->offline_root);
757 if (strncmp(file_name, conf->offline_root, len) == 0)
758 file_name += len;
759 }
760
761 return file_name;
762 }
763
764 void file_hash_remove(const char *file_name)
765 {
766 file_name = strip_offline_root(file_name);
767 hash_table_remove(&conf->file_hash, file_name);
768 }
769
770 pkg_t *file_hash_get_file_owner(const char *file_name)
771 {
772 file_name = strip_offline_root(file_name);
773 return hash_table_get(&conf->file_hash, file_name);
774 }
775
776 void file_hash_set_file_owner(const char *file_name, pkg_t * owning_pkg)
777 {
778 pkg_t *old_owning_pkg;
779 int file_name_len = strlen(file_name);
780
781 if (file_name[file_name_len - 1] == '/')
782 return;
783
784 file_name = strip_offline_root(file_name);
785
786 old_owning_pkg = hash_table_get(&conf->file_hash, file_name);
787 hash_table_insert(&conf->file_hash, file_name, owning_pkg);
788
789 if (old_owning_pkg) {
790 pkg_get_installed_files(old_owning_pkg);
791 str_list_remove_elt(old_owning_pkg->installed_files, file_name);
792 pkg_free_installed_files(old_owning_pkg);
793
794 /* mark this package to have its filelist written */
795 old_owning_pkg->state_flag |= SF_FILELIST_CHANGED;
796 owning_pkg->state_flag |= SF_FILELIST_CHANGED;
797 }
798 }