Bug 7771

Summary: rpm -i/-U does not check for duplicates passed on the command line.
Product: [Retired] Red Hat Linux Reporter: Sam Varshavchik <mrsam>
Component: rpmAssignee: Jeff Johnson <jbj>
Status: CLOSED RAWHIDE QA Contact:
Severity: low Docs Contact:
Priority: medium    
Version: 6.1CC: aleksey, rhw
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2001-06-06 17:35:12 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Sam Varshavchik 1999-12-12 17:33:00 UTC
rpm -i rejects packages which are already installed, but does not check for
duplicate packages specified on the command line.  With -U, rpm gets
slightly confused about %config files as well:

Script started on Sun Dec 12 12:21:28 1999
[root@gwl SPECS]# cat foo.spec
Summary: Foo
Name: foo
Group: Application
License: FOOPL
Version: 0.1
Release: 1

%description
Foo
%prep
%build
%install

echo "%{version}" >/tmp/foo
%files
%config /tmp/foo
[root@gwl SPECS]# rpm -bb foo.spec
Executing: %prep
+ umask 022
+ cd /usr/src/redhat/BUILD
+ exit 0
Executing: %build
+ umask 022
+ cd /usr/src/redhat/BUILD
+ exit 0
Executing: %install
+ umask 022
+ cd /usr/src/redhat/BUILD
+ echo 0.1
+ exit 0
Processing files: foo
Finding  Provides: (using /usr/lib/rpm/find-provides)...
Finding  Requires: (using /usr/lib/rpm/find-requires)...
Wrote: /usr/src/redhat/RPMS/i386/foo-0.1-1.i386.rpm
[root@gwl SPECS]# rpm -i ../RPMS/i386/foo-0.1-1.i386.rpm
../RPMS/i386/foo-0.1-1.i386.rpm    # Line wrap, same .rpm entered twice
[root@gwl SPECS]# rpm -i ../RPMS/i386/foo-0.1-1.i386.rpm
package foo-0.1-1 is already installed
[root@gwl SPECS]# exit


Now, with -U, rpm becomes a bit more confused:

Script started on Sun Dec 12 12:34:18 1999
[root@gwl SPECS]# rpm -q foo
foo-0.1-1
[root@gwl SPECS]# cat foo.spec
Summary: Foo
Name: foo
Group: Application
License: FOOPL
Version: 0.2
Release: 1

%description
Foo
%prep
%build
%install

echo "%{version}" >/tmp/foo
%files
%config /tmp/foo
[root@gwl SPECS]# rpm -bb foo.spec
Executing: %prep
+ umask 022
+ cd /usr/src/redhat/BUILD
+ exit 0
Executing: %build
+ umask 022
+ cd /usr/src/redhat/BUILD
+ exit 0
Executing: %install
+ umask 022
+ cd /usr/src/redhat/BUILD
+ echo 0.2
+ exit 0
Processing files: foo
Finding  Provides: (using /usr/lib/rpm/find-provides)...
Finding  Requires: (using /usr/lib/rpm/find-requires)...
Wrote: /usr/src/redhat/RPMS/i386/foo-0.2-1.i386.rpm
[root@gwl SPECS]# rpm -U ../RPMS/i386/foo-0.2-1.i386.rpm
../RPMS/i386/foo-0.2-1.i386.rpm
warning: /tmp/foo saved as /tmp/foo.rpmsave
[root@gwl SPECS]# rpm -q foo
package foo is not installed
[root@gwl SPECS]# rpm -q -f /tmp/foo
file /tmp/foo is not owned by any package
[root@gwl SPECS]# rpm -e foo
error: package foo is not installed
[root@gwl SPECS]# rpm -U ../RPMS/i386/foo-0.2-1.i386.rpm
../RPMS/i386/foo-0.2-1.i386.rpm
warning: /tmp/foo saved as /tmp/foo.rpmorig
[root@gwl SPECS]# rpm -q foo
foo-0.2-1
[root@gwl SPECS]# exit

Script done on Sun Dec 12 12:35:41 1999

Comment 1 Jeff Johnson 1999-12-12 18:13:59 UTC
The short answer is: Yup.

The long answer involves describing some of the subtler nuances of package
installation:

1) Even detecting "duplicates" is hard, because what is duplicated is not
packages, but package contents. There are even packages, like kernel, that are
intentionally duplicated, and other packages, like tetex-*, that intentionally
share many, many files. Ditto provides et al, but let's not go there ...

2) Rpm, when invoked with -i, *never* removes a package, even if all the
contents of the new package are going to overwrite the contents of the
already installed package. This is by design.

