lib/depends.c: make rpmRangesOverlap() handle DistTag

In a constraint (Requires, Conflicts), some components of E:V-R:D may
be unspecified; here are the sensible possibilities:

V
E:V-R
E:V-R:D

Remember that the DistTag represents the ID of a particular build. (V
represents a particular upstream version. E:V-R represents a
particular source package release.)

To satisfy a requirement, only the specified components must be
checked.

So, if the requirement doesn't specify a DistTag, then we don't have
to check the DistTag to satisfy it.

If the requirement does specify a DistTag, then if it is an "equals"
requirement, then only the same DistTag can satisfy it. (I.e., we want
that particular build.)

A "less" (or "greater") requirement of a DistTag basically makes no
sense, because the build IDs are not ordered. So, such a requirement
cannot be satisfied, if it has come to checking the DistTag, i.e. the
EVRs have been equal. (It cannot be satisfied by a package with an
equal EVR and any DistTag value, but can be satisfied by a package
with EVR which is strictly less or greater.)

What does the last part mean for "Requires" and "Conflicts"?

Requires: N>E:V-R:D would have the same effect as Requires: N>E:V-R

Conflicts: N>E:V-R:D would have the same effect as Conflicts: N>E:V-R

i.e., a conflict would not disallow packages with the specified E:V-R,
but a different DistTag. (We can't do any better, unless there is a
"not-equals" type of requirement in RPM.)

Commit message author: Ivan Zakharyaschev <imz@altlinux.org>

Commit is based on 6cb615d6112a2ca841481d8153ba652d512a2f23 of

git://git.altlinux.org/gears/r/rpm.git
(cherry picked from commit d169679410a0d02a731addb8b526ecbc8a3a56fc)
This commit is contained in:
Vladimir D. Seleznev 2019-01-16 22:35:19 +03:00 committed by Ivan Zakharyaschev
parent ee2e436b00
commit e624792819

View File

@ -139,16 +139,41 @@ int rpmRangesOverlap(const char * AName, const char * AEVR, int AFlags,
goto exit;
}
else {
const char *aE, *aV, *aR, *bE, *bV, *bR;
const char *aE, *aV, *aR, *aD, *bE, *bV, *bR, *bD;
/* Both AEVR and BEVR exist. */
parseEVR(strdupa(AEVR), &aE, &aV, &aR);
parseEVR(strdupa(BEVR), &bE, &bV, &bR);
parseEVRD(strdupa(AEVR), &aE, &aV, &aR, &aD);
parseEVRD(strdupa(BEVR), &bE, &bV, &bR, &bD);
/* rpmEVRcmp() is also shared; the code moved to rpmvercmp.c */
if (rpmIsDebug()) {
aDepend = printDepend(NULL, AName, AEVR, AFlags);
bDepend = printDepend(NULL, BName, BEVR, BFlags);
}
sense = rpmEVRcmp(aE, aV, aR, aDepend, bE, bV, bR, bDepend);
/* We can't merge the DistTag comparison into rpmEVRcmp(), because
rpmEVRcmp() doesn't have a return code for incomparable things.
That's similar to set comparison which is done in this function.
*/
if (sense == 0) {
if (bD && *bD) {
/* (Remember: we are in the case when the EVR components
are equal.) We might detect equal DistTags here.
If not, since DistTags have no order, there is
no possibility here that one thing will be less or greater
than the other; the result is "incomparable".
*/
if (aD && *aD && strcmp(aD, bD) == 0)
sense = 0;
else {
result = 0;
goto exit;
}
} else if (aD && *aD) {
/* Support for underspecification on the side of Requires/Conflicts */
rpmMessage(RPMMESS_DEBUG, _("the \"B\" dependency doesn't specify a disttag, letting it match any in \"A\"\n\tA %s\tB %s\n"),
aDepend, bDepend);
sense = 0;
}
}
}
sense_result: