Red Hat Bugzilla – Bug 81965
Epoch comparison in rpm 4.1 seems inconsistent
Last modified: 2007-04-18 12:50:01 EDT
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20021003
Description of problem:
There seems to be some inconsistancy in the way RPM is handling version
comparison wrt promoting the epoch of install and build dependancies, vs when it
is checking for conflicts on install or dependancies on package removal. For
the former case, the epoch is not promoted, and in the latter case, it is. My
understanding is that in rpm 4.1, if there is no epoch on the dependency, then
it is assumed to be == 0 (no epoch promotion). However, install dependencies
and build prereqs still promote the epoch.
The following spec file demonstrates this for a build dependancy:
Summary: Test for epoch comparison.
License: Whaever you damn well want.
Group: Useless Stuff
Packager: Joe Mama, Inc.
BuildPrereq: make > 3.79.1-14
This RPM is useless. Do not use it. Just walk away.
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/tmp
run the following command (which will fail the BuildPrereq check):
rpmbuild -vv -bs foo.spec
and notice the following in the output:
D: rpmdsCompare: makeD: The "B" dependency needs an epoch (assuming same epoch
A = "make = 1:3.79.1-14" B = "make > 3.79.1-14"
The nopromote member of the "B" rpmds structure is not set to 1, so the epoch is
It seems that when the add/remove elements are added to the transaction set,
addTE is called (through a few other functions) to do the dirty work of
assembling the element based on the bits of information in the header. In this
function, rpmdsNew is called a bunch of times starting around line 115 to build
dep sets for the requires, conflicts, etc.. rpmdsNew creates the dep set with
nopromote == 0. addTE makes no attempt to call rpmdsSetNoPromote() on the newly
created set. More on that in a second.
Later on in the chain of events of an install, remove, or a build (which seems
to be taken as a special case of install for the purpose of BuildPrereq
checking), rpmtsCheck() is called against the fully assembled transaction. As
it iterates through the elements, it behaves differently based on whether it is
an add or remove. For removes, a call to checkDependentPackages() is made,
which in turn calls checkPackageSet(). For conflict checking on install, a call
to checkDependentConflicts() is made which also calls checkPackageSet().
checkPackageSet() calls rpmdsSetNoPromote() before calling checkPackageDeps() -
sort of, see below. For _dependancy_ checking on install (or build prereq), it
goes directly to checkPackageDeps() and given the paragraph above, there is
never a chance to set the nopromote flag on the requires dep set before falling
through to rpmdsCompare (through another function or two).
I say checkPackageSet() sort of sets the flag because of this code in depends.c,
line 697 - 700:
requires = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem);
(void) rpmdsSetNoPromote(requires, _rpmds_nopromote);
conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem);
(void) rpmdsSetNoPromote(requires, _rpmds_nopromote);
Seems to be a copy/paste error, the requires dep set has its flag set twice.
Is this context-sensitive behavior intentional?
Version-Release number of selected component (if applicable):
Steps to Reproduce:
See above description.
I just finished figuring out all these details for myself. Because of this
inconsistency, a number of packages crept into Red Hat 9 with missing epochs in
requirements (as I mentioned on rpm-list: gnome-libs, ORBit-devel, esound-devel,
Here is a reproduction recipe which illustrates the problem:
1. Prepare an RPM which "Provides: gnome-libs". Call it "bozo".
2. Install gnome-libs and gnome-libs-devel from Red Hat 9.
Here, we go through the rpmtsCheck -> checkPackageDeps code path, which
does not set nopromote. The install succeeds.
3. Install bozo.
4. Try to remove bozo.
Here, we go through the rpmtsCheck -> checkPackageSet code path, which
does set nopromote. We get a dependency failure for gnome-libs-devel.
FWIW, there's a large number of dependencies that
have a missing Epoich:. See the complete set by doing
rpm -Vav --nofiles
Hmmm, yes, there's a cut and paste error for conflicts.
Yes, you get different answers fro missing dependencies.
While adding, a missing Epoch: in EVR comparison is treated
as same as specified Epoch: (i.e. Epoch: comparison is skipped),
while after install missing Epoch: is treated as Epoch: 0.
Presumably this is the cause of your test case failure.
In all cases, the best fix is to supply an explict value for Epoch:,
as some value needs to be guessed for a missing Epoch: in order
to do the most significant elment of an epoch-version-release comparison.
Yup, gnome-libs-* has an Epoch:, so what is needed in
bozo is (at least)
Provides: gnome-libs = 1:
(Note: this provides all possible version/release combos for Epoch: 1)
You appear to misunderstand. bozo isn't supposed to satisfy the
gnome-libs-devel dependency; gnome-libs is supposed to. The only role bozo has
in the test case is to trigger a checkPackageSet() call on gnome-libs-devel.
Making bozo provide gnome-libs=1: wouldn't change anything.
I agree that life would be better if every requires line specified an epoch when
appropriate, but I have no control over Red Hat 9. As things stand, rpm is
dangerously inconsistent; it allows mismatched epochs on the way in and then
complains about them once they're there.
(If the epoch promotion actually went into the database, and didn't merely
affect the result of the comparison, then things would be better.)
If gnome-libs-devel has
Requires: gnome-libs = V-R
(i.e. w/o an Epoch: specified), then this problem
is a packaging, not rpm, error.
There's is simply no way to guess what Epoch: is intended
if not specified.
Please open a bug against gnome-libs.
I can file bug reports against the individual packages, but that doesn't make
rpm any less at fault for encouraging the situation. Either rpm should be lax
about missing epochs in all cases, or it should be strict about them in all
cases. (Or, I suppose, it would be okay to be strict about them on the way in
but lax if they're already there; that would be reasonable transition behavior.)
Being lax on the way in and strict once they're there is just insane.
Encouraging? Heh ...
rpm is transiting from loose to strict, changing to what should have been
A missing Epoch: is equivalent to Epoch: 0.
All delays on that pathway, even if insane, are due to
attempts to accomodate legacy behavior and lots of already deployed
broken packaging. The rate limiting step is exactly
Missing Epoch: is exactly the same as Epoch: 0, everywhere and always.
Use --promoteepoch if you need/want the traditional behavior.