Diversions allow files from a package pkg-A to be temporarily replaced by files from another package pkg-B. When pkg-B is uninstalled, the files from pkg-A are put back into place.
For example, the vim-tiny package includes a small stub file in /usr/share/vim/doc/help.txt, which is renamed to help.txt.vim-tiny to make room for a fuller version when vim-runtime is installed. When vim-runtime is uninstalled, the help.txt.vim-tiny is renamed back to help.txt.
Diversions are a bit finicky. Consider whether a Conflicts relation or update-alternatives might be a better way to achieve what you are trying to accomplish.
Adding a diversion to a package
See Appendix G in the Debian policy manual, but take into account the information within is currently quite out-of-date.
In preinst, make sure the diversion is added in all cases. If you want to avoid spurious messages on upgrades, you can check for versions known to already include the diversion, or you can explicitly check whether the diversion already exists.
diversion_added_version=1.0.9-1 this_version=3.8-2 if test "$1" = install || dpkg --compare-versions "$2" lt "$diversion_added_version" || dpkg --compare-versions "$this_version" lt "$2" then dpkg-divert --add --rename /usr/share/foo fi
In postrm, remove the diversion if and only if the package is being either removed or downgraded to a version before the diversion was added. On upgrades to a newer version, do nothing: the diversion is the new version’s responsibility now.
diversion_added_version=1.0.9-1 this_version=3.8-2 losing_diversion=n if test "$1" = failed-upgrade then dpkg --compare-versions "$2" le-nl "$this_version" || # An upgrade from a newer version failed. # There is no way for us to know enough to take over from here, # so abort the upgrade. exit 1 elif dpkg --compare-versions "$2" lt-nl "$diversion_added_version" then losing_diversion=y fi case "$1,$losing_diversion" in remove,*|abort-install,*|disappear,*|*,y) dpkg-divert --remove --rename /usr/share/foo ;; esac
Removing a diversion from a package
In postinst and prerm, remove the diversion. Since failed upgrades can change the version number without configuration succeeding, the last version configured is not a reliable indication of whether the diversion is still around. If you want to avoid spurious messages, you can check for the diversion before removing it.
if dpkg-divert --list | grep -F "/usr/share/foo.distrib" then dpkg-divert --remove --rename /usr/share/foo fi
Without perfect foresight, the prerm surely cannot recover from failed attempts to upgrade from a newer version. (Nor can any other package; arguably this is a flaw in policy.) So supporting such downgrades reliably requires a check.
this_version=7.1 if test "$1" = failed-upgrade then dpkg --compare-versions "$2" le "$this_version" || # An upgrade from a newer version failed. # There is no way for us to know enough to take over from here, # so abort the upgrade. exit 1 fi
Diverting configuration files
Diversions can also be used to provide ConfigPackages without throwing dpkg into an interactive conflict resolution system.