3) Rpm, when installing packages that share files, *requires* that the
packages be installed at the same time, and *expects* that shared files
have identical MD5 sums.

4) Rpm, when installing %config files, has some heuristics implemented
in order to make the Right Thing Happen wrto upgrading a Red Hat (or other)
distribution that are sometimes counter-intuitive to a user upgrading a
couple of packages. There is really no way to improve the heuristics without a
massive ripple effect throughout all of RPM-dom.

5) Rpm, because it installs-before-erasing on upgrade, depends on being able
to adjust the file disposition of overlapped files (e.g. a file that is being
installed in the incoming, but removed in the outgoing package needs to have the
file disposition changed to "skipped" in the outgoing package) by looking only
at the first match (rather than all matches in order) of an overlapped file.

Comment 2 Anonymous 1999-12-12 18:30:59 UTC
"There are even packages, like kernel, that are intentionally duplicated, and
other packages."

But what you have there are different versions or releases of kernel installed
at the same time.

Here, we have the same package/version/release duplicated.  RPM can't even track
each individual copy after installation, and show two different copies of the
same thing installed.

Comment 3 Jeff Johnson 1999-12-12 18:41:59 UTC
Yup.

Comment 4 Riley H Williams 1999-12-12 21:13:59 UTC
"Rpm, when installing packages that share files, *requires* that the packages
be installed at the same time, and *expects* that shared files have identical
MD5 sums"

Whilst that works when INSTALLING and UPGRADING packages, it doesn't quite work
when FRESHENING packages with -Fvh and this is a fact I've previously reported.

The problem with -Fvh occurs when the new version of a package requires one or
more packages that the old version didn't require, as there is currently no
means to satisfy those dependancies with the -Fvh version of the command on its
own.

I'm not at home at the moment, so I can't quote actual rpm's, but basically,
the situation is as follows:

 Q> rpm -Fvh a-1.3-1.i386.rpm b-1.0-1.i386.rpm c-1.0-1.i386.rpm

 Q> Currently installed is a-1.2-1.i386.rpm but there are no versions
 Q> of b or c currently installed. In addition, a-1.2-1.i386.rpm did
 Q> NOT depend on either b or c but a-1.3-1.i386.rpm depends on both
 Q> of them.

This particular combination is identified by the following all being true at
the same time:

 1. There is an old version of package a installed.

 2. The new version of package a requires one or more packages that
    were NOT required by the currently installed version of that
    package.

 3. All the packages that the new version depends on that the old
    version did not depend on that are not currently installed are
    listed on the rpm command line.

When this combination arises, IMVHO, the `rpm -Fvh ...` command should act as
if a previous version the packages in point 3 was already installed. This would
effectively turn -Fvh into -Uvh for those packages.

Comment 5 Jeff Johnson 1999-12-13 13:06:59 UTC
rpm -Fvh is implemented in the shell script /usr/lib/rpm/freshen.sh. Basically
the shell script implements a policy
	Upgrade only those packages that are already installed.
by deleting packages from the argument list that are not already installed.
However, the actual install *is* rpm -U on the packages that survive the
freshen policy culling.

What you are suggesting is actually a slightly different policy than what
freshen implements
	Upgrade only those packages that are already installed, or that
	are necessary to resolve new requirements, or that share files
	with a package that is being upgraded.

Comment 6 Riley H Williams 1999-12-14 14:01:59 UTC
Q> What you are suggesting is actually a slightly different policy
 Q> than what freshen implements: Upgrade only those packages...

 Q> 1. ...that are already installed, or
 Q> 2. ...that are necessary to resolve new requirements, or
 Q> 3. ...that share files with a package that is being upgraded.

Basically, what you're saying is that (1) is what -Fvh currently implements,
and that I am adding both (2) and (3) to that? If so, then no, that's not
quite what I was saying, as it also misses an essential step. Can I paint
the scenario I was looking at and ask what is wrong with that first?

My belief is that the following scenario should be possible with RPM, the
versions  being those that I tried this with and failed, but it should be
equally possible to submit any other pair of versions:

 1. Perform a random installation of RedHat 5.2 when it is current. By
    "random", I mean that the particular set of packages to install should
    make no difference whatsoever.

 2. Download ONLY the RPM's for RedHat 6.1 from ftp.redhat.com into a
    single directory on one's local hard drive.

 3. Using a SINGLE rpm command and just the RPM's that were downloaded,
    upgrade the system to RedHat 6.1 but WITHOUT installing any RPM's
    that are not needed for the upgrade.

The only single command I know of that even comes close to guaranteeing to
perform that upgrade is...

    rpm -Uvh *.rpm

...and even that sometimes fails due to a different problem: RPM's that have
been discontinued, but were requirements for other installed RPM's, and whose
contents have been moved to other RPM's that now conflict!

Basically, what I was asking was for -Fvh to implement something along the
lines of the following logic, which will probably require changes to the
spec file format as well as to the script:

 1. Where an earlier version of a package is already installed,
    upgrade it.

 2. Where a package is installed that has been obsoleted by one
    or more packages listed on the command line, both delete the
    obsoleted package and install the replacements.

 3. Where a package is not installed, but is a requirement for
    one or more of the other upgrade packages that are installed,
    install that package.

I'm not sure about condition (3) in your list as that's something I hadn't
considered, and I'm not really sure whether it's even necessary. As far as I
can see, where packages share files in such a way that both of the packages
need to be installed for those files to be usable, those packages should list
each other as dependancies, and in that case, the above rules will deal with
them without any additional logic.

The change I can envisage is for condition (2) in my list above, as I don't
believe there is an "Obsoletes" field for spec files. If there is, I'll
apologise in advance, and put it down to the confusing documentation for RPM
that is on my system.

Comment 7 Jeff Johnson 1999-12-14 15:31:59 UTC
Rpm has had Obsoletes for quite a while (no matter).

Rpm -Uvh (and rpm -Fvh which is a shell wrapper around -Uvh) already implement
your points 1) and 2). Your point 3) is implemented in the installer (which
uses rpmlib) but not from the rpm command line. The major difficulty in
implementing 3) is the resources necessary to load the available package
headers from the "everything installed" rpmdb-redhat package so that the
package that would satisfy a new requirement can be discovered. A moderately
complicated set of new requirements imposed by, for example, a GNOME upgrade
might need 3-10 megabytes of "available package" headers loaded in order to
understand which packages will satisfy new requirements.

For now, you might consider doing upgrades using the rpm installer which
already implements all of 1), 2) and 3) (at least within the context of
a *single* pile of available packages like what is found on the distribution
CD).

The other problem with "rpm -Uvh" that you mention, the inability to identify
and remove discontinued packages, is usually due to the inability to identify
a new (but uninstalled) package that would obsolete and replace the discontinued
package. For example, Red Hat 6.1 discontinued postgres-clients and replaced
it with a set of postgres-* packages, one of which will obsolete the
discontinued postgres-clients if it were to be installed. What's missing is
a mechanism to inform rpm -U that, if you're going to upgrade package A, you
want to include package B even if B was not already installed. I dunno yet
how that mechanism will be implemented, but I believe that's the "missing
piece" in "rpm -U" (and rpm -F).

Meanwhile, the Red Hat installer sometimes has heuristics to work around this
missing piece, so I suggest you use that instead of the rpm CLI.

Comment 8 Riley H Williams 1999-12-14 15:37:59 UTC
"For now, you might consider doing upgrades using the rpm installer which
already implements all of 1), 2) and 3) (at least within the context of a
*single* pile of available packages like what is found on the distribution CD)."

Unfortunately, that's not possible on the system in question due to memory
constraints: RH 5.2 will install with 8M of RAM but RH 6.1's installer needs 12M
of RAM. Since the system in question only has 8x30-pin SIMM slots, all filled
with 1M SIMM's, and 4M SIMM's just aren't available, I have no opportunity to do
that.

The only work-around I can think of is to set up a CD with the 5.2 installer,
but with the 6.1 RPM's in /RedHat/RPMS on the CD instead of the 5.2 ones, and
I've no idea whether that would even work...

Comment 9 Jeff Johnson 2001-01-09 16:05:02 UTC
*** Bug 10548 has been marked as a duplicate of this bug. ***

Comment 10 Jeff Johnson 2001-01-09 16:06:23 UTC
*** Bug 10743 has been marked as a duplicate of this bug. ***

Comment 11 Jeff Johnson 2001-01-09 16:07:41 UTC
*** Bug 16684 has been marked as a duplicate of this bug. ***

Comment 12 Jeff Johnson 2001-01-09 16:09:09 UTC
*** Bug 21241 has been marked as a duplicate of this bug. ***

Comment 13 Jeff Johnson 2001-06-06 17:27:27 UTC
*** Bug 43010 has been marked as a duplicate of this bug. ***

Comment 14 Aleksey Nogin 2001-06-06 17:35:08 UTC
According to all the duplicates, this bug should be updated:
Summary: "-i/-U" -> "-i/-U/-F"
Version: 6.1 -> 7.1

Comment 15 Jeff Johnson 2002-07-13 20:15:00 UTC
The original problem, packages with the same
name in a single transaction, is fixed in rpm-4.1
by always preferring the "newer" package.