static void virt_package(struct varbuf *vb, const struct pkginfo *pkg, const struct pkgbin *pkgbin, enum fwriteflags flags, const struct fieldinfo *fip) { varbuf_add_pkgbin_name(vb, pkg, pkgbin, pnaw_nonambig); }
/** * Cycle breaking works recursively down the package dependency tree. * * ‘sofar’ is the list of packages we've descended down already - if we * encounter any of its packages again in a dependency we have found a cycle. */ static bool findbreakcyclerecursive(struct pkginfo *pkg, struct cyclesofarlink *sofar) { struct cyclesofarlink thislink, *sol; struct dependency *dep; struct deppossi *possi, *providelink; struct pkginfo *provider, *pkg_pos; if (pkg->clientdata->color == PKG_CYCLE_BLACK) return false; pkg->clientdata->color = PKG_CYCLE_GRAY; if (debug_has_flag(dbg_depcondetail)) { struct varbuf str_pkgs = VARBUF_INIT; for (sol = sofar; sol; sol = sol->prev) { varbuf_add_str(&str_pkgs, " <- "); varbuf_add_pkgbin_name(&str_pkgs, sol->pkg, &sol->pkg->installed, pnaw_nonambig); } varbuf_end_str(&str_pkgs); debug(dbg_depcondetail, "findbreakcyclerecursive %s %s", pkg_name(pkg, pnaw_always), str_pkgs.buf); varbuf_destroy(&str_pkgs); } thislink.pkg= pkg; thislink.prev = sofar; thislink.possi = NULL; for (dep= pkg->installed.depends; dep; dep= dep->next) { if (dep->type != dep_depends && dep->type != dep_predepends) continue; for (possi= dep->list; possi; possi= possi->next) { struct deppossi_pkg_iterator *possi_iter; /* Don't find the same cycles again. */ if (possi->cyclebreak) continue; thislink.possi= possi; possi_iter = deppossi_pkg_iter_new(possi, wpb_installed); while ((pkg_pos = deppossi_pkg_iter_next(possi_iter))) if (foundcyclebroken(&thislink, sofar, pkg_pos, possi)) { deppossi_pkg_iter_free(possi_iter); return true; } deppossi_pkg_iter_free(possi_iter); /* Right, now we try all the providers ... */ for (providelink = possi->ed->depended.installed; providelink; providelink = providelink->rev_next) { if (providelink->up->type != dep_provides) continue; provider= providelink->up->up; if (provider->clientdata->istobe == PKG_ISTOBE_NORMAL) continue; /* We don't break things at ‘provides’ links, so ‘possi’ is * still the one we use. */ if (foundcyclebroken(&thislink, sofar, provider, possi)) return true; } } } /* Nope, we didn't find a cycle to break. */ pkg->clientdata->color = PKG_CYCLE_BLACK; return false; }
/* * Checks [Pre]-Depends only. */ enum dep_check dependencies_ok(struct pkginfo *pkg, struct pkginfo *removing, struct varbuf *aemsgs) { /* Valid values: 2 = ok, 1 = defer, 0 = halt. */ enum dep_check ok; /* Valid values: 0 = none, 1 = defer, 2 = withwarning, 3 = ok. */ enum found_status found, thisf; int interestingwarnings; bool matched, anycannotfixbytrig; struct varbuf oemsgs = VARBUF_INIT; struct dependency *dep; struct deppossi *possi, *provider; struct pkginfo *possfixbytrig, *canfixbytrig; interestingwarnings= 0; ok = DEP_CHECK_OK; debug(dbg_depcon,"checking dependencies of %s (- %s)", pkg_name(pkg, pnaw_always), removing ? pkg_name(removing, pnaw_always) : "<none>"); anycannotfixbytrig = false; canfixbytrig = NULL; for (dep= pkg->installed.depends; dep; dep= dep->next) { if (dep->type != dep_depends && dep->type != dep_predepends) continue; debug(dbg_depcondetail," checking group ..."); matched = false; varbuf_reset(&oemsgs); found = FOUND_NONE; possfixbytrig = NULL; for (possi = dep->list; found != FOUND_OK && possi; possi = possi->next) { struct deppossi_pkg_iterator *possi_iter; struct pkginfo *pkg_pos; debug(dbg_depcondetail," checking possibility -> %s",possi->ed->name); if (possi->cyclebreak) { debug(dbg_depcondetail," break cycle so ok and found"); found = FOUND_OK; break; } thisf = FOUND_NONE; possi_iter = deppossi_pkg_iter_new(possi, wpb_installed); while ((pkg_pos = deppossi_pkg_iter_next(possi_iter))) { thisf = deppossi_ok_found(pkg_pos, pkg, removing, NULL, &possfixbytrig, &matched, possi, &interestingwarnings, &oemsgs); if (thisf > found) found = thisf; if (found == FOUND_OK) break; } deppossi_pkg_iter_free(possi_iter); if (found != FOUND_OK) { for (provider = possi->ed->depended.installed; found != FOUND_OK && provider; provider = provider->rev_next) { if (provider->up->type != dep_provides) continue; debug(dbg_depcondetail, " checking provider %s", pkg_name(provider->up->up, pnaw_always)); if (!deparchsatisfied(&provider->up->up->installed, provider->arch, possi)) { debug(dbg_depcondetail, " provider does not satisfy arch"); continue; } thisf = deppossi_ok_found(provider->up->up, pkg, removing, provider, &possfixbytrig, &matched, possi, &interestingwarnings, &oemsgs); if (thisf == FOUND_DEFER && provider->up->up == pkg && !removing) { /* IOW, if the pkg satisfies its own dep (via a provide), then * we let it pass, even if it isn't configured yet (as we're * installing it). */ thisf = FOUND_OK; } if (thisf > found) found = thisf; } } debug(dbg_depcondetail," found %d",found); if (thisf > found) found= thisf; } if (in_force(FORCE_DEPENDS)) { thisf = found_forced_on(DEPEND_TRY_FORCE_DEPENDS); if (thisf > found) { found = thisf; debug(dbg_depcondetail, " rescued by force-depends, found %d", found); } } debug(dbg_depcondetail, " found %d matched %d possfixbytrig %s", found, matched, possfixbytrig ? pkg_name(possfixbytrig, pnaw_always) : "-"); if (removing && !matched) continue; switch (found) { case FOUND_NONE: anycannotfixbytrig = true; ok = DEP_CHECK_HALT; /* Fall through. */ case FOUND_FORCED: varbuf_add_str(aemsgs, " "); varbuf_add_pkgbin_name(aemsgs, pkg, &pkg->installed, pnaw_nonambig); varbuf_add_str(aemsgs, _(" depends on ")); varbufdependency(aemsgs, dep); if (interestingwarnings) { /* Don't print the line about the package to be removed if * that's the only line. */ varbuf_end_str(&oemsgs); varbuf_add_str(aemsgs, _("; however:\n")); varbuf_add_str(aemsgs, oemsgs.buf); } else { varbuf_add_str(aemsgs, ".\n"); } break; case FOUND_DEFER: if (possfixbytrig) canfixbytrig = possfixbytrig; else anycannotfixbytrig = true; if (ok > DEP_CHECK_DEFER) ok = DEP_CHECK_DEFER; break; case FOUND_OK: break; default: internerr("unknown value for found '%d'", found); } } if (ok == DEP_CHECK_HALT && (pkg->clientdata && pkg->clientdata->istobe == PKG_ISTOBE_REMOVE)) ok = DEP_CHECK_DEFER; if (!anycannotfixbytrig && canfixbytrig) progress_bytrigproc = canfixbytrig; varbuf_destroy(&oemsgs); debug(dbg_depcon,"ok %d msgs >>%.*s<<", ok, (int)aemsgs->used, aemsgs->buf); return ok; }
/* * Checks [Pre]-Depends only. */ enum dep_check dependencies_ok(struct pkginfo *pkg, struct pkginfo *removing, struct varbuf *aemsgs) { /* Valid values: 2 = ok, 1 = defer, 0 = halt. */ enum dep_check ok; /* Valid values: 0 = none, 1 = defer, 2 = withwarning, 3 = ok. */ enum found_status found, thisf; int interestingwarnings; bool matched, anycannotfixbytrig; struct varbuf oemsgs = VARBUF_INIT; struct dependency *dep; struct deppossi *possi, *provider; struct pkginfo *possfixbytrig, *canfixbytrig; interestingwarnings= 0; ok = dep_check_ok; debug(dbg_depcon,"checking dependencies of %s (- %s)", pkg_name(pkg, pnaw_always), removing ? pkg_name(removing, pnaw_always) : "<none>"); anycannotfixbytrig = false; canfixbytrig = NULL; for (dep= pkg->installed.depends; dep; dep= dep->next) { if (dep->type != dep_depends && dep->type != dep_predepends) continue; debug(dbg_depcondetail," checking group ..."); matched = false; varbuf_reset(&oemsgs); found = found_none; possfixbytrig = NULL; for (possi = dep->list; found != found_ok && possi; possi = possi->next) { struct deppossi_pkg_iterator *possi_iter; struct pkginfo *pkg_pos; debug(dbg_depcondetail," checking possibility -> %s",possi->ed->name); if (possi->cyclebreak) { debug(dbg_depcondetail," break cycle so ok and found"); found = found_ok; break; } thisf = found_none; possi_iter = deppossi_pkg_iter_new(possi, wpb_installed); while ((pkg_pos = deppossi_pkg_iter_next(possi_iter))) { thisf = deppossi_ok_found(pkg_pos, pkg, removing, NULL, &possfixbytrig, &matched, possi, &interestingwarnings, &oemsgs); if (thisf > found) found = thisf; if (found == found_ok) break; } deppossi_pkg_iter_free(possi_iter); if (found != found_ok && possi->verrel == dpkg_relation_none) { for (provider = possi->ed->depended.installed; found != found_ok && provider; provider = provider->rev_next) { if (provider->up->type != dep_provides) continue; debug(dbg_depcondetail, " checking provider %s", pkg_name(provider->up->up, pnaw_always)); if (!deparchsatisfied(&provider->up->up->installed, provider->arch, possi)) { debug(dbg_depcondetail, " provider does not satisfy arch"); continue; } thisf = deppossi_ok_found(provider->up->up, pkg, removing, possi->ed, &possfixbytrig, &matched, NULL, &interestingwarnings, &oemsgs); if (thisf > found) found = thisf; } } debug(dbg_depcondetail," found %d",found); if (thisf > found) found= thisf; } if (fc_depends) { thisf = (dependtry >= 4) ? found_forced : found_defer; if (thisf > found) { found = thisf; debug(dbg_depcondetail, " rescued by force-depends, found %d", found); } } debug(dbg_depcondetail, " found %d matched %d possfixbytrig %s", found, matched, possfixbytrig ? pkg_name(possfixbytrig, pnaw_always) : "-"); if (removing && !matched) continue; switch (found) { case found_none: anycannotfixbytrig = true; ok = dep_check_halt; case found_forced: varbuf_add_str(aemsgs, " "); varbuf_add_pkgbin_name(aemsgs, pkg, &pkg->installed, pnaw_nonambig); varbuf_add_str(aemsgs, _(" depends on ")); varbufdependency(aemsgs, dep); if (interestingwarnings) { /* Don't print the line about the package to be removed if * that's the only line. */ varbuf_end_str(&oemsgs); varbuf_add_str(aemsgs, _("; however:\n")); varbuf_add_str(aemsgs, oemsgs.buf); } else { varbuf_add_str(aemsgs, ".\n"); } break; case found_defer: if (possfixbytrig) canfixbytrig = possfixbytrig; else anycannotfixbytrig = true; if (ok > dep_check_defer) ok = dep_check_defer; break; case found_ok: break; default: internerr("unknown value for found '%d'", found); } } if (ok == dep_check_halt && (pkg->clientdata && pkg->clientdata->istobe == itb_remove)) ok = dep_check_defer; if (!anycannotfixbytrig && canfixbytrig) progress_bytrigproc = canfixbytrig; varbuf_destroy(&oemsgs); debug(dbg_depcon,"ok %d msgs >>%.*s<<", ok, (int)aemsgs->used, aemsgs->buf); return ok; }