build/interdep.c: cycles must not be pruned completely

%package -n test
Requires: libtest = %version-%release
Requires: libtest-common = %version-%release

%package -n libtest
Requires: libtest-common = %version-%release

%package -n libtest-common
Requires: libtest = %version-%release

Here libtest and libtest-common make a cycle, and the "test" package
requires a cycle.  Naiive optimization against a cycle can simply
wipe out all dependencies: the dependency on libtest-common will be
optimized out, because libtest-common is already required by libtest;
likewise, the dependency on libtest will be optimized out, because
libtest is already required required by libtest-common.
This commit is contained in:
Alexey Tourbin 2011-02-07 06:57:43 +03:00
parent e9d4612abe
commit a71e004bdf

View File

@ -541,7 +541,7 @@ void pruneExtraDeps(struct Req *r, Spec spec)
// assuming pkg1 has strict dependency on pkg2, prune deps required by pkg2
static
void pruneRDeps1(Package pkg1, Package pkg2)
void pruneRDeps1(struct Req *r, Package pkg1, Package pkg2)
{
TFI_t fi = pkg1->cpioList;
if (fi == NULL)
@ -578,10 +578,23 @@ void pruneRDeps1(Package pkg1, Package pkg2)
int npruned = 0;
char pruned[reqc];
bzero(pruned, reqc);
// check if pkg2 is non-last part of a cycle
int cycle = 0;
Package pkg3;
for (pkg3 = pkg2->next; pkg3; pkg3 = pkg3->next) {
if (pkg3 == pkg1)
continue;
if (Requires(r, pkg2, pkg3) && Requires(r, pkg3, pkg2)) {
cycle = 1;
break;
}
}
void prune(int i, int j)
{
if (strcmp(reqNv[i], provNv[j]))
return;
if (cycle && (reqFv[i] & RPMSENSE_SENSEMASK) == RPMSENSE_EQUAL)
return;
dep_compare_t cmp = compare_deps(RPMTAG_REQUIRENAME,
provVv[j], provFv[j], reqVv[i], reqFv[i]);
if (!(cmp == DEP_ST || cmp == DEP_EQ))
@ -625,10 +638,10 @@ void pruneExtraRDeps(struct Req *r, Spec spec)
for (pkg1 = spec->packages; pkg1; pkg1 = pkg1->next)
for (pkg2 = pkg1->next; pkg2; pkg2 = pkg2->next)
if (Requires(r, pkg1, pkg2))
pruneRDeps1(pkg1, pkg2);
pruneRDeps1(r, pkg1, pkg2);
// "else" guards against mutual deletions
else if (Requires(r, pkg2, pkg1))
pruneRDeps1(pkg2, pkg1);
pruneRDeps1(r, pkg2, pkg1);
}
int processInterdep(Spec spec)