9. Special requirements of uninstallation scripts and triggers

The -r option to %preun, %postun, %triggerun, and %triggerpostun scripts indicates that the package's required resources must be present when running the script. Although that seems to be a natural requirement, doing so may require significant extra disk space when upgrading packages. Therefore, LPMtool bends the rules a little bit and ignores the package's required resources when running uninstallation scripts, by default. The -r must be explicitly specified in order for LPMtool to do everything by the book.

Note

This also includes some other package's %triggerun and %triggerpostun that are triggered by this subpackage.

This chapter explains the problem with taking into account a package's required resources, when running uninstallation script. This chapter uses an example of two related packages: the main package, and a subpackage which requires some resources from the main package.

It is common to have subpackage that requires resources from the main package. Consider a package called gizmo and a subpackage called gizmo-server. Subpackages typically have a listed dependency on the main package. Therefore the existing package gizmo-server version 1 requires the existing package gizmo version 1.

Let's see what happens during an update of these packages to the next version. The new packages are gizmo version 2, and gizmo-server version 2, which requires gizmo 2.

LPMtool begins the update process by creating two transactions:

  1. Upgrade gizmo version 1 to gizmo version 2.

  2. Upgrade gizmo-server version 1 to gizmo-server version 2.

Each upgrade transaction consists of two steps: install the new package, then uninstall the old package. Therefore, the two transactions are:

  1. Install gizmo 2. Uninstall gizmo 1.

  2. Install gizmo-server 2. Uninstall gizmo-server 1.

LPMtool will normally choose the order of transactions that preserves all existing requirements and dependencies at each step of the process. LPMtool now needs to choose the order in which these two transactions will be processed. LPMtool computes the transaction order by considering the dependencies of all the involved packages:

When LPMtool encounters such a circular dependency - two transactions that mutually require each other to occur first - LPMtool solves the circular dependency by merging both transaction into a single transaction:

  1. Install gizmo 2. Install gizmo-server 2. Uninstall gizmo-server 1. Uninstall gizmo 1.

When more than two transaction are mutually dependent on each other, they are also merged together into a single transaction.

Naturally, if the gizmo and gizmo-server packages contain 5Mb worth of data in each package, only 5Mb of extra disk space is required to upgrade both packages in two separate transactions:

  1. Install the newer version of the first package, using up the extra 5Mb of disk space.

  2. Uninstall the older version of the first package, freeing up 5Mb of disk space used by the older version.

  3. Install the newer version of the second package, using up the extra 5Mb of disk space.

  4. Uninstall the older version of the second package, freeing up 5Mb of disk space used by the older version.

Merging both transactions will now require an extra 10Mb of disk space instead of five, because both new packages now get installed before the old packages get removed.

Note

The amount of disk space required to upgrade an arbitrary list of packages can be estimated by the following formula: N-O+L, where:

N

Total estimated disk space used by the new packages.

O

Total estimated disk space used by the old packages.

L

Total estimated disk space used by the new packages in the largest transaction, disk space-wise.

Nearly all subpackages require the main application package to be installed first. It's not unusual for large applications to have four, five, or even more subpackages. If LPMtool were to follow the dependency rules strictly, every upgrade of the main package and all of its subpackags would have to be done as a single, merged, mega-transaction. Therefore, LPMtool bends the rules a little bit in order to avoid having to merge all transactions into one big mega-transaction that requires a large chunk of disk space.

Therefore, dependencies of a package that's slated for uninstallation will only be considered if there's an uninstallation script with the -r option. If an uninstallation script wasn't provided, the only thing LPMtool will do is remove a bunch of files. Since nothing gets executed before or after the fact, it should be fairly safe to remove the files. The default bending of the dependency rules should be sufficient to break the circular dependency in nearly all cases, causing LPMtool to upgrade the main package and subpackages as separate, smaller transaction.

Note

There's an exception to the exception. LPMtool will consider all dependencies, without considering the presence or absence of uninstallation scripts, when LPMtool is invoked only to remove packages (the -e option to lpm). Therefore, when packages are removed completely (as opposed to updating or installing packages), the subpackages will always be uninstalled first.

There are some extremely marginal situation where bending the dependency rules in this fashion will end up breaking something. To force LPMtool to properly consider all dependencies, specify an empty %postun or %preun script, and give the -r option:

%postun -r

:

Before doing that, however, examine closely the requirements of all involved packages. Chances are that LPMtool does not pick up some requirement automatically, and it should be explicitly added using the Requires: header.