summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/evr.c16
-rw-r--r--src/problems.c17
-rw-r--r--src/repo.h16
-rw-r--r--src/solver.c13
-rw-r--r--src/solver.h2
-rw-r--r--src/solver_private.h18
-rw-r--r--src/solver_util.c178
7 files changed, 186 insertions, 74 deletions
diff --git a/src/evr.c b/src/evr.c
index a7d4311..c63878e 100644
--- a/src/evr.c
+++ b/src/evr.c
@@ -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;
diff --git a/src/repo.h b/src/repo.h
index 4abfb0f..58704f1 100644
--- a/src/repo.h
+++ b/src/repo.h
@@ -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