2 * Copyright (c) 2017, SUSE Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Dependency solver helper functions
20 #include "solver_private.h"
27 /*-------------------------------------------------------------------
28 * check if a installed package p is being updated
31 solver_is_updating(Solver *solv, Id p)
33 /* check if the update rule is true */
34 Pool *pool = solv->pool;
37 if (solv->decisionmap[p] >= 0)
38 return 0; /* old package stayed */
39 r = solv->rules + solv->updaterules + (p - solv->installed->start);
40 FOR_RULELITERALS(l, pp, r)
41 if (l > 0 && l != p && solv->decisionmap[l] > 0)
46 /*-------------------------------------------------------------------
47 * handle split provides
49 * a splitprovides dep looks like
50 * namespace:splitprovides(pkg REL_WITH path)
51 * and is only true if pkg is installed and contains the specified path.
52 * we also make sure that pkg is selected for an update, otherwise the
53 * update would always be forced onto the user.
54 * Map m is the map used when called from dep_possible.
57 solver_splitprovides(Solver *solv, Id dep, Map *m)
59 Pool *pool = solv->pool;
64 if (!solv->dosplitprovides || !solv->installed)
68 rd = GETRELDEP(pool, dep);
69 if (rd->flags != REL_WITH)
72 * things are a bit tricky here if pool->addedprovides == 1, because most split-provides are in
73 * a non-standard location. If we simply call pool_whatprovides, we'll drag in the complete
74 * file list. Instead we rely on pool_addfileprovides ignoring the addfileprovidesfiltered flag
75 * for installed packages and check the lazywhatprovidesq (ignoring the REL_WITH part, but
76 * we filter the package name further down anyway).
78 if (pool->addedfileprovides == 1 && !ISRELDEP(rd->evr) && !pool->whatprovides[rd->evr])
79 pp = pool_searchlazywhatprovidesq(pool, rd->evr);
81 pp = pool_whatprovides(pool, dep);
82 while ((p = pool->whatprovidesdata[pp++]) != 0)
84 /* here we have packages that provide the correct name and contain the path,
85 * now do extra filtering */
86 s = pool->solvables + p;
87 if (s->repo != solv->installed || s->name != rd->name)
89 /* check if the package is updated. if m is set, we're called from dep_possible */
90 if (m || solver_is_updating(solv, p))
97 solver_dep_possible_slow(Solver *solv, Id dep, Map *m)
99 Pool *pool = solv->pool;
104 Reldep *rd = GETRELDEP(pool, dep);
107 if (rd->flags == REL_COND || rd->flags == REL_UNLESS)
109 if (rd->flags == REL_AND)
111 if (!solver_dep_possible_slow(solv, rd->name, m))
113 return solver_dep_possible_slow(solv, rd->evr, m);
115 if (rd->flags == REL_OR)
117 if (solver_dep_possible_slow(solv, rd->name, m))
119 return solver_dep_possible_slow(solv, rd->evr, m);
121 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
122 return solver_splitprovides(solv, rd->evr, m);
125 FOR_PROVIDES(p, pp, dep)
134 solver_dep_fulfilled_cplx(Solver *solv, Reldep *rd)
136 Pool *pool = solv->pool;
137 if (rd->flags == REL_COND)
139 if (ISRELDEP(rd->evr))
141 Reldep *rd2 = GETRELDEP(pool, rd->evr);
142 if (rd2->flags == REL_ELSE)
144 if (solver_dep_fulfilled(solv, rd2->name))
145 return solver_dep_fulfilled(solv, rd->name);
146 return solver_dep_fulfilled(solv, rd2->evr);
149 if (solver_dep_fulfilled(solv, rd->name))
151 return !solver_dep_fulfilled(solv, rd->evr);
153 if (rd->flags == REL_UNLESS)
155 if (ISRELDEP(rd->evr))
157 Reldep *rd2 = GETRELDEP(pool, rd->evr);
158 if (rd2->flags == REL_ELSE)
160 if (!solver_dep_fulfilled(solv, rd2->name))
161 return solver_dep_fulfilled(solv, rd->name);
162 return solver_dep_fulfilled(solv, rd2->evr);
165 if (!solver_dep_fulfilled(solv, rd->name))
167 return !solver_dep_fulfilled(solv, rd->evr);
169 if (rd->flags == REL_AND)
171 if (!solver_dep_fulfilled(solv, rd->name))
173 return solver_dep_fulfilled(solv, rd->evr);
175 if (rd->flags == REL_OR)
177 if (solver_dep_fulfilled(solv, rd->name))
179 return solver_dep_fulfilled(solv, rd->evr);
185 solver_dep_fulfilled_complex_func(Solver *solv, Reldep *rd, int (*dep_fullfilled)(Solver *, Id))
187 Pool *pool = solv->pool;
189 if (rd->flags == REL_COND)
191 if (ISRELDEP(rd->evr))
193 Reldep *rd2 = GETRELDEP(pool, rd->evr);
194 if (rd2->flags == REL_ELSE)
196 r1 = dep_fullfilled(solv, rd2->name);
199 r2 = dep_fullfilled(solv, rd->name);
200 return r2 && r1 == 2 ? 2 : r2;
202 return dep_fullfilled(solv, rd2->evr);
205 r1 = dep_fullfilled(solv, rd->name);
206 r2 = !dep_fullfilled(solv, rd->evr);
209 return r1 == 2 ? 2 : 1;
211 if (rd->flags == REL_UNLESS)
213 if (ISRELDEP(rd->evr))
215 Reldep *rd2 = GETRELDEP(pool, rd->evr);
216 if (rd2->flags == REL_ELSE)
218 r1 = dep_fullfilled(solv, rd2->name);
221 r2 = dep_fullfilled(solv, rd2->evr);
222 return r2 && r1 == 2 ? 2 : r2;
224 return dep_fullfilled(solv, rd->name);
228 r1 = dep_fullfilled(solv, rd->name);
229 r2 = !dep_fullfilled(solv, rd->evr);
232 return r1 == 2 ? 2 : 1;
234 if (rd->flags == REL_AND)
236 r1 = dep_fullfilled(solv, rd->name);
239 r2 = dep_fullfilled(solv, rd->evr);
242 return r1 == 2 || r2 == 2 ? 2 : 1;
244 if (rd->flags == REL_OR)
246 r1 = dep_fullfilled(solv, rd->name);
247 r2 = dep_fullfilled(solv, rd->evr);
250 return r1 == 2 || r2 == 2 ? 2 : 1;
255 /* mirrors solver_dep_fulfilled, but returns 2 if a new package
258 solver_dep_fulfilled_alreadyinstalled(Solver *solv, Id dep)
260 Pool *pool = solv->pool;
266 Reldep *rd = GETRELDEP(pool, dep);
267 if (rd->flags == REL_COND || rd->flags == REL_UNLESS || rd->flags == REL_AND || rd->flags == REL_OR)
268 return solver_dep_fulfilled_complex_func(solv, rd, solver_dep_fulfilled_alreadyinstalled);
269 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
270 return solver_splitprovides(solv, rd->evr, 0) ? 2 : 0;
271 if (rd->flags == REL_NAMESPACE && solv->installsuppdepq)
273 Queue *q = solv->installsuppdepq;
275 for (i = 0; i < q->count; i++)
276 if (q->elements[i] == dep || q->elements[i] == rd->name)
281 FOR_PROVIDES(p, pp, dep)
282 if (solv->decisionmap[p] > 0)
284 Solvable *s = pool->solvables + p;
285 if (s->repo && s->repo != solv->installed)
293 solver_dep_fulfilled_namespace(Solver *solv, Id dep)
295 Pool *pool = solv->pool;
301 Reldep *rd = GETRELDEP(pool, dep);
302 if (rd->flags == REL_COND || rd->flags == REL_UNLESS || rd->flags == REL_AND || rd->flags == REL_OR)
303 return solver_dep_fulfilled_complex_func(solv, rd, solver_dep_fulfilled_namespace);
304 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
305 return solver_splitprovides(solv, rd->evr, 0) ? 2 : 0;
306 if (rd->flags == REL_NAMESPACE)
309 FOR_PROVIDES(p, pp, dep)
310 if (solv->decisionmap[p] > 0)
316 solver_is_supplementing_alreadyinstalled(Solver *solv, Solvable *s)
319 supp = s->repo->idarraydata + s->supplements;
320 while ((sup = *supp++) != 0)
322 if (!solv->addalreadyrecommended && solver_dep_fulfilled_alreadyinstalled(solv, sup) != 2)
324 if (solv->only_namespace_recommended && solver_dep_fulfilled_namespace(solv, sup) != 2)
332 solver_is_namespace_dep_slow(Solver *solv, Reldep *rd)
334 Pool *pool = solv->pool;
337 if (rd->flags == REL_NAMESPACE)
339 if (ISRELDEP(rd->name) && solver_is_namespace_dep_slow(solv, GETRELDEP(pool, rd->name)))
341 if (!ISRELDEP(rd->evr))
343 rd = GETRELDEP(pool, rd->evr);
348 * add all installed packages that package p obsoletes to Queue q.
349 * Package p is not installed. Also, we know that if
350 * solv->keepexplicitobsoletes is not set, p is not in the multiversion map.
351 * Entries may get added multiple times.
354 solver_add_obsoleted(Solver *solv, Id p, Queue *q)
356 Pool *pool = solv->pool;
357 Repo *installed = solv->installed;
359 Solvable *s = pool->solvables + p;
363 if (!solv->keepexplicitobsoletes || !(solv->multiversion.size && MAPTST(&solv->multiversion, p)))
365 FOR_PROVIDES(p2, pp2, s->name)
367 Solvable *ps = pool->solvables + p2;
368 if (ps->repo != installed)
370 if (!pool->implicitobsoleteusesprovides && ps->name != s->name)
372 if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
380 obsp = s->repo->idarraydata + s->obsoletes;
381 while ((obs = *obsp++) != 0)
382 FOR_PROVIDES(p2, pp2, obs)
384 Solvable *ps = pool->solvables + p2;
385 if (ps->repo != installed)
387 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
389 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
399 * Call solver_add_obsoleted and intersect the result with the
400 * elements in Queue q starting at qstart.
401 * Assumes that it's the first call if qstart == q->count.
402 * May use auxillary map m for the intersection process, all
403 * elements of q starting at qstart must have their bit cleared.
404 * (This is also true after the function returns.)
405 * (See solver_add_obsoleted for limitations of the package p)
408 solver_intersect_obsoleted(Solver *solv, Id p, Queue *q, int qstart, Map *m)
411 int qcount = q->count;
413 solver_add_obsoleted(solv, p, q);
414 if (qcount == qstart)
415 return; /* first call */
416 if (qcount == q->count)
418 else if (qcount == qstart + 1)
420 /* easy if there's just one element */
422 for (i = qcount; i < q->count; i++)
423 if (q->elements[i] == q->elements[qstart])
425 j++; /* keep the element */
429 else if (!m || (!m->size && q->count - qstart <= 8))
431 /* faster than a map most of the time */
433 for (i = j = qstart; i < qcount; i++)
435 Id ip = q->elements[i];
436 for (k = qcount; k < q->count; k++)
437 if (q->elements[k] == ip)
439 q->elements[j++] = ip;
446 /* for the really pathologic cases we use the map */
447 Repo *installed = solv->installed;
449 map_init(m, installed->end - installed->start);
450 for (i = qcount; i < q->count; i++)
451 MAPSET(m, q->elements[i] - installed->start);
452 for (i = j = qstart; i < qcount; i++)
453 if (MAPTST(m, q->elements[i] - installed->start))
455 MAPCLR(m, q->elements[i] - installed->start);
456 q->elements[j++] = q->elements[i];
459 queue_truncate(q, j);