Exemplo n.º 1
0
/**
 * 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;

  if (pkg->clientdata->color == black)
    return false;
  pkg->clientdata->color = gray;

  if (f_debug & dbg_depcondetail) {
    struct varbuf str_pkgs = VARBUF_INIT;

    for (sol = sofar; sol; sol = sol->prev) {
      varbufaddstr(&str_pkgs, " <- ");
      varbufaddstr(&str_pkgs, sol->pkg->name);
    }
    varbufaddc(&str_pkgs, '\0');
    debug(dbg_depcondetail, "findbreakcyclerecursive %s %s", pkg->name,
          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) {
      /* Don't find the same cycles again. */
      if (possi->cyclebreak) continue;
      thislink.possi= possi;
      if (foundcyclebroken(&thislink, sofar, possi->ed,possi))
        return true;
      /* Right, now we try all the providers ... */
      for (providelink= possi->ed->installed.depended;
           providelink;
           providelink = providelink->rev_next) {
        if (providelink->up->type != dep_provides) continue;
        provider= providelink->up->up;
        if (provider->clientdata->istobe == itb_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 = black;
  return false;
}
Exemplo n.º 2
0
/**
 * 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;
}