/** * find dependency deepness for package removal and record it to pdp->level */ static void remove_dep_deepness(Plisthead *deptreehead) { char *depname; Pkglist *pdp; Plisthead *lvldeptree; /* get higher recursion level */ SLIST_FOREACH(pdp, deptreehead, next) { if (pdp->level == -1) { /* unique package, just return */ pdp->level = 0; return; } pdp->level = 1; if (pdp->depend == NULL) /* there's something wrong with database's record, * probably a mistaken dependency */ continue; /* depname received from deptreehead is in package format */ XSTRDUP(depname, pdp->depend); trunc_str(depname, '-', STR_BACKWARD); lvldeptree = init_head(); full_dep_tree(depname, LOCAL_REVERSE_DEPS, lvldeptree); if (!SLIST_EMPTY(lvldeptree)) pdp->level = SLIST_FIRST(lvldeptree)->level + 1; XFREE(depname); free_pkglist(&lvldeptree, DEPTREE); #if 0 printf("%s -> %d\n", pdp->depend, pdp->level); #endif } }
/* find dependency deepness for upgrade and record it to pimpact->level */ static void upgrade_dep_deepness(Plisthead *impacthead) { char *pkgname; Pkglist *pimpact; Plisthead *lvldeptree; /* get higher recursion level */ SLIST_FOREACH(pimpact, impacthead, next) { if (pimpact->level == -1) { /* unique package, just return */ pimpact->level = 0; return; } /* only deal with TOUPGRADE and TOREMOVE */ if (pimpact->action == TOINSTALL) continue; pimpact->level = 1; /* depname received from impact is in full package format */ XSTRDUP(pkgname, pimpact->full); trunc_str(pkgname, '-', STR_BACKWARD); lvldeptree = init_head(); full_dep_tree(pkgname, LOCAL_REVERSE_DEPS, lvldeptree); if (!SLIST_EMPTY(lvldeptree)) pimpact->level = SLIST_FIRST(lvldeptree)->level + 1; #if 0 printf("%s (%s) -> %d\n", pimpact->full, pkgname, pimpact->level); #endif XFREE(pkgname); free_pkglist(&lvldeptree, DEPTREE); } }
static void break_depends(Plisthead *impacthead) { Pkglist *rmimpact, *pimpact; Plisthead *rdphead, *fdphead; Pkglist *rdp, *fdp; char *pkgname, *rpkg; int dep_break, exists; SLIST_FOREACH(pimpact, impacthead, next) { if (pimpact->old == NULL) /* DONOTHING or TOINSTALL */ continue; rdphead = init_head(); XSTRDUP(pkgname, pimpact->old); trunc_str(pkgname, '-', STR_BACKWARD); /* fetch old package reverse dependencies */ full_dep_tree(pkgname, LOCAL_REVERSE_DEPS, rdphead); XFREE(pkgname); /* browse reverse dependencies */ SLIST_FOREACH(rdp, rdphead, next) { exists = 0; /* check if rdp was already on impact list */ SLIST_FOREACH(rmimpact, impacthead, next) if (strcmp(rmimpact->depend, rdp->depend) == 0) { exists = 1; break; } if (exists) continue; fdphead = init_head(); /* * reverse dependency is a full package name, * use it and strip it */ XSTRDUP(rpkg, rdp->depend); trunc_str(rpkg, '-', STR_BACKWARD); /* fetch dependencies for rdp */ full_dep_tree(rpkg, DIRECT_DEPS, fdphead); /* initialize to broken dependency */ dep_break = 1; /* empty full dep tree, this can't happen in normal situation. * If it does, that means that the reverse dependency we're * analyzing has no direct dependency. * Such a situation could occur if the reverse dependency is not on * the repository anymore, leading to no information regarding this * package. * So we will check if local package dependencies are satisfied by * our newly upgraded packages. */ if (SLIST_EMPTY(fdphead)) { free_pkglist(&fdphead, DEPTREE); fdphead = init_head(); full_dep_tree(rpkg, LOCAL_DIRECT_DEPS, fdphead); } XFREE(rpkg); /* * browse dependencies for rdp and see if * new package to be installed matches */ SLIST_FOREACH(fdp, fdphead, next) { if (pkg_match(fdp->depend, pimpact->full)) { dep_break = 0; break; } } free_pkglist(&fdphead, DEPTREE); if (!dep_break) continue; /* dependency break, insert rdp in remove-list */ rmimpact = malloc_pkglist(IMPACT); XSTRDUP(rmimpact->depend, rdp->depend); XSTRDUP(rmimpact->full, rdp->depend); XSTRDUP(rmimpact->old, rdp->depend); rmimpact->action = TOREMOVE; rmimpact->level = 0; SLIST_INSERT_HEAD(impacthead, rmimpact, next); } free_pkglist(&rdphead, DEPTREE); }