summaryrefslogtreecommitdiff
path: root/lib/depends.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/depends.c')
-rw-r--r--lib/depends.c98
1 files changed, 94 insertions, 4 deletions
diff --git a/lib/depends.c b/lib/depends.c
index fc413a903..c73e64953 100644
--- a/lib/depends.c
+++ b/lib/depends.c
@@ -17,6 +17,8 @@
#include "lib/rpmfi_internal.h" /* rpmfiles stuff for now */
#include "lib/misc.h"
+#include "lib/backend/dbiset.h"
+
#include "debug.h"
const char * const RPMVERSION = VERSION;
@@ -510,7 +512,7 @@ int rpmtsAddEraseElement(rpmts ts, Header h, int dboffset)
}
/* Cached rpmdb provide lookup, returns 0 if satisfied, 1 otherwise */
-static int rpmdbProvides(rpmts ts, depCache dcache, rpmds dep)
+static int rpmdbProvides(rpmts ts, depCache dcache, rpmds dep, dbiIndexSet *matches)
{
const char * Name = rpmdsN(dep);
const char * DNEVR = rpmdsDNEVR(dep);
@@ -524,7 +526,7 @@ static int rpmdbProvides(rpmts ts, depCache dcache, rpmds dep)
unsigned int keyhash = 0;
/* See if we already looked this up */
- if (prune) {
+ if (prune && !matches) {
keyhash = depCacheKeyHash(dcache, DNEVR);
if (depCacheGetHEntry(dcache, DNEVR, keyhash, &cachedrc, NULL, NULL)) {
rc = *cachedrc;
@@ -533,6 +535,8 @@ static int rpmdbProvides(rpmts ts, depCache dcache, rpmds dep)
}
}
+ if (matches)
+ *matches = dbiIndexSetNew(0);
/*
* See if a filename dependency is a real file in some package,
* taking file state into account: replaced, wrong colored and
@@ -547,6 +551,10 @@ static int rpmdbProvides(rpmts ts, depCache dcache, rpmds dep)
if (instance && instance == rpmdsInstance(dep))
continue;
}
+ if (matches) {
+ dbiIndexSetAppendOne(*matches, headerGetInstance(h), 0, 0);
+ continue;
+ }
rpmdsNotify(dep, "(db files)", rc);
break;
}
@@ -577,6 +585,10 @@ static int rpmdbProvides(rpmts ts, depCache dcache, rpmds dep)
match = 0;
}
if (match) {
+ if (matches) {
+ dbiIndexSetAppendOne(*matches, headerGetInstance(h), 0, 0);
+ continue;
+ }
rpmdsNotify(dep, "(db provides)", rc);
break;
}
@@ -585,13 +597,81 @@ static int rpmdbProvides(rpmts ts, depCache dcache, rpmds dep)
}
rc = (h != NULL) ? 0 : 1;
+ if (matches) {
+ dbiIndexSetUniq(*matches, 0);
+ rc = dbiIndexSetCount(*matches) ? 0 : 1;
+ }
+
/* Cache the relatively expensive rpmdb lookup results */
/* Caching the oddball non-pruned case would mess up other results */
- if (prune)
+ if (prune && !matches)
depCacheAddHEntry(dcache, xstrdup(DNEVR), keyhash, rc);
return rc;
}
+static dbiIndexSet unsatisfiedDependSet(rpmts ts, rpmds dep)
+{
+ dbiIndexSet set1 = NULL, set2 = NULL;
+ tsMembers tsmem = rpmtsMembers(ts);
+ rpmsenseFlags dsflags = rpmdsFlags(dep);
+
+ if (dsflags & RPMSENSE_RPMLIB)
+ goto exit;
+
+ if (rpmdsIsRich(dep)) {
+ rpmds ds1, ds2;
+ rpmrichOp op;
+ char *emsg = 0;
+
+ if (rpmdsParseRichDep(dep, &ds1, &ds2, &op, &emsg) != RPMRC_OK) {
+ rpmdsNotify(dep, emsg ? emsg : "(parse error)", 1);
+ _free(emsg);
+ goto exit;
+ }
+ /* only a subset of ops is supported in set mode */
+ if (op != RPMRICHOP_WITH && op != RPMRICHOP_WITHOUT
+ && op != RPMRICHOP_OR && op != RPMRICHOP_SINGLE) {
+ rpmdsNotify(dep, "(unsupported op in set mode)", 1);
+ goto exit_rich;
+ }
+
+ set1 = unsatisfiedDependSet(ts, ds1);
+ if (op == RPMRICHOP_SINGLE)
+ goto exit_rich;
+ if (op != RPMRICHOP_OR && dbiIndexSetCount(set1) == 0)
+ goto exit_rich;
+ set2 = unsatisfiedDependSet(ts, ds2);
+ if (op == RPMRICHOP_WITH) {
+ dbiIndexSetFilterSet(set1, set2, 0);
+ } else if (op == RPMRICHOP_WITHOUT) {
+ dbiIndexSetPruneSet(set1, set2, 0);
+ } else if (op == RPMRICHOP_OR) {
+ dbiIndexSetAppendSet(set1, set2, 0);
+ }
+exit_rich:
+ ds1 = rpmdsFree(ds1);
+ ds2 = rpmdsFree(ds2);
+ goto exit;
+ }
+
+ /* match database entries */
+ rpmdbProvides(ts, NULL, dep, &set1);
+
+ /* Pretrans dependencies can't be satisfied by added packages. */
+ if (!(dsflags & RPMSENSE_PRETRANS)) {
+ rpmte *matches = rpmalAllSatisfiesDepend(tsmem->addedPackages, dep);
+ if (matches) {
+ for (rpmte *p = matches; *p; p++)
+ dbiIndexSetAppendOne(set1, rpmalLookupTE(tsmem->addedPackages, *p), 1, 0);
+ }
+ _free(matches);
+ }
+
+exit:
+ set2 = dbiIndexSetFree(set2);
+ return set1 ? set1 : dbiIndexSetNew(0);
+}
+
/**
* Check dep for an unsatisfied dependency.
* @param ts transaction set
@@ -643,6 +723,16 @@ retry:
_free(emsg);
goto exit;
}
+ if (op == RPMRICHOP_WITH || op == RPMRICHOP_WITHOUT) {
+ /* switch to set mode processing */
+ dbiIndexSet set = unsatisfiedDependSet(ts, dep);
+ rc = dbiIndexSetCount(set) ? 0 : 1;
+ dbiIndexSetFree(set);
+ ds1 = rpmdsFree(ds1);
+ ds2 = rpmdsFree(ds2);
+ rpmdsNotify(dep, "(rich)", rc);
+ goto exit;
+ }
if (op == RPMRICHOP_IF) {
if (rpmdsIsRich(ds2)) {
/* check if this is a IF...ELSE combination */
@@ -683,7 +773,7 @@ retry:
}
/* See if the rpmdb provides it */
- if (rpmdbProvides(ts, dcache, dep) == 0)
+ if (rpmdbProvides(ts, dcache, dep, NULL) == 0)
goto exit;
/* Search for an unsatisfied dependency. */