|
Packit Service |
ff689b |
/*
|
|
Packit Service |
ff689b |
* Copyright (c) 2017, SUSE Inc.
|
|
Packit Service |
ff689b |
*
|
|
Packit Service |
ff689b |
* This program is licensed under the BSD license, read LICENSE.BSD
|
|
Packit Service |
ff689b |
* for further information
|
|
Packit Service |
ff689b |
*/
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
/*
|
|
Packit Service |
ff689b |
* solver_util.c
|
|
Packit Service |
ff689b |
*
|
|
Packit Service |
ff689b |
* Dependency solver helper functions
|
|
Packit Service |
ff689b |
*/
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
#include <stdio.h>
|
|
Packit Service |
ff689b |
#include <stdlib.h>
|
|
Packit Service |
ff689b |
#include <unistd.h>
|
|
Packit Service |
ff689b |
#include <string.h>
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
#include "solver.h"
|
|
Packit Service |
ff689b |
#include "solver_private.h"
|
|
Packit Service |
ff689b |
#include "bitmap.h"
|
|
Packit Service |
ff689b |
#include "pool.h"
|
|
Packit Service |
ff689b |
#include "poolarch.h"
|
|
Packit Service |
ff689b |
#include "util.h"
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
/*-------------------------------------------------------------------
|
|
Packit Service |
ff689b |
* check if a installed package p is being updated
|
|
Packit Service |
ff689b |
*/
|
|
Packit Service |
ff689b |
static int
|
|
Packit Service |
ff689b |
solver_is_updating(Solver *solv, Id p)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
/* check if the update rule is true */
|
|
Packit Service |
ff689b |
Pool *pool = solv->pool;
|
|
Packit Service |
ff689b |
Rule *r;
|
|
Packit Service |
ff689b |
Id l, pp;
|
|
Packit Service |
ff689b |
if (solv->decisionmap[p] >= 0)
|
|
Packit Service |
ff689b |
return 0; /* old package stayed */
|
|
Packit Service |
ff689b |
r = solv->rules + solv->updaterules + (p - solv->installed->start);
|
|
Packit Service |
ff689b |
FOR_RULELITERALS(l, pp, r)
|
|
Packit Service |
ff689b |
if (l > 0 && l != p && solv->decisionmap[l] > 0)
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
/*-------------------------------------------------------------------
|
|
Packit Service |
ff689b |
* handle split provides
|
|
Packit Service |
ff689b |
*
|
|
Packit Service |
ff689b |
* a splitprovides dep looks like
|
|
Packit Service |
ff689b |
* namespace:splitprovides(pkg REL_WITH path)
|
|
Packit Service |
ff689b |
* and is only true if pkg is installed and contains the specified path.
|
|
Packit Service |
ff689b |
* we also make sure that pkg is selected for an update, otherwise the
|
|
Packit Service |
ff689b |
* update would always be forced onto the user.
|
|
Packit Service |
ff689b |
* Map m is the map used when called from dep_possible.
|
|
Packit Service |
ff689b |
*/
|
|
Packit Service |
ff689b |
int
|
|
Packit Service |
ff689b |
solver_splitprovides(Solver *solv, Id dep, Map *m)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Pool *pool = solv->pool;
|
|
Packit Service |
ff689b |
Id p, pp;
|
|
Packit Service |
ff689b |
Reldep *rd;
|
|
Packit Service |
ff689b |
Solvable *s;
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
if (!solv->dosplitprovides || !solv->installed)
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
if (!ISRELDEP(dep))
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
rd = GETRELDEP(pool, dep);
|
|
Packit Service |
ff689b |
if (rd->flags != REL_WITH)
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
/*
|
|
Packit Service |
ff689b |
* things are a bit tricky here if pool->addedprovides == 1, because most split-provides are in
|
|
Packit Service |
ff689b |
* a non-standard location. If we simply call pool_whatprovides, we'll drag in the complete
|
|
Packit Service |
ff689b |
* file list. Instead we rely on pool_addfileprovides ignoring the addfileprovidesfiltered flag
|
|
Packit Service |
ff689b |
* for installed packages and check the lazywhatprovidesq (ignoring the REL_WITH part, but
|
|
Packit Service |
ff689b |
* we filter the package name further down anyway).
|
|
Packit Service |
ff689b |
*/
|
|
Packit Service |
ff689b |
if (pool->addedfileprovides == 1 && !ISRELDEP(rd->evr) && !pool->whatprovides[rd->evr])
|
|
Packit Service |
ff689b |
pp = pool_searchlazywhatprovidesq(pool, rd->evr);
|
|
Packit Service |
ff689b |
else
|
|
Packit Service |
ff689b |
pp = pool_whatprovides(pool, dep);
|
|
Packit Service |
ff689b |
while ((p = pool->whatprovidesdata[pp++]) != 0)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
/* here we have packages that provide the correct name and contain the path,
|
|
Packit Service |
ff689b |
* now do extra filtering */
|
|
Packit Service |
ff689b |
s = pool->solvables + p;
|
|
Packit Service |
ff689b |
if (s->repo != solv->installed || s->name != rd->name)
|
|
Packit Service |
ff689b |
continue;
|
|
Packit Service |
ff689b |
/* check if the package is updated. if m is set, we're called from dep_possible */
|
|
Packit Service |
ff689b |
if (m || solver_is_updating(solv, p))
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
int
|
|
Packit Service |
ff689b |
solver_dep_possible_slow(Solver *solv, Id dep, Map *m)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Pool *pool = solv->pool;
|
|
Packit Service |
ff689b |
Id p, pp;
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
if (ISRELDEP(dep))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Reldep *rd = GETRELDEP(pool, dep);
|
|
Packit Service |
ff689b |
if (rd->flags >= 8)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (rd->flags == REL_COND || rd->flags == REL_UNLESS)
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
if (rd->flags == REL_AND)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (!solver_dep_possible_slow(solv, rd->name, m))
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
return solver_dep_possible_slow(solv, rd->evr, m);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (rd->flags == REL_OR)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (solver_dep_possible_slow(solv, rd->name, m))
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
return solver_dep_possible_slow(solv, rd->evr, m);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
|
|
Packit Service |
ff689b |
return solver_splitprovides(solv, rd->evr, m);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
FOR_PROVIDES(p, pp, dep)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (MAPTST(m, p))
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
int
|
|
Packit Service |
ff689b |
solver_dep_fulfilled_cplx(Solver *solv, Reldep *rd)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Pool *pool = solv->pool;
|
|
Packit Service |
ff689b |
if (rd->flags == REL_COND)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (ISRELDEP(rd->evr))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Reldep *rd2 = GETRELDEP(pool, rd->evr);
|
|
Packit Service |
ff689b |
if (rd2->flags == REL_ELSE)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (solver_dep_fulfilled(solv, rd2->name))
|
|
Packit Service |
ff689b |
return solver_dep_fulfilled(solv, rd->name);
|
|
Packit Service |
ff689b |
return solver_dep_fulfilled(solv, rd2->evr);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (solver_dep_fulfilled(solv, rd->name))
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
return !solver_dep_fulfilled(solv, rd->evr);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (rd->flags == REL_UNLESS)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (ISRELDEP(rd->evr))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Reldep *rd2 = GETRELDEP(pool, rd->evr);
|
|
Packit Service |
ff689b |
if (rd2->flags == REL_ELSE)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (!solver_dep_fulfilled(solv, rd2->name))
|
|
Packit Service |
ff689b |
return solver_dep_fulfilled(solv, rd->name);
|
|
Packit Service |
ff689b |
return solver_dep_fulfilled(solv, rd2->evr);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (!solver_dep_fulfilled(solv, rd->name))
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
return !solver_dep_fulfilled(solv, rd->evr);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (rd->flags == REL_AND)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (!solver_dep_fulfilled(solv, rd->name))
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
return solver_dep_fulfilled(solv, rd->evr);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (rd->flags == REL_OR)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (solver_dep_fulfilled(solv, rd->name))
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
return solver_dep_fulfilled(solv, rd->evr);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
static int
|
|
Packit Service |
ff689b |
solver_dep_fulfilled_complex_func(Solver *solv, Reldep *rd, int (*dep_fullfilled)(Solver *, Id))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Pool *pool = solv->pool;
|
|
Packit Service |
ff689b |
int r1, r2;
|
|
Packit Service |
ff689b |
if (rd->flags == REL_COND)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (ISRELDEP(rd->evr))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Reldep *rd2 = GETRELDEP(pool, rd->evr);
|
|
Packit Service |
ff689b |
if (rd2->flags == REL_ELSE)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
r1 = dep_fullfilled(solv, rd2->name);
|
|
Packit Service |
ff689b |
if (r1)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
r2 = dep_fullfilled(solv, rd->name);
|
|
Packit Service |
ff689b |
return r2 && r1 == 2 ? 2 : r2;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
return dep_fullfilled(solv, rd2->evr);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
r1 = dep_fullfilled(solv, rd->name);
|
|
Packit Service |
ff689b |
r2 = !dep_fullfilled(solv, rd->evr);
|
|
Packit Service |
ff689b |
if (!r1 && !r2)
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
return r1 == 2 ? 2 : 1;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (rd->flags == REL_UNLESS)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (ISRELDEP(rd->evr))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Reldep *rd2 = GETRELDEP(pool, rd->evr);
|
|
Packit Service |
ff689b |
if (rd2->flags == REL_ELSE)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
r1 = dep_fullfilled(solv, rd2->name);
|
|
Packit Service |
ff689b |
if (r1)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
r2 = dep_fullfilled(solv, rd2->evr);
|
|
Packit Service |
ff689b |
return r2 && r1 == 2 ? 2 : r2;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
return dep_fullfilled(solv, rd->name);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
/* A AND NOT(B) */
|
|
Packit Service |
ff689b |
r1 = dep_fullfilled(solv, rd->name);
|
|
Packit Service |
ff689b |
r2 = !dep_fullfilled(solv, rd->evr);
|
|
Packit Service |
ff689b |
if (!r1 || !r2)
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
return r1 == 2 ? 2 : 1;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (rd->flags == REL_AND)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
r1 = dep_fullfilled(solv, rd->name);
|
|
Packit Service |
ff689b |
if (!r1)
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
r2 = dep_fullfilled(solv, rd->evr);
|
|
Packit Service |
ff689b |
if (!r2)
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
return r1 == 2 || r2 == 2 ? 2 : 1;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (rd->flags == REL_OR)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
r1 = dep_fullfilled(solv, rd->name);
|
|
Packit Service |
ff689b |
r2 = dep_fullfilled(solv, rd->evr);
|
|
Packit Service |
ff689b |
if (!r1 && !r2)
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
return r1 == 2 || r2 == 2 ? 2 : 1;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
/* mirrors solver_dep_fulfilled, but returns 2 if a new package
|
|
Packit Service |
ff689b |
* was involved */
|
|
Packit Service |
ff689b |
static int
|
|
Packit Service |
ff689b |
solver_dep_fulfilled_alreadyinstalled(Solver *solv, Id dep)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Pool *pool = solv->pool;
|
|
Packit Service |
ff689b |
Id p, pp;
|
|
Packit Service |
ff689b |
int r;
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
if (ISRELDEP(dep))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Reldep *rd = GETRELDEP(pool, dep);
|
|
Packit Service |
ff689b |
if (rd->flags == REL_COND || rd->flags == REL_UNLESS || rd->flags == REL_AND || rd->flags == REL_OR)
|
|
Packit Service |
ff689b |
return solver_dep_fulfilled_complex_func(solv, rd, solver_dep_fulfilled_alreadyinstalled);
|
|
Packit Service |
ff689b |
if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
|
|
Packit Service |
ff689b |
return solver_splitprovides(solv, rd->evr, 0) ? 2 : 0;
|
|
Packit Service |
ff689b |
if (rd->flags == REL_NAMESPACE && solv->installsuppdepq)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Queue *q = solv->installsuppdepq;
|
|
Packit Service |
ff689b |
int i;
|
|
Packit Service |
ff689b |
for (i = 0; i < q->count; i++)
|
|
Packit Service |
ff689b |
if (q->elements[i] == dep || q->elements[i] == rd->name)
|
|
Packit Service |
ff689b |
return 2;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
r = 0;
|
|
Packit Service |
ff689b |
FOR_PROVIDES(p, pp, dep)
|
|
Packit Service |
ff689b |
if (solv->decisionmap[p] > 0)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Solvable *s = pool->solvables + p;
|
|
Packit Service |
ff689b |
if (s->repo && s->repo != solv->installed)
|
|
Packit Service |
ff689b |
return 2;
|
|
Packit Service |
ff689b |
r = 1;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
return r;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
static int
|
|
Packit Service |
ff689b |
solver_dep_fulfilled_namespace(Solver *solv, Id dep)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Pool *pool = solv->pool;
|
|
Packit Service |
ff689b |
Id p, pp;
|
|
Packit Service |
ff689b |
int r = 1;
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
if (ISRELDEP(dep))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Reldep *rd = GETRELDEP(pool, dep);
|
|
Packit Service |
ff689b |
if (rd->flags == REL_COND || rd->flags == REL_UNLESS || rd->flags == REL_AND || rd->flags == REL_OR)
|
|
Packit Service |
ff689b |
return solver_dep_fulfilled_complex_func(solv, rd, solver_dep_fulfilled_namespace);
|
|
Packit Service |
ff689b |
if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
|
|
Packit Service |
ff689b |
return solver_splitprovides(solv, rd->evr, 0) ? 2 : 0;
|
|
Packit Service |
ff689b |
if (rd->flags == REL_NAMESPACE)
|
|
Packit Service |
ff689b |
r = 2;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
FOR_PROVIDES(p, pp, dep)
|
|
Packit Service |
ff689b |
if (solv->decisionmap[p] > 0)
|
|
Packit Service |
ff689b |
return r;
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
int
|
|
Packit Service |
ff689b |
solver_is_supplementing_alreadyinstalled(Solver *solv, Solvable *s)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Id sup, *supp;
|
|
Packit Service |
ff689b |
supp = s->repo->idarraydata + s->supplements;
|
|
Packit Service |
ff689b |
while ((sup = *supp++) != 0)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (!solv->addalreadyrecommended && solver_dep_fulfilled_alreadyinstalled(solv, sup) != 2)
|
|
Packit Service |
ff689b |
continue;
|
|
Packit Service |
ff689b |
if (solv->only_namespace_recommended && solver_dep_fulfilled_namespace(solv, sup) != 2)
|
|
Packit Service |
ff689b |
continue;
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
int
|
|
Packit Service |
ff689b |
solver_is_namespace_dep_slow(Solver *solv, Reldep *rd)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Pool *pool = solv->pool;
|
|
Packit Service |
ff689b |
for (;;)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (rd->flags == REL_NAMESPACE)
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
if (ISRELDEP(rd->name) && solver_is_namespace_dep_slow(solv, GETRELDEP(pool, rd->name)))
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
if (!ISRELDEP(rd->evr))
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
rd = GETRELDEP(pool, rd->evr);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
/*
|
|
Packit Service |
ff689b |
* add all installed packages that package p obsoletes to Queue q.
|
|
Packit Service |
ff689b |
* Package p is not installed. Also, we know that if
|
|
Packit Service |
ff689b |
* solv->keepexplicitobsoletes is not set, p is not in the multiversion map.
|
|
Packit Service |
ff689b |
* Entries may get added multiple times.
|
|
Packit Service |
ff689b |
*/
|
|
Packit Service |
ff689b |
static void
|
|
Packit Service |
ff689b |
solver_add_obsoleted(Solver *solv, Id p, Queue *q)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Pool *pool = solv->pool;
|
|
Packit Service |
ff689b |
Repo *installed = solv->installed;
|
|
Packit Service |
ff689b |
Id p2, pp2;
|
|
Packit Service |
ff689b |
Solvable *s = pool->solvables + p;
|
|
Packit Service |
ff689b |
Id obs, *obsp;
|
|
Packit Service |
ff689b |
Id lastp2 = 0;
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
if (!solv->keepexplicitobsoletes || !(solv->multiversion.size && MAPTST(&solv->multiversion, p)))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
FOR_PROVIDES(p2, pp2, s->name)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Solvable *ps = pool->solvables + p2;
|
|
Packit Service |
ff689b |
if (ps->repo != installed)
|
|
Packit Service |
ff689b |
continue;
|
|
Packit Service |
ff689b |
if (!pool->implicitobsoleteusesprovides && ps->name != s->name)
|
|
Packit Service |
ff689b |
continue;
|
|
Packit Service |
ff689b |
if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
|
|
Packit Service |
ff689b |
continue;
|
|
Packit Service |
ff689b |
queue_push(q, p2);
|
|
Packit Service |
ff689b |
lastp2 = p2;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (!s->obsoletes)
|
|
Packit Service |
ff689b |
return;
|
|
Packit Service |
ff689b |
obsp = s->repo->idarraydata + s->obsoletes;
|
|
Packit Service |
ff689b |
while ((obs = *obsp++) != 0)
|
|
Packit Service |
ff689b |
FOR_PROVIDES(p2, pp2, obs)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Solvable *ps = pool->solvables + p2;
|
|
Packit Service |
ff689b |
if (ps->repo != installed)
|
|
Packit Service |
ff689b |
continue;
|
|
Packit Service |
ff689b |
if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
|
|
Packit Service |
ff689b |
continue;
|
|
Packit Service |
ff689b |
if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
|
|
Packit Service |
ff689b |
continue;
|
|
Packit Service |
ff689b |
if (p2 == lastp2)
|
|
Packit Service |
ff689b |
continue;
|
|
Packit Service |
ff689b |
queue_push(q, p2);
|
|
Packit Service |
ff689b |
lastp2 = p2;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
/*
|
|
Packit Service |
ff689b |
* Call solver_add_obsoleted and intersect the result with the
|
|
Packit Service |
ff689b |
* elements in Queue q starting at qstart.
|
|
Packit Service |
ff689b |
* Assumes that it's the first call if qstart == q->count.
|
|
Packit Service |
ff689b |
* May use auxillary map m for the intersection process, all
|
|
Packit Service |
ff689b |
* elements of q starting at qstart must have their bit cleared.
|
|
Packit Service |
ff689b |
* (This is also true after the function returns.)
|
|
Packit Service |
ff689b |
* (See solver_add_obsoleted for limitations of the package p)
|
|
Packit Service |
ff689b |
*/
|
|
Packit Service |
ff689b |
void
|
|
Packit Service |
ff689b |
solver_intersect_obsoleted(Solver *solv, Id p, Queue *q, int qstart, Map *m)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
int i, j;
|
|
Packit Service |
ff689b |
int qcount = q->count;
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
solver_add_obsoleted(solv, p, q);
|
|
Packit Service |
ff689b |
if (qcount == qstart)
|
|
Packit Service |
ff689b |
return; /* first call */
|
|
Packit Service |
ff689b |
if (qcount == q->count)
|
|
Packit Service |
ff689b |
j = qstart;
|
|
Packit Service |
ff689b |
else if (qcount == qstart + 1)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
/* easy if there's just one element */
|
|
Packit Service |
ff689b |
j = qstart;
|
|
Packit Service |
ff689b |
for (i = qcount; i < q->count; i++)
|
|
Packit Service |
ff689b |
if (q->elements[i] == q->elements[qstart])
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
j++; /* keep the element */
|
|
Packit Service |
ff689b |
break;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
else if (!m || (!m->size && q->count - qstart <= 8))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
/* faster than a map most of the time */
|
|
Packit Service |
ff689b |
int k;
|
|
Packit Service |
ff689b |
for (i = j = qstart; i < qcount; i++)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
Id ip = q->elements[i];
|
|
Packit Service |
ff689b |
for (k = qcount; k < q->count; k++)
|
|
Packit Service |
ff689b |
if (q->elements[k] == ip)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
q->elements[j++] = ip;
|
|
Packit Service |
ff689b |
break;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
else
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
/* for the really pathologic cases we use the map */
|
|
Packit Service |
ff689b |
Repo *installed = solv->installed;
|
|
Packit Service |
ff689b |
if (!m->size)
|
|
Packit Service |
ff689b |
map_init(m, installed->end - installed->start);
|
|
Packit Service |
ff689b |
for (i = qcount; i < q->count; i++)
|
|
Packit Service |
ff689b |
MAPSET(m, q->elements[i] - installed->start);
|
|
Packit Service |
ff689b |
for (i = j = qstart; i < qcount; i++)
|
|
Packit Service |
ff689b |
if (MAPTST(m, q->elements[i] - installed->start))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
MAPCLR(m, q->elements[i] - installed->start);
|
|
Packit Service |
ff689b |
q->elements[j++] = q->elements[i];
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
queue_truncate(q, j);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|