[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Upgrading a package with diversions



Package: dpkg
Version: *

I'm having trouble making the maintainer scripts suggested in
diversions.txt work in all cases.

: 2. Package maintainer wants to provide an `improved' version of a
:    file in another package.
: 
:      fileutils.deb_______                   ____________________
:      |  ...              |                 /                    \
:      | /bin/ls ----------+----.           |\____________________/|
:      |  ...              |     \          |                      |
:      |___________________|      \         | /                    |
:                                  \        | /bin                 |
:      colour-ls.deb_______         `-------> /bin/ls.mono         |
:      |  ...              |       .--------> /bin/ls              |
:      | /bin/ls ----------+------'         |                      |
:      |  ...              |                 \____________________/
:      |...................|
:      |preinst:           |
:      | dpkg-override --divert /bin/ls.mono \
:      |   --package colour-ls /bin/ls
:      |...................|
:      |postrm:            |
:      | dpkg-override --remove --divert /bin/ls.mono \
:      |   --package colour-ls /bin/ls
:      |___________________|
: 

The first problem is that --rename isn't used.  This means that
colour-ls cannot actually be deinstalled, because it will leave a hole
in fileutils.  Adding --rename to each invocation of dpkg-divert (or
doing the mv seperately) allows colour-ls to be installed and removed at
will, but now causes upgrades to fail.

Here is what goes wrong during an upgrade.  For the example, I'll
consider that geewhiz-1.0-1 is currently installed, containing
replacements of /bin/foo and /bin/bar; and it is being upgraded to
geewhiz-2.0-1, containing replacements of /bin/bar and /bin/baz.

1. dpkg looks for a prerm in 1.0.

2. Conflicting packages are resolved.

3. 2.0's preinst is run.  It tries to divert /bin/bar, but that's
already done; and it adds a diversion of /bin/baz.

4. dpkg overwrites /bin/bar with the new version, and installs the
replacement /bin/baz.

5. 1.0's postrm is run.  It removes the /bin/foo diversion (correctly),
and also the /bin/bar diversion!

6. dpkg removes /bin/foo, which is the non-geewhiz version (it was put
back in step 5).  There is now no /bin/foo on the system!

One solution to this would be to have dpkg execute steps 3 to 5 in a
different order -- old postrm, new preinst, install files.  This would
probably have consequences elsewhere, but if not, the ability to remove
and install diverting packages as easily as normal packages would be
very useful.

Another answer would be to stop using the --rename flags in the
maintainer scripts, and instead require that when you remove a package
which replaces part of another, you reinstall the original package.  To
do this right, there would need to be a new field in
/var/lib/dpkg/status, listing the packages that will need to be
reinstalled if geewhiz is removed; dpkg-divert would need to do a dpkg
-S and update that field, and dpkg would have to flag packages as
half-installed based on it.

My preference would be for the former solution, which makes an update
more like a removal and reinstallation, and lets the user not worry
about whether a package contains diversions or not.  But I don't know if
it would disturb the more complex packages' maintainer scripts.



Reply to: