/** * \fn order_install * * order the install list according to dependency level * here we only rely on basic level given by pkg_summary, the only drawback * is that pkg_add will install direct dependencies, giving a "failed, * package already installed" */ Plisthead * order_install(Plisthead *impacthead) { Plisthead *ordtreehead; Pkglist *pimpact, *pdp, *pi_dp = NULL; int i, maxlevel = 0; char tmpcheck[BUFSIZ]; /* record higher dependency level on impact list */ SLIST_FOREACH(pimpact, impacthead, next) { if ((pimpact->action == TOUPGRADE || pimpact->action == TOINSTALL) && pimpact->level > maxlevel) maxlevel = pimpact->level; } ordtreehead = init_head(); for (i = 0; i <= maxlevel; i++) { SLIST_FOREACH(pimpact, impacthead, next) { if ((pimpact->action == TOUPGRADE || pimpact->action == TOINSTALL) && pimpact->level == i) { if (pkg_in_impact(ordtreehead, pimpact->full)) continue; pdp = malloc_pkglist(DEPTREE); pdp->computed = pimpact->action; /* XXX: ugly*/ XSTRDUP(pdp->depend, pimpact->full); pdp->name = NULL; /* safety */ pdp->level = pimpact->level; /* record package size for download check */ pdp->file_size = pimpact->file_size; /* check for pkg_install upgrade */ strcpy(tmpcheck, pimpact->full); trunc_str(tmpcheck, '-', STR_BACKWARD); /* match on pkg_install */ if (strcmp(tmpcheck, PKG_INSTALL) == 0) { pi_upgrade = 1; /* backup pdp for future insertion */ pi_dp = pdp; } else SLIST_INSERT_HEAD(ordtreehead, pdp, next); } /* action == TOINSTALL */ } /* SLIST_FOREACH pimpact */ } /* for i < maxlevel */ /* pkg_install is to be upgraded, make it first */ if (pi_upgrade && pi_dp != NULL) SLIST_INSERT_HEAD(ordtreehead, pi_dp, next); return ordtreehead; }
/** * sqlite callback * DIRECT_DEPS or REVERSE_DEPS result, feeds a Pkglist SLIST * Plisthead is the head of Pkglist */ int pdb_rec_depends(void *param, int argc, char **argv, char **colname) { Pkglist *deptree, *pdp, *pkg_map; Plisthead *pdphead = (Plisthead *)param, *plisthead; if (argv == NULL) return PDB_ERR; /* check if dependency is already recorded, do not insert on list */ SLIST_FOREACH(pdp, pdphead, next) if (strcmp(DEPS_PKGNAME, pdp->name) == 0) { TRACE(" < dependency %s already recorded\n", pdp->name); /* proceed to next result */ return PDB_OK; } deptree = malloc_pkglist(DEPTREE); XSTRDUP(deptree->depend, DEPS_FULLPKG); /* unresolved pkgname because of complex dependency glob */ if (non_trivial_glob(DEPS_FULLPKG)) { /* check wether we're getting local or remote dependencies */ if (strncmp(colname[0], "LOCAL_", 6) == 0) plisthead = &l_plisthead; else plisthead = &r_plisthead; /* map corresponding pkgname */ if ((pkg_map = map_pkg_to_dep(plisthead, deptree->depend)) != NULL) XSTRDUP(deptree->name, pkg_map->name); else /* some dependencies just don't match anything */ XSTRDUP(deptree->name, DEPS_PKGNAME); } else /* case handled by get_pkgname_from_depend() */ XSTRDUP(deptree->name, DEPS_PKGNAME); deptree->computed = 0; deptree->level = 0; /* used in LOCAL_REVERSE_DEPS / autoremove.c */ if (argc > 2 && PKG_KEEP != NULL) deptree->keep = 1; else deptree->keep = 0; SLIST_INSERT_HEAD(pdphead, deptree, next); return PDB_OK; }
/** * SQLite callback, record package list */ int pdb_rec_list(void *param, int argc, char **argv, char **colname) { Pkglist *plist; Plistnumbered *plisthead = (Plistnumbered *)param; int i; if (argv == NULL) return PDB_ERR; /* FULLPKGNAME was empty, probably a package installed * from pkgsrc or wip that does not exist in * pkg_summary(5), return */ if (argv[0] == NULL) return PDB_ERR; plist = malloc_pkglist(LIST); /* * rec_pkglist is used for convenience for REQUIRES / PROVIDES * otherwise contains FULLPKGNAME */ XSTRDUP(plist->full, argv[0]); for (i = 1; i < argc; i++) { if (argv[i] == NULL) continue; if (strcmp(colname[i], "PKGNAME") == 0) XSTRDUP(plist->name, argv[i]); if (strcmp(colname[i], "PKGVERS") == 0) XSTRDUP(plist->version, argv[i]); if (strcmp(colname[i], "COMMENT") == 0) XSTRDUP(plist->comment, argv[i]); if (strcmp(colname[i], "PKGPATH") == 0) XSTRDUP(plist->pkgpath, argv[i]); if (strcmp(colname[i], "CATEGORIES") == 0) XSTRDUP(plist->category, argv[i]); if (strcmp(colname[i], "FILE_SIZE") == 0) plist->file_size = strtol(argv[i], (char **)NULL, 10); if (strcmp(colname[i], "SIZE_PKG") == 0) plist->size_pkg = strtol(argv[i], (char **)NULL, 10); } SLIST_INSERT_HEAD(plisthead->P_Plisthead, plist, next); plisthead->P_count++; return PDB_OK; }
/** * \fn order_upgrade_remove * * \brief order the remove-for-upgrade list according to dependency level */ Plisthead * order_upgrade_remove(Plisthead *impacthead) { Plisthead *ordtreehead; Pkglist *pimpact, *pdp; int i, maxlevel = 0; upgrade_dep_deepness(impacthead); /* record higher dependency level on impact upgrade list */ SLIST_FOREACH(pimpact, impacthead, next) if ((pimpact->action == TOUPGRADE || pimpact->action == TOREMOVE) && pimpact->level > maxlevel) maxlevel = pimpact->level; ordtreehead = init_head(); for (i = maxlevel; i >= 0; i--) SLIST_FOREACH(pimpact, impacthead, next) { if ((pimpact->action == TOUPGRADE || pimpact->action == TOREMOVE) && pimpact->level == i) { if (pkg_in_impact(ordtreehead, pimpact->old)) continue; pdp = malloc_pkglist(DEPTREE); XSTRDUP(pdp->depend, pimpact->old); pdp->name = NULL; /* safety */ /* XXX: use the "computed" value to record * action type. Ugly. */ pdp->computed = pimpact->action; /* informative only */ pdp->level = pimpact->level; SLIST_INSERT_HEAD(ordtreehead, pdp, next); } /* action == TOUPGRADE || TOREMOVE */ } /* for maxlevel */ return ordtreehead; }
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); }