Re: Taking over a previously diverted file
On Tue, Oct 17, 2006 at 09:05:46PM +0700, Theppitak Karoonboonyanan wrote:
> I wonder what is the best practice to remove a diversion from a package,
> when the new version will own the file itself, and no more steals it by a
> The situation is that my package (thailatex), has previously diverted
> a file from another package (tetex-base). But now tetex-base has
> moved the file from /usr/share/texmf to /usr/share/texmf-tetex,
> allowing my package to take over that file.
> Bug #393519 in my package, which breaks upgrading from sarge,
> is caused by an attempt to remove the diversion in preinst:
> case "1" in
> dpkg-divert --package thailatex --remove --rename \
> --divert /usr/share/texmf/tex/generic/babel/babel.sty.real \
> This causes an error like this:
> Preparing to replace thailatex 0.3.2 (using .../thailatex_0.3.7-1_all.deb)
> Removing `diversion of /usr/share/texmf/tex/generic/babel/babel.sty
> to /usr/share/texmf/tex/generic/babel/babel.sty.real by thailatex'
> dpkg-divert: rename involves overwriting
> `/usr/share/texmf/tex/generic/babel/babel.sty' with
> different file
> My guess is that at preinst stage, the diverted file is still owned by
> the package itself. So it's not allowed to be overwritten.
> But if I remove the old version before installing the new one, the
> old version's postrm will remove the diversion cleanly. And the new
> version just installs correctly.
> So, I got an idea to add Conflicts: with the old version of itself, hoping
> the sarge version to be removed before the new one being installed.
> But it doesn't behave as I thought. Rather, it just upgrades as usual,
> and causes the same error.
> So, my question is: how to completely take over the previously
> diverted file?
So the constraints are:
- the old version of tetex-base must be removed before the new thailatex is
unpacked, otherwise you will have a file conflict
- there must be no /usr/share/texmf/tex/generic/babel/babel.sty in place
when the diversion is removed, because dpkg-divert --remove will throw an
error if the diverted-from file exists (whether or not the diverted-to
file still exists)
- any actions taken in the preinst must be reversible on failure, so that
the old package can be returned to installed state
Let's give this a try. In the postinst:
if [ -e $TEXDIR/babel.sty ]; then
mv -i $TEXDIR/babel.sty $TEXDIR/babel.sty.undivert < /dev/null
dpkg-divert --package thailatex --remove --rename \
--divert $TEXDIR/babel.sty.real \
mv $TEXDIR/babel.sty.undivert $TEXDIR/babel.sty
and in debian/control:
Conflicts: tetex-base (<< $version)
Replaces: tetex-base (<< $version)
This solution has the following properties.
- The version of tetex-base which contains $TEXDIR/babel.sty will always be
removed from the system before the postinst for the new thailatex is run.
(I chose this option over just Replaces:, because I'm not sure how
Replaces: would interact with a diversion.) This means that
$TEXDIR/babel.sty.real will not exist when the postinst runs.
- The script is idempotent; we know that $TEXDIR/babel.sty will exist the
*first* time the script is run, and that $TEXDIR/babel.sty.undivert should
not exist, but we allow for the possibility that the postinst script fails
later (before reverting the "mv") and that the user has manually fiddled
with files in between -- if the user has manuall added $TEXDIR/babel.sty,
the mv -i will silently fail, and the dpkg-divert --remove will /noisily/
- The diversion removal will always succeed unless the user has manually
- The final mv will always succeed unless the user has manually adjusted
files, and as a result give us a $TEXDIR/babel.sty file that we're assured
of being the copy from thailatex.
- By avoiding any use of the preinst, we also avoid any rollback
Completely untested in real-world conditions, let me know if you find I've
screwed something up :)
Steve Langasek Give me a lever long enough and a Free OS
Debian Developer to set it on, and I can move the world.