On this page
- §7.2.1 Preconditions
- §7.2.2 File diff
- §7.2.3 Procedure
- §7.2.3.1 Step 1: parse and validate
- §7.2.3.2 Step 2: prepare diff
- §7.2.3.3 Step 3: stage replacement
- §7.2.3.4 Step 4: apply diff
- §7.2.3.5 Step 5: side effects
- §7.2.3.6 Step 6: update registration
- §7.2.4 Replaces relations
- §7.2.5 Downgrade
- §7.2.6 Concurrent dependent updates
Upgrade
This section defines the upgrade operation: the procedure for replacing an installed version of a package with a different version.
Upgrade is conceptually a single atomic operation combining an install of the new version and an uninstall of the old version, with the property that no point in time leaves the system without the package's content available.
The same procedure handles upgrades (newer version replacing older) and downgrades (older version replacing newer). The two cases differ only in which version comparison applies; the format treats both identically.
§7.2.1 Preconditions
An upgrade operation begins with the following inputs:
- The new version's
.peipkgfile (already fetched). - The currently-installed version of the same package.
- The repository the new version was fetched from.
- The current resolution plan.
The following preconditions MUST hold:
- All preconditions of install (§7.1.1) hold for the new version, except the "not already installed" check which is replaced by "the currently-installed version has the same name and architecture but a different version".
- The new version's dependencies are satisfied (or will be satisfied by the in-flight transaction's other operations).
- No package depends on the currently-installed version in a way that the new version cannot satisfy.
- If the new version is older than the currently- installed version (downgrade), the user has explicitly authorised the downgrade.
§7.2.2 File diff
An upgrade is computed as a diff between the old version's file set and the new version's file set:
- Files in old but not in new: REMOVED at upgrade commit.
- Files in both old and new with identical content hash: untouched.
- Files in both old and new with different content hash: REPLACED.
- Files in new but not in old: ADDED at upgrade commit.
Files in /etc/ are handled by modified-detection. For a
REPLACED /etc/ file, the package manager compares the
file's current on-disk content hash against the hash
recorded for that file at install:
- Unmodified — the on-disk content matches the recorded hash: the file is replaced with the new version's content, like any other REPLACED file.
- Modified — the on-disk content differs: the
operator's file MUST be left in place; the new
version's default is written alongside it as
<name>.peipkg-new, and the divergence MUST be surfaced in the operation report.
/etc/ by hand, and an upgrade replaces seed
configuration unconditionally. Until the reconciller
framework exists, modified-detection prevents an
upgrade from destroying a hand-edited /etc/ file.
The models converge: once reconcillers claim a set of
/etc/ paths, the package manager applies
modified-detection only to the unclaimed remainder and
replaces reconciller-managed seed files unconditionally.§7.2.3 Procedure
The upgrade procedure consists of the following ordered steps:
§7.2.3.1 Step 1: parse and validate
Identical to install step 1 (§7.1.2.1) for the new version's package.
§7.2.3.2 Step 2: prepare diff
- Read the currently-installed version's file list from the package database.
- Read the new version's file list from the new
.peipkg'sfiles.json. - Compute the diff (§7.2.2).
- Verify disk space per §7.1.2.2 step 2 — the staged ADDED and REPLACED content. Backups of REPLACED and REMOVED files are made by renaming the old files aside (§7.5.1.3) and cost no additional space.
- Verify no ADDED path collides with a path owned by a different package than the one being upgraded.
§7.2.3.3 Step 3: stage replacement
For each REPLACED or ADDED file:
- Extract from the new
.peipkgto a temporary file within the destination's own directory, so the commit-time rename is intra-directory and cannot fail withEXDEV(§7.1.2.3). - Verify content hash against
files.json.
Staged files are named so as not to collide with payload entries, and are not visible as installed content until commit, when an atomic rename moves each into place.
§7.2.3.4 Step 4: apply diff
At transaction commit (§7.4):
- For each ADDED file: rename the staged file into place at the install path (§7.1.2.3) and apply its SD per §3.4.7.
- For each REPLACED file: rename the existing file aside as a backup (§7.5.1.3), then rename the staged file into place; apply the new file's SD per §3.4.7.
- For each REMOVED file: rename the file aside as a backup (§7.5.1.3). The backup is discarded once the transaction commits and any retention window expires.
- Remove empty directories that are no longer owned by any installed package.
§7.2.3.5 Step 5: side effects
Side effects declared by the new version are scheduled
for invocation at transaction commit. Side effects are
also scheduled if files were REMOVED whose absence
affects the side-effect target (e.g., removing a shared
library requires ldconfig, removing a kernel module
requires depmod).
A package manager MAY infer additional side-effect invocations from REMOVED files even if the new package does not explicitly declare them.
§7.2.3.6 Step 6: update registration
Replace the package database's record for this package with the new version's identity, file list, and manifest contents. The database update is part of the transaction.
§7.2.4 Replaces relations
An upgrade triggered by a replaces relation (§4.1.5)
follows the same procedure with the replaced package
treated as the "currently installed version", even though
its name differs from the new package's name.
The package database's record for the replaced package is removed; a new record for the replacing package is created. From the system's perspective, the replaced package is uninstalled and the replacing package is installed; the diff procedure ensures no payload files are spuriously removed during the transition.
§7.2.5 Downgrade
A downgrade is an upgrade where the new version is older than the installed version per §2.2.6. The procedure is identical to upgrade, with one additional precondition: the user MUST have explicitly authorised the downgrade.
§7.2.6 Concurrent dependent updates
If an upgrade in progress would temporarily violate a dependent package's dependencies (because the new version is incompatible with the dependent), the resolution plan MUST include the dependent's upgrade in the same transaction.
The upgrade procedure MUST NOT be invoked on a single package without ensuring that any dependents whose constraints are not satisfied by the new version are also upgraded (or removed) in the same transaction.