diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/evr.c | 16 | ||||
-rw-r--r-- | src/problems.c | 17 | ||||
-rw-r--r-- | src/repo.h | 16 | ||||
-rw-r--r-- | src/solver.c | 13 | ||||
-rw-r--r-- | src/solver.h | 2 | ||||
-rw-r--r-- | src/solver_private.h | 18 | ||||
-rw-r--r-- | src/solver_util.c | 178 |
7 files changed, 186 insertions, 74 deletions
@@ -77,10 +77,10 @@ solv_vercmp_rpm(const char *s1, const char *q1, const char *s2, const char *q2) for (;;) { while (s1 < q1 && !(*s1 >= '0' && *s1 <= '9') && - !(*s1 >= 'a' && *s1 <= 'z') && !(*s1 >= 'A' && *s1 <= 'Z') && *s1 != '~') + !(*s1 >= 'a' && *s1 <= 'z') && !(*s1 >= 'A' && *s1 <= 'Z') && *s1 != '~' && *s1 != '^') s1++; while (s2 < q2 && !(*s2 >= '0' && *s2 <= '9') && - !(*s2 >= 'a' && *s2 <= 'z') && !(*s2 >= 'A' && *s2 <= 'Z') && *s2 != '~') + !(*s2 >= 'a' && *s2 <= 'z') && !(*s2 >= 'A' && *s2 <= 'Z') && *s2 != '~' && *s2 != '^') s2++; if (s1 < q1 && *s1 == '~') { @@ -94,6 +94,18 @@ solv_vercmp_rpm(const char *s1, const char *q1, const char *s2, const char *q2) } if (s2 < q2 && *s2 == '~') return 1; + if (s1 < q1 && *s1 == '^') + { + if (s2 < q2 && *s2 == '^') + { + s1++; + s2++; + continue; + } + return s2 < q2 ? -1 : 1; + } + if (s2 < q2 && *s2 == '^') + return s1 < q1 ? 1 : -1; if (s1 >= q1 || s2 >= q2) break; if ((*s1 >= '0' && *s1 <= '9') || (*s2 >= '0' && *s2 <= '9')) diff --git a/src/problems.c b/src/problems.c index df751c4..2b5cefd 100644 --- a/src/problems.c +++ b/src/problems.c @@ -247,8 +247,23 @@ solver_autouninstall(Solver *solv, int start) if (v >= solv->updaterules && v < solv->updaterules_end) { Rule *r; + Id p = solv->installed->start + (v - solv->updaterules); if (m && !MAPTST(m, v - solv->updaterules)) continue; + if (pool->considered && !MAPTST(pool->considered, p)) + continue; /* do not uninstalled disabled packages */ + if (solv->bestrules_pkg && solv->bestrules_end > solv->bestrules) + { + int j; + for (j = start + 1; j < solv->problems.count - 1; j++) + { + Id vv = solv->problems.elements[j]; + if (vv >= solv->bestrules && vv < solv->bestrules_end && solv->bestrules_pkg[vv - solv->bestrules] == p) + break; + } + if (j < solv->problems.count - 1) + continue; /* best rule involved, do not uninstall */ + } /* check if identical to feature rule, we don't like that (except for orphans) */ r = solv->rules + solv->featurerules + (v - solv->updaterules); if (!r->p) @@ -260,7 +275,7 @@ solver_autouninstall(Solver *solv, int start) if (solv->keep_orphans) { r = solv->rules + v; - if (!r->d && !r->w2 && r->p == (solv->installed->start + (v - solv->updaterules))) + if (!r->d && !r->w2 && r->p == p) { lastfeature = v; lastupdate = 0; @@ -101,20 +101,18 @@ static inline int pool_disabled_solvable(const Pool *pool, Solvable *s) static inline int pool_badarch_solvable(const Pool *pool, Solvable *s) { - if (!s->arch) - return 1; - if (pool->id2arch && pool_arch2score(pool, s->arch) == 0) + if (pool->id2arch && (!s->arch || pool_arch2score(pool, s->arch) == 0)) return 1; return 0; } static inline int pool_installable(const Pool *pool, Solvable *s) { - if (!s->arch || s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) + if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) return 0; if (s->repo && s->repo->disabled) return 0; - if (pool->id2arch && pool_arch2score(pool, s->arch) == 0) + if (pool->id2arch && (!s->arch || pool_arch2score(pool, s->arch) == 0)) return 0; if (pool->considered) { @@ -125,6 +123,14 @@ static inline int pool_installable(const Pool *pool, Solvable *s) return 1; } +/* not in solvable.h because we need the repo definition */ +static inline Solvable *solvable_free(Solvable *s, int reuseids) +{ + if (s && s->repo) + repo_free_solvable(s->repo, s - s->repo->pool->solvables, reuseids); + return 0; +} + /* search callback values */ #define SEARCH_NEXT_KEY 1 #define SEARCH_NEXT_SOLVABLE 2 diff --git a/src/solver.c b/src/solver.c index a4e0c4b..57fa3e4 100644 --- a/src/solver.c +++ b/src/solver.c @@ -1443,6 +1443,8 @@ solver_get_flag(Solver *solv, int flag) return solv->strongrecommends; case SOLVER_FLAG_INSTALL_ALSO_UPDATES: return solv->install_also_updates; + case SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED: + return solv->only_namespace_recommended; default: break; } @@ -1533,6 +1535,9 @@ solver_set_flag(Solver *solv, int flag, int value) case SOLVER_FLAG_INSTALL_ALSO_UPDATES: solv->install_also_updates = value; break; + case SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED: + solv->only_namespace_recommended = value; + break; default: break; } @@ -2092,12 +2097,14 @@ resolve_weak(Solver *solv, int level, int disablerules, Queue *dq, Queue *dqs, i Id *recp, rec, pp, p; if (!solv->addalreadyrecommended && s->repo == solv->installed) continue; - /* XXX need to special case AND ? */ if (s->recommends) { recp = s->repo->idarraydata + s->recommends; while ((rec = *recp++) != 0) { + /* cheat: we just look if there is REL_NAMESPACE in the dep */ + if (solv->only_namespace_recommended && !solver_is_namespace_dep(solv, rec)) + continue; #ifdef ENABLE_COMPLEX_DEPS if (pool_is_complex_dep(pool, rec)) { @@ -2186,7 +2193,7 @@ resolve_weak(Solver *solv, int level, int disablerules, Queue *dq, Queue *dqs, i } /* filter out all already supplemented packages if requested */ - if (!solv->addalreadyrecommended && dqs->count) + if ((!solv->addalreadyrecommended || solv->only_namespace_recommended) && dqs->count) { /* filter out old supplements */ for (i = j = 0; i < dqs->count; i++) @@ -3245,7 +3252,7 @@ solver_solve(Solver *solv, Queue *job) POOL_DEBUG(SOLV_DEBUG_STATS, "allowuninstall=%d, allowdowngrade=%d, allownamechange=%d, allowarchchange=%d, allowvendorchange=%d\n", solv->allowuninstall, solv->allowdowngrade, solv->allownamechange, solv->allowarchchange, solv->allowvendorchange); POOL_DEBUG(SOLV_DEBUG_STATS, "promoteepoch=%d, forbidselfconflicts=%d\n", pool->promoteepoch, pool->forbidselfconflicts); POOL_DEBUG(SOLV_DEBUG_STATS, "obsoleteusesprovides=%d, implicitobsoleteusesprovides=%d, obsoleteusescolors=%d, implicitobsoleteusescolors=%d\n", pool->obsoleteusesprovides, pool->implicitobsoleteusesprovides, pool->obsoleteusescolors, pool->implicitobsoleteusescolors); - POOL_DEBUG(SOLV_DEBUG_STATS, "dontinstallrecommended=%d, addalreadyrecommended=%d\n", solv->dontinstallrecommended, solv->addalreadyrecommended); + POOL_DEBUG(SOLV_DEBUG_STATS, "dontinstallrecommended=%d, addalreadyrecommended=%d onlynamespacerecommended=%d\n", solv->dontinstallrecommended, solv->addalreadyrecommended, solv->only_namespace_recommended); /* create whatprovides if not already there */ if (!pool->whatprovides) diff --git a/src/solver.h b/src/solver.h index 4c85b4d..6fc2e9f 100644 --- a/src/solver.h +++ b/src/solver.h @@ -167,6 +167,7 @@ struct s_Solver { int urpmreorder; /* true: do special urpm package reordering */ int strongrecommends; /* true: create weak rules for recommends */ int install_also_updates; /* true: do not prune install job rules to installed packages */ + int only_namespace_recommended; /* true: only install packages recommended by namespace */ int process_orphans; /* true: do special orphan processing */ Map dupmap; /* dup to those packages */ @@ -317,6 +318,7 @@ typedef struct s_Solver Solver; #define SOLVER_FLAG_FOCUS_BEST 24 #define SOLVER_FLAG_STRONG_RECOMMENDS 25 #define SOLVER_FLAG_INSTALL_ALSO_UPDATES 26 +#define SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED 27 #define GET_USERINSTALLED_NAMES (1 << 0) /* package names instead of ids */ #define GET_USERINSTALLED_INVERTED (1 << 1) /* autoinstalled */ diff --git a/src/solver_private.h b/src/solver_private.h index e92617d..406b304 100644 --- a/src/solver_private.h +++ b/src/solver_private.h @@ -21,6 +21,7 @@ extern int solver_dep_possible_slow(Solver *solv, Id dep, Map *m); extern int solver_dep_fulfilled_cplx(Solver *solv, Reldep *rd); extern int solver_is_supplementing_alreadyinstalled(Solver *solv, Solvable *s); extern void solver_intersect_obsoleted(Solver *solv, Id p, Queue *q, int qstart, Map *m); +extern int solver_is_namespace_dep_slow(Solver *solv, Reldep *rd); extern void solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded); extern int solver_check_cleandeps_mistakes(Solver *solv); @@ -92,4 +93,21 @@ solver_is_enhancing(Solver *solv, Solvable *s) return 0; } +static inline int +solver_is_namespace_dep(Solver *solv, Id dep) +{ + Pool *pool = solv->pool; + Reldep *rd; + if (!ISRELDEP(dep)) + return 0; + rd = GETRELDEP(pool, dep); + if (rd->flags == REL_NAMESPACE) + return 1; + if (ISRELDEP(rd->name)) + return solver_is_namespace_dep_slow(solv, rd); + if (ISRELDEP(rd->evr)) + return solver_is_namespace_dep_slow(solv, GETRELDEP(pool, rd->evr)); + return 0; +} + #endif /* LIBSOLV_SOLVER_PRIVATE_H */ diff --git a/src/solver_util.c b/src/solver_util.c index bd5d4b4..fb17bf4 100644 --- a/src/solver_util.c +++ b/src/solver_util.c @@ -181,84 +181,91 @@ solver_dep_fulfilled_cplx(Solver *solv, Reldep *rd) return 0; } - -/* mirrors solver_dep_fulfilled, but returns 2 if a new package - * was involved */ static int -solver_dep_fulfilled_alreadyinstalled(Solver *solv, Id dep) +solver_dep_fulfilled_complex_func(Solver *solv, Reldep *rd, int (*dep_fullfilled)(Solver *, Id)) { Pool *pool = solv->pool; - Id p, pp; - int r; - - if (ISRELDEP(dep)) + int r1, r2; + if (rd->flags == REL_COND) { - Reldep *rd = GETRELDEP(pool, dep); - if (rd->flags == REL_COND) + if (ISRELDEP(rd->evr)) { - int r1, r2; - if (ISRELDEP(rd->evr)) + Reldep *rd2 = GETRELDEP(pool, rd->evr); + if (rd2->flags == REL_ELSE) { - Reldep *rd2 = GETRELDEP(pool, rd->evr); - if (rd2->flags == REL_ELSE) + r1 = dep_fullfilled(solv, rd2->name); + if (r1) { - r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd2->name); - if (r1) - { - r2 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name); - return r2 && r1 == 2 ? 2 : r2; - } - return solver_dep_fulfilled_alreadyinstalled(solv, rd2->evr); + r2 = dep_fullfilled(solv, rd->name); + return r2 && r1 == 2 ? 2 : r2; } + return dep_fullfilled(solv, rd2->evr); } - r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name); - r2 = !solver_dep_fulfilled_alreadyinstalled(solv, rd->evr); - if (!r1 && !r2) - return 0; - return r1 == 2 ? 2 : 1; } - if (rd->flags == REL_UNLESS) + r1 = dep_fullfilled(solv, rd->name); + r2 = !dep_fullfilled(solv, rd->evr); + if (!r1 && !r2) + return 0; + return r1 == 2 ? 2 : 1; + } + if (rd->flags == REL_UNLESS) + { + if (ISRELDEP(rd->evr)) { - int r1, r2; - if (ISRELDEP(rd->evr)) + Reldep *rd2 = GETRELDEP(pool, rd->evr); + if (rd2->flags == REL_ELSE) { - Reldep *rd2 = GETRELDEP(pool, rd->evr); - if (rd2->flags == REL_ELSE) + r1 = dep_fullfilled(solv, rd2->name); + if (r1) { - r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd2->name); - if (r1) - { - r2 = solver_dep_fulfilled_alreadyinstalled(solv, rd2->evr); - return r2 && r1 == 2 ? 2 : r2; - } - return solver_dep_fulfilled_alreadyinstalled(solv, rd->name); + r2 = dep_fullfilled(solv, rd2->evr); + return r2 && r1 == 2 ? 2 : r2; } + return dep_fullfilled(solv, rd->name); } - /* A AND NOT(B) */ - r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name); - r2 = !solver_dep_fulfilled_alreadyinstalled(solv, rd->evr); - if (!r1 || !r2) - return 0; - return r1 == 2 ? 2 : 1; - } - if (rd->flags == REL_AND) - { - int r2, r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name); - if (!r1) - return 0; - r2 = solver_dep_fulfilled_alreadyinstalled(solv, rd->evr); - if (!r2) - return 0; - return r1 == 2 || r2 == 2 ? 2 : 1; - } - if (rd->flags == REL_OR) - { - int r2, r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name); - r2 = solver_dep_fulfilled_alreadyinstalled(solv, rd->evr); - if (!r1 && !r2) - return 0; - return r1 == 2 || r2 == 2 ? 2 : 1; } + /* A AND NOT(B) */ + r1 = dep_fullfilled(solv, rd->name); + r2 = !dep_fullfilled(solv, rd->evr); + if (!r1 || !r2) + return 0; + return r1 == 2 ? 2 : 1; + } + if (rd->flags == REL_AND) + { + r1 = dep_fullfilled(solv, rd->name); + if (!r1) + return 0; + r2 = dep_fullfilled(solv, rd->evr); + if (!r2) + return 0; + return r1 == 2 || r2 == 2 ? 2 : 1; + } + if (rd->flags == REL_OR) + { + r1 = dep_fullfilled(solv, rd->name); + r2 = dep_fullfilled(solv, rd->evr); + if (!r1 && !r2) + return 0; + return r1 == 2 || r2 == 2 ? 2 : 1; + } + return 0; +} + +/* mirrors solver_dep_fulfilled, but returns 2 if a new package + * was involved */ +static int +solver_dep_fulfilled_alreadyinstalled(Solver *solv, Id dep) +{ + Pool *pool = solv->pool; + Id p, pp; + int r; + + if (ISRELDEP(dep)) + { + Reldep *rd = GETRELDEP(pool, dep); + if (rd->flags == REL_COND || rd->flags == REL_UNLESS || rd->flags == REL_AND || rd->flags == REL_OR) + return solver_dep_fulfilled_complex_func(solv, rd, solver_dep_fulfilled_alreadyinstalled); if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES) return solver_splitprovides(solv, rd->evr, 0) ? 2 : 0; if (rd->flags == REL_NAMESPACE && solv->installsuppdepq) @@ -282,16 +289,61 @@ solver_dep_fulfilled_alreadyinstalled(Solver *solv, Id dep) return r; } +static int +solver_dep_fulfilled_namespace(Solver *solv, Id dep) +{ + Pool *pool = solv->pool; + Id p, pp; + int r = 1; + + if (ISRELDEP(dep)) + { + Reldep *rd = GETRELDEP(pool, dep); + if (rd->flags == REL_COND || rd->flags == REL_UNLESS || rd->flags == REL_AND || rd->flags == REL_OR) + return solver_dep_fulfilled_complex_func(solv, rd, solver_dep_fulfilled_namespace); + if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES) + return solver_splitprovides(solv, rd->evr, 0) ? 2 : 0; + if (rd->flags == REL_NAMESPACE) + r = 2; + } + FOR_PROVIDES(p, pp, dep) + if (solv->decisionmap[p] > 0) + return r; + return 0; +} + int solver_is_supplementing_alreadyinstalled(Solver *solv, Solvable *s) { Id sup, *supp; supp = s->repo->idarraydata + s->supplements; while ((sup = *supp++) != 0) - if (solver_dep_fulfilled_alreadyinstalled(solv, sup) == 2) + { + if (!solv->addalreadyrecommended && solver_dep_fulfilled_alreadyinstalled(solv, sup) != 2) + continue; + if (solv->only_namespace_recommended && solver_dep_fulfilled_namespace(solv, sup) != 2) + continue; return 1; + } return 0; } + +int +solver_is_namespace_dep_slow(Solver *solv, Reldep *rd) +{ + Pool *pool = solv->pool; + for (;;) + { + if (rd->flags == REL_NAMESPACE) + return 1; + if (ISRELDEP(rd->name) && solver_is_namespace_dep_slow(solv, GETRELDEP(pool, rd->name))) + return 1; + if (!ISRELDEP(rd->evr)) + return 0; + rd = GETRELDEP(pool, rd->evr); + } +} + /* * add all installed packages that package p obsoletes to Queue q. * Package p is not installed. Also, we know that if |