Bug 81965 - Epoch comparison in rpm 4.1 seems inconsistent
Summary: Epoch comparison in rpm 4.1 seems inconsistent
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: rpm
Version: 8.0
Hardware: All
OS: Linux
Target Milestone: ---
Assignee: Jeff Johnson
QA Contact: Mike McLean
Depends On:
TreeView+ depends on / blocked
Reported: 2003-01-15 20:48 UTC by Phil D'Amore
Modified: 2007-04-18 16:50 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Last Closed: 2003-06-25 15:29:47 UTC

Attachments (Terms of Use)

Description Phil D'Amore 2003-01-15 20:48:16 UTC
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.
Name: foo
Version: 1.0
Release: 0
Epoch: 0
BuildArch: noarch
License: Whaever you damn well want.
Group: Useless Stuff
Packager: Joe Mama, Inc.
BuildRoot: /var/tmp/foo-tmp
BuildPrereq: make > 3.79.1-14


This RPM is useless.  Do not use it.  Just walk away.

mkdir -p $RPM_BUILD_ROOT/tmp
touch $RPM_BUILD_ROOT/tmp/sadlfkj.txt


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
as "A")
       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):

How reproducible:

Steps to Reproduce:
See above description.

Additional info:

Comment 1 Greg Hudson 2003-05-06 21:56:06 UTC
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,
probably others).

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.

Comment 2 Jeff Johnson 2003-05-06 23:08:36 UTC
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.

Comment 3 Jeff Johnson 2003-05-06 23:14:08 UTC
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)

Comment 4 Greg Hudson 2003-05-06 23:31:12 UTC
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.)

Comment 5 Jeff Johnson 2003-05-07 13:06:09 UTC
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.

Comment 6 Greg Hudson 2003-05-07 14:34:23 UTC
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.

Comment 7 Jeff Johnson 2003-05-07 15:47:15 UTC
Encouraging? Heh ...

rpm is transiting from loose to strict, changing to what should have been
implemented originally
    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
    Broken packages.

Comment 8 Jeff Johnson 2003-06-25 15:29:47 UTC
rpm-4.2.1 has
    Missing Epoch: is exactly the same as Epoch: 0, everywhere and always.

Use --promoteepoch if you need/want the traditional behavior.

Note You need to log in before you can comment on or make changes to this bug.