160 lines
5.3 KiB
Plaintext
160 lines
5.3 KiB
Plaintext
/*! \page tsort Package ordering in rpm-4.0.1 and later
|
|
|
|
The package ordering algorithm in rpm-4.0.1 has changed.
|
|
|
|
\section tsort_problem The Problem
|
|
|
|
Here's a simple test to illustrate the need for the change (from
|
|
bugzilla #12327):
|
|
|
|
Assume the minimal 7.0 package manifest in /tmp/list
|
|
\verbatim
|
|
/mnt/redhat/comps/dist/7.0/sparc/bash-2.04-11.sparc.rpm
|
|
/mnt/redhat/comps/dist/7.0.2/sparc/glibc-2.1.94-1.sparc.rpm
|
|
/mnt/redhat/comps/dist/7.0/sparc/mktemp-1.5-5.sparc.rpm
|
|
/mnt/redhat/comps/dist/7.0/noarch/basesystem-7.0-2.noarch.rpm
|
|
/mnt/redhat/comps/dist/7.0/noarch/setup-2.3.4-1.noarch.rpm
|
|
/mnt/redhat/comps/dist/7.0/noarch/filesystem-2.0.7-1.noarch.rpm
|
|
/mnt/redhat/comps/dist/7.0/sparc/libtermcap-2.0.8-25.sparc.rpm
|
|
/mnt/redhat/comps/dist/7.0/noarch/termcap-11.0.1-3.noarch.rpm
|
|
\endverbatim
|
|
|
|
with database initialization as
|
|
\verbatim
|
|
mkdir -p /tmp/ROOT/var/lib/rpm
|
|
rpm --initdb /tmp/ROOT/var/lib/rpm
|
|
\endverbatim
|
|
|
|
This command "works"
|
|
\verbatim
|
|
rpm -Uvh -r /tmp/ROOT `cat /tmp/list`
|
|
\endverbatim
|
|
while this command
|
|
\verbatim
|
|
rpm -Uvh -r /tmp/ROOT `tac /tmp/list`
|
|
\endverbatim
|
|
fails with
|
|
\verbatim
|
|
loop in prerequisite chain: libtermcap bash libtermcap
|
|
\endverbatim
|
|
|
|
\note The 2nd upgrade reverse orders the packages in the manifest.
|
|
|
|
The problem is that the previous ordering algorithm, basically a very clever
|
|
implementation of tsort, was sensitive to initial conditions, and the first
|
|
command "happens" to snip a loop, while the second does not.
|
|
|
|
\section tsort_solution The Solution
|
|
|
|
The current ordering algorithm is exactly tsort from Knuth V1, with one further
|
|
twist. Since the only way out of a dependency loop is to snip the loop
|
|
somewhere, rpm uses hints from Requires: dependencies to distinguish
|
|
co-requisite (these are not needed to install, only to use, a package) from
|
|
pre-requisite (these are guaranteed to be installed before the package that
|
|
includes the dependency) relations.
|
|
|
|
There is now syntax in spec files to explicitly specify the source of a
|
|
Requires: dependency. If, for example, you use grep in %post, then you
|
|
as a packager would normally add
|
|
\verbatim
|
|
PreReq: grep
|
|
\endverbatim
|
|
in order to insure that grep was installed before attempted use by the
|
|
%postun scriptlet.
|
|
|
|
Now the same dependency can be expressed more precisely as
|
|
\verbatim
|
|
Requires(post): grep
|
|
\endverbatim
|
|
|
|
For completeness, here's the complete set of tokens that may be
|
|
added to Requires: as in the example above:
|
|
\verbatim
|
|
"interp", RPMSENSE_INTERP
|
|
"prereq", RPMSENSE_PREREQ
|
|
"preun", RPMSENSE_SCRIPT_PREUN
|
|
"pre", RPMSENSE_SCRIPT_PRE
|
|
"postun", RPMSENSE_SCRIPT_POSTUN
|
|
"post", RPMSENSE_SCRIPT_POST
|
|
"rpmlib", RPMSENSE_RPMLIB
|
|
"verify", RPMSENSE_SCRIPT_VERIFY
|
|
\endverbatim
|
|
|
|
Ditto BuildRequires:
|
|
\verbatim
|
|
"prep", RPMSENSE_SCRIPT_PREP
|
|
"build", RPMSENSE_SCRIPT_BUILD
|
|
"install", RPMSENSE_SCRIPT_INSTALL
|
|
"clean", RPMSENSE_SCRIPT_CLEAN
|
|
\endverbatim
|
|
but let's not go there (yet).
|
|
|
|
For giggles, you can also do stuff like
|
|
\verbatim
|
|
Requires(pre,post): /bin/sh
|
|
\endverbatim
|
|
|
|
By marking dependencies more precisely, rpm can distinguish between
|
|
an upgrade context (like the use of grep in %post above) and an installed
|
|
context (like the autogenerated Requires: in a package that includes a
|
|
script with #!/bin/sh), and that permits rpm to differentiate pre-requisites
|
|
from co-requisites while doing package ordering.
|
|
|
|
Here's what cures the libtermcap <-> bash loop:
|
|
\verbatim
|
|
Requires(postun): /bin/sh
|
|
\endverbatim
|
|
which, since the dependency is clearly not useful or necessary in determining
|
|
install ordering, is safely ignored.
|
|
|
|
\section tsort_sideeffects Side Effects
|
|
|
|
One of the side effects of changing the package install ordering, is that
|
|
there are a handful of new loops that are detected. Here's what I found
|
|
looking at supported Red Hat releases:
|
|
|
|
\verbatim
|
|
ghostscript-fonts ghostscript
|
|
/* 7.0 only */
|
|
pango-gtkbeta-devel pango-gtkbeta
|
|
XFree86 Mesa
|
|
compat-glibc db2
|
|
compat-glibc db1
|
|
pam initscripts
|
|
kernel initscripts
|
|
initscripts sysklogd
|
|
/* 6.2 */
|
|
egcs-c++ libstdc++
|
|
/* 6.1 */
|
|
pilot-link-devel pilot-link
|
|
/* 5.2 */
|
|
pam pamconfig
|
|
\endverbatim
|
|
|
|
Why are there new loops? Because tsort is trying to use all of the
|
|
dependency relations for ordering, while the previous tsort ignored all
|
|
Requires: from added packages.
|
|
|
|
Except for the "well known" libtermcap <-> bash loop (which is just wrong),
|
|
all of the other dependencies are simply not needed in an upgrade context
|
|
to perform package ordering. Please note that all of the known to cause
|
|
loop dependencies listed above are, for now, explicitly ignored when
|
|
determining package install ordering.
|
|
|
|
\section tsort_summary Summary
|
|
|
|
So what does this all mean? Basically not much, unless you find yourself
|
|
trying to specify dependencies amongst a set of packages correctly and
|
|
happen to create a dependency loop.
|
|
|
|
And, before you start adding the new-fangled syntax to packages, please
|
|
remember that rpm will almost certainly be auto-generating fine-grained
|
|
dependencies for %post et al scriptlets pretty soon. Truly, rpm needs to
|
|
make packaging easier, not provide Yet More Complicated Syntax in spec files.
|
|
|
|
With thanks to Ken Estes for doing the implementation in bash2 that makes
|
|
it possible to auto-generate scriptlet dependencies, blame me for the long,
|
|
slow deployment.
|
|
|
|
*/
|