+/* check if it is illegal to replace installed
+ * package "is" with package "s" (which must obsolete "is")
+ */
+int
+policy_is_illegal(Solver *solv, Solvable *is, Solvable *s, int ignore)
+{
+ Pool *pool = solv->pool;
+ int ret = 0;
+ int duppkg = solv->dupmap_all ? 1 : 0;
+ if (!(ignore & POLICY_ILLEGAL_DOWNGRADE) && !(duppkg ? solv->dup_allowdowngrade : solv->allowdowngrade))
+ {
+ if (is->name == s->name && pool_evrcmp(pool, is->evr, s->evr, EVRCMP_COMPARE) > 0)
+ ret |= POLICY_ILLEGAL_DOWNGRADE;
+ }
+ if (!(ignore & POLICY_ILLEGAL_ARCHCHANGE) && !(duppkg ? solv->dup_allowarchchange : solv->allowarchchange))
+ {
+ if (is->arch != s->arch && policy_illegal_archchange(solv, is, s))
+ ret |= POLICY_ILLEGAL_ARCHCHANGE;
+ }
+ if (!(ignore & POLICY_ILLEGAL_VENDORCHANGE) && !(duppkg ? solv->dup_allowvendorchange : solv->allowvendorchange))
+ {
+ if (is->vendor != s->vendor && policy_illegal_vendorchange(solv, is, s))
+ ret |= POLICY_ILLEGAL_VENDORCHANGE;
+ }
+ if (!(ignore & POLICY_ILLEGAL_NAMECHANGE) && !(duppkg ? solv->dup_allownamechange : solv->allownamechange))
+ {
+ if (is->name != s->name)
+ ret |= POLICY_ILLEGAL_NAMECHANGE;
+ }
+ return ret;
+}
+
+/*-------------------------------------------------------------------
+ *
+ * create reverse obsoletes map for installed solvables
+ *
+ * For each installed solvable find which packages with *different* names
+ * obsolete the solvable.
+ * This index is used in policy_findupdatepackages() below.
+ */
+void
+policy_create_obsolete_index(Solver *solv)
+{
+ Pool *pool = solv->pool;
+ Solvable *s;
+ Repo *installed = solv->installed;
+ Id p, pp, obs, *obsp, *obsoletes, *obsoletes_data;
+ int i, n, cnt;
+
+ solv->obsoletes = solv_free(solv->obsoletes);
+ solv->obsoletes_data = solv_free(solv->obsoletes_data);
+ if (!installed || installed->start == installed->end)
+ return;
+ cnt = installed->end - installed->start;
+ solv->obsoletes = obsoletes = solv_calloc(cnt, sizeof(Id));
+ for (i = 1; i < pool->nsolvables; i++)
+ {
+ s = pool->solvables + i;
+ if (!s->obsoletes)
+ continue;
+ if (!pool_installable(pool, s))
+ continue;
+ obsp = s->repo->idarraydata + s->obsoletes;
+ while ((obs = *obsp++) != 0)
+ {
+ FOR_PROVIDES(p, pp, obs)
+ {
+ Solvable *ps = pool->solvables + p;;
+ if (ps->repo != installed)
+ continue;
+ if (ps->name == s->name)
+ continue;
+ if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
+ continue;
+ if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
+ continue;
+ obsoletes[p - installed->start]++;
+ }
+ }
+ }
+ n = 0;
+ for (i = 0; i < cnt; i++)
+ if (obsoletes[i])
+ {
+ n += obsoletes[i] + 1;
+ obsoletes[i] = n;
+ }
+ solv->obsoletes_data = obsoletes_data = solv_calloc(n + 1, sizeof(Id));
+ POOL_DEBUG(SOLV_DEBUG_STATS, "obsoletes data: %d entries\n", n + 1);
+ for (i = pool->nsolvables - 1; i > 0; i--)
+ {
+ s = pool->solvables + i;
+ if (!s->obsoletes)
+ continue;
+ if (!pool_installable(pool, s))
+ continue;
+ obsp = s->repo->idarraydata + s->obsoletes;
+ while ((obs = *obsp++) != 0)
+ {
+ FOR_PROVIDES(p, pp, obs)
+ {
+ Solvable *ps = pool->solvables + p;;
+ if (ps->repo != installed)
+ continue;
+ if (ps->name == s->name)
+ continue;
+ if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
+ continue;
+ if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
+ continue;
+ if (obsoletes_data[obsoletes[p - installed->start]] != i)
+ obsoletes_data[--obsoletes[p - installed->start]] = i;
+ }
+ }
+ }
+}
+
+
+/*
+ * find update candidates
+ *
+ * s: installed solvable to be updated
+ * qs: [out] queue to hold Ids of candidates
+ * allow_all: 0 = dont allow downgrades, 1 = allow all candidates
+ * 2 = dup mode
+ *
+ */