summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2016-10-27 14:54:23 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2016-10-27 14:54:24 +0900
commit1a93853889c819ac2d3c8e83e856f4775e664b00 (patch)
tree283fb5892b7e064fb16c1f192bc61c86110f31c2 /src
parent8a7ffe4fc2b44b84fb045f80c1a016b3f200aa8b (diff)
downloadlibsolv-1a93853889c819ac2d3c8e83e856f4775e664b00.tar.gz
libsolv-1a93853889c819ac2d3c8e83e856f4775e664b00.tar.bz2
libsolv-1a93853889c819ac2d3c8e83e856f4775e664b00.zip
Imported Upstream version 0.6.11upstream/0.6.11
Change-Id: Ia7fcc570c551205421c68cc6feb2ecfd3c97e149 Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/cplxdeps.c119
-rw-r--r--src/cplxdeps.h8
-rw-r--r--src/libsolv.ver1
-rw-r--r--src/policy.c90
-rw-r--r--src/policy.h1
-rw-r--r--src/pool.c123
-rw-r--r--src/pool.h8
-rw-r--r--src/problems.c6
-rw-r--r--src/repopack.h12
-rw-r--r--src/rules.c450
-rw-r--r--src/rules.h2
-rw-r--r--src/solver.c906
-rw-r--r--src/solver.h5
-rw-r--r--src/solver_private.h3
-rw-r--r--src/solverdebug.c2
16 files changed, 957 insertions, 781 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b78a82a..f60853e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -28,7 +28,9 @@ SET (libsolv_HEADERS
chksum.h dataiterator.h ${CMAKE_BINARY_DIR}/src/solvversion.h)
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+IF (HAVE_LINKER_VERSION_SCRIPT)
SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINK_FLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/src/libsolv.ver")
+ENDIF (HAVE_LINKER_VERSION_SCRIPT)
IF (DISABLE_SHARED)
ADD_LIBRARY (libsolv STATIC ${libsolv_SRCS})
diff --git a/src/cplxdeps.c b/src/cplxdeps.c
index 9e42194..1be6868 100644
--- a/src/cplxdeps.c
+++ b/src/cplxdeps.c
@@ -68,6 +68,33 @@ expand_simpledeps(Pool *pool, Queue *bq, int start, int split)
return newsplit;
}
+#ifdef CPLXDEBUG
+static void
+print_depblocks(Pool *pool, Queue *bq, int start)
+{
+ int i;
+
+ for (i = start; i < bq->count; i++)
+ {
+ if (bq->elements[i] == pool->nsolvables)
+ {
+ Id *dp = pool->whatprovidesdata + bq->elements[++i];
+ printf(" (");
+ while (*dp)
+ printf(" %s", pool_solvid2str(pool, *dp++));
+ printf(" )");
+ }
+ else if (bq->elements[i] > 0)
+ printf(" %s", pool_solvid2str(pool, bq->elements[i]));
+ else if (bq->elements[i] < 0)
+ printf(" -%s", pool_solvid2str(pool, -bq->elements[i]));
+ else
+ printf(" ||");
+ }
+ printf("\n");
+}
+#endif
+
/* invert all literals in the blocks. note that this also turns DNF into CNF and vice versa */
static void
invert_depblocks(Pool *pool, Queue *bq, int start)
@@ -82,7 +109,7 @@ invert_depblocks(Pool *pool, Queue *bq, int start)
bq->elements[i] = -bq->elements[i];
continue;
}
- /* end of block reached, reorder */
+ /* end of block reached, reverse */
if (i - 1 > j)
{
int k;
@@ -104,11 +131,12 @@ invert_depblocks(Pool *pool, Queue *bq, int start)
* -1: at least one block
*/
static int
-normalize_dep(Pool *pool, Id dep, Queue *bq, int todnf)
+normalize_dep(Pool *pool, Id dep, Queue *bq, int flags)
{
int bqcnt = bq->count;
int bqcnt2;
- Id dp;
+ int todnf = flags & CPLXDEPS_TODNF ? 1 : 0;
+ Id p, dp;
#ifdef CPLXDEBUG
printf("normalize_dep %s todnf:%d\n", pool_dep2str(pool, dep), todnf);
@@ -118,58 +146,60 @@ normalize_dep(Pool *pool, Id dep, Queue *bq, int todnf)
Reldep *rd = GETRELDEP(pool, dep);
if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_COND)
{
- int flags = rd->flags;
+ int rdflags = rd->flags;
int r, mode;
/* in inverted mode, COND means AND. otherwise it means OR NOT */
- if (flags == REL_COND && todnf)
- flags = REL_AND;
- mode = flags == REL_AND ? 0 : 1;
+ if (rdflags == REL_COND && todnf)
+ rdflags = REL_AND;
+ mode = rdflags == REL_AND ? 0 : 1;
/* get blocks of first argument */
- r = normalize_dep(pool, rd->name, bq, todnf);
+ r = normalize_dep(pool, rd->name, bq, flags);
if (r == 0)
{
- if (flags == REL_AND)
+ if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) == 0)
return 0;
- if (flags == REL_COND)
+ if (rdflags == REL_COND)
{
- r = normalize_dep(pool, rd->evr, bq, todnf ^ 1);
+ r = normalize_dep(pool, rd->evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
if (r == 0 || r == 1)
return r == 0 ? 1 : 0;
invert_depblocks(pool, bq, bqcnt); /* invert block for COND */
return r;
}
- return normalize_dep(pool, rd->evr, bq, todnf);
+ return normalize_dep(pool, rd->evr, bq, flags);
}
if (r == 1)
{
- if (flags != REL_AND)
+ if (rdflags != REL_AND)
return 1;
- return normalize_dep(pool, rd->evr, bq, todnf);
+ return normalize_dep(pool, rd->evr, bq, flags);
}
/* get blocks of second argument */
bqcnt2 = bq->count;
- /* COND is OR with NEG on evr block, so we invert the todnf flag in that case*/
- r = normalize_dep(pool, rd->evr, bq, flags == REL_COND ? todnf ^ 1 : todnf);
+ /* COND is OR with NEG on evr block, so we invert the todnf flag in that case */
+ r = normalize_dep(pool, rd->evr, bq, rdflags == REL_COND ? ((flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX) : flags);
if (r == 0)
{
- if (flags == REL_OR)
+ if (rdflags == REL_OR)
+ return -1;
+ if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) != 0)
return -1;
queue_truncate(bq, bqcnt);
- return flags == REL_COND ? 1 : 0;
+ return rdflags == REL_COND ? 1 : 0;
}
if (r == 1)
{
- if (flags == REL_OR)
+ if (rdflags == REL_OR)
{
queue_truncate(bq, bqcnt);
return 1;
}
return -1;
}
- if (flags == REL_COND)
+ if (rdflags == REL_COND)
invert_depblocks(pool, bq, bqcnt2); /* invert 2nd block */
if (mode == todnf)
{
@@ -247,16 +277,29 @@ normalize_dep(Pool *pool, Id dep, Queue *bq, int todnf)
return dp == 2 ? 1 : 0;
if (pool->whatprovidesdata[dp] == SYSTEMSOLVABLE)
return 1;
- if (todnf)
+ bqcnt = bq->count;
+ if ((flags & CPLXDEPS_NAME) != 0)
{
- for (; pool->whatprovidesdata[dp]; dp++)
- queue_push2(bq, pool->whatprovidesdata[dp], 0);
+ while ((p = pool->whatprovidesdata[dp++]) != 0)
+ {
+ if (!pool_match_nevr(pool, pool->solvables + p, dep))
+ continue;
+ queue_push(bq, p);
+ if (todnf)
+ queue_push(bq, 0);
+ }
}
- else
+ else if (todnf)
{
- queue_push2(bq, pool->nsolvables, dp); /* not yet expanded marker */
- queue_push(bq, 0);
+ while ((p = pool->whatprovidesdata[dp++]) != 0)
+ queue_push2(bq, p, 0);
}
+ else
+ queue_push2(bq, pool->nsolvables, dp); /* not yet expanded marker + offset */
+ if (bq->count == bqcnt)
+ return 0; /* no provider */
+ if (!todnf)
+ queue_push(bq, 0); /* finish block */
return -1;
}
@@ -265,7 +308,7 @@ pool_normalize_complex_dep(Pool *pool, Id dep, Queue *bq, int flags)
{
int i, bqcnt = bq->count;
- i = normalize_dep(pool, dep, bq, (flags & CPLXDEPS_TODNF) ? 1 : 0);
+ i = normalize_dep(pool, dep, bq, flags);
if ((flags & CPLXDEPS_EXPAND) != 0)
{
if (i != 0 && i != 1)
@@ -284,27 +327,7 @@ pool_normalize_complex_dep(Pool *pool, Id dep, Queue *bq, int flags)
else if (i == 1)
printf("ALL\n");
else
- {
- for (i = bqcnt; i < bq->count; i++)
- {
- if (bq->elements[i] == pool->nsolvables)
- {
- Id *dp = pool->whatprovidesdata + bq->elements[++i];
- printf(" (");
- while (*dp)
- printf(" %s", pool_solvid2str(pool, *dp++));
- printf(" )");
- }
- else if (bq->elements[i] > 0)
- printf(" %s", pool_solvid2str(pool, bq->elements[i]));
- else if (bq->elements[i] < 0)
- printf(" -%s", pool_solvid2str(pool, -bq->elements[i]));
- else
- printf(" ||");
- }
- printf("\n");
- i = -1;
- }
+ print_depblocks(pool, bq, bqcnt);
#endif
return i;
}
diff --git a/src/cplxdeps.h b/src/cplxdeps.h
index 101d7ad..b553305 100644
--- a/src/cplxdeps.h
+++ b/src/cplxdeps.h
@@ -28,9 +28,11 @@ pool_is_complex_dep(Pool *pool, Id dep)
extern int pool_normalize_complex_dep(Pool *pool, Id dep, Queue *bq, int flags);
-#define CPLXDEPS_TODNF (1 << 0)
-#define CPLXDEPS_EXPAND (1 << 1)
-#define CPLXDEPS_INVERT (1 << 2)
+#define CPLXDEPS_TODNF (1 << 0)
+#define CPLXDEPS_EXPAND (1 << 1)
+#define CPLXDEPS_INVERT (1 << 2)
+#define CPLXDEPS_NAME (1 << 3)
+#define CPLXDEPS_DONTFIX (1 << 4)
#endif
diff --git a/src/libsolv.ver b/src/libsolv.ver
index c795b7a..b8d9764 100644
--- a/src/libsolv.ver
+++ b/src/libsolv.ver
@@ -74,6 +74,7 @@ SOLV_1.0 {
pool_id2langid;
pool_id2rel;
pool_id2str;
+ pool_ids2whatprovides;
pool_intersect_evrs;
pool_isemptyupdatejob;
pool_job2solvables;
diff --git a/src/policy.c b/src/policy.c
index 93d7440..fadfcda 100644
--- a/src/policy.c
+++ b/src/policy.c
@@ -220,6 +220,11 @@ solver_prune_to_highest_prio_per_name(Solver *solv, Queue *plist)
#ifdef ENABLE_COMPLEX_DEPS
+/* simple fixed-size hash for package ids */
+#define CPLXDEPHASH_EMPTY(elements) (memset(elements, 0, sizeof(Id) * 256))
+#define CPLXDEPHASH_SET(elements, p) (elements[(p) & 255] |= (1 << ((p) >> 8 & 31)))
+#define CPLXDEPHASH_TST(elements, p) (elements[(p) & 255] && (elements[(p) & 255] & (1 << ((p) >> 8 & 31))))
+
static void
check_complex_dep(Solver *solv, Id dep, Map *m, Queue **cqp)
{
@@ -241,55 +246,64 @@ check_complex_dep(Solver *solv, Id dep, Map *m, Queue **cqp)
qcnt = q.count;
for (i = 0; i < qcnt; i++)
{
- for (; (p = q.elements[i]) != 0; i++)
+ /* we rely on the fact that blocks are ordered here.
+ * if we reach a positive element, we know that we
+ * saw all negative ones */
+ for (; (p = q.elements[i]) < 0; i++)
{
- if (p < 0)
- {
- if (solv->decisionmap[-p] > 0)
- continue;
- if (solv->decisionmap[-p] < 0)
- break;
- queue_push(&q, -p);
- }
- if (p > 0 && qcnt == q.count)
- MAPSET(m, p);
+ if (solv->decisionmap[-p] < 0)
+ break;
+ if (solv->decisionmap[-p] == 0)
+ queue_push(&q, -p); /* undecided negative literal */
}
- if (q.elements[i])
+ if (p <= 0)
{
#if 0
- printf("complex dep block cannot be true\n");
+ printf("complex dep block cannot be true or no pos literals\n");
#endif
while (q.elements[i])
i++;
if (qcnt != q.count)
queue_truncate(&q, qcnt);
+ continue;
}
- else if (qcnt != q.count)
+ if (qcnt == q.count)
{
+ /* all negative literals installed, add positive literals to map */
+ for (; (p = q.elements[i]) != 0; i++)
+ MAPSET(m, p);
+ }
+ else
+ {
+ /* at least one undecided negative literal, postpone */
int j, k;
- Queue *cq = *cqp;
+ Queue *cq;
#if 0
printf("add new complex dep block\n");
for (j = qcnt; j < q.count; j++)
printf(" - %s\n", pool_solvid2str(pool, q.elements[j]));
#endif
- if (!cq)
+ while (q.elements[i])
+ i++;
+ if (!(cq = *cqp))
{
cq = solv_calloc(1, sizeof(Queue));
queue_init(cq);
+ queue_insertn(cq, 0, 256, 0); /* allocate hash area */
*cqp = cq;
- queue_insertn(cq, 0, 256, 0);
}
for (j = qcnt; j < q.count; j++)
{
p = q.elements[j];
+ /* check if we already have this (dep, p) entry */
for (k = 256; k < cq->count; k += 2)
if (cq->elements[k + 1] == dep && cq->elements[k] == p)
break;
if (k == cq->count)
{
+ /* a new one. add to cq and hash */
queue_push2(cq, p, dep);
- cq->elements[p & 255] |= (1 << (p >> 8 & 31));
+ CPLXDEPHASH_SET(cq->elements, p);
}
}
queue_truncate(&q, qcnt);
@@ -299,13 +313,15 @@ check_complex_dep(Solver *solv, Id dep, Map *m, Queue **cqp)
}
static void
-recheck_complex_dep(Solver *solv, Id p, Map *m, Queue **cqp)
+recheck_complex_deps(Solver *solv, Id p, Map *m, Queue **cqp)
{
Queue *cq = *cqp;
+ Id pp;
int i;
#if 0
- printf("recheck_complex_dep for package %s\n", pool_solvid2str(solv->pool, p));
+ printf("recheck_complex_deps for package %s\n", pool_solvid2str(solv->pool, p));
#endif
+ /* make sure that we don't have a false hit */
for (i = 256; i < cq->count; i += 2)
if (cq->elements[i] == p)
break;
@@ -313,9 +329,11 @@ recheck_complex_dep(Solver *solv, Id p, Map *m, Queue **cqp)
return; /* false alert */
if (solv->decisionmap[p] <= 0)
return; /* just in case... */
- memset(cq->elements, 0, sizeof(Id) * 256);
+
+ /* rebuild the hash, call check_complex_dep for our package */
+ CPLXDEPHASH_EMPTY(cq->elements);
for (i = 256; i < cq->count; i += 2)
- if (cq->elements[i] == p)
+ if ((pp = cq->elements[i]) == p)
{
Id dep = cq->elements[i + 1];
queue_deleten(cq, i, 2);
@@ -323,10 +341,7 @@ recheck_complex_dep(Solver *solv, Id p, Map *m, Queue **cqp)
check_complex_dep(solv, dep, m, &cq);
}
else
- {
- Id pp = cq->elements[i];
- cq->elements[pp & 255] |= (1 << (pp >> 8 & 31));
- }
+ CPLXDEPHASH_SET(cq->elements, pp);
}
#endif
@@ -364,12 +379,11 @@ policy_update_recommendsmap(Solver *solv)
continue;
s = pool->solvables + p;
#ifdef ENABLE_COMPLEX_DEPS
- if (solv->recommendscplxq && solv->recommendscplxq->elements[p & 255])
- if (solv->recommendscplxq->elements[p & 255] & (1 << (p >> 8 & 31)))
- recheck_complex_dep(solv, p, &solv->recommendsmap, &solv->recommendscplxq);
- if (solv->suggestscplxq && solv->suggestscplxq->elements[p & 255])
- if (solv->suggestscplxq->elements[p & 255] & (1 << (p >> 8 & 31)))
- recheck_complex_dep(solv, p, &solv->suggestsmap, &solv->suggestscplxq);
+ /* re-check postponed complex blocks */
+ if (solv->recommendscplxq && CPLXDEPHASH_TST(solv->recommendscplxq->elements, p))
+ recheck_complex_deps(solv, p, &solv->recommendsmap, &solv->recommendscplxq);
+ if (solv->suggestscplxq && CPLXDEPHASH_TST(solv->suggestscplxq->elements, p))
+ recheck_complex_deps(solv, p, &solv->suggestsmap, &solv->suggestscplxq);
#endif
if (s->recommends)
{
@@ -877,9 +891,11 @@ sort_by_name_evr_sortcmp(const void *ap, const void *bp, void *dp)
Id r = aa[1] - bb[1];
if (r)
return r < 0 ? -1 : 1;
+ if (aa[2] == bb[2])
+ return 0;
a = aa[2] < 0 ? -aa[2] : aa[2];
b = bb[2] < 0 ? -bb[2] : bb[2];
- if (pool->disttype != DISTTYPE_DEB)
+ if (pool->disttype != DISTTYPE_DEB && a != b)
{
/* treat release-less versions different */
const char *as = pool_id2str(pool, a);
@@ -1113,10 +1129,10 @@ policy_filter_unwanted(Solver *solv, Queue *plist, int mode)
prune_to_best_arch(pool, plist);
if (plist->count > 1)
prune_to_best_version(pool, plist);
- if (plist->count > 1 && mode == POLICY_MODE_CHOOSE)
+ if (plist->count > 1 && (mode == POLICY_MODE_CHOOSE || mode == POLICY_MODE_CHOOSE_NOREORDER))
{
prune_to_recommended(solv, plist);
- if (plist->count > 1)
+ if (plist->count > 1 && mode != POLICY_MODE_CHOOSE_NOREORDER)
{
/* do some fancy reordering */
#if 0
@@ -1346,7 +1362,7 @@ policy_findupdatepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all)
}
else if (!allownamechange)
continue;
- else if (!solv->noupdateprovide && ps->obsoletes) /* provides/obsoletes combination ? */
+ else if ((!solv->noupdateprovide || solv->needupdateprovide) && ps->obsoletes) /* provides/obsoletes combination ? */
{
/* check if package ps obsoletes installed package s */
/* implicitobsoleteusescolors is somewhat wrong here, but we nevertheless
@@ -1386,7 +1402,7 @@ policy_findupdatepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all)
return;
/* if we have found some valid candidates and noupdateprovide is not set, we're
done. otherwise we fallback to all obsoletes */
- if (!solv->noupdateprovide && haveprovobs)
+ if (solv->needupdateprovide || (!solv->noupdateprovide && haveprovobs))
return;
if (solv->obsoletes && solv->obsoletes[n - solv->installed->start])
{
diff --git a/src/policy.h b/src/policy.h
index a4dd4c4..73410ee 100644
--- a/src/policy.h
+++ b/src/policy.h
@@ -19,6 +19,7 @@ extern "C" {
#define POLICY_MODE_CHOOSE 0
#define POLICY_MODE_RECOMMEND 1
#define POLICY_MODE_SUGGEST 2
+#define POLICY_MODE_CHOOSE_NOREORDER 3 /* internal, do not use */
#define POLICY_ILLEGAL_DOWNGRADE 1
diff --git a/src/pool.c b/src/pool.c
index 8de4cc5..f78f71a 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -194,6 +194,8 @@ pool_get_flag(Pool *pool, int flag)
return pool->noobsoletesmultiversion;
case POOL_FLAG_ADDFILEPROVIDESFILTERED:
return pool->addfileprovidesfiltered;
+ case POOL_FLAG_NOWHATPROVIDESAUX:
+ return pool->nowhatprovidesaux;
default:
break;
}
@@ -236,6 +238,9 @@ pool_set_flag(Pool *pool, int flag, int value)
case POOL_FLAG_ADDFILEPROVIDESFILTERED:
pool->addfileprovidesfiltered = value;
break;
+ case POOL_FLAG_NOWHATPROVIDESAUX:
+ pool->nowhatprovidesaux = value;
+ break;
default:
break;
}
@@ -393,6 +398,34 @@ pool_shrink_whatprovides(Pool *pool)
memset(pool->whatprovidesdata + o, 0, r * sizeof(Id));
}
+/* this gets rid of all the zeros in the aux */
+static void
+pool_shrink_whatprovidesaux(Pool *pool)
+{
+ int num = pool->whatprovidesauxoff;
+ Id id;
+ Offset newoff;
+ Id *op, *wp = pool->whatprovidesauxdata + 1;
+ int i;
+
+ for (i = 0; i < num; i++)
+ {
+ Offset o = pool->whatprovidesaux[i];
+ if (o < 2)
+ continue;
+ op = pool->whatprovidesauxdata + o;
+ pool->whatprovidesaux[i] = wp - pool->whatprovidesauxdata;
+ if (op < wp)
+ abort();
+ while ((id = *op++) != 0)
+ *wp++ = id;
+ }
+ newoff = wp - pool->whatprovidesauxdata;
+ solv_realloc(pool->whatprovidesauxdata, newoff * sizeof(Id));
+ POOL_DEBUG(SOLV_DEBUG_STATS, "shrunk whatprovidesauxdata from %d to %d\n", pool->whatprovidesauxdataoff, newoff);
+ pool->whatprovidesauxdataoff = newoff;
+}
+
/*
* pool_createwhatprovides()
@@ -409,7 +442,8 @@ pool_createwhatprovides(Pool *pool)
Id id;
Offset *idp, n;
Offset *whatprovides;
- Id *whatprovidesdata, *d;
+ Id *whatprovidesdata, *dp, *whatprovidesauxdata;
+ Offset *whatprovidesaux;
Repo *installed = pool->installed;
unsigned int now;
@@ -477,6 +511,16 @@ pool_createwhatprovides(Pool *pool)
whatprovidesdata = solv_calloc(off + extra, sizeof(Id));
whatprovidesdata[2] = SYSTEMSOLVABLE;
+ /* alloc aux vector */
+ whatprovidesauxdata = 0;
+ if (!pool->nowhatprovidesaux)
+ {
+ pool->whatprovidesaux = whatprovidesaux = solv_calloc(num, sizeof(Offset));
+ pool->whatprovidesauxoff = num;
+ pool->whatprovidesauxdataoff = off;
+ pool->whatprovidesauxdata = whatprovidesauxdata = solv_calloc(pool->whatprovidesauxdataoff, sizeof(Id));
+ }
+
/* now fill data for all provides */
for (i = pool->nsolvables - 1; i > 0; i--)
{
@@ -491,24 +535,35 @@ pool_createwhatprovides(Pool *pool)
pp = s->repo->idarraydata + s->provides;
while ((id = *pp++) != 0)
{
+ Id auxid = id;
while (ISRELDEP(id))
{
Reldep *rd = GETRELDEP(pool, id);
id = rd->name;
}
- d = whatprovidesdata + whatprovides[id]; /* offset into whatprovidesdata */
- if (*d != i) /* don't add same solvable twice */
+ dp = whatprovidesdata + whatprovides[id]; /* offset into whatprovidesdata */
+ if (*dp != i) /* don't add same solvable twice */
{
- d[-1] = i;
+ dp[-1] = i;
whatprovides[id]--;
}
+ else
+ auxid = 1;
+ if (whatprovidesauxdata)
+ whatprovidesauxdata[whatprovides[id]] = auxid;
}
}
+ if (pool->whatprovidesaux)
+ memcpy(pool->whatprovidesaux, pool->whatprovides, num * sizeof(Id));
pool->whatprovidesdata = whatprovidesdata;
pool->whatprovidesdataoff = off;
pool->whatprovidesdataleft = extra;
pool_shrink_whatprovides(pool);
+ if (pool->whatprovidesaux)
+ pool_shrink_whatprovidesaux(pool);
POOL_DEBUG(SOLV_DEBUG_STATS, "whatprovides memory used: %d K id array, %d K data\n", (pool->ss.nstrings + pool->nrels + WHATPROVIDES_BLOCK) / (int)(1024/sizeof(Id)), (pool->whatprovidesdataoff + pool->whatprovidesdataleft) / (int)(1024/sizeof(Id)));
+ if (pool->whatprovidesaux)
+ POOL_DEBUG(SOLV_DEBUG_STATS, "whatprovidesaux memory used: %d K id array, %d K data\n", pool->whatprovidesauxoff / (int)(1024/sizeof(Id)), pool->whatprovidesauxdataoff / (int)(1024/sizeof(Id)));
queue_empty(&pool->lazywhatprovidesq);
if ((!pool->addedfileprovides && pool->disttype == DISTTYPE_RPM) || pool->addedfileprovides == 1)
@@ -527,6 +582,8 @@ pool_createwhatprovides(Pool *pool)
if (pool->whatprovides[i] > 1)
queue_push2(&pool->lazywhatprovidesq, i, pool->whatprovides[i]);
pool->whatprovides[i] = 0;
+ if (pool->whatprovidesaux)
+ pool->whatprovidesaux[i] = 0; /* sorry */
}
POOL_DEBUG(SOLV_DEBUG_STATS, "lazywhatprovidesq size: %d entries\n", pool->lazywhatprovidesq.count / 2);
}
@@ -547,6 +604,10 @@ pool_freewhatprovides(Pool *pool)
pool->whatprovidesdata = solv_free(pool->whatprovidesdata);
pool->whatprovidesdataoff = 0;
pool->whatprovidesdataleft = 0;
+ pool->whatprovidesaux = solv_free(pool->whatprovidesaux);
+ pool->whatprovidesauxdata = solv_free(pool->whatprovidesauxdata);
+ pool->whatprovidesauxoff = 0;
+ pool->whatprovidesauxdataoff = 0;
}
@@ -560,15 +621,15 @@ pool_freewhatprovides(Pool *pool)
* returns: Offset into whatprovidesdata
*
*/
+
Id
-pool_queuetowhatprovides(Pool *pool, Queue *q)
+pool_ids2whatprovides(Pool *pool, Id *ids, int count)
{
Offset off;
- int count = q->count;
if (count == 0) /* queue empty -> 1 */
return 1;
- if (count == 1 && q->elements[0] == SYSTEMSOLVABLE)
+ if (count == 1 && *ids == SYSTEMSOLVABLE)
return 2;
/* extend whatprovidesdata if needed, +1 for 0-termination */
@@ -581,7 +642,7 @@ pool_queuetowhatprovides(Pool *pool, Queue *q)
/* copy queue to next free slot */
off = pool->whatprovidesdataoff;
- memcpy(pool->whatprovidesdata + pool->whatprovidesdataoff, q->elements, count * sizeof(Id));
+ memcpy(pool->whatprovidesdata + pool->whatprovidesdataoff, ids, count * sizeof(Id));
/* adapt count and 0-terminate */
pool->whatprovidesdataoff += count;
@@ -591,6 +652,17 @@ pool_queuetowhatprovides(Pool *pool, Queue *q)
return (Id)off;
}
+Id
+pool_queuetowhatprovides(Pool *pool, Queue *q)
+{
+ int count = q->count;
+ if (count == 0) /* queue empty -> 1 */
+ return 1;
+ if (count == 1 && q->elements[0] == SYSTEMSOLVABLE)
+ return 2;
+ return pool_ids2whatprovides(pool, q->elements, count);
+}
+
/*************************************************************************/
@@ -1100,11 +1172,14 @@ pool_addrelproviders(Pool *pool, Id d)
}
else if (flags)
{
+ Id *ppaux = 0;
/* simple version comparison relation */
#if 0
POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: what provides %s?\n", pool_dep2str(pool, name));
#endif
pp = pool_whatprovides_ptr(pool, name);
+ if (!ISRELDEP(name) && name < pool->whatprovidesauxoff)
+ ppaux = pool->whatprovidesaux[name] ? pool->whatprovidesauxdata + pool->whatprovidesaux[name] : 0;
while (ISRELDEP(name))
{
rd = GETRELDEP(pool, name);
@@ -1113,6 +1188,34 @@ pool_addrelproviders(Pool *pool, Id d)
while ((p = *pp++) != 0)
{
Solvable *s = pool->solvables + p;
+ if (ppaux)
+ {
+ pid = *ppaux++;
+ if (pid && pid != 1)
+ {
+#if 0
+ POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: aux hit %d %s\n", p, pool_dep2str(pool, pid));
+#endif
+ if (!ISRELDEP(pid))
+ {
+ if (pid != name)
+ continue; /* wrong provides name */
+ if (pool->disttype == DISTTYPE_DEB)
+ continue; /* unversioned provides can never match versioned deps */
+ }
+ else
+ {
+ prd = GETRELDEP(pool, pid);
+ if (prd->name != name)
+ continue; /* wrong provides name */
+ /* right package, both deps are rels. check flags/evr */
+ if (!pool_match_flags_evr(pool, prd->flags, prd->evr, flags, evr))
+ continue;
+ }
+ queue_push(&plist, p);
+ continue;
+ }
+ }
if (!s->provides)
{
/* no provides - check nevr */
@@ -1338,7 +1441,7 @@ pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct sea
dep = rd->name;
else if (rd->flags == REL_NAMESPACE)
{
- if (rd->name == NAMESPACE_INSTALLED || rd->name == NAMESPACE_SPLITPROVIDES)
+ if (rd->name == NAMESPACE_SPLITPROVIDES)
{
csf = isf;
if (!csf || MAPTST(&csf->seen, sid))
@@ -2499,6 +2602,8 @@ add_new_provider(Pool *pool, Id id, Id p)
if (p)
queue_push(&q, p);
pool->whatprovides[id] = pool_queuetowhatprovides(pool, &q);
+ if (id < pool->whatprovidesauxoff)
+ pool->whatprovidesaux[id] = 0; /* sorry */
queue_free(&q);
}
diff --git a/src/pool.h b/src/pool.h
index f6e5d29..6b98efc 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -155,6 +155,12 @@ struct _Pool {
int addfileprovidesfiltered; /* 1: only use filtered file list for addfileprovides */
int addedfileprovides; /* true: application called addfileprovides */
Queue lazywhatprovidesq; /* queue to store old whatprovides offsets */
+ int nowhatprovidesaux; /* don't allocate and use the whatprovides aux helper */
+ Offset *whatprovidesaux;
+ Offset whatprovidesauxoff;
+ Id *whatprovidesauxdata;
+ Offset whatprovidesauxdataoff;
+
#endif
};
@@ -190,6 +196,7 @@ struct _Pool {
#define POOL_FLAG_NOOBSOLETESMULTIVERSION 8
#define POOL_FLAG_ADDFILEPROVIDESFILTERED 9
#define POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS 10
+#define POOL_FLAG_NOWHATPROVIDESAUX 11
/* ----------------------------------------------- */
@@ -306,6 +313,7 @@ extern void pool_addfileprovides(Pool *pool);
extern void pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst);
extern void pool_freewhatprovides(Pool *pool);
extern Id pool_queuetowhatprovides(Pool *pool, Queue *q);
+extern Id pool_ids2whatprovides(Pool *pool, Id *ids, int count);
extern Id pool_searchlazywhatprovidesq(Pool *pool, Id d);
extern Id pool_addrelproviders(Pool *pool, Id d);
diff --git a/src/problems.c b/src/problems.c
index 528aa2e..b57d980 100644
--- a/src/problems.c
+++ b/src/problems.c
@@ -152,6 +152,8 @@ enableweakrules(Solver *solv)
int i;
Rule *r;
+ if (!solv->weakrulemap.size)
+ return;
for (i = 1, r = solv->rules + i; i < solv->learntrules; i++, r++)
{
if (r->d >= 0) /* already enabled? */
@@ -227,9 +229,7 @@ refine_suggestion(Solver *solv, Id *problem, Id sug, Queue *refined, int essenti
int njob, nfeature, nupdate, pass;
queue_empty(&solv->problems);
solver_reset(solv);
-
- if (!solv->problems.count)
- solver_run_sat(solv, 0, 0);
+ solver_run_sat(solv, 0, 0);
if (!solv->problems.count)
{
diff --git a/src/repopack.h b/src/repopack.h
index f7828ab..3079239 100644
--- a/src/repopack.h
+++ b/src/repopack.h
@@ -235,8 +235,14 @@ data_skip(unsigned char *dp, int type)
return dp + SIZEOF_MD5;
case REPOKEY_TYPE_SHA1:
return dp + SIZEOF_SHA1;
+ case REPOKEY_TYPE_SHA224:
+ return dp + SIZEOF_SHA224;
case REPOKEY_TYPE_SHA256:
return dp + SIZEOF_SHA256;
+ case REPOKEY_TYPE_SHA384:
+ return dp + SIZEOF_SHA384;
+ case REPOKEY_TYPE_SHA512:
+ return dp + SIZEOF_SHA512;
case REPOKEY_TYPE_IDARRAY:
case REPOKEY_TYPE_REL_IDARRAY:
while ((*dp & 0xc0) != 0)
@@ -307,8 +313,14 @@ data_skip_verify(unsigned char *dp, int type, int maxid, int maxdir)
return dp + SIZEOF_MD5;
case REPOKEY_TYPE_SHA1:
return dp + SIZEOF_SHA1;
+ case REPOKEY_TYPE_SHA224:
+ return dp + SIZEOF_SHA224;
case REPOKEY_TYPE_SHA256:
return dp + SIZEOF_SHA256;
+ case REPOKEY_TYPE_SHA384:
+ return dp + SIZEOF_SHA384;
+ case REPOKEY_TYPE_SHA512:
+ return dp + SIZEOF_SHA512;
case REPOKEY_TYPE_ID:
dp = data_read_id(dp, &id);
if (id >= maxid)
diff --git a/src/rules.c b/src/rules.c
index c9bbf81..67de769 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -31,7 +31,7 @@
#define RULES_BLOCK 63
-static void addpkgruleinfo(Solver *solv, Id p, Id d, int type, Id dep);
+static void addpkgruleinfo(Solver *solv, Id p, Id p2, Id d, int type, Id dep);
static void solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded);
/*-------------------------------------------------------------------
@@ -66,8 +66,6 @@ dep_possible(Solver *solv, Id dep, Map *m)
}
if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
return solver_splitprovides(solv, rd->evr, m);
- if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
- return solver_dep_installed(solv, rd->evr);
}
}
FOR_PROVIDES(p, pp, dep)
@@ -243,27 +241,23 @@ hashrule(Solver *solv, Id p, Id d, int n)
/*
* add rule
- * p = direct literal; always < 0 for installed pkg rules
- * d, if < 0 direct literal, if > 0 offset into whatprovides, if == 0 rule is assertion (look at p only)
- *
*
* A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3)
*
- * p < 0 : pkg id of A
- * d > 0 : Offset in whatprovidesdata (list of providers of b)
+ * p < 0 : pkg id of A
+ * d > 0 : Offset in whatprovidesdata (list of providers of b)
*
* A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3)
- * p < 0 : pkg id of A
- * d < 0 : Id of solvable (e.g. B1)
+ * p < 0 : pkg id of A
+ * p2 < 0 : Id of solvable (e.g. B1)
*
- * d == 0: unary rule, assertion => (A) or (-A)
+ * d == 0, p2 == 0: unary rule, assertion => (A) or (-A)
*
* Install: p > 0, d = 0 (A) user requested install
* Remove: p < 0, d = 0 (-A) user requested remove (also: uninstallable)
* Requires: p < 0, d > 0 (-A|B1|B2|...) d: <list of providers for requirement of p>
- * Requires: p > 0, d < 0 (B|-A) hack to save a whatprovides allocation, gets converted into (-A|B)
* Updates: p > 0, d > 0 (A|B1|B2|...) d: <list of updates for solvable p>
- * Conflicts: p < 0, d < 0 (-A|-B) either p (conflict issuer) or d (conflict provider) (binary rule)
+ * Conflicts: p < 0, p2 < 0 (-A|-B) either p (conflict issuer) or d (conflict provider) (binary rule)
* also used for obsoletes
* No-op ?: p = 0, d = 0 (null) (used as placeholder in update/feature rules)
*
@@ -277,118 +271,87 @@ hashrule(Solver *solv, Id p, Id d, int n)
*/
Rule *
-solver_addrule(Solver *solv, Id p, Id d)
+solver_addrule(Solver *solv, Id p, Id p2, Id d)
{
Pool *pool = solv->pool;
- Rule *r = 0;
- Id *dp = 0;
+ Rule *r;
+
+ if (d)
+ {
+ assert(!p2 && d > 0);
+ if (!pool->whatprovidesdata[d])
+ d = 0;
+ else if (!pool->whatprovidesdata[d + 1])
+ {
+ p2 = pool->whatprovidesdata[d];
+ d = 0;
+ }
+ }
- int n = 0; /* number of literals in rule - 1
- 0 = direct assertion (single literal)
- 1 = binary rule
- >1 = multi-literal rule
- */
+ /* now we have two cases:
+ * 1 or 2 literals: d = 0, p, p2 contain the literals
+ * 3 or more literals: d > 0, p2 == 0, d is offset into whatprovidesdata
+ */
/* it often happenes that requires lead to adding the same pkg rule
* multiple times, so we prune those duplicates right away to make
* the work for unifyrules a bit easier */
-
if (!solv->pkgrules_end) /* we add pkg rules */
{
- r = solv->rules + solv->nrules - 1; /* get the last added rule */
- if (r->p == p && r->d == d && (d != 0 || !r->w2))
- return r;
- }
-
- /* compute number of literals (n) in rule */
- if (d < 0)
- {
- if (p == -d)
- return 0; /* rule is self-fulfilling */
- if (p == d)
- d = 0; /* normalize to assertion */
+ r = solv->rules + solv->nrules - 1;
+ if (d)
+ {
+ Id *dp;
+ /* check if rule is identical */
+ if (r->p == p)
+ {
+ Id *dp2;
+ if (r->d == d)
+ return r;
+ dp2 = pool->whatprovidesdata + r->d;
+ for (dp = pool->whatprovidesdata + d; *dp; dp++, dp2++)
+ if (*dp != *dp2)
+ break;
+ if (*dp == *dp2)
+ return r;
+ }
+ /* check if rule is self-fulfilling */
+ for (dp = pool->whatprovidesdata + d; *dp; dp++)
+ if (*dp == -p)
+ return 0; /* rule is self-fulfilling */
+ }
else
- n = 1; /* binary rule */
- }
- else if (d > 0)
- {
- for (dp = pool->whatprovidesdata + d; *dp; dp++, n++)
- if (*dp == -p)
- return 0; /* rule is self-fulfilling */
- if (n == 1) /* convert to binary rule */
- d = dp[-1];
- }
-
- if (n == 1 && p > d && !solv->pkgrules_end)
- {
- /* put smallest literal first so we can find dups */
- n = p; p = d; d = n; /* p <-> d */
- n = 1; /* re-set n, was used as temp var */
- }
-
- /*
- * check for duplicate (r is only set if we're adding pkg rules)
- */
- if (r)
- {
- /* check if the last added rule (r) is exactly the same as what we're looking for. */
- if (n == 1 && !r->d && r->p == p && r->w2 == d)
- return r;
- /* have n-ary rule with same first literal, check other literals */
- if (n > 1 && r->d && r->p == p)
{
- /* Rule where d is an offset in whatprovidesdata */
- Id *dp2;
- if (d == r->d)
- return r;
- dp2 = pool->whatprovidesdata + r->d;
- for (dp = pool->whatprovidesdata + d; *dp; dp++, dp2++)
- if (*dp != *dp2)
- break;
- if (*dp == *dp2)
+ if (p2 && p > p2)
+ {
+ Id o = p; /* switch p1 and p2 */
+ p = p2;
+ p2 = o;
+ }
+ if (r->p == p && !r->d && r->w2 == p2)
return r;
+ if (p == -p2)
+ return 0; /* rule is self-fulfilling */
}
}
- /*
- * allocate new rule r
- */
solv->rules = solv_extend(solv->rules, solv->nrules, 1, sizeof(Rule), RULES_BLOCK);
r = solv->rules + solv->nrules++; /* point to rule space */
-
r->p = p;
- if (n == 0)
- {
- /* direct assertion, no watch needed */
- r->d = 0;
- r->w1 = p;
- r->w2 = 0;
- }
- else if (n == 1)
- {
- /* binary rule */
- r->d = 0;
- r->w1 = p;
- r->w2 = d;
- }
- else
- {
- r->d = d;
- r->w1 = p;
- r->w2 = pool->whatprovidesdata[d];
- }
+ r->d = d;
+ r->w1 = p;
+ r->w2 = d ? pool->whatprovidesdata[d] : p2;
r->n1 = 0;
r->n2 = 0;
-
IF_POOLDEBUG (SOLV_DEBUG_RULE_CREATION)
{
POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, " Add rule: ");
solver_printrule(solv, SOLV_DEBUG_RULE_CREATION, r);
}
-
return r;
}
+
void
solver_shrinkrules(Solver *solv, int nrules)
{
@@ -434,7 +397,7 @@ makemultiversionconflict(Solver *solv, Id n, Id con)
queue_push(&q, p);
}
if (q.count == 1)
- n = -n; /* no other package found, generate normal conflict */
+ n = 0; /* no other package found, normal conflict handling */
else
n = pool_queuetowhatprovides(pool, &q);
queue_free(&q);
@@ -442,12 +405,12 @@ makemultiversionconflict(Solver *solv, Id n, Id con)
}
static inline void
-addpkgrule(Solver *solv, Id p, Id d, int type, Id dep)
+addpkgrule(Solver *solv, Id p, Id p2, Id d, int type, Id dep)
{
if (!solv->ruleinfoq)
- solver_addrule(solv, p, d);
+ solver_addrule(solv, p, p2, d);
else
- addpkgruleinfo(solv, p, d, type, dep);
+ addpkgruleinfo(solv, p, p2, d, type, dep);
}
#ifdef ENABLE_LINKED_PKGS
@@ -469,19 +432,19 @@ addlinks(Solver *solv, Solvable *s, Id req, Queue *qr, Id prv, Queue *qp, Map *m
#endif
if (qr->count == 1)
- addpkgrule(solv, qr->elements[0], -(s - pool->solvables), SOLVER_RULE_PKG_REQUIRES, req);
+ addpkgrule(solv, -(s - pool->solvables), qr->elements[0], 0, SOLVER_RULE_PKG_REQUIRES, req);
else
- addpkgrule(solv, -(s - pool->solvables), pool_queuetowhatprovides(pool, qr), SOLVER_RULE_PKG_REQUIRES, req);
+ addpkgrule(solv, -(s - pool->solvables), 0, pool_queuetowhatprovides(pool, qr), SOLVER_RULE_PKG_REQUIRES, req);
if (qp->count > 1)
{
Id d = pool_queuetowhatprovides(pool, qp);
for (i = 0; i < qr->count; i++)
- addpkgrule(solv, -qr->elements[i], d, SOLVER_RULE_PKG_REQUIRES, prv);
+ addpkgrule(solv, -qr->elements[i], 0, d, SOLVER_RULE_PKG_REQUIRES, prv);
}
else if (qp->count)
{
for (i = 0; i < qr->count; i++)
- addpkgrule(solv, qp->elements[0], -qr->elements[i], SOLVER_RULE_PKG_REQUIRES, prv);
+ addpkgrule(solv, -qr->elements[i], qp->elements[0], 0, SOLVER_RULE_PKG_REQUIRES, prv);
}
if (!m)
return; /* nothing more to do if called from getpkgruleinfos() */
@@ -535,13 +498,16 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w
{
Pool *pool = solv->pool;
Repo *installed = solv->installed;
- int i, j;
+ int i, j, flags;
Queue bq;
queue_init(&bq);
-
+ flags = dontfix ? CPLXDEPS_DONTFIX : 0;
/* CNF expansion for requires, DNF + INVERT expansion for conflicts */
- i = pool_normalize_complex_dep(pool, dep, &bq, type == SOLVER_RULE_PKG_REQUIRES ? 0 : (CPLXDEPS_TODNF | CPLXDEPS_EXPAND | CPLXDEPS_INVERT));
+ if (type == SOLVER_RULE_PKG_CONFLICTS)
+ flags |= CPLXDEPS_TODNF | CPLXDEPS_EXPAND | CPLXDEPS_INVERT;
+
+ i = pool_normalize_complex_dep(pool, dep, &bq, flags);
/* handle special cases */
if (i == 0)
{
@@ -552,7 +518,7 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w
else
{
POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable (%s)\n", pool_solvid2str(pool, p), p, pool_dep2str(pool, dep));
- addpkgrule(solv, -p, 0, type == SOLVER_RULE_PKG_REQUIRES ? SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP : type, dep);
+ addpkgrule(solv, -p, 0, 0, type == SOLVER_RULE_PKG_REQUIRES ? SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP : type, dep);
}
queue_free(&bq);
return;
@@ -579,19 +545,15 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w
if (pool->solvables[dp[j]].repo == installed)
break; /* provider was installed */
if (!dp[j])
- {
- POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "ignoring broken requires %s of installed package %s\n", pool_dep2str(pool, dep), pool_solvid2str(pool, p));
- continue;
- }
- }
- if (!*dp)
- {
- /* nothing provides req! */
- POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable (%s)\n", pool_solvid2str(pool, p), p, pool_dep2str(pool, dep));
- addpkgrule(solv, -p, 0, SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP, dep);
- continue;
+ continue;
}
- addpkgrule(solv, -p, dp - pool->whatprovidesdata, SOLVER_RULE_PKG_REQUIRES, dep);
+ /* check if the rule contains both p and -p */
+ for (j = 0; dp[j] != 0; j++)
+ if (dp[j] == p)
+ break;
+ if (dp[j])
+ continue;
+ addpkgrule(solv, -p, 0, dp - pool->whatprovidesdata, SOLVER_RULE_PKG_REQUIRES, dep);
/* push all non-visited providers on the work queue */
if (m)
for (; *dp; dp++)
@@ -601,29 +563,30 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w
}
if (!bq.elements[i + 1])
{
- Id p2 = bq.elements[i];
- /* simple rule with just two literals */
- if (dontfix && p2 < 0 && pool->solvables[-p2].repo == installed)
- continue;
- if (dontfix && p2 > 0 && pool->solvables[p2].repo != installed)
- continue;
- if (p == p2)
- continue;
+ Id p2 = bq.elements[i++];
+ /* simple rule with just two literals, we'll add a (-p, p2) rule */
+ if (dontfix)
+ {
+ if (p2 < 0 && pool->solvables[-p2].repo == installed)
+ continue;
+ if (p2 > 0 && pool->solvables[p2].repo != installed)
+ continue;
+ }
if (-p == p2)
{
if (type == SOLVER_RULE_PKG_CONFLICTS)
{
if (pool->forbidselfconflicts && !is_otherproviders_dep(pool, dep))
- addpkgrule(solv, -p, 0, SOLVER_RULE_PKG_SELF_CONFLICT, dep);
+ addpkgrule(solv, -p, 0, 0, SOLVER_RULE_PKG_SELF_CONFLICT, dep);
continue;
}
- addpkgrule(solv, -p, 0, type, dep);
+ addpkgrule(solv, -p, 0, 0, type, dep);
continue;
}
- if (p2 > 0)
- addpkgrule(solv, p2, -p, type, dep); /* hack so that we don't need pool_queuetowhatprovides */
- else
- addpkgrule(solv, -p, p2, type, dep);
+ /* check if the rule contains both p and -p */
+ if (p == p2)
+ continue;
+ addpkgrule(solv, -p, p2, 0, type, dep);
if (m && p2 > 0 && !MAPTST(m, p2))
queue_push(workq, p2);
}
@@ -667,19 +630,13 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w
for (j = 0; j < qcnt; j++)
if (qele[j] == p)
break;
- if (j == qcnt)
- {
- /* hack: create fake queue 'q' so that we can call pool_queuetowhatprovides */
- Queue q;
- memset(&q, 0, sizeof(q));
- q.count = qcnt - 1;
- q.elements = qele + 1;
- addpkgrule(solv, qele[0], pool_queuetowhatprovides(pool, &q), type, dep);
- if (m)
- for (j = 0; j < qcnt; j++)
- if (qele[j] > 0 && !MAPTST(m, qele[j]))
- queue_push(workq, qele[j]);
- }
+ if (j < qcnt)
+ continue;
+ addpkgrule(solv, qele[0], 0, pool_ids2whatprovides(pool, qele + 1, qcnt - 1), type, dep);
+ if (m)
+ for (j = 0; j < qcnt; j++)
+ if (qele[j] > 0 && !MAPTST(m, qele[j]))
+ queue_push(workq, qele[j]);
}
}
queue_free(&bq);
@@ -764,7 +721,7 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m)
: !pool_installable(pool, s))
{
POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable\n", pool_solvid2str(pool, n), n);
- addpkgrule(solv, -n, 0, SOLVER_RULE_PKG_NOT_INSTALLABLE, 0);
+ addpkgrule(solv, -n, 0, 0, SOLVER_RULE_PKG_NOT_INSTALLABLE, 0);
}
}
@@ -821,10 +778,16 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m)
if (!*dp)
{
POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable (%s)\n", pool_solvid2str(pool, n), n, pool_dep2str(pool, req));
- addpkgrule(solv, -n, 0, SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP, req);
+ addpkgrule(solv, -n, 0, 0, SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP, req);
continue;
}
+ for (i = 0; dp[i] != 0; i++)
+ if (n == dp[i])
+ break;
+ if (dp[i])
+ continue; /* provided by itself, no need to add rule */
+
IF_POOLDEBUG (SOLV_DEBUG_RULE_CREATION)
{
POOL_DEBUG(SOLV_DEBUG_RULE_CREATION," %s requires %s\n", pool_solvable2str(pool, s), pool_dep2str(pool, req));
@@ -834,7 +797,7 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m)
/* add 'requires' dependency */
/* rule: (-requestor|provider1|provider2|...|providerN) */
- addpkgrule(solv, -n, dp - pool->whatprovidesdata, SOLVER_RULE_PKG_REQUIRES, req);
+ addpkgrule(solv, -n, 0, dp - pool->whatprovidesdata, SOLVER_RULE_PKG_REQUIRES, req);
/* push all non-visited providers on the work queue */
if (m)
@@ -888,16 +851,23 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m)
{
if (!pool->forbidselfconflicts || is_otherproviders_dep(pool, con))
continue;
- addpkgrule(solv, -n, 0, SOLVER_RULE_PKG_SELF_CONFLICT, con);
+ addpkgrule(solv, -n, 0, 0, SOLVER_RULE_PKG_SELF_CONFLICT, con);
continue;
}
if (ispatch && solv->multiversion.size && MAPTST(&solv->multiversion, p) && ISRELDEP(con))
{
/* our patch conflicts with a multiversion package */
- p = -makemultiversionconflict(solv, p, con);
+ Id d = makemultiversionconflict(solv, p, con);
+ if (d)
+ {
+ addpkgrule(solv, -n, 0, d, SOLVER_RULE_PKG_CONFLICTS, con);
+ continue;
+ }
}
+ if (p == SYSTEMSOLVABLE)
+ p = 0;
/* rule: -n|-p: either solvable _or_ provider of conflict */
- addpkgrule(solv, -n, p == SYSTEMSOLVABLE ? 0 : -p, SOLVER_RULE_PKG_CONFLICTS, con);
+ addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_CONFLICTS, con);
}
}
}
@@ -930,10 +900,12 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m)
continue;
if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
continue;
+ if (p == SYSTEMSOLVABLE)
+ p = 0;
if (!isinstalled)
- addpkgrule(solv, -n, -p, SOLVER_RULE_PKG_OBSOLETES, obs);
+ addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_OBSOLETES, obs);
else
- addpkgrule(solv, -n, -p, SOLVER_RULE_PKG_INSTALLED_OBSOLETES, obs);
+ addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_INSTALLED_OBSOLETES, obs);
}
}
}
@@ -959,10 +931,21 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m)
continue;
if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
continue;
+ if (p == SYSTEMSOLVABLE)
+ p = 0;
if (s->name == ps->name)
- addpkgrule(solv, -n, -p, SOLVER_RULE_PKG_SAME_NAME, 0);
+ {
+ /* optimization: do not add the same-name conflict rule if it was
+ * already added when we looket at the other package.
+ * (this assumes pool_colormatch is symmetric) */
+ if (p && m && ps->repo != installed && MAPTST(m, p) &&
+ (ps->arch != ARCH_SRC && ps->arch != ARCH_NOSRC) &&
+ !(solv->multiversion.size && MAPTST(&solv->multiversion, p)))
+ continue;
+ addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_SAME_NAME, 0);
+ }
else
- addpkgrule(solv, -n, -p, SOLVER_RULE_PKG_IMPLICIT_OBSOLETES, s->name);
+ addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_IMPLICIT_OBSOLETES, s->name);
}
}
}
@@ -1234,7 +1217,7 @@ solver_addupdaterule(Solver *solv, Solvable *s, int allow_all)
{
/* a linked pseudo package. As it is linked, we do not need an update rule */
/* nevertheless we set specialupdaters so we can update */
- solver_addrule(solv, 0, 0);
+ solver_addrule(solv, 0, 0, 0);
if (!allow_all && qs.count)
{
if (p != -SYSTEMSOLVABLE)
@@ -1305,16 +1288,25 @@ solver_addupdaterule(Solver *solv, Solvable *s, int allow_all)
{
/* could fallthrough, but then we would do pool_queuetowhatprovides twice */
queue_free(&qs);
- solver_addrule(solv, p, d); /* allow update of s */
+ solver_addrule(solv, p, 0, d); /* allow update of s */
return;
}
}
}
if (qs.count && p == -SYSTEMSOLVABLE)
p = queue_shift(&qs);
- d = qs.count ? pool_queuetowhatprovides(pool, &qs) : 0;
- queue_free(&qs);
- solver_addrule(solv, p, d); /* allow update of s */
+ if (qs.count > 1)
+ {
+ d = pool_queuetowhatprovides(pool, &qs);
+ queue_free(&qs);
+ solver_addrule(solv, p, 0, d); /* allow update of s */
+ }
+ else
+ {
+ d = qs.count ? qs.elements[0] : 0;
+ queue_free(&qs);
+ solver_addrule(solv, p, d, 0); /* allow update of s */
+ }
}
static inline void
@@ -1543,7 +1535,10 @@ solver_addinfarchrules(Solver *solv, Map *addedmap)
if (installed && pool->solvables[p].repo == installed && !haveinstalled)
continue; /* installed package not in lock-step */
}
- solver_addrule(solv, -p, lsq.count ? pool_queuetowhatprovides(pool, &lsq) : 0);
+ if (lsq.count < 2)
+ solver_addrule(solv, -p, lsq.count ? lsq.elements[0] : 0, 0);
+ else
+ solver_addrule(solv, -p, 0, pool_queuetowhatprovides(pool, &lsq));
}
}
queue_free(&lsq);
@@ -1726,6 +1721,15 @@ solver_createdupmaps(Solver *solv)
solver_addtodupmaps(solv, p, how, targeted);
}
}
+ else if (select == SOLVER_SOLVABLE_ALL)
+ {
+ FOR_POOL_SOLVABLES(p)
+ {
+ MAPSET(&solv->dupinvolvedmap, p);
+ if (installed && pool->solvables[p].repo != installed)
+ MAPSET(&solv->dupmap, p);
+ }
+ }
else
{
targeted = how & SOLVER_TARGETED ? 1 : 0;
@@ -1810,13 +1814,13 @@ solver_addduprules(Solver *solv, Map *addedmap)
break;
}
if (!ip)
- solver_addrule(solv, -p, 0); /* no match, sorry */
+ solver_addrule(solv, -p, 0, 0); /* no match, sorry */
else
MAPSET(&solv->dupmap, p); /* for best rules processing */
}
}
else if (!MAPTST(&solv->dupmap, p))
- solver_addrule(solv, -p, 0);
+ solver_addrule(solv, -p, 0, 0);
}
}
solv->duprules_end = solv->nrules;
@@ -2374,34 +2378,30 @@ solver_reenablepolicyrules_cleandeps(Solver *solv, Id pkg)
***/
static void
-addpkgruleinfo(Solver *solv, Id p, Id d, int type, Id dep)
+addpkgruleinfo(Solver *solv, Id p, Id p2, Id d, int type, Id dep)
{
Pool *pool = solv->pool;
Rule *r;
- Id w2, op, od, ow2;
- /* check if this creates the rule we're searching for */
- r = solv->rules + solv->ruleinfoq->elements[0];
- op = r->p;
- od = r->d < 0 ? -r->d - 1 : r->d;
- ow2 = 0;
-
- /* normalize */
- w2 = d > 0 ? 0 : d;
- if (p < 0 && d > 0 && (!pool->whatprovidesdata[d] || !pool->whatprovidesdata[d + 1]))
+ if (d)
{
- w2 = pool->whatprovidesdata[d];
- d = 0;
- }
- if (p > 0 && d < 0) /* this hack is used for package links and complex deps */
- {
- w2 = p;
- p = d;
+ assert(!p2 && d > 0);
+ if (!pool->whatprovidesdata[d])
+ d = 0;
+ else if (!pool->whatprovidesdata[d + 1])
+ {
+ p2 = pool->whatprovidesdata[d];
+ d = 0;
+ }
}
- if (d > 0)
+ /* check if this creates the rule we're searching for */
+ r = solv->rules + solv->ruleinfoq->elements[0];
+ if (d)
{
- if (p != op && !od)
+ /* three or more literals */
+ Id od = r->d < 0 ? -r->d - 1 : r->d;
+ if (p != r->p && !od)
return;
if (d != od)
{
@@ -2413,46 +2413,33 @@ addpkgruleinfo(Solver *solv, Id p, Id d, int type, Id dep)
if (*odp)
return;
}
- w2 = 0;
- /* handle multiversion conflict rules */
- if (p < 0 && pool->whatprovidesdata[d] < 0)
- {
- w2 = pool->whatprovidesdata[d];
- /* XXX: free memory */
- }
+ if (p < 0 && pool->whatprovidesdata[d] < 0 && type == SOLVER_RULE_PKG_CONFLICTS)
+ p2 = pool->whatprovidesdata[d];
}
else
{
- if (od)
- return;
- ow2 = r->w2;
- if (p > w2)
+ /* one or two literals */
+ Id op = p, op2 = p2;
+ if (op2 && op > op2) /* normalize */
{
- if (w2 != op || p != ow2)
- return;
+ Id o = op;
+ op = op2;
+ op2 = o;
}
- else
+ if (r->p != op || r->w2 != op2 || (r->d && r->d != -1))
+ return;
+ if (type == SOLVER_RULE_PKG_CONFLICTS && !p2)
+ p2 = -SYSTEMSOLVABLE;
+ if (type == SOLVER_RULE_PKG_SAME_NAME)
{
- if (p != op || w2 != ow2)
- return;
+ p = op; /* we normalize same name order */
+ p2 = op2;
}
- /* should use a different type instead */
- if (type == SOLVER_RULE_PKG_CONFLICTS && !w2)
- w2 = -SYSTEMSOLVABLE;
}
/* yep, rule matches. record info */
queue_push(solv->ruleinfoq, type);
- if (type == SOLVER_RULE_PKG_SAME_NAME)
- {
- /* we normalize same name order */
- queue_push(solv->ruleinfoq, op < 0 ? -op : 0);
- queue_push(solv->ruleinfoq, ow2 < 0 ? -ow2 : 0);
- }
- else
- {
- queue_push(solv->ruleinfoq, p < 0 ? -p : 0);
- queue_push(solv->ruleinfoq, w2 < 0 ? -w2 : 0);
- }
+ queue_push(solv->ruleinfoq, p < 0 ? -p : 0);
+ queue_push(solv->ruleinfoq, p2 < 0 ? -p2 : 0);
queue_push(solv->ruleinfoq, dep);
}
@@ -2706,7 +2693,7 @@ solver_ruleclass(Solver *solv, Id rid)
return SOLVER_RULE_YUMOBS;
if (rid >= solv->choicerules && rid < solv->choicerules_end)
return SOLVER_RULE_CHOICE;
- if (rid >= solv->learntrules)
+ if (rid >= solv->learntrules && rid < solv->nrules)
return SOLVER_RULE_LEARNT;
return SOLVER_RULE_UNKNOWN;
}
@@ -3068,7 +3055,7 @@ solver_addchoicerules(Solver *solv)
lastaddedd = d;
lastaddedcnt = q.count;
- solver_addrule(solv, r->p, d);
+ solver_addrule(solv, r->p, 0, d);
queue_push(&solv->weakruleq, solv->nrules - 1);
solv->choicerules_ref[solv->nrules - 1 - solv->choicerules] = rid;
#if 0
@@ -3200,7 +3187,10 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs)
if (q.count == oldcnt)
continue; /* nothing filtered */
p2 = queue_shift(&q);
- solver_addrule(solv, p2, q.count ? pool_queuetowhatprovides(pool, &q) : 0);
+ if (q.count < 2)
+ solver_addrule(solv, p2, q.count ? q.elements[0] : 0, 0);
+ else
+ solver_addrule(solv, p2, 0, pool_queuetowhatprovides(pool, &q));
queue_push(&r2pkg, -(solv->jobrules + j));
}
}
@@ -3267,7 +3257,10 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs)
}
}
p2 = queue_shift(&q);
- solver_addrule(solv, p2, q.count ? pool_queuetowhatprovides(pool, &q) : 0);
+ if (q.count < 2)
+ solver_addrule(solv, p2, q.count ? q.elements[0] : 0, 0);
+ else
+ solver_addrule(solv, p2, 0, pool_queuetowhatprovides(pool, &q));
queue_push(&r2pkg, p);
}
}
@@ -3481,11 +3474,10 @@ for (j = 0; j < qq.count; j++)
if (group != groupk && k > groupstart)
{
/* add the rule */
- Queue qhelper;
- memset(&qhelper, 0, sizeof(qhelper));
- qhelper.count = k - groupstart;
- qhelper.elements = qq.elements + groupstart;
- solver_addrule(solv, -p, pool_queuetowhatprovides(pool, &qhelper));
+ if (k - groupstart == 1)
+ solver_addrule(solv, -p, qq.elements[groupstart], 0);
+ else
+ solver_addrule(solv, -p, 0, pool_ids2whatprovides(pool, qq.elements + groupstart, k - groupstart));
queue_push(&yumobsinfoq, qo.elements[i]);
}
groupstart = k + 1;
@@ -3538,8 +3530,6 @@ dep_pkgcheck(Solver *solv, Id dep, Map *m, Queue *q)
}
if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
return;
- if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
- return;
}
}
FOR_PROVIDES(p, pp, dep)
@@ -3576,8 +3566,6 @@ check_xsupp(Solver *solv, Queue *depq, Id dep)
#else
return 0;
#endif
- if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
- return solver_dep_installed(solv, rd->evr);
}
if (depq && rd->flags == REL_NAMESPACE)
{
@@ -3783,7 +3771,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
/* have special namespace cleandeps erases */
if (iq.count)
{
- for (ip = solv->installed->start; ip < solv->installed->end; ip++)
+ for (ip = installed->start; ip < installed->end; ip++)
{
s = pool->solvables + ip;
if (s->repo != installed)
@@ -3792,7 +3780,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
continue;
supp = s->repo->idarraydata + s->supplements;
while ((sup = *supp++) != 0)
- if (check_xsupp(solv, &iq, sup) && !check_xsupp(solv, 0, sup))
+ if (ISRELDEP(sup) && check_xsupp(solv, &iq, sup) && !check_xsupp(solv, 0, sup))
{
#ifdef CLEANDEPSDEBUG
printf("xsupp %s from %s\n", pool_dep2str(pool, sup), pool_solvid2str(pool, ip));
diff --git a/src/rules.h b/src/rules.h
index 8f55af3..606819b 100644
--- a/src/rules.h
+++ b/src/rules.h
@@ -99,7 +99,7 @@ solver_enablerule(struct _Solver *solv, Rule *r)
r->d = -r->d - 1;
}
-extern Rule *solver_addrule(struct _Solver *solv, Id p, Id d);
+extern Rule *solver_addrule(struct _Solver *solv, Id p, Id p2, Id d);
extern void solver_unifyrules(struct _Solver *solv);
extern int solver_rulecmp(struct _Solver *solv, Rule *r1, Rule *r2);
extern void solver_shrinkrules(struct _Solver *solv, int nrules);
diff --git a/src/solver.c b/src/solver.c
index 46d0ca3..f551731 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -30,6 +30,7 @@
#define RULES_BLOCK 63
+
/********************************************************************
*
* dependency check helpers
@@ -104,93 +105,66 @@ solver_splitprovides(Solver *solv, Id dep, Map *m)
}
-/*-------------------------------------------------------------------
- * solver_dep_installed
- */
-
-int
-solver_dep_installed(Solver *solv, Id dep)
-{
-#if 0
- Pool *pool = solv->pool;
- Id p, pp;
-
- if (ISRELDEP(dep))
- {
- Reldep *rd = GETRELDEP(pool, dep);
- if (rd->flags == REL_AND)
- {
- if (!solver_dep_installed(solv, rd->name))
- return 0;
- return solver_dep_installed(solv, rd->evr);
- }
- if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
- return solver_dep_installed(solv, rd->evr);
- }
- FOR_PROVIDES(p, pp, dep)
- {
- if (p == SYSTEMSOLVABLE || (solv->installed && pool->solvables[p].repo == solv->installed))
- return 1;
- }
-#endif
- return 0;
-}
-
-/* mirrors solver_dep_installed, but returns 2 if a
- * dependency listed in solv->installsuppdepq was involved */
+/* mirrors solver_dep_fulfilled, but returns 2 if a new package
+ * was involved */
static int
-solver_check_installsuppdepq_dep(Solver *solv, Id dep)
+solver_dep_fulfilled_alreadyinstalled(Solver *solv, Id dep)
{
Pool *pool = solv->pool;
Id p, pp;
- Queue *q;
+ int r;
if (ISRELDEP(dep))
{
Reldep *rd = GETRELDEP(pool, dep);
if (rd->flags == REL_AND)
{
- int r2, r1 = solver_check_installsuppdepq_dep(solv, rd->name);
+ int r2, r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name);
if (!r1)
return 0;
- r2 = solver_check_installsuppdepq_dep(solv, rd->evr);
+ 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_check_installsuppdepq_dep(solv, rd->name);
- r2 = solver_check_installsuppdepq_dep(solv, rd->evr);
+ 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;
}
if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
return solver_splitprovides(solv, rd->evr, 0);
- if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
- return solver_dep_installed(solv, rd->evr);
- if (rd->flags == REL_NAMESPACE && (q = solv->installsuppdepq) != 0)
+ if (rd->flags == REL_NAMESPACE && solv->installsuppdepq)
{
+ Queue *q = solv->installsuppdepq;
int i;
for (i = 0; i < q->count; i++)
if (q->elements[i] == dep || q->elements[i] == rd->name)
return 2;
}
}
+ r = 0;
FOR_PROVIDES(p, pp, dep)
if (solv->decisionmap[p] > 0)
- return 1;
- return 0;
+ {
+ Solvable *s = pool->solvables + p;
+ if (s->repo && s->repo != solv->installed)
+ return 2;
+ r = 1;
+ }
+ return r;
}
static int
-solver_check_installsuppdepq(Solver *solv, Solvable *s)
+solver_is_supplementing_alreadyinstalled(Solver *solv, Solvable *s)
{
Id sup, *supp;
supp = s->repo->idarraydata + s->supplements;
while ((sup = *supp++) != 0)
- if (solver_check_installsuppdepq_dep(solv, sup) == 2)
+ if (solver_dep_fulfilled_alreadyinstalled(solv, sup) == 2)
return 1;
return 0;
}
@@ -208,17 +182,10 @@ autouninstall(Solver *solv, Id *problem)
{
if (v < 0)
extraflags &= solv->job.elements[-v - 1];
- if (v >= solv->featurerules && v < solv->featurerules_end)
- if (v > lastfeature)
- lastfeature = v;
if (v >= solv->updaterules && v < solv->updaterules_end)
{
- /* check if identical to feature rule */
- Id p = solv->rules[v].p;
- Rule *r;
- if (p <= 0)
- continue;
- r = solv->rules + solv->featurerules + (p - solv->installed->start);
+ /* check if identical to feature rule, we don't like that */
+ Rule *r = solv->rules + solv->featurerules + (v - solv->updaterules);
if (!r->p)
{
/* update rule == feature rule */
@@ -362,7 +329,7 @@ makeruledecisions(Solver *solv)
continue;
/* do weak rules in phase 2 */
- if (ri < solv->learntrules && MAPTST(&solv->weakrulemap, ri))
+ if (ri < solv->learntrules && solv->weakrulemap.size && MAPTST(&solv->weakrulemap, ri))
continue;
v = r->p;
@@ -504,7 +471,7 @@ makeruledecisions(Solver *solv)
if (rr->p != vv /* not affecting the literal */
&& rr->p != -vv)
continue;
- if (MAPTST(&solv->weakrulemap, i)) /* weak: silently ignore */
+ if (solv->weakrulemap.size && MAPTST(&solv->weakrulemap, i)) /* weak: silently ignore */
continue;
POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, " - disabling rule #%d\n", i);
@@ -531,6 +498,8 @@ makeruledecisions(Solver *solv)
/*
* phase 2: now do the weak assertions
*/
+ if (!solv->weakrulemap.size)
+ break; /* no weak rules, no phase 2 */
for (ii = 0; ii < solv->ruleassertions.count; ii++)
{
ri = solv->ruleassertions.elements[ii];
@@ -600,14 +569,9 @@ makewatches(Solver *solv)
int nsolvables = solv->pool->nsolvables;
solv_free(solv->watches);
- /* lower half for removals, upper half for installs */
+ /* lower half for removals, upper half for installs */
solv->watches = solv_calloc(2 * nsolvables, sizeof(Id));
-#if 1
- /* do it reverse so pkg rules get triggered first (XXX: obsolete?) */
for (i = 1, r = solv->rules + solv->nrules - 1; i < solv->nrules; i++, r--)
-#else
- for (i = 1, r = solv->rules + 1; i < solv->nrules; i++, r++)
-#endif
{
if (!r->w2) /* assertions do not need watches */
continue;
@@ -678,7 +642,6 @@ propagate(Solver *solv, int level)
Id p, pkg, other_watch;
Id *dp;
Id *decisionmap = solv->decisionmap;
-
Id *watches = solv->watches + pool->nsolvables; /* place ptr in middle */
POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate -----\n");
@@ -686,10 +649,10 @@ propagate(Solver *solv, int level)
/* foreach non-propagated decision */
while (solv->propagate_index < solv->decisionq.count)
{
- /*
- * 'pkg' was just decided
- * negate because our watches trigger if literal goes FALSE
- */
+ /*
+ * 'pkg' was just decided
+ * negate because our watches trigger if literal goes FALSE
+ */
pkg = -solv->decisionq.elements[solv->propagate_index++];
IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
@@ -718,11 +681,11 @@ propagate(Solver *solv, int level)
solver_printrule(solv, SOLV_DEBUG_PROPAGATE, r);
}
- /* 'pkg' was just decided (was set to FALSE)
- *
- * now find other literal watch, check clause
- * and advance on linked list
- */
+ /*
+ * 'pkg' was just decided (was set to FALSE), so this rule
+ * may now be unit.
+ */
+ /* find the other watch */
if (pkg == r->w1)
{
other_watch = r->w2;
@@ -734,17 +697,16 @@ propagate(Solver *solv, int level)
next_rp = &r->n2;
}
- /*
- * This term is already true (through the other literal)
- * so we have nothing to do
- */
+ /*
+ * if the other watch is true we have nothing to do
+ */
if (DECISIONMAP_TRUE(other_watch))
continue;
- /*
- * The other literal is FALSE or UNDEF
- *
- */
+ /*
+ * The other literal is FALSE or UNDEF
+ *
+ */
if (r->d)
{
@@ -755,6 +717,8 @@ propagate(Solver *solv, int level)
* and not FALSE
*
* (TRUE is also ok, in that case the rule is fulfilled)
+ * As speed matters here we do not use the FOR_RULELITERALS
+ * macro.
*/
if (r->p /* we have a 'p' */
&& r->p != other_watch /* which is not watched */
@@ -786,7 +750,7 @@ propagate(Solver *solv, int level)
if (p > 0)
POOL_DEBUG(SOLV_DEBUG_PROPAGATE, " -> move w%d to %s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, p));
else
- POOL_DEBUG(SOLV_DEBUG_PROPAGATE," -> move w%d to !%s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, -p));
+ POOL_DEBUG(SOLV_DEBUG_PROPAGATE, " -> move w%d to !%s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, -p));
}
*rp = *next_rp;
@@ -853,25 +817,96 @@ propagate(Solver *solv, int level)
/*-------------------------------------------------------------------
*
+ * revert
+ * revert decisionq to a level
+ */
+
+static void
+revert(Solver *solv, int level)
+{
+ Pool *pool = solv->pool;
+ Id v, vv;
+ while (solv->decisionq.count)
+ {
+ v = solv->decisionq.elements[solv->decisionq.count - 1];
+ vv = v > 0 ? v : -v;
+ if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
+ break;
+ POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "reverting decision %d at %d\n", v, solv->decisionmap[vv]);
+ solv->decisionmap[vv] = 0;
+ solv->decisionq.count--;
+ solv->decisionq_why.count--;
+ solv->propagate_index = solv->decisionq.count;
+ }
+ while (solv->branches.count && solv->branches.elements[solv->branches.count - 1] >= level)
+ solv->branches.count -= solv->branches.elements[solv->branches.count - 2];
+ if (solv->recommends_index > solv->decisionq.count)
+ solv->recommends_index = -1; /* rebuild recommends/suggests maps */
+ if (solv->decisionq.count < solv->decisioncnt_jobs)
+ solv->decisioncnt_jobs = 0;
+ if (solv->decisionq.count < solv->decisioncnt_update)
+ solv->decisioncnt_update = 0;
+ if (solv->decisionq.count < solv->decisioncnt_keep)
+ solv->decisioncnt_keep = 0;
+ if (solv->decisionq.count < solv->decisioncnt_resolve)
+ solv->decisioncnt_resolve = 0;
+ if (solv->decisionq.count < solv->decisioncnt_weak)
+ solv->decisioncnt_weak= 0;
+ if (solv->decisionq.count < solv->decisioncnt_orphan)
+ solv->decisioncnt_orphan = 0;
+}
+
+/*-------------------------------------------------------------------
+ *
+ * watch2onhighest - put watch2 on literal with highest level
+ */
+
+static inline void
+watch2onhighest(Solver *solv, Rule *r)
+{
+ int l, wl = 0;
+ Id d, v, *dp;
+
+ d = r->d < 0 ? -r->d - 1 : r->d;
+ if (!d)
+ return; /* binary rule, both watches are set */
+ dp = solv->pool->whatprovidesdata + d;
+ while ((v = *dp++) != 0)
+ {
+ l = solv->decisionmap[v < 0 ? -v : v];
+ if (l < 0)
+ l = -l;
+ if (l > wl)
+ {
+ r->w2 = dp[-1];
+ wl = l;
+ }
+ }
+}
+
+
+/*-------------------------------------------------------------------
+ *
* analyze
* and learn
*/
static int
-analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *whyp)
+analyze(Solver *solv, int level, Rule *c, Rule **lrp)
{
Pool *pool = solv->pool;
- Queue r;
- Id r_buf[4];
+ Queue q;
+ Rule *r;
+ Id q_buf[8];
int rlevel = 1;
Map seen; /* global? */
- Id d, v, vv, *dp, why;
+ Id p = 0, pp, v, vv, why;
int l, i, idx;
int num = 0, l1num = 0;
int learnt_why = solv->learnt_pool.count;
Id *decisionmap = solv->decisionmap;
- queue_init_buffer(&r, r_buf, sizeof(r_buf)/sizeof(*r_buf));
+ queue_init_buffer(&q, q_buf, sizeof(q_buf)/sizeof(*q_buf));
POOL_DEBUG(SOLV_DEBUG_ANALYZE, "ANALYZE at %d ----------------------\n", level);
map_init(&seen, pool->nsolvables);
@@ -881,43 +916,31 @@ analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *whyp)
IF_POOLDEBUG (SOLV_DEBUG_ANALYZE)
solver_printruleclass(solv, SOLV_DEBUG_ANALYZE, c);
queue_push(&solv->learnt_pool, c - solv->rules);
- d = c->d < 0 ? -c->d - 1 : c->d;
- dp = d ? pool->whatprovidesdata + d : 0;
- /* go through all literals of the rule */
- for (i = -1; ; i++)
+ FOR_RULELITERALS(v, pp, c)
{
- if (i == -1)
- v = c->p;
- else if (d == 0)
- v = i ? 0 : c->w2;
- else
- v = *dp++;
- if (v == 0)
- break;
-
if (DECISIONMAP_TRUE(v)) /* the one true literal */
continue;
vv = v > 0 ? v : -v;
if (MAPTST(&seen, vv))
continue;
+ MAPSET(&seen, vv); /* mark that we also need to look at this literal */
l = solv->decisionmap[vv];
if (l < 0)
l = -l;
- MAPSET(&seen, vv); /* mark that we also need to look at this literal */
if (l == 1)
l1num++; /* need to do this one in level1 pass */
else if (l == level)
num++; /* need to do this one as well */
else
{
- queue_push(&r, v); /* not level1 or conflict level, add to new rule */
+ queue_push(&q, v); /* not level1 or conflict level, add to new rule */
if (l > rlevel)
rlevel = l;
}
}
l1retry:
if (!num && !--l1num)
- break; /* all level 1 literals done */
+ break; /* all literals done */
/* find the next literal to investigate */
/* (as num + l1num > 0, we know that we'll always find one) */
@@ -933,14 +956,15 @@ l1retry:
if (num && --num == 0)
{
- *pr = -v; /* so that v doesn't get lost */
+ /* done with normal literals, now start level 1 literal processing */
+ p = -v; /* so that v doesn't get lost */
if (!l1num)
break;
POOL_DEBUG(SOLV_DEBUG_ANALYZE, "got %d involved level 1 decisions\n", l1num);
/* clear non-l1 bits from seen map */
- for (i = 0; i < r.count; i++)
+ for (i = 0; i < q.count; i++)
{
- v = r.elements[i];
+ v = q.elements[i];
MAPCLR(&seen, v > 0 ? v : -v);
}
/* only level 1 marks left in seen map */
@@ -954,27 +978,49 @@ l1retry:
c = solv->rules + why;
}
map_free(&seen);
-
- if (r.count == 0)
- *dr = 0;
- else if (r.count == 1 && r.elements[0] < 0)
- *dr = r.elements[0];
- else
- *dr = pool_queuetowhatprovides(pool, &r);
+ assert(p != 0);
+ assert(rlevel > 0 && rlevel < level);
IF_POOLDEBUG (SOLV_DEBUG_ANALYZE)
{
POOL_DEBUG(SOLV_DEBUG_ANALYZE, "learned rule for level %d (am %d)\n", rlevel, level);
- solver_printruleelement(solv, SOLV_DEBUG_ANALYZE, 0, *pr);
- for (i = 0; i < r.count; i++)
- solver_printruleelement(solv, SOLV_DEBUG_ANALYZE, 0, r.elements[i]);
+ solver_printruleelement(solv, SOLV_DEBUG_ANALYZE, 0, p);
+ for (i = 0; i < q.count; i++)
+ solver_printruleelement(solv, SOLV_DEBUG_ANALYZE, 0, q.elements[i]);
}
/* push end marker on learnt reasons stack */
queue_push(&solv->learnt_pool, 0);
- if (whyp)
- *whyp = learnt_why;
- queue_free(&r);
solv->stats_learned++;
- return rlevel;
+
+ POOL_DEBUG(SOLV_DEBUG_ANALYZE, "reverting decisions (level %d -> %d)\n", level, rlevel);
+ level = rlevel;
+ revert(solv, level);
+ if (q.count < 2)
+ {
+ Id d = q.count ? q.elements[0] : 0;
+ queue_free(&q);
+ r = solver_addrule(solv, p, d, 0);
+ }
+ else
+ {
+ Id d = pool_queuetowhatprovides(pool, &q);
+ queue_free(&q);
+ r = solver_addrule(solv, p, 0, d);
+ }
+ assert(solv->learnt_why.count == (r - solv->rules) - solv->learntrules);
+ queue_push(&solv->learnt_why, learnt_why);
+ if (r->w2)
+ {
+ /* needs watches */
+ watch2onhighest(solv, r);
+ addwatches_rule(solv, r);
+ }
+ else
+ {
+ /* rule is an assertion */
+ queue_push(&solv->ruleassertions, r - solv->rules);
+ }
+ *lrp = r;
+ return level;
}
@@ -989,7 +1035,6 @@ l1retry:
void
solver_reset(Solver *solv)
{
- Pool *pool = solv->pool;
int i;
Id v;
@@ -1008,10 +1053,6 @@ solver_reset(Solver *solv)
/* adapt learnt rule status to new set of enabled/disabled rules */
enabledisablelearntrules(solv);
-
- /* redo all assertion rule decisions */
- makeruledecisions(solv);
- POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "decisions so far: %d\n", solv->decisionq.count);
}
@@ -1041,7 +1082,7 @@ analyze_unsolvable_rule(Solver *solv, Rule *r, Id *lastweakp, Map *rseen)
analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i], lastweakp, rseen);
return;
}
- if (MAPTST(&solv->weakrulemap, why))
+ if (solv->weakrulemap.size && MAPTST(&solv->weakrulemap, why))
if (!*lastweakp || why > *lastweakp)
*lastweakp = why;
/* do not add pkg rules to problem */
@@ -1079,7 +1120,7 @@ analyze_unsolvable_rule(Solver *solv, Rule *r, Id *lastweakp, Map *rseen)
/*-------------------------------------------------------------------
*
- * analyze_unsolvable
+ * analyze_unsolvable (called from setpropagatelearn)
*
* We know that the problem is not solvable. Record all involved
* rules (i.e. the "proof") into solv->learnt_pool.
@@ -1090,11 +1131,11 @@ analyze_unsolvable_rule(Solver *solv, Rule *r, Id *lastweakp, Map *rseen)
* If the proof contains at least one weak rule, we disable the
* last of them.
*
- * Otherwise we return 0 if disablerules is not set or disable
- * _all_ of the problem rules and return 1.
+ * Otherwise we return -1 if disablerules is not set or disable
+ * _all_ of the problem rules and return 0.
*
- * return: 1 - disabled some rules, try again
- * 0 - hopeless
+ * return: 0 - disabled some rules, try again
+ * -1 - hopeless
*/
static int
@@ -1102,10 +1143,10 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
{
Pool *pool = solv->pool;
Rule *r;
- Map seen; /* global to speed things up? */
+ Map involved; /* global to speed things up? */
Map rseen;
- Id d, v, vv, *dp, why;
- int l, i, idx;
+ Id pp, v, vv, why;
+ int i, idx;
Id *decisionmap = solv->decisionmap;
int oldproblemcount;
int oldlearntpoolcount;
@@ -1123,38 +1164,25 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
queue_push(&solv->problems, 0);
r = cr;
- map_init(&seen, pool->nsolvables);
+ map_init(&involved, pool->nsolvables);
map_init(&rseen, solv->learntrules ? solv->nrules - solv->learntrules : 0);
if (record_proof)
queue_push(&solv->learnt_pool, r - solv->rules);
lastweak = 0;
analyze_unsolvable_rule(solv, r, &lastweak, &rseen);
- d = r->d < 0 ? -r->d - 1 : r->d;
- dp = d ? pool->whatprovidesdata + d : 0;
- for (i = -1; ; i++)
+ FOR_RULELITERALS(v, pp, r)
{
- if (i == -1)
- v = r->p;
- else if (d == 0)
- v = i ? 0 : r->w2;
- else
- v = *dp++;
- if (v == 0)
- break;
if (DECISIONMAP_TRUE(v)) /* the one true literal */
continue;
vv = v > 0 ? v : -v;
- l = solv->decisionmap[vv];
- if (l < 0)
- l = -l;
- MAPSET(&seen, vv);
+ MAPSET(&involved, vv);
}
idx = solv->decisionq.count;
while (idx > 0)
{
v = solv->decisionq.elements[--idx];
vv = v > 0 ? v : -v;
- if (!MAPTST(&seen, vv) || vv == SYSTEMSOLVABLE)
+ if (!MAPTST(&involved, vv) || vv == SYSTEMSOLVABLE)
continue;
why = solv->decisionq_why.elements[idx];
assert(why > 0);
@@ -1162,28 +1190,15 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
queue_push(&solv->learnt_pool, why);
r = solv->rules + why;
analyze_unsolvable_rule(solv, r, &lastweak, &rseen);
- d = r->d < 0 ? -r->d - 1 : r->d;
- dp = d ? pool->whatprovidesdata + d : 0;
- for (i = -1; ; i++)
+ FOR_RULELITERALS(v, pp, r)
{
- if (i == -1)
- v = r->p;
- else if (d == 0)
- v = i ? 0 : r->w2;
- else
- v = *dp++;
- if (v == 0)
- break;
if (DECISIONMAP_TRUE(v)) /* the one true literal */
continue;
vv = v > 0 ? v : -v;
- l = solv->decisionmap[vv];
- if (l < 0)
- l = -l;
- MAPSET(&seen, vv);
+ MAPSET(&involved, vv);
}
}
- map_free(&seen);
+ map_free(&involved);
map_free(&rseen);
queue_push(&solv->problems, 0); /* mark end of this problem */
@@ -1204,7 +1219,7 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
if (v < 0)
solver_reenablepolicyrules(solv, -v);
solver_reset(solv);
- return 1;
+ return 0;
}
if (solv->allowuninstall && (v = autouninstall(solv, solv->problems.elements + oldproblemcount + 1)) != 0)
@@ -1212,7 +1227,7 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
solv->problems.count = oldproblemcount;
solv->learnt_pool.count = oldlearntpoolcount;
solver_reset(solv);
- return 1;
+ return 0;
}
/* finish proof */
@@ -1229,84 +1244,10 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
solver_disableproblem(solv, solv->problems.elements[i]);
/* XXX: might want to enable all weak rules again */
solver_reset(solv);
- return 1;
+ return 0;
}
POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "UNSOLVABLE\n");
- return 0;
-}
-
-
-/********************************************************************/
-/* Decision revert */
-
-/*-------------------------------------------------------------------
- *
- * revert
- * revert decisionq to a level
- */
-
-static void
-revert(Solver *solv, int level)
-{
- Pool *pool = solv->pool;
- Id v, vv;
- while (solv->decisionq.count)
- {
- v = solv->decisionq.elements[solv->decisionq.count - 1];
- vv = v > 0 ? v : -v;
- if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
- break;
- POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "reverting decision %d at %d\n", v, solv->decisionmap[vv]);
- solv->decisionmap[vv] = 0;
- solv->decisionq.count--;
- solv->decisionq_why.count--;
- solv->propagate_index = solv->decisionq.count;
- }
- while (solv->branches.count && solv->branches.elements[solv->branches.count - 1] >= level)
- solv->branches.count -= solv->branches.elements[solv->branches.count - 2];
- if (solv->recommends_index > solv->decisionq.count)
- solv->recommends_index = -1; /* rebuild recommends/suggests maps */
- if (solv->decisionq.count < solv->decisioncnt_jobs)
- solv->decisioncnt_jobs = 0;
- if (solv->decisionq.count < solv->decisioncnt_update)
- solv->decisioncnt_update = 0;
- if (solv->decisionq.count < solv->decisioncnt_keep)
- solv->decisioncnt_keep = 0;
- if (solv->decisionq.count < solv->decisioncnt_resolve)
- solv->decisioncnt_resolve = 0;
- if (solv->decisionq.count < solv->decisioncnt_weak)
- solv->decisioncnt_weak= 0;
- if (solv->decisionq.count < solv->decisioncnt_orphan)
- solv->decisioncnt_orphan = 0;
-}
-
-
-/*-------------------------------------------------------------------
- *
- * watch2onhighest - put watch2 on literal with highest level
- */
-
-static inline void
-watch2onhighest(Solver *solv, Rule *r)
-{
- int l, wl = 0;
- Id d, v, *dp;
-
- d = r->d < 0 ? -r->d - 1 : r->d;
- if (!d)
- return; /* binary rule, both watches are set */
- dp = solv->pool->whatprovidesdata + d;
- while ((v = *dp++) != 0)
- {
- l = solv->decisionmap[v < 0 ? -v : v];
- if (l < 0)
- l = -l;
- if (l > wl)
- {
- r->w2 = dp[-1];
- wl = l;
- }
- }
+ return -1;
}
@@ -1322,7 +1263,7 @@ watch2onhighest(Solver *solv, Rule *r)
* rule to learnt rule set, make decision from learnt
* rule (always unit) and re-propagate.
*
- * returns the new solver level or 0 if unsolvable
+ * returns the new solver level or -1 if unsolvable
*
*/
@@ -1330,11 +1271,8 @@ static int
setpropagatelearn(Solver *solv, int level, Id decision, int disablerules, Id ruleid)
{
Pool *pool = solv->pool;
- Rule *r;
- Id p = 0, d = 0;
- int l, why;
+ Rule *r, *lr;
- assert(ruleid >= 0);
if (decision)
{
level++;
@@ -1345,6 +1283,7 @@ setpropagatelearn(Solver *solv, int level, Id decision, int disablerules, Id rul
queue_push(&solv->decisionq, decision);
queue_push(&solv->decisionq_why, -ruleid); /* <= 0 -> free decision */
}
+ assert(ruleid >= 0 && level > 0);
for (;;)
{
r = propagate(solv, level);
@@ -1353,36 +1292,18 @@ setpropagatelearn(Solver *solv, int level, Id decision, int disablerules, Id rul
if (level == 1)
return analyze_unsolvable(solv, r, disablerules);
POOL_DEBUG(SOLV_DEBUG_ANALYZE, "conflict with rule #%d\n", (int)(r - solv->rules));
- l = analyze(solv, level, r, &p, &d, &why); /* learnt rule in p and d */
- assert(l > 0 && l < level);
- POOL_DEBUG(SOLV_DEBUG_ANALYZE, "reverting decisions (level %d -> %d)\n", level, l);
- level = l;
- revert(solv, level);
- r = solver_addrule(solv, p, d);
- assert(r);
- assert(solv->learnt_why.count == (r - solv->rules) - solv->learntrules);
- queue_push(&solv->learnt_why, why);
- if (d)
- {
- /* at least 2 literals, needs watches */
- watch2onhighest(solv, r);
- addwatches_rule(solv, r);
- }
- else
- {
- /* learnt rule is an assertion */
- queue_push(&solv->ruleassertions, r - solv->rules);
- }
+ level = analyze(solv, level, r, &lr);
/* the new rule is unit by design */
- solv->decisionmap[p > 0 ? p : -p] = p > 0 ? level : -level;
- queue_push(&solv->decisionq, p);
- queue_push(&solv->decisionq_why, r - solv->rules);
+ decision = lr->p;
+ solv->decisionmap[decision > 0 ? decision : -decision] = decision > 0 ? level : -level;
+ queue_push(&solv->decisionq, decision);
+ queue_push(&solv->decisionq_why, lr - solv->rules);
IF_POOLDEBUG (SOLV_DEBUG_ANALYZE)
{
POOL_DEBUG(SOLV_DEBUG_ANALYZE, "decision: ");
- solver_printruleelement(solv, SOLV_DEBUG_ANALYZE, 0, p);
+ solver_printruleelement(solv, SOLV_DEBUG_ANALYZE, 0, decision);
POOL_DEBUG(SOLV_DEBUG_ANALYZE, "new rule: ");
- solver_printrule(solv, SOLV_DEBUG_ANALYZE, r);
+ solver_printrule(solv, SOLV_DEBUG_ANALYZE, lr);
}
}
return level;
@@ -1505,7 +1426,7 @@ takebranch(Solver *solv, int pos, int end, const char *msg, int disablerules)
* install best package from the queue. We add an extra package, inst, if
* provided. See comment in weak install section.
*
- * returns the new solver level or 0 if unsolvable
+ * returns the new solver level or -1 if unsolvable
*
*/
@@ -1651,8 +1572,6 @@ resolve_jobrules(Solver *solv, int level, int disablerules, Queue *dq)
level = selectandinstall(solv, level, dq, disablerules, i);
if (level <= olevel)
{
- if (level == 0)
- return 0; /* unsolvable */
if (level == olevel)
{
i--;
@@ -1791,6 +1710,8 @@ solver_get_flag(Solver *solv, int flag)
return solv->focus_installed;
case SOLVER_FLAG_YUM_OBSOLETES:
return solv->do_yum_obsoletes;
+ case SOLVER_FLAG_NEED_UPDATEPROVIDE:
+ return solv->needupdateprovide;
default:
break;
}
@@ -1866,14 +1787,17 @@ solver_set_flag(Solver *solv, int flag, int value)
case SOLVER_FLAG_YUM_OBSOLETES:
solv->do_yum_obsoletes = value;
break;
+ case SOLVER_FLAG_NEED_UPDATEPROVIDE:
+ solv->needupdateprovide = value;
+ break;
default:
break;
}
return old;
}
-int
-cleandeps_check_mistakes(Solver *solv, int level)
+static int
+cleandeps_check_mistakes(Solver *solv)
{
Pool *pool = solv->pool;
Rule *r;
@@ -1919,8 +1843,6 @@ cleandeps_check_mistakes(Solver *solv, int level)
solver_reenablepolicyrules_cleandeps(solv, i);
mademistake = 1;
}
- if (mademistake)
- solver_reset(solv);
return mademistake;
}
@@ -2093,7 +2015,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
int i, j, n;
Solvable *s;
Pool *pool = solv->pool;
- Id p, pp, *dp;
+ Id p, pp, *dp, postponed;
int minimizationsteps;
int installedpos = solv->installed ? solv->installed->start : 0;
@@ -2104,10 +2026,8 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
solver_printruleclass(solv, SOLV_DEBUG_RULE_CREATION, solv->rules + i);
}
- POOL_DEBUG(SOLV_DEBUG_SOLVER, "initial decisions: %d\n", solv->decisionq.count);
-
/* start SAT algorithm */
- level = 1;
+ level = 0;
systemlevel = level + 1;
POOL_DEBUG(SOLV_DEBUG_SOLVER, "solving...\n");
@@ -2116,7 +2036,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
/*
* here's the main loop:
- * 1) propagate new decisions (only needed once)
+ * 1) decide assertion rules and propagate
* 2) fulfill jobs
* 3) try to keep installed packages
* 4) fulfill all unresolved rules
@@ -2132,16 +2052,24 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
/*
* initial propagation of the assertions
*/
- if (level == 1)
+ if (level <= 0)
{
- POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "propagating (propagate_index: %d; size decisionq: %d)...\n", solv->propagate_index, solv->decisionq.count);
+ if (level < 0)
+ break;
+ makeruledecisions(solv);
+ level = 1;
+ if (!disablerules && solv->problems.count)
+ {
+ level = -1;
+ break;
+ }
+ POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "initial propagate (propagate_index: %d; size decisionq: %d)...\n", solv->propagate_index, solv->decisionq.count);
if ((r = propagate(solv, level)) != 0)
{
- if (analyze_unsolvable(solv, r, disablerules))
- continue;
- level = 0;
- break; /* unsolvable */
+ level = analyze_unsolvable(solv, r, disablerules);
+ continue;
}
+ systemlevel = level + 1;
}
/*
@@ -2152,11 +2080,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
olevel = level;
level = resolve_jobrules(solv, level, disablerules, &dq);
if (level < olevel)
- {
- if (level == 0)
- break; /* unsolvable */
- continue;
- }
+ continue;
systemlevel = level + 1;
}
@@ -2273,15 +2197,9 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
{
olevel = level;
level = selectandinstall(solv, level, &dq, disablerules, rr - solv->rules);
- if (level == 0)
- {
- queue_free(&dq);
- queue_free(&dqs);
- return;
- }
if (level <= olevel)
{
- if (level == 1 || level < passlevel)
+ if (level < passlevel)
break; /* trouble */
if (level < olevel)
n = installed->start; /* redo all */
@@ -2308,11 +2226,9 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
POOL_DEBUG(SOLV_DEBUG_POLICY, "keeping %s\n", pool_solvid2str(pool, i));
level = setpropagatelearn(solv, level, i, disablerules, r - solv->rules);
}
- if (level == 0)
- break;
if (level <= olevel)
{
- if (level == 1 || level < passlevel)
+ if (level < passlevel)
break; /* trouble */
if (level < olevel)
n = installed->start; /* redo all */
@@ -2329,8 +2245,6 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
}
installedpos = installed->start; /* reset installedpos */
}
- if (level == 0)
- break; /* unsolvable */
systemlevel = level + 1;
if (pass < 2)
continue; /* had trouble, retry */
@@ -2343,11 +2257,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
olevel = level;
level = resolve_jobrules(solv, level, disablerules, &dq);
if (level < olevel)
- {
- if (level == 0)
- break; /* unsolvable */
- continue;
- }
+ continue;
systemlevel = level + 1;
}
@@ -2360,8 +2270,17 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
if (!solv->decisioncnt_resolve)
solv->decisioncnt_resolve = solv->decisionq.count;
POOL_DEBUG(SOLV_DEBUG_POLICY, "deciding unresolved rules\n");
- for (i = 1, n = 1; n < solv->nrules; i++, n++)
+ postponed = 0;
+ for (i = 1, n = 1; ; i++, n++)
{
+ if (n >= solv->nrules)
+ {
+ if (postponed <= 0)
+ break;
+ i = postponed;
+ postponed = -1;
+ n = 1;
+ }
if (i == solv->nrules)
i = 1;
r = solv->rules + i;
@@ -2443,22 +2362,27 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
}
}
+ if (dq.count > 1 && postponed >= 0)
+ {
+ policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE_NOREORDER);
+ if (dq.count > 1)
+ {
+ if (!postponed)
+ postponed = i;
+ continue;
+ }
+ }
+
olevel = level;
level = selectandinstall(solv, level, &dq, disablerules, r - solv->rules);
- if (level == 0)
- break; /* unsolvable */
- if (level < systemlevel || level == 1)
+ if (level < systemlevel)
break; /* trouble */
/* something changed, so look at all rules again */
n = 0;
}
- if (n != solv->nrules) /* ran into trouble? */
- {
- if (level == 0)
- break; /* unsolvable */
- continue; /* start over */
- }
+ if (n < solv->nrules) /* ran into trouble? */
+ continue; /* start over */
/* decide leftover cleandeps packages */
if (solv->cleandepsmap.size && solv->installed)
@@ -2586,39 +2510,15 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
/* filter out all already supplemented packages if requested */
if (!solv->addalreadyrecommended && dqs.count)
{
- /* turn off all new packages */
- for (i = 0; i < solv->decisionq.count; i++)
- {
- p = solv->decisionq.elements[i];
- if (p < 0)
- continue;
- s = pool->solvables + p;
- if (s->repo && s->repo != solv->installed)
- solv->decisionmap[p] = -solv->decisionmap[p];
- }
/* filter out old supplements */
for (i = j = 0; i < dqs.count; i++)
{
p = dqs.elements[i];
s = pool->solvables + p;
- if (!s->supplements)
- continue;
- if (!solver_is_supplementing(solv, s))
- dqs.elements[j++] = p;
- else if (solv->installsuppdepq && solver_check_installsuppdepq(solv, s))
+ if (s->supplements && solver_is_supplementing_alreadyinstalled(solv, s))
dqs.elements[j++] = p;
}
dqs.count = j;
- /* undo turning off */
- for (i = 0; i < solv->decisionq.count; i++)
- {
- p = solv->decisionq.elements[i];
- if (p < 0)
- continue;
- s = pool->solvables + p;
- if (s->repo && s->repo != solv->installed)
- solv->decisionmap[p] = -solv->decisionmap[p];
- }
}
/* multiversion doesn't mix well with supplements.
@@ -2665,8 +2565,6 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
else
POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
level = setpropagatelearn(solv, level, p, 0, 0);
- if (level == 0)
- break;
continue; /* back to main loop */
}
@@ -2693,8 +2591,6 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
if (i < dqs.count || solv->decisionq.count < decisioncount)
{
map_free(&dqmap);
- if (level == 0)
- break;
continue;
}
@@ -2749,8 +2645,6 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
break; /* had a problem above, quit loop */
}
map_free(&dqmap);
- if (level == 0)
- break;
continue; /* back to main loop so that all deps are checked */
}
}
@@ -2780,11 +2674,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
break;
}
if (installedone || i < solv->orphaned.count)
- {
- if (level == 0)
- break;
- continue; /* back to main loop */
- }
+ continue; /* back to main loop */
for (i = 0; i < solv->orphaned.count; i++)
{
p = solv->orphaned.elements[i];
@@ -2797,11 +2687,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
break;
}
if (i < solv->orphaned.count)
- {
- if (level == 0)
- break;
- continue; /* back to main loop */
- }
+ continue; /* back to main loop */
if (solv->brokenorphanrules)
{
solver_check_brokenorphanrules(solv, &dq);
@@ -2817,8 +2703,6 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
if (level < olevel)
break;
}
- if (level == 0)
- break;
continue;
}
}
@@ -2841,21 +2725,14 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
break;
}
if (p < solv->installed->end)
- {
- if (level == 0)
- break;
- continue; /* back to main loop */
- }
+ continue; /* back to main loop */
}
- if (solv->installed && solv->cleandepsmap.size)
+ if (solv->installed && solv->cleandepsmap.size && cleandeps_check_mistakes(solv))
{
- if (cleandeps_check_mistakes(solv, level))
- {
- level = 1; /* restart from scratch */
- systemlevel = level + 1;
- continue;
- }
+ solver_reset(solv);
+ level = 0; /* restart from scratch */
+ continue;
}
if (solv->solution_callback)
@@ -2884,8 +2761,6 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
while (i > 0 && solv->branches.elements[i - 1] > 0)
i--;
level = takebranch(solv, i, endi, "branching", disablerules);
- if (level == 0)
- break;
continue;
}
}
@@ -2941,8 +2816,6 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
{
minimizationsteps++;
level = takebranch(solv, lasti, lastiend, "minimizing", disablerules);
- if (level == 0)
- break;
continue; /* back to main loop */
}
}
@@ -2955,7 +2828,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
POOL_DEBUG(SOLV_DEBUG_STATS, "done solving.\n\n");
queue_free(&dq);
queue_free(&dqs);
- if (level == 0)
+ if (level < 0)
{
/* unsolvable */
solv->decisioncnt_jobs = solv->decisionq.count;
@@ -3158,9 +3031,9 @@ solver_calculate_noobsmap(Pool *pool, Queue *job, Map *multiversionmap)
* add a rule created by a job, record job number and weak flag
*/
static inline void
-solver_addjobrule(Solver *solv, Id p, Id d, Id job, int weak)
+solver_addjobrule(Solver *solv, Id p, Id p2, Id d, Id job, int weak)
{
- solver_addrule(solv, p, d);
+ solver_addrule(solv, p, p2, d);
queue_push(&solv->ruletojob, job);
if (weak)
queue_push(&solv->weakruleq, solv->nrules - 1);
@@ -3360,6 +3233,39 @@ deduceq2addedmap(Solver *solv, Map *addedmap)
}
}
+#ifdef ENABLE_COMPLEX_DEPS
+static int
+add_complex_jobrules(Solver *solv, Id dep, int flags, int jobidx, int weak)
+{
+ Pool *pool = solv->pool;
+ Queue bq;
+ int i, j;
+
+ queue_init(&bq);
+ i = pool_normalize_complex_dep(pool, dep, &bq, flags | CPLXDEPS_EXPAND);
+ if (i == 0 || i == 1)
+ {
+ queue_free(&bq);
+ if (i == 0)
+ solver_addjobrule(solv, -SYSTEMSOLVABLE, 0, 0, jobidx, weak);
+ return 0;
+ }
+ for (i = 0; i < bq.count; i++)
+ {
+ if (!bq.elements[i])
+ continue;
+ for (j = 0; bq.elements[i + j + 1]; j++)
+ ;
+ if (j > 1)
+ solver_addjobrule(solv, bq.elements[i], 0, pool_ids2whatprovides(pool, bq.elements + i + 1, j), jobidx, weak);
+ else
+ solver_addjobrule(solv, bq.elements[i], bq.elements[i + 1], 0, jobidx, weak);
+ i += j + 1;
+ }
+ queue_free(&bq);
+ return 1;
+}
+#endif
/*
*
@@ -3637,7 +3543,7 @@ solver_solve(Solver *solv, Queue *job)
if (how & SOLVER_FORCEBEST)
solv->bestupdatemap_all = 1;
}
- if (!solv->dupmap_all)
+ if (!solv->dupmap_all || solv->allowuninstall)
hasdupjob = 1;
break;
default:
@@ -3651,10 +3557,7 @@ solver_solve(Solver *solv, Queue *job)
* add rules for suggests, enhances
*/
oldnrules = solv->nrules;
- if (hasdupjob && !solv->updatemap_all && solv->dosplitprovides && solv->installed)
- solver_addpkgrulesforweak(solv, &addedmap);
- else
- solver_addpkgrulesforweak(solv, &addedmap);
+ solver_addpkgrulesforweak(solv, &addedmap);
POOL_DEBUG(SOLV_DEBUG_STATS, "added %d pkg rules because of weak dependencies\n", solv->nrules - oldnrules);
#ifdef ENABLE_LINKED_PKGS
@@ -3719,7 +3622,7 @@ solver_solve(Solver *solv, Queue *job)
{
if (s->repo != installed)
{
- solver_addrule(solv, 0, 0); /* create dummy rule */
+ solver_addrule(solv, 0, 0, 0); /* create dummy rule */
continue;
}
solver_addupdaterule(solv, s, 1); /* allow s to be updated */
@@ -3747,7 +3650,7 @@ solver_solve(Solver *solv, Queue *job)
if (s->repo != installed)
{
- solver_addrule(solv, 0, 0); /* create dummy rule */
+ solver_addrule(solv, 0, 0, 0); /* create dummy rule */
continue;
}
solver_addupdaterule(solv, s, 0); /* allowall = 0: downgrades not allowed */
@@ -3798,6 +3701,15 @@ solver_solve(Solver *solv, Queue *job)
p = what;
d = 0;
}
+#ifdef ENABLE_COMPLEX_DEPS
+ else if ((select == SOLVER_SOLVABLE_PROVIDES || select == SOLVER_SOLVABLE_NAME) && pool_is_complex_dep(pool, what))
+ {
+ if (add_complex_jobrules(solv, what, select == SOLVER_SOLVABLE_NAME ? CPLXDEPS_NAME : 0, i, weak))
+ if (how & SOLVER_FORCEBEST)
+ hasbestinstalljob = 1;
+ break;
+ }
+#endif
else
{
queue_empty(&q);
@@ -3828,7 +3740,7 @@ solver_solve(Solver *solv, Queue *job)
queue_pushunique(solv->installsuppdepq, rd->evr == 0 ? rd->name : what);
}
}
- solver_addjobrule(solv, p, d, i, weak);
+ solver_addjobrule(solv, p, 0, d, i, weak);
if (how & SOLVER_FORCEBEST)
hasbestinstalljob = 1;
break;
@@ -3841,21 +3753,29 @@ solver_solve(Solver *solv, Queue *job)
if (select == SOLVER_SOLVABLE_ALL) /* hmmm ;) */
{
FOR_POOL_SOLVABLES(p)
- solver_addjobrule(solv, -p, 0, i, weak);
+ solver_addjobrule(solv, -p, 0, 0, i, weak);
}
else if (select == SOLVER_SOLVABLE_REPO)
{
Repo *repo = pool_id2repo(pool, what);
if (repo)
FOR_REPO_SOLVABLES(repo, p, s)
- solver_addjobrule(solv, -p, 0, i, weak);
+ solver_addjobrule(solv, -p, 0, 0, i, weak);
+ }
+#ifdef ENABLE_COMPLEX_DEPS
+ else if ((select == SOLVER_SOLVABLE_PROVIDES || select == SOLVER_SOLVABLE_NAME) && pool_is_complex_dep(pool, what))
+ {
+ /* no special "erase a specific solvable" handling? */
+ add_complex_jobrules(solv, what, select == SOLVER_SOLVABLE_NAME ? (CPLXDEPS_NAME | CPLXDEPS_TODNF | CPLXDEPS_INVERT) : (CPLXDEPS_TODNF | CPLXDEPS_INVERT), i, weak);
+ break;
}
+#endif
FOR_JOB_SELECT(p, pp, select, what)
{
s = pool->solvables + p;
if (installed && s->repo == installed)
name = !name ? s->name : -1;
- solver_addjobrule(solv, -p, 0, i, weak);
+ solver_addjobrule(solv, -p, 0, 0, i, weak);
}
/* special case for "erase a specific solvable": we also
* erase all other solvables with that name, so that they
@@ -3883,7 +3803,7 @@ solver_solve(Solver *solv, Queue *job)
if (solv->rules[j].p == -p)
break;
if (j == k)
- solver_addjobrule(solv, -p, 0, i, weak); /* remove by id */
+ solver_addjobrule(solv, -p, 0, 0, i, weak); /* remove by id */
}
}
break;
@@ -3909,17 +3829,17 @@ solver_solve(Solver *solv, Queue *job)
if (select == SOLVER_SOLVABLE_ALL)
{
FOR_POOL_SOLVABLES(p)
- solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, i, weak);
+ solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
}
else if (select == SOLVER_SOLVABLE_REPO)
{
Repo *repo = pool_id2repo(pool, what);
if (repo)
FOR_REPO_SOLVABLES(repo, p, s)
- solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, i, weak);
+ solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
}
FOR_JOB_SELECT(p, pp, select, what)
- solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, i, weak);
+ solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
break;
case SOLVER_DISTUPGRADE:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: distupgrade %s\n", solver_select2str(pool, select, what));
@@ -4009,11 +3929,14 @@ solver_solve(Solver *solv, Queue *job)
POOL_DEBUG(SOLV_DEBUG_STATS, "overall rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024);
/* create weak map */
- map_init(&solv->weakrulemap, solv->nrules);
- for (i = 0; i < solv->weakruleq.count; i++)
+ if (solv->weakruleq.count)
{
- p = solv->weakruleq.elements[i];
- MAPSET(&solv->weakrulemap, p);
+ map_grow(&solv->weakrulemap, solv->nrules);
+ for (i = 0; i < solv->weakruleq.count; i++)
+ {
+ p = solv->weakruleq.elements[i];
+ MAPSET(&solv->weakrulemap, p);
+ }
}
/* enable cleandepsmap creation if we have updatepkgs */
@@ -4045,10 +3968,6 @@ solver_solve(Solver *solv, Queue *job)
if (solv->dupmap_all && solv->orphaned.count && solv->break_orphans)
solver_breakorphans(solv);
- /* make initial decisions based on assertion rules */
- makeruledecisions(solv);
- POOL_DEBUG(SOLV_DEBUG_SOLVER, "problems so far: %d\n", solv->problems.count);
-
/*
* ********************************************
* solve!
@@ -4665,21 +4584,69 @@ get_userinstalled_cmp_names(const void *ap, const void *bp, void *dp)
return strcmp(pool_id2str(pool, *(Id *)ap), pool_id2str(pool, *(Id *)bp));
}
+static int
+get_userinstalled_cmp_namearch(const void *ap, const void *bp, void *dp)
+{
+ Pool *pool = dp;
+ int r;
+ r = strcmp(pool_id2str(pool, ((Id *)ap)[0]), pool_id2str(pool, ((Id *)bp)[0]));
+ if (r)
+ return r;
+ return strcmp(pool_id2str(pool, ((Id *)ap)[1]), pool_id2str(pool, ((Id *)bp)[1]));
+}
+
static void
get_userinstalled_sort_uniq(Pool *pool, Queue *q, int flags)
{
- Id lastp = -1;
+ Id lastp = -1, lasta = -1;
int i, j;
- if ((flags & GET_USERINSTALLED_NAMES) != 0)
+ if (q->count < ((flags & GET_USERINSTALLED_NAMEARCH) ? 4 : 2))
+ return;
+ if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
+ solv_sort(q->elements, q->count / 2, 2 * sizeof(Id), get_userinstalled_cmp_namearch, pool);
+ else if ((flags & GET_USERINSTALLED_NAMES) != 0)
solv_sort(q->elements, q->count, sizeof(Id), get_userinstalled_cmp_names, pool);
else
solv_sort(q->elements, q->count, sizeof(Id), get_userinstalled_cmp, 0);
- for (i = j = 0; i < q->count; i++)
- if (q->elements[i] != lastp)
- q->elements[j++] = lastp = q->elements[i];
+ if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
+ {
+ for (i = j = 0; i < q->count; i += 2)
+ if (q->elements[i] != lastp || q->elements[i + 1] != lasta)
+ {
+ q->elements[j++] = lastp = q->elements[i];
+ q->elements[j++] = lasta = q->elements[i + 1];
+ }
+ }
+ else
+ {
+ for (i = j = 0; i < q->count; i++)
+ if (q->elements[i] != lastp)
+ q->elements[j++] = lastp = q->elements[i];
+ }
queue_truncate(q, j);
}
+static void
+namearch2solvables(Pool *pool, Queue *q, Queue *qout, int job)
+{
+ int i;
+ if (!pool->installed)
+ return;
+ for (i = 0; i < q->count; i += 2)
+ {
+ Id p, pp, name = q->elements[i], arch = q->elements[i + 1];
+ FOR_PROVIDES(p, pp, name)
+ {
+ Solvable *s = pool->solvables + p;
+ if (s->repo != pool->installed || s->name != name || (arch && s->arch != arch))
+ continue;
+ if (job)
+ queue_push(qout, job);
+ queue_push(qout, p);
+ }
+ }
+}
+
void
solver_get_userinstalled(Solver *solv, Queue *q, int flags)
{
@@ -4789,8 +4756,20 @@ solver_get_userinstalled(Solver *solv, Queue *q, int flags)
}
}
map_free(&userinstalled);
- /* convert to names if asked */
- if ((flags & GET_USERINSTALLED_NAMES) != 0)
+
+ /* convert to desired output format */
+ if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
+ {
+ int qcount = q->count;
+ queue_insertn(q, 0, qcount, 0);
+ for (i = j = 0; i < qcount; i++)
+ {
+ s = pool->solvables + q->elements[i + qcount];
+ q->elements[j++] = s->name;
+ q->elements[j++] = s->arch;
+ }
+ }
+ else if ((flags & GET_USERINSTALLED_NAMES) != 0)
{
for (i = 0; i < q->count; i++)
{
@@ -4799,9 +4778,9 @@ solver_get_userinstalled(Solver *solv, Queue *q, int flags)
}
}
/* sort and unify */
- if (q->count > 1)
- get_userinstalled_sort_uniq(pool, q, flags);
- /* invert if asked */
+ get_userinstalled_sort_uniq(pool, q, flags);
+
+ /* invert if asked for */
if ((flags & GET_USERINSTALLED_INVERTED) != 0)
{
/* first generate queue with all installed packages */
@@ -4815,30 +4794,52 @@ solver_get_userinstalled(Solver *solv, Queue *q, int flags)
s = pool->solvables + p;
if (!s->repo)
continue;
- if ((flags & GET_USERINSTALLED_NAMES) != 0)
+ if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
+ queue_push2(&invq, s->name, s->arch);
+ else if ((flags & GET_USERINSTALLED_NAMES) != 0)
queue_push(&invq, s->name);
else
queue_push(&invq, p);
}
/* push q on invq, just in case... */
queue_insertn(&invq, invq.count, q->count, q->elements);
- if (invq.count > 1)
- get_userinstalled_sort_uniq(pool, &invq, flags);
+ get_userinstalled_sort_uniq(pool, &invq, flags);
/* subtract queues (easy as they are sorted and invq is a superset of q) */
- if (q->count)
+ if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
{
- for (i = j = 0; i < invq.count; i++)
- if (invq.elements[i] == q->elements[j])
- {
- invq.elements[i] = 0;
- if (++j >= q->count)
- break;
- }
- queue_empty(q);
+ if (q->count)
+ {
+ for (i = j = 0; i < invq.count; i += 2)
+ if (invq.elements[i] == q->elements[j] && invq.elements[i + 1] == q->elements[j + 1])
+ {
+ invq.elements[i] = invq.elements[i + 1] = 0;
+ j += 2;
+ if (j >= q->count)
+ break;
+ }
+ queue_empty(q);
+ }
+ for (i = 0; i < invq.count; i += 2)
+ if (invq.elements[i])
+ queue_push2(q, invq.elements[i], invq.elements[i + 1]);
+ }
+ else
+ {
+ if (q->count)
+ {
+ for (i = j = 0; i < invq.count; i++)
+ if (invq.elements[i] == q->elements[j])
+ {
+ invq.elements[i] = 0;
+ if (++j >= q->count)
+ break;
+ }
+ queue_empty(q);
+ }
+ for (i = 0; i < invq.count; i++)
+ if (invq.elements[i])
+ queue_push(q, invq.elements[i]);
}
- for (i = j = 0; i < invq.count; i++)
- if (invq.elements[i])
- queue_push(q, invq.elements[i]);
queue_free(&invq);
}
}
@@ -4848,7 +4849,7 @@ pool_add_userinstalled_jobs(Pool *pool, Queue *q, Queue *job, int flags)
{
int i;
- if (flags & GET_USERINSTALLED_INVERTED)
+ if ((flags & GET_USERINSTALLED_INVERTED) != 0)
{
Queue invq;
Id p, lastid;
@@ -4857,13 +4858,25 @@ pool_add_userinstalled_jobs(Pool *pool, Queue *q, Queue *job, int flags)
if (!pool->installed)
return;
queue_init(&invq);
+ if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
+ flags &= ~GET_USERINSTALLED_NAMES; /* just in case */
FOR_REPO_SOLVABLES(pool->installed, p, s)
queue_push(&invq, flags & GET_USERINSTALLED_NAMES ? s->name : p);
- queue_insertn(&invq, invq.count, q->count, q->elements);
- if (invq.count > 1)
- get_userinstalled_sort_uniq(pool, &invq, flags);
- /* now the fun part, add q again, sort, and remove all dups */
- queue_insertn(&invq, invq.count, q->count, q->elements);
+ if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
+ {
+ /* for namearch we convert to packages */
+ namearch2solvables(pool, q, &invq, 0);
+ get_userinstalled_sort_uniq(pool, &invq, flags);
+ namearch2solvables(pool, q, &invq, 0);
+ flags = 0;
+ }
+ else
+ {
+ queue_insertn(&invq, invq.count, q->count, q->elements);
+ get_userinstalled_sort_uniq(pool, &invq, flags);
+ /* now the fun part, add q again, sort, and remove all dups */
+ queue_insertn(&invq, invq.count, q->count, q->elements);
+ }
if (invq.count > 1)
{
if ((flags & GET_USERINSTALLED_NAMES) != 0)
@@ -4891,8 +4904,13 @@ pool_add_userinstalled_jobs(Pool *pool, Queue *q, Queue *job, int flags)
}
else
{
- for (i = 0; i < q->count; i++)
- queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), q->elements[i]);
+ if (flags & GET_USERINSTALLED_NAMEARCH)
+ namearch2solvables(pool, q, job, SOLVER_USERINSTALLED | SOLVER_SOLVABLE);
+ else
+ {
+ for (i = 0; i < q->count; i++)
+ queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), q->elements[i]);
+ }
}
}
diff --git a/src/solver.h b/src/solver.h
index 1cb9f15..1a47ae0 100644
--- a/src/solver.h
+++ b/src/solver.h
@@ -155,6 +155,7 @@ struct _Solver {
int allowvendorchange; /* allow to change vendor of installed solvables */
int allowuninstall; /* allow removal of installed solvables */
int noupdateprovide; /* true: update packages needs not to provide old package */
+ int needupdateprovide; /* true: update packages must provide old package */
int dosplitprovides; /* true: consider legacy split provides */
int dontinstallrecommended; /* true: do not install recommended packages */
int addalreadyrecommended; /* true: also install recommended packages that were already recommended by the installed packages */
@@ -295,9 +296,11 @@ typedef struct _Solver Solver;
#define SOLVER_FLAG_BREAK_ORPHANS 19
#define SOLVER_FLAG_FOCUS_INSTALLED 20
#define SOLVER_FLAG_YUM_OBSOLETES 21
+#define SOLVER_FLAG_NEED_UPDATEPROVIDE 22
-#define GET_USERINSTALLED_NAMES (1 << 0) /* package names instead if ids */
+#define GET_USERINSTALLED_NAMES (1 << 0) /* package names instead of ids */
#define GET_USERINSTALLED_INVERTED (1 << 1) /* autoinstalled */
+#define GET_USERINSTALLED_NAMEARCH (1 << 2) /* package/arch tuples instead of ids */
#define SOLVER_ALTERNATIVE_TYPE_RULE 1
#define SOLVER_ALTERNATIVE_TYPE_RECOMMENDS 2
diff --git a/src/solver_private.h b/src/solver_private.h
index f30b03a..f8df8c7 100644
--- a/src/solver_private.h
+++ b/src/solver_private.h
@@ -16,7 +16,6 @@
extern void solver_run_sat(Solver *solv, int disablerules, int doweak);
extern void solver_reset(Solver *solv);
-extern int solver_dep_installed(Solver *solv, Id dep);
extern int solver_splitprovides(Solver *solv, Id dep, Map *m);
static inline int
@@ -42,8 +41,6 @@ solver_dep_fulfilled(Solver *solv, Id dep)
}
if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
return solver_splitprovides(solv, rd->evr, 0);
- if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
- return solver_dep_installed(solv, rd->evr);
}
FOR_PROVIDES(p, pp, dep)
{
diff --git a/src/solverdebug.c b/src/solverdebug.c
index 3e84046..39f5d78 100644
--- a/src/solverdebug.c
+++ b/src/solverdebug.c
@@ -108,7 +108,7 @@ solver_printruleclass(Solver *solv, int type, Rule *r)
Id p = r - solv->rules;
assert(p >= 0);
if (p < solv->learntrules)
- if (MAPTST(&solv->weakrulemap, p))
+ if (solv->weakrulemap.size && MAPTST(&solv->weakrulemap, p))
POOL_DEBUG(type, "WEAK ");
if (solv->learntrules && p >= solv->learntrules)
POOL_DEBUG(type, "LEARNT ");