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
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.
"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.
Yup.
"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.
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.
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.
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.
"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...
*** Bug 10548 has been marked as a duplicate of this bug. ***
*** Bug 10743 has been marked as a duplicate of this bug. ***
*** Bug 16684 has been marked as a duplicate of this bug. ***
*** Bug 21241 has been marked as a duplicate of this bug. ***
*** Bug 43010 has been marked as a duplicate of this bug. ***
According to all the duplicates, this bug should be updated: Summary: "-i/-U" -> "-i/-U/-F" Version: 6.1 -> 7.1
The original problem, packages with the same name in a single transaction, is fixed in rpm-4.1 by always preferring the "newer" package.