2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <sys/types.h>
36 #include "razor-internal.h"
40 provider_satisfies_requirement(struct razor_property *provider,
41 const char *provider_strings,
46 const char *provided = &provider_strings[provider->version];
51 if (flags & RAZOR_PROPERTY_LESS)
57 cmp = razor_versioncmp(provided, required);
59 switch (flags & RAZOR_PROPERTY_RELATION_MASK) {
60 case RAZOR_PROPERTY_LESS:
63 case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
66 /* fall through: FIXME, make sure this is correct */
68 case RAZOR_PROPERTY_EQUAL:
72 /* "foo == 1.1" is satisfied by "foo 1.1-2" */
73 len = strlen(required);
74 if (!strncmp(required, provided, len) && provided[len] == '-')
78 case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
81 case RAZOR_PROPERTY_GREATER:
85 /* shouldn't happen */
89 #define TRANS_PACKAGE_PRESENT 1
90 #define TRANS_PACKAGE_UPDATE 2
91 #define TRANS_PROPERTY_SATISFIED 0x80000000
93 struct transaction_set {
94 struct razor_set *set;
99 struct razor_transaction {
100 int package_count, errors;
101 struct transaction_set system, upstream;
106 transaction_set_init(struct transaction_set *ts, struct razor_set *set)
111 count = set->packages.size / sizeof (struct razor_package);
112 ts->packages = zalloc(count * sizeof *ts->packages);
113 count = set->properties.size / sizeof (struct razor_property);
114 ts->properties = zalloc(count * sizeof *ts->properties);
118 transaction_set_release(struct transaction_set *ts)
121 free(ts->properties);
125 transaction_set_install_package(struct transaction_set *ts,
126 struct razor_package *package)
128 struct razor_package *pkgs;
132 pkgs = ts->set->packages.data;
134 if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
137 ts->packages[i] = TRANS_PACKAGE_PRESENT;
139 prop = list_first(&package->properties, &ts->set->property_pool);
141 ts->properties[prop->data]++;
142 prop = list_next(prop);
147 transaction_set_remove_package(struct transaction_set *ts,
148 struct razor_package *package)
150 struct razor_package *pkgs;
154 pkgs = ts->set->packages.data;
156 if (ts->packages[i] == 0)
161 prop = list_first(&package->properties, &ts->set->property_pool);
163 ts->properties[prop->data]--;
164 prop = list_next(prop);
168 RAZOR_EXPORT struct razor_transaction *
169 razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
171 struct razor_transaction *trans;
172 struct razor_package *p, *spkgs, *pend;
174 trans = zalloc(sizeof *trans);
175 transaction_set_init(&trans->system, system);
176 transaction_set_init(&trans->upstream, upstream);
178 spkgs = trans->system.set->packages.data;
179 pend = trans->system.set->packages.data +
180 trans->system.set->packages.size;
181 for (p = spkgs; p < pend; p++)
182 transaction_set_install_package(&trans->system, p);
188 razor_transaction_install_package(struct razor_transaction *trans,
189 struct razor_package *package)
191 assert (trans != NULL);
192 assert (package != NULL);
194 transaction_set_install_package(&trans->upstream, package);
199 razor_transaction_remove_package(struct razor_transaction *trans,
200 struct razor_package *package)
202 assert (trans != NULL);
203 assert (package != NULL);
205 transaction_set_remove_package(&trans->system, package);
210 razor_transaction_update_package(struct razor_transaction *trans,
211 struct razor_package *package)
213 struct razor_package *spkgs, *upkgs, *end;
215 assert (trans != NULL);
216 assert (package != NULL);
218 spkgs = trans->system.set->packages.data;
219 upkgs = trans->upstream.set->packages.data;
220 end = trans->system.set->packages.data +
221 trans->system.set->packages.size;
222 if (spkgs <= package && package < end)
223 trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
225 trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
229 struct razor_property *p, *start, *end;
235 prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
237 pi->p = ts->set->properties.data;
238 pi->start = ts->set->properties.data;
239 pi->end = ts->set->properties.data + ts->set->properties.size;
240 pi->pool = ts->set->string_pool.data;
241 pi->present = ts->properties;
245 prop_iter_next(struct prop_iter *pi, uint32_t flags, struct razor_property **p)
247 while (pi->p < pi->end) {
248 if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
249 (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) == flags) {
259 static struct razor_property *
260 prop_iter_seek_to(struct prop_iter *pi,
261 uint32_t flags, const char *match)
265 while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
268 if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
272 while (pi->p < pi->end &&
273 pi->p->name == name &&
274 (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) != flags)
277 if (pi->p == pi->end || pi->p->name != name)
283 /* Remove packages from set that provide any of the matching (same
284 * name and type) providers from ppi onwards that match the
285 * requirement that rpi points to. */
287 remove_matching_providers(struct razor_transaction *trans,
288 struct prop_iter *ppi,
292 struct razor_property *p;
293 struct razor_package *pkg, *pkgs;
294 struct razor_package_iterator pkg_iter;
295 struct razor_set *set;
299 if (ppi->present == trans->system.properties)
300 set = trans->system.set;
302 set = trans->upstream.set;
304 pkgs = (struct razor_package *) set->packages.data;
305 type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
308 p->name == ppi->p->name &&
309 (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
311 if (!ppi->present[p - ppi->start])
313 if (!provider_satisfies_requirement(p, ppi->pool,
317 razor_package_iterator_init_for_property(&pkg_iter, set, p);
318 while (razor_package_iterator_next(&pkg_iter, &pkg,
319 RAZOR_DETAIL_NAME, &n,
320 RAZOR_DETAIL_VERSION, &v,
321 RAZOR_DETAIL_LAST)) {
322 fprintf(stderr, "removing %s-%s\n", n, v);
323 razor_transaction_remove_package(trans, pkg);
329 flag_matching_providers(struct razor_transaction *trans,
330 struct prop_iter *ppi,
331 struct razor_property *r,
332 struct prop_iter *rpi,
335 struct razor_property *p;
336 struct razor_package *pkg, *pkgs;
337 struct razor_package_iterator pkg_iter;
338 struct razor_set *set;
339 const char *name, *version;
340 uint32_t *flags, type;
342 if (ppi->present == trans->system.properties) {
343 set = trans->system.set;
344 flags = trans->system.packages;
346 set = trans->upstream.set;
347 flags = trans->upstream.packages;
350 pkgs = (struct razor_package *) set->packages.data;
351 type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
354 p->name == ppi->p->name &&
355 (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
357 if (!ppi->present[p - ppi->start])
359 if (!provider_satisfies_requirement(p, ppi->pool,
361 &rpi->pool[r->version]))
364 razor_package_iterator_init_for_property(&pkg_iter, set, p);
365 while (razor_package_iterator_next(&pkg_iter, &pkg,
366 RAZOR_DETAIL_NAME, &name,
367 RAZOR_DETAIL_VERSION, &version,
368 RAZOR_DETAIL_LAST)) {
370 fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
374 rpi->pool + r->version);
375 flags[pkg - pkgs] |= flag;
380 static struct razor_package *
381 pick_matching_provider(struct razor_set *set,
382 struct prop_iter *ppi,
386 struct razor_property *p;
387 struct razor_package *pkgs;
391 /* This is where we decide which pkgs to pull in to satisfy a
392 * requirement. There may be several different providers
393 * (different versions) and each version of a provider may
394 * come from a number of packages. We pick the first package
395 * from the first provider that matches. */
397 pkgs = set->packages.data;
398 type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
401 p->name == ppi->p->name &&
402 (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type &&
403 ppi->present[p - ppi->start] == 0;
405 if (!provider_satisfies_requirement(p, ppi->pool,
409 i = list_first(&p->packages, &set->package_pool);
411 return &pkgs[i->data];
418 remove_obsoleted_packages(struct razor_transaction *trans)
420 struct razor_property *up;
421 struct razor_package *spkgs;
422 struct prop_iter spi, upi;
424 spkgs = trans->system.set->packages.data;
425 prop_iter_init(&spi, &trans->system);
426 prop_iter_init(&upi, &trans->upstream);
428 while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
429 if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
430 &upi.pool[up->name]))
432 remove_matching_providers(trans, &spi, up->flags,
433 &upi.pool[up->version]);
438 any_provider_satisfies_requirement(struct prop_iter *ppi,
442 struct razor_property *p;
445 type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
448 p->name == ppi->p->name &&
449 (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
451 if (ppi->present[p - ppi->start] > 0 &&
452 provider_satisfies_requirement(p, ppi->pool,
461 clear_requires_flags(struct transaction_set *ts)
463 struct razor_property *p;
468 count = ts->set->properties.size / sizeof *p;
469 p = ts->set->properties.data;
470 pool = ts->set->string_pool.data;
471 for (i = 0; i < count; i++) {
472 ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
473 sub = strchr(&pool[p[i].name], '(');
474 if (sub && sub[strlen(sub) - 1] == ')') {
475 sub = strdup(sub + 1);
476 sub[strlen(sub) - 1] = '\0';
477 if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
478 ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
479 if (strncmp(&pool[p[i].name], "lua(", 4) == 0 &&
480 razor_get_lua_loader(sub) &&
481 p[i].flags & RAZOR_PROPERTY_SCRIPT_MASK)
482 ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
489 mark_satisfied_requires(struct razor_transaction *trans,
490 struct transaction_set *rts,
491 struct transaction_set *pts)
493 struct prop_iter rpi, ppi;
494 struct razor_property *rp;
496 prop_iter_init(&rpi, rts);
497 prop_iter_init(&ppi, pts);
499 while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
500 if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
501 &rpi.pool[rp->name]))
504 if (any_provider_satisfies_requirement(&ppi, rp->flags,
505 &rpi.pool[rp->version]))
506 rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
511 mark_all_satisfied_requires(struct razor_transaction *trans)
513 clear_requires_flags(&trans->system);
514 clear_requires_flags(&trans->upstream);
515 mark_satisfied_requires(trans, &trans->system, &trans->system);
516 mark_satisfied_requires(trans, &trans->system, &trans->upstream);
517 mark_satisfied_requires(trans, &trans->upstream, &trans->system);
518 mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
522 update_unsatisfied_packages(struct razor_transaction *trans)
524 struct razor_package *spkgs, *pkg;
525 struct razor_property *sp;
526 struct prop_iter spi;
527 struct razor_package_iterator pkg_iter;
530 spkgs = trans->system.set->packages.data;
531 prop_iter_init(&spi, &trans->system);
533 while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
534 if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
537 razor_package_iterator_init_for_property(&pkg_iter,
540 while (razor_package_iterator_next(&pkg_iter, &pkg,
541 RAZOR_DETAIL_NAME, &name,
542 RAZOR_DETAIL_LAST)) {
543 fprintf(stderr, "updating %s because %s %s %s "
545 name, spi.pool + sp->name,
546 razor_property_relation_to_string(sp),
547 spi.pool + sp->version);
548 trans->system.packages[pkg - spkgs] |=
549 TRANS_PACKAGE_UPDATE;
555 razor_transaction_update_all(struct razor_transaction *trans)
557 struct razor_package *p;
560 assert (trans != NULL);
562 count = trans->system.set->packages.size / sizeof *p;
563 for (i = 0; i < count; i++)
564 trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
568 update_conflicted_packages(struct razor_transaction *trans)
570 struct razor_package *pkg, *spkgs;
571 struct razor_property *up, *sp;
572 struct prop_iter spi, upi;
573 struct razor_package_iterator pkg_iter;
574 const char *name, *version;
576 spkgs = trans->system.set->packages.data;
577 prop_iter_init(&spi, &trans->system);
578 prop_iter_init(&upi, &trans->upstream);
580 while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
581 if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
582 &spi.pool[sp->name]))
585 if (!any_provider_satisfies_requirement(&upi, sp->flags,
586 &spi.pool[sp->version]))
589 razor_package_iterator_init_for_property(&pkg_iter,
592 while (razor_package_iterator_next(&pkg_iter, &pkg,
593 RAZOR_DETAIL_NAME, &name,
594 RAZOR_DETAIL_VERSION, &version,
595 RAZOR_DETAIL_LAST)) {
596 fprintf(stderr, "updating %s %s because it "
597 "conflicts with %s\n",
598 name, version, spi.pool + sp->name);
599 trans->system.packages[pkg - spkgs] |=
600 TRANS_PACKAGE_UPDATE;
604 prop_iter_init(&spi, &trans->system);
605 prop_iter_init(&upi, &trans->upstream);
607 while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
608 sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
609 &upi.pool[upi.p->name]);
612 flag_matching_providers(trans, &spi, up, &upi,
613 TRANS_PACKAGE_UPDATE);
618 pull_in_requirements(struct razor_transaction *trans,
619 struct prop_iter *rpi, struct prop_iter *ppi)
621 struct razor_property *rp, *pp;
622 struct razor_package *pkg, *upkgs;
624 upkgs = trans->upstream.set->packages.data;
625 while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
626 if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
629 pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
630 &rpi->pool[rp->name]);
633 pkg = pick_matching_provider(trans->upstream.set,
635 &rpi->pool[rp->version]);
639 rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
641 fprintf(stderr, "pulling in %s-%s.%s which provides %s %s %s "
642 "to satisfy %s %s %s\n",
643 ppi->pool + pkg->name,
644 ppi->pool + pkg->version,
645 ppi->pool + pkg->arch,
646 ppi->pool + pp->name,
647 razor_property_relation_to_string(pp),
648 ppi->pool + pp->version,
649 &rpi->pool[rp->name],
650 razor_property_relation_to_string(rp),
651 &rpi->pool[rp->version]);
653 trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
658 pull_in_all_requirements(struct razor_transaction *trans)
660 struct prop_iter rpi, ppi;
662 prop_iter_init(&rpi, &trans->system);
663 prop_iter_init(&ppi, &trans->upstream);
664 pull_in_requirements(trans, &rpi, &ppi);
666 prop_iter_init(&rpi, &trans->upstream);
667 prop_iter_init(&ppi, &trans->upstream);
668 pull_in_requirements(trans, &rpi, &ppi);
672 flush_scheduled_system_updates(struct razor_transaction *trans)
674 struct razor_package_iterator *pi;
675 struct razor_package *p, *pkg, *spkgs;
676 struct prop_iter ppi;
677 const char *name, *version;
679 spkgs = trans->system.set->packages.data;
680 pi = razor_package_iterator_create(trans->system.set);
681 prop_iter_init(&ppi, &trans->upstream);
683 while (razor_package_iterator_next(pi, &p,
684 RAZOR_DETAIL_NAME, &name,
685 RAZOR_DETAIL_VERSION, &version,
686 RAZOR_DETAIL_LAST)) {
687 if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
690 if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
693 pkg = pick_matching_provider(trans->upstream.set, &ppi,
694 RAZOR_PROPERTY_GREATER, version);
698 fprintf(stderr, "updating %s-%s to %s-%s\n",
700 &ppi.pool[pkg->name], &ppi.pool[pkg->version]);
702 razor_transaction_remove_package(trans, p);
703 razor_transaction_install_package(trans, pkg);
706 razor_package_iterator_destroy(pi);
710 flush_scheduled_upstream_updates(struct razor_transaction *trans)
712 struct razor_package_iterator *pi;
713 struct razor_package *p, *upkgs;
714 struct prop_iter spi;
715 const char *name, *version;
717 upkgs = trans->upstream.set->packages.data;
718 pi = razor_package_iterator_create(trans->upstream.set);
719 prop_iter_init(&spi, &trans->system);
721 while (razor_package_iterator_next(pi, &p,
722 RAZOR_DETAIL_NAME, &name,
723 RAZOR_DETAIL_VERSION, &version,
724 RAZOR_DETAIL_LAST)) {
725 if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
728 if (prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
729 remove_matching_providers(trans,
733 razor_transaction_install_package(trans, p);
734 fprintf(stderr, "installing %s-%s\n", name, version);
739 razor_transaction_resolve(struct razor_transaction *trans)
743 flush_scheduled_system_updates(trans);
744 flush_scheduled_upstream_updates(trans);
746 while (last < trans->changes) {
747 last = trans->changes;
748 remove_obsoleted_packages(trans);
749 mark_all_satisfied_requires(trans);
750 update_unsatisfied_packages(trans);
751 update_conflicted_packages(trans);
752 pull_in_all_requirements(trans);
753 flush_scheduled_system_updates(trans);
754 flush_scheduled_upstream_updates(trans);
757 return trans->changes;
761 describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
763 struct razor_package_iterator pi;
764 struct razor_package *pkg;
765 const char *name, *version, *arch, *pool;
767 pool = set->string_pool.data;
768 if (pool[rp->version] == '\0') {
769 razor_package_iterator_init_for_property(&pi, set, rp);
770 while (razor_package_iterator_next(&pi, &pkg,
771 RAZOR_DETAIL_NAME, &name,
772 RAZOR_DETAIL_VERSION, &version,
773 RAZOR_DETAIL_ARCH, &arch,
775 fprintf(stderr, "%s is needed by %s-%s.%s\n",
777 name, version, arch);
779 razor_package_iterator_init_for_property(&pi, set, rp);
780 while (razor_package_iterator_next(&pi, &pkg,
781 RAZOR_DETAIL_NAME, &name,
782 RAZOR_DETAIL_VERSION, &version,
783 RAZOR_DETAIL_ARCH, &arch,
785 fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
787 razor_property_relation_to_string(rp),
789 name, version, arch);
794 razor_transaction_describe(struct razor_transaction *trans)
796 struct prop_iter rpi;
797 struct razor_property *rp;
800 flush_scheduled_system_updates(trans);
801 flush_scheduled_upstream_updates(trans);
802 mark_all_satisfied_requires(trans);
805 prop_iter_init(&rpi, &trans->system);
806 while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
807 if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
808 describe_unsatisfied(trans->system.set, rp);
813 prop_iter_init(&rpi, &trans->upstream);
814 while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
815 if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
816 describe_unsatisfied(trans->upstream.set, rp);
825 razor_transaction_unsatisfied_property(struct razor_transaction *trans,
831 struct razor_property *p;
833 prop_iter_init(&pi, &trans->system);
834 while (prop_iter_next(&pi, flags & RAZOR_PROPERTY_TYPE_MASK, &p)) {
835 if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
837 strcmp(&pi.pool[p->name], name) == 0 &&
838 strcmp(&pi.pool[p->version], version) == 0)
843 prop_iter_init(&pi, &trans->upstream);
844 while (prop_iter_next(&pi, flags & RAZOR_PROPERTY_TYPE_MASK, &p)) {
845 if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
847 strcmp(&pi.pool[p->name], name) == 0 &&
848 strcmp(&pi.pool[p->version], version) == 0)
856 RAZOR_EXPORT struct razor_set *
857 razor_transaction_finish(struct razor_transaction *trans)
859 struct razor_merger *merger;
860 struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
864 s = trans->system.set->packages.data;
865 spkgs = trans->system.set->packages.data;
866 send = trans->system.set->packages.data +
867 trans->system.set->packages.size;
868 spool = trans->system.set->string_pool.data;
870 u = trans->upstream.set->packages.data;
871 upkgs = trans->upstream.set->packages.data;
872 uend = trans->upstream.set->packages.data +
873 trans->upstream.set->packages.size;
874 upool = trans->upstream.set->string_pool.data;
876 merger = razor_merger_create(trans->system.set, trans->upstream.set);
877 while (s < send || u < uend) {
878 if (s < send && u < uend)
879 cmp = strcmp(&spool[s->name], &upool[u->name]);
886 if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
887 razor_merger_add_package(merger, s);
889 } else if (cmp == 0) {
890 if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
891 razor_merger_add_package(merger, s);
892 if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
893 razor_merger_add_package(merger, u);
898 if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
899 razor_merger_add_package(merger, u);
904 razor_transaction_destroy(trans);
906 return razor_merger_finish(merger);
910 razor_transaction_destroy(struct razor_transaction *trans)
912 assert (trans != NULL);
914 transaction_set_release(&trans->system);
915 transaction_set_release(&trans->upstream);