diff options
Diffstat (limited to 'lib/depends.c')
-rw-r--r-- | lib/depends.c | 98 |
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. */ |