summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2022-09-21 09:39:09 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2022-09-21 09:39:09 +0900
commit2d757ccc60324e7bfcc07f6f46d7f38e30642fcb (patch)
tree110f2ad79b7046a6e0a1415e3e17c223169d4ca7 /src
parent11600c0259c8cd27ad8c87b16421e65030b4b126 (diff)
downloadlibsolv-2d757ccc60324e7bfcc07f6f46d7f38e30642fcb.tar.gz
libsolv-2d757ccc60324e7bfcc07f6f46d7f38e30642fcb.tar.bz2
libsolv-2d757ccc60324e7bfcc07f6f46d7f38e30642fcb.zip
Imported Upstream version 0.7.22upstream/0.7.22
Diffstat (limited to 'src')
-rw-r--r--src/knownid.h3
-rw-r--r--src/libsolv.ver1
-rw-r--r--src/order.c196
-rw-r--r--src/repo_write.c7
-rw-r--r--src/rules.c169
-rw-r--r--src/solver.c45
-rw-r--r--src/transaction.h2
7 files changed, 250 insertions, 173 deletions
diff --git a/src/knownid.h b/src/knownid.h
index d131e78..2bb27b2 100644
--- a/src/knownid.h
+++ b/src/knownid.h
@@ -270,7 +270,8 @@ KNOWNID(SOLVABLE_TRACK_FEATURES, "solvable:track_features"), /* conda */
KNOWNID(SOLVABLE_ISDEFAULT, "solvable:isdefault"),
KNOWNID(SOLVABLE_LANGONLY, "solvable:langonly"),
-KNOWNID(UPDATE_COLLECTIONLIST, "update:collectionlist"), /* list of UPDATE_COLLECTION (actually packages) and UPDATE_MODULE */
+KNOWNID(UPDATE_COLLECTIONLIST, "update:collectionlist"), /* list of UPDATE_COLLECTION (actually packages) and UPDATE_MODULE */
+KNOWNID(SOLVABLE_MULTIARCH, "solvable:multiarch"), /* debian multi-arch field */
KNOWNID(ID_NUM_INTERNAL, 0)
diff --git a/src/libsolv.ver b/src/libsolv.ver
index 51819fb..c77f8d3 100644
--- a/src/libsolv.ver
+++ b/src/libsolv.ver
@@ -434,6 +434,7 @@ SOLV_1.0 {
transaction_order_add_choices;
transaction_order_get_cycle;
transaction_order_get_cycleids;
+ transaction_order_get_edges;
transaction_print;
transaction_type;
local:
diff --git a/src/order.c b/src/order.c
index a6be968..f36e446 100644
--- a/src/order.c
+++ b/src/order.c
@@ -35,19 +35,23 @@ struct s_TransactionOrderdata {
Id *invedgedata;
int ninvedgedata;
Queue *cycles;
+ Queue *edgedataq; /* from SOLVER_TRANSACTION_KEEP_ORDEREDGES */
};
#define TYPE_BROKEN (1<<0)
#define TYPE_CON (1<<1)
-#define TYPE_REQ_P (1<<2)
-#define TYPE_PREREQ_P (1<<3)
+/* uninstall edges */
+#define TYPE_REQ_UI (1<<4)
+#define TYPE_PREREQ_UI (1<<5)
+#define TYPE_REQ_UU (1<<6)
+#define TYPE_PREREQ_UU (1<<7)
-#define TYPE_SUG (1<<4)
-#define TYPE_REC (1<<5)
-
-#define TYPE_REQ (1<<6)
-#define TYPE_PREREQ (1<<7)
+/* install edges */
+#define TYPE_SUG (1<<8)
+#define TYPE_REC (1<<9)
+#define TYPE_REQ (1<<10)
+#define TYPE_PREREQ (1<<11)
#define TYPE_CYCLETAIL (1<<16)
#define TYPE_CYCLEHEAD (1<<17)
@@ -70,6 +74,11 @@ transaction_clone_orderdata(Transaction *trans, Transaction *srctrans)
trans->orderdata->cycles = solv_calloc(1, sizeof(Queue));
queue_init_clone(trans->orderdata->cycles, od->cycles);
}
+ if (od->edgedataq)
+ {
+ trans->orderdata->edgedataq = solv_calloc(1, sizeof(Queue));
+ queue_init_clone(trans->orderdata->edgedataq, od->edgedataq);
+ }
}
void
@@ -85,6 +94,11 @@ transaction_free_orderdata(Transaction *trans)
queue_free(od->cycles);
od->cycles = solv_free(od->cycles);
}
+ if (od->edgedataq)
+ {
+ queue_init(od->edgedataq);
+ od->edgedataq = solv_free(od->edgedataq);
+ }
trans->orderdata = solv_free(trans->orderdata);
}
}
@@ -100,6 +114,7 @@ struct orderdata {
Queue cycles;
Queue cyclesdata;
int ncycles;
+ Queue edgedataq;
};
static void
@@ -212,27 +227,34 @@ addedge(struct orderdata *od, Id from, Id to, int type)
}
static inline int
-havescripts(Pool *pool, Id solvid)
+havescripts(Pool *pool, Id solvid, Queue *ignoreinst)
{
Solvable *s = pool->solvables + solvid;
- const char *dep;
if (s->requires)
{
Id req, *reqp;
- int inpre = 0;
reqp = s->repo->idarraydata + s->requires;
while ((req = *reqp++) != 0)
+ if (req == SOLVABLE_PREREQMARKER)
+ break;
+ if (!req)
+ return 0;
+ while ((req = *reqp++) != 0)
{
- if (req == SOLVABLE_PREREQMARKER)
+ const char *dep = pool_id2str(pool, req);
+ if (*dep == '/' && strcmp(dep, "/sbin/ldconfig") != 0)
{
- inpre = 1;
- continue;
+ if (ignoreinst && ignoreinst->count)
+ {
+ int i;
+ for (i = 0; i < ignoreinst->count; i++)
+ if (req == ignoreinst->elements[i])
+ break;
+ if (i < ignoreinst->count)
+ continue;
+ }
+ return 1;
}
- if (!inpre)
- continue;
- dep = pool_id2str(pool, req);
- if (*dep == '/' && strcmp(dep, "/sbin/ldconfig") != 0)
- return 1;
}
}
return 0;
@@ -247,7 +269,7 @@ addsolvableedges(struct orderdata *od, Solvable *s)
int i, j, pre, numins;
Repo *installed = pool->installed;
Solvable *s2;
- Queue depq;
+ Queue depq, ignoreinst;
int provbyinst;
#if 0
@@ -255,9 +277,20 @@ addsolvableedges(struct orderdata *od, Solvable *s)
#endif
p = s - pool->solvables;
queue_init(&depq);
+ queue_init(&ignoreinst);
if (s->requires)
{
Id req, *reqp;
+ if (installed && s->repo == installed)
+ {
+ reqp = s->repo->idarraydata + s->requires;
+ while ((req = *reqp++) != 0)
+ if (req == SOLVABLE_PREREQMARKER)
+ {
+ solvable_lookup_idarray(s, SOLVABLE_PREREQ_IGNOREINST, &ignoreinst);
+ break;
+ }
+ }
reqp = s->repo->idarraydata + s->requires;
pre = TYPE_REQ;
while ((req = *reqp++) != 0)
@@ -267,6 +300,16 @@ addsolvableedges(struct orderdata *od, Solvable *s)
pre = TYPE_PREREQ;
continue;
}
+ if (pre == TYPE_PREREQ && ignoreinst.count)
+ {
+ /* check if this req is filtered. assumes that ignoreinst.count is small */
+ int i;
+ for (i = 0; i < ignoreinst.count; i++)
+ if (req == ignoreinst.elements[i])
+ break;
+ if (i < ignoreinst.count)
+ continue;
+ }
queue_empty(&depq);
numins = 0; /* number of packages to be installed providing it */
provbyinst = 0; /* provided by kept package */
@@ -300,9 +343,9 @@ addsolvableedges(struct orderdata *od, Solvable *s)
queue_pushunique(&depq, p2);
}
}
- if (provbyinst)
+ if (provbyinst && s->repo == installed)
{
- /* prune to harmless ->inst edges */
+ /* prune to harmless uninst->inst edges */
for (i = j = 0; i < depq.count; i++)
if (pool->solvables[depq.elements[i]].repo != installed)
depq.elements[j++] = depq.elements[i];
@@ -326,7 +369,7 @@ addsolvableedges(struct orderdata *od, Solvable *s)
#if 0
printf("add interrreq uninst->inst edge (%s -> %s -> %s)\n", pool_solvid2str(pool, depq.elements[i]), pool_dep2str(pool, req), pool_solvid2str(pool, depq.elements[j]));
#endif
- addedge(od, depq.elements[i], depq.elements[j], pre == TYPE_PREREQ ? TYPE_PREREQ_P : TYPE_REQ_P);
+ addedge(od, depq.elements[i], depq.elements[j], pre == TYPE_PREREQ ? TYPE_PREREQ_UI : TYPE_REQ_UI);
}
}
}
@@ -344,7 +387,7 @@ addsolvableedges(struct orderdata *od, Solvable *s)
if (pool->solvables[p2].repo != installed)
{
/* all elements of depq are installs, thus have different TEs */
- if (pool->solvables[p].repo != installed)
+ if (s->repo != installed)
{
#if 0
printf("add inst->inst edge (%s -> %s -> %s)\n", pool_solvid2str(pool, p), pool_dep2str(pool, req), pool_solvid2str(pool, p2));
@@ -356,7 +399,7 @@ addsolvableedges(struct orderdata *od, Solvable *s)
#if 0
printf("add uninst->inst edge (%s -> %s -> %s)\n", pool_solvid2str(pool, p), pool_dep2str(pool, req), pool_solvid2str(pool, p2));
#endif
- addedge(od, p, p2, pre == TYPE_PREREQ ? TYPE_PREREQ_P : TYPE_REQ_P);
+ addedge(od, p, p2, pre == TYPE_PREREQ ? TYPE_PREREQ_UI : TYPE_REQ_UI);
}
}
else
@@ -365,16 +408,16 @@ addsolvableedges(struct orderdata *od, Solvable *s)
continue; /* no inst->uninst edges, please! */
/* uninst -> uninst edge. Those make trouble. Only add if we must */
- if (trans->transaction_installed[p - installed->start] && !havescripts(pool, p))
+ if (trans->transaction_installed[p - installed->start] && !havescripts(pool, p, &ignoreinst))
{
/* p is obsoleted by another package and has no scripts */
- /* we assume that the obsoletor is good enough to replace p */
+ /* we assume that the obsoleter is good enough to replace p */
continue;
}
#if 0
printf("add uninst->uninst edge (%s -> %s -> %s)\n", pool_solvid2str(pool, p), pool_dep2str(pool, req), pool_solvid2str(pool, p2));
#endif
- addedge(od, p2, p, pre == TYPE_PREREQ ? TYPE_PREREQ_P : TYPE_REQ_P);
+ addedge(od, p2, p, pre == TYPE_PREREQ ? TYPE_PREREQ_UU : TYPE_REQ_UU);
}
}
}
@@ -515,9 +558,25 @@ addsolvableedges(struct orderdata *od, Solvable *s)
}
}
}
+ queue_free(&ignoreinst);
queue_free(&depq);
}
+static inline int
+scriptletedge(Pool *pool, struct orderdata *od, Id *cycle, int k)
+{
+ int deg = od->edgedata[cycle[k + 1] + 1];
+ if ((deg & TYPE_REQ_UU) || (deg & TYPE_PREREQ_UU))
+ {
+ /* the UU edges are reverse edges, so we have to check the next element for scripts */
+ if (havescripts(pool, od->tes[cycle[k + 2]].p, 0))
+ return 1;
+ deg &= ~(TYPE_REQ_UU | TYPE_PREREQ_UU);
+ }
+ if (deg && havescripts(pool, od->tes[cycle[k]].p, 0))
+ return 1;
+ return 0;
+}
/* break an edge in a cycle */
static void
@@ -533,23 +592,31 @@ breakcycle(struct orderdata *od, Id *cycle)
for (k = 0; cycle[k + 1]; k += 2)
{
ddeg = od->edgedata[cycle[k + 1] + 1];
+ /* map UU to UI for the comparison */
+ if (ddeg & TYPE_REQ_UU)
+ {
+ ddeg ^= TYPE_REQ_UU;
+ ddeg |= TYPE_REQ_UI;
+ }
+ if (ddeg & TYPE_PREREQ_UU)
+ {
+ ddeg ^= TYPE_PREREQ_UU;
+ ddeg |= TYPE_PREREQ_UI;
+ }
if (ddeg > ddegmax)
ddegmax = ddeg;
if (!k || ddeg < ddegmin)
{
l = k;
ddegmin = ddeg;
- continue;
}
- if (ddeg == ddegmin)
+ else if (ddeg == ddegmin)
{
- if (havescripts(pool, od->tes[cycle[l]].p) && !havescripts(pool, od->tes[cycle[k]].p))
+ if (scriptletedge(pool, od, cycle, l) && !scriptletedge(pool, od, cycle, k))
{
/* prefer k, as l comes from a package with contains scriptlets */
l = k;
- continue;
}
- /* same edge value, check for prereq */
}
}
@@ -573,10 +640,11 @@ breakcycle(struct orderdata *od, Id *cycle)
/* break that edge */
od->edgedata[cycle[l + 1] + 1] |= TYPE_BROKEN;
-#if 1
- if (ddegmin < TYPE_REQ)
+
+ IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS)
+ ;
+ else if (ddegmin < TYPE_REQ)
return;
-#endif
/* cycle recorded, print it */
if (ddegmin >= TYPE_REQ && (ddegmax & TYPE_PREREQ) != 0)
@@ -807,12 +875,7 @@ transaction_order(Transaction *trans, int flags)
POOL_DEBUG(SOLV_DEBUG_STATS, "ordering transaction\n");
/* free old data if present */
if (trans->orderdata)
- {
- struct s_TransactionOrderdata *od = trans->orderdata;
- od->tes = solv_free(od->tes);
- od->invedgedata = solv_free(od->invedgedata);
- trans->orderdata = solv_free(trans->orderdata);
- }
+ transaction_free_orderdata(trans);
/* create a transaction element for every active component */
numte = 0;
@@ -837,6 +900,8 @@ transaction_order(Transaction *trans, int flags)
od.edgedata[0] = 0;
od.nedgedata = 1;
queue_init(&od.cycles);
+ queue_init(&od.cyclesdata);
+ queue_init(&od.edgedataq);
/* initialize TEs */
for (i = 0, te = od.tes + 1; i < tr->count; i++)
@@ -974,6 +1039,14 @@ transaction_order(Transaction *trans, int flags)
#if 0
dump_tes(&od);
#endif
+ if ((flags & SOLVER_TRANSACTION_KEEP_ORDEREDGES) != 0)
+ {
+ queue_insertn(&od.edgedataq, 0, od.nedgedata, od.edgedata);
+ queue_insertn(&od.edgedataq, 0, numte, 0);
+ for (i = 1, te = od.tes + i; i < numte; i++, te++)
+ od.edgedataq.elements[i] = te->edges + numte;
+ }
+
/* all edges are finally set up and there are no cycles, now the easy part.
* Create an ordered transaction */
now = solv_timems(0);
@@ -1143,7 +1216,7 @@ printf("free %s [%d]\n", pool_solvid2str(pool, te2->p), temedianr[od.invedgedata
POOL_DEBUG(SOLV_DEBUG_STATS, "creating new transaction took %d ms\n", solv_timems(now));
POOL_DEBUG(SOLV_DEBUG_STATS, "transaction ordering took %d ms\n", solv_timems(start));
- if ((flags & (SOLVER_TRANSACTION_KEEP_ORDERDATA | SOLVER_TRANSACTION_KEEP_ORDERCYCLES)) != 0)
+ if ((flags & (SOLVER_TRANSACTION_KEEP_ORDERDATA | SOLVER_TRANSACTION_KEEP_ORDERCYCLES | SOLVER_TRANSACTION_KEEP_ORDEREDGES)) != 0)
{
struct s_TransactionOrderdata *tod;
trans->orderdata = tod = solv_calloc(1, sizeof(*trans->orderdata));
@@ -1158,7 +1231,7 @@ printf("free %s [%d]\n", pool_solvid2str(pool, te2->p), temedianr[od.invedgedata
queue_insertn(cycles, cycles->count, od.cycles.count, od.cycles.elements);
queue_push(cycles, od.cycles.count / 4);
}
- if ((flags & SOLVER_TRANSACTION_KEEP_ORDERDATA) != 0)
+ if ((flags & (SOLVER_TRANSACTION_KEEP_ORDERDATA | SOLVER_TRANSACTION_KEEP_ORDEREDGES)) != 0)
{
tod->tes = od.tes;
tod->ntes = numte;
@@ -1167,10 +1240,16 @@ printf("free %s [%d]\n", pool_solvid2str(pool, te2->p), temedianr[od.invedgedata
od.tes = 0;
od.invedgedata = 0;
}
+ if ((flags & SOLVER_TRANSACTION_KEEP_ORDEREDGES) != 0)
+ {
+ Queue *edgedataq = tod->edgedataq = solv_calloc(1, sizeof(Queue));
+ queue_init_clone(edgedataq, &od.edgedataq);
+ }
}
solv_free(od.tes);
solv_free(od.invedgedata);
queue_free(&od.cycles);
+ queue_free(&od.edgedataq);
queue_free(&od.cyclesdata);
}
@@ -1375,7 +1454,7 @@ transaction_check_order(Transaction *trans)
lastins = p;
if (s->repo != pool->installed)
MAPSET(&ins, p);
- if (havescripts(pool, p))
+ if (havescripts(pool, p, 0))
{
MAPZERO(&seen);
transaction_check_pkg(trans, p, p, &ins, &seen, 1, lastins, 0);
@@ -1445,3 +1524,32 @@ transaction_order_get_cycle(Transaction *trans, Id cid, Queue *q)
return severity;
}
+void
+transaction_order_get_edges(Transaction *trans, Id p, Queue *q, int unbroken)
+{
+ struct s_TransactionOrderdata *od = trans->orderdata;
+ struct s_TransactionElement *te;
+ int i;
+ Queue *eq;
+
+ queue_empty(q);
+ if (!od || !od->edgedataq)
+ return;
+ for (i = 1, te = od->tes + i; i < od->ntes; i++, te++)
+ if (te->p == p)
+ break;
+ if (i == od->ntes)
+ return;
+ eq = od->edgedataq;
+ for (i = eq->elements[i]; eq->elements[i]; i += 2)
+ {
+ int type = eq->elements[i + 1];
+ if (unbroken)
+ {
+ type &= ~(TYPE_BROKEN | TYPE_CYCLETAIL | TYPE_CYCLEHEAD);
+ if (type == 0)
+ continue;
+ }
+ queue_push2(q, od->tes[eq->elements[i]].p, type);
+ }
+}
diff --git a/src/repo_write.c b/src/repo_write.c
index b3a6bbc..a73eebf 100644
--- a/src/repo_write.c
+++ b/src/repo_write.c
@@ -1179,9 +1179,9 @@ repowriter_set_userdata(Repowriter *writer, const void *data, int len)
{
writer->userdata = solv_free(writer->userdata);
writer->userdatalen = 0;
- if (len < 0 || len >= 65536)
+ if (len <= 0)
return;
- writer->userdata = len ? solv_memdup(data, len) : 0;
+ writer->userdata = solv_memdup(data, len);
writer->userdatalen = len;
}
@@ -1249,6 +1249,9 @@ repowriter_write(Repowriter *writer, FILE *fp)
Id type_constantid = 0;
+ /* sanity checks */
+ if (writer->userdatalen < 0 || writer->userdatalen >= 65536)
+ return pool_error(pool, -1, "illegal userdata length: %d", writer->userdatalen);
memset(&cbdata, 0, sizeof(cbdata));
cbdata.pool = pool;
diff --git a/src/rules.c b/src/rules.c
index a260c2d..2c56959 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -3255,6 +3255,12 @@ solver_rule2rules(Solver *solv, Id rid, Queue *q, int recursive)
/* check if the newest versions of pi still provides the dependency we're looking for */
+/* pi: installed package
+ * r: rule for the dependency
+ * m: map with all positive elements of r
+ * return 0: at least one provider
+ * return 1: the newest versions do not provide the dependency
+ */
static int
solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m, Queue *q)
{
@@ -3303,94 +3309,6 @@ solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m, Queue *q)
return 1; /* none of the new packages provided it */
}
-static int
-solver_choicerulecheck2(Solver *solv, Id pi, Id pt, Queue *q)
-{
- Pool *pool = solv->pool;
- Rule *ur;
- Id p, pp;
- int i;
-
- if (!q->count || q->elements[0] != pi)
- {
- if (q->count)
- queue_empty(q);
- ur = solv->rules + solv->updaterules + (pi - pool->installed->start);
- if (!ur->p)
- ur = solv->rules + solv->featurerules + (pi - pool->installed->start);
- if (!ur->p)
- return 1; /* orphaned, thus newest */
- queue_push2(q, pi, 0);
- FOR_RULELITERALS(p, pp, ur)
- if (p > 0 && p != pi)
- queue_push(q, p);
- queue_push(q, pi);
- }
- if (q->count <= 3)
- return q->count == 3 && q->elements[2] == pt ? 1 : 0;
- if (!q->elements[1])
- {
- queue_deleten(q, 0, 2);
- policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE);
- queue_unshift(q, 1); /* filter mark */
- queue_unshift(q, pi);
- }
- for (i = 2; i < q->count; i++)
- if (q->elements[i] == pt)
- return 1;
- return 0; /* not newest */
-}
-
-static int
-solver_choicerulecheck3(Solver *solv, Id pt, Queue *q)
-{
- Pool *pool = solv->pool;
- Id p, pp;
- int i;
-
- if (!q->count || q->elements[0] != pt)
- {
- Solvable *s = pool->solvables + pt;
- if (q->count)
- queue_empty(q);
- /* no installed package, so check all with same name */
- queue_push2(q, pt, 0);
- FOR_PROVIDES(p, pp, s->name)
- if (pool->solvables[p].name == s->name && p != pt)
- queue_push(q, p);
- queue_push(q, pt);
- }
- if (q->count <= 3)
- return q->count == 3 && q->elements[2] == pt ? 1 : 0;
- if (!q->elements[1])
- {
- queue_deleten(q, 0, 2);
- policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE);
- queue_unshift(q, 1); /* filter mark */
- queue_unshift(q, pt);
- }
- for (i = 2; i < q->count; i++)
- if (q->elements[i] == pt)
- return 1;
- return 0; /* not newest */
-}
-
-static inline void
-queue_removeelement(Queue *q, Id el)
-{
- int i, j;
- for (i = 0; i < q->count; i++)
- if (q->elements[i] == el)
- break;
- if (i < q->count)
- {
- for (j = i++; i < q->count; i++)
- if (q->elements[i] != el)
- q->elements[j++] = q->elements[i];
- queue_truncate(q, j);
- }
-}
-
static Id
choicerule_find_installed(Pool *pool, Id p)
{
@@ -3439,14 +3357,14 @@ solver_addchoicerules(Solver *solv)
Pool *pool = solv->pool;
Map m, mneg;
Rule *r;
- Queue q, qi, qcheck, qcheck2, infoq;
+ Queue q, qi, qcheck, infoq;
int i, j, rid, havechoice, negcnt;
Id p, d, pp, p2;
Solvable *s;
Id lastaddedp, lastaddedd;
int lastaddedcnt;
unsigned int now;
- int isnewest = 0;
+ int isinstalled;
solv->choicerules = solv->nrules;
if (!pool->installed)
@@ -3458,7 +3376,6 @@ solver_addchoicerules(Solver *solv)
queue_init(&q);
queue_init(&qi);
queue_init(&qcheck);
- queue_init(&qcheck2);
queue_init(&infoq);
map_init(&m, pool->nsolvables);
map_init(&mneg, pool->nsolvables);
@@ -3478,20 +3395,28 @@ solver_addchoicerules(Solver *solv)
if (r->p >= 0 || ((r->d == 0 || r->d == -1) && r->w2 <= 0))
continue; /* only look at requires rules */
/* solver_printrule(solv, SOLV_DEBUG_RESULT, r); */
- queue_empty(&q);
queue_empty(&qi);
havechoice = 0;
+ isinstalled = 0;
FOR_RULELITERALS(p, pp, r)
{
if (p < 0)
- continue;
+ {
+ Solvable *s = pool->solvables - p;
+ p2 = s->repo == pool->installed ? -p : 0;
+ if (p2)
+ {
+ if (!(solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p2 - solv->installed->start))))
+ isinstalled = 1;
+ }
+ continue;
+ }
s = pool->solvables + p;
if (!s->repo)
continue;
if (s->repo == pool->installed)
{
queue_push2(&qi, p, p);
- queue_push(&q, p);
continue;
}
/* find an installed package p2 that we can update/downgrade to p */
@@ -3503,7 +3428,6 @@ solver_addchoicerules(Solver *solv)
if (policy_is_illegal(solv, pool->solvables + p2, s, 0))
continue;
queue_push2(&qi, p2, p);
- queue_push(&q, p);
continue;
}
/* package p is independent of the installed ones */
@@ -3512,47 +3436,31 @@ solver_addchoicerules(Solver *solv)
#if 0
printf("havechoice: %d qcount %d qicount %d\n", havechoice, q.count, qi.count);
#endif
- if (!havechoice || !q.count || !qi.count)
+ if (!havechoice || !qi.count)
continue; /* no choice */
FOR_RULELITERALS(p, pp, r)
if (p > 0)
MAPSET(&m, p);
- isnewest = 1;
- FOR_RULELITERALS(p, pp, r)
- {
- if (p > 0)
- break;
- p2 = choicerule_find_installed(pool, -p);
- if (p2 && !solver_choicerulecheck2(solv, p2, -p, &qcheck2))
- {
- isnewest = 0;
- break;
- }
- if (!p2 && !solver_choicerulecheck3(solv, -p, &qcheck2))
- {
- isnewest = 0;
- break;
- }
- }
- /* do extra checking */
- for (i = j = 0; i < qi.count; i += 2)
+ if (!isinstalled)
{
- p2 = qi.elements[i];
- if (!p2)
- continue;
- if (isnewest && solver_choicerulecheck(solv, p2, r, &m, &qcheck))
+ /* do extra checking for packages related to installed packages */
+ for (i = j = 0; i < qi.count; i += 2)
{
- /* oops, remove element p from q */
- queue_removeelement(&q, qi.elements[i + 1]);
- continue;
+ p2 = qi.elements[i];
+ if (solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p2 - solv->installed->start)))
+ {
+ if (solver_choicerulecheck(solv, p2, r, &m, &qcheck))
+ continue;
+ }
+ qi.elements[j++] = p2;
+ qi.elements[j++] = qi.elements[i + 1];
}
- qi.elements[j++] = p2;
+ queue_truncate(&qi, j);
}
- queue_truncate(&qi, j);
- if (!q.count || !qi.count)
+ if (!qi.count)
{
FOR_RULELITERALS(p, pp, r)
if (p > 0)
@@ -3560,6 +3468,15 @@ solver_addchoicerules(Solver *solv)
continue;
}
+ queue_empty(&q);
+ /* split q from qi */
+ for (i = j = 0; i < qi.count; i += 2)
+ {
+ queue_push(&q, qi.elements[i + 1]);
+ qi.elements[j++] = qi.elements[i];
+ }
+ queue_truncate(&qi, j);
+
/* now check the update rules of the installed package.
* if all packages of the update rules are contained in
@@ -3579,6 +3496,7 @@ solver_addchoicerules(Solver *solv)
break;
if (p)
break;
+ /* speed improvement: only check each package once */
for (j = i + 1; j < qi.count; j++)
if (qi.elements[i] == qi.elements[j])
qi.elements[j] = 0;
@@ -3636,7 +3554,6 @@ solver_addchoicerules(Solver *solv)
queue_free(&q);
queue_free(&qi);
queue_free(&qcheck);
- queue_free(&qcheck2);
queue_free(&infoq);
map_free(&m);
map_free(&mneg);
diff --git a/src/solver.c b/src/solver.c
index 23285ff..28341d6 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -2620,6 +2620,43 @@ resolve_orphaned(Solver *solv, int level, int disablerules, Queue *dq, int *reru
return level;
}
+int
+solver_check_unneeded_choicerules(Solver *solv)
+{
+ Pool *pool = solv->pool;
+ Rule *r, *or;
+ Id p, pp, p2, pp2;
+ int i;
+ int havedisabled = 0;
+
+ /* check if some choice rules could have been broken */
+ for (i = solv->choicerules, r = solv->rules + i; i < solv->choicerules_end; i++, r++)
+ {
+ if (r->d < 0)
+ continue;
+ or = solv->rules + solv->choicerules_info[i - solv->choicerules];
+ if (or->d < 0)
+ continue;
+ FOR_RULELITERALS(p, pp, or)
+ {
+ if (p < 0 || solv->decisionmap[p] <= 0)
+ continue;
+ FOR_RULELITERALS(p2, pp2, r)
+ if (p2 == p)
+ break;
+ if (!p2)
+ {
+ /* did not find p in choice rule, disable it */
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "disabling unneeded choice rule #%d\n", i);
+ solver_disablechoicerules(solv, r);
+ havedisabled = 1;
+ break;
+ }
+ }
+ }
+ return havedisabled;
+}
+
/*-------------------------------------------------------------------
*
* solver_run_sat
@@ -2805,6 +2842,14 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
continue;
}
+ if (solv->choicerules != solv->choicerules_end && solver_check_unneeded_choicerules(solv))
+ {
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "did choice rule minimization, rerunning solver\n");
+ solver_reset(solv);
+ level = 0; /* restart from scratch */
+ continue;
+ }
+
if (solv->solution_callback)
{
solv->solution_callback(solv, solv->solution_callback_data);
diff --git a/src/transaction.h b/src/transaction.h
index 5b01354..001412d 100644
--- a/src/transaction.h
+++ b/src/transaction.h
@@ -86,6 +86,7 @@ typedef struct s_Transaction {
/* order flags */
#define SOLVER_TRANSACTION_KEEP_ORDERDATA (1 << 0)
#define SOLVER_TRANSACTION_KEEP_ORDERCYCLES (1 << 1)
+#define SOLVER_TRANSACTION_KEEP_ORDEREDGES (1 << 2)
/* cycle severities */
#define SOLVER_ORDERCYCLE_HARMLESS 0
@@ -137,6 +138,7 @@ extern void transaction_check_order(Transaction *trans);
/* order cycle introspection */
extern void transaction_order_get_cycleids(Transaction *trans, Queue *q, int minseverity);
extern int transaction_order_get_cycle(Transaction *trans, Id cid, Queue *q);
+extern void transaction_order_get_edges(Transaction *trans, Id p, Queue *q, int unbroken);
extern void transaction_free_orderdata(Transaction *trans);
extern void transaction_clone_orderdata(Transaction *trans, Transaction *srctrans);