Skip to content

snapshot restore: version-changed packages can leave orphaned .dist-info after rollback #1548

Description

@synap5e

Component: src/main/lib/snapshots/restore.ts (createTargetedBackup / restoreFromBackup)

What happens

When a snapshot restore changes a package's version and then fails, the rollback
can leave the package with two sets of metadata: the pre-restore one it restored,
and the one the install created.

createTargetedBackup() saves the site-packages entries belonging to each
affected package. restoreFromBackup() copies those saved entries back, removing
each destination first. What it never does is remove entries that exist now but
were not in the backup — and an install of a different version creates exactly
that: a new <name>-<newversion>.dist-info directory alongside the old one.

So after a failed restore of pkg 1.0 → 2.0, site-packages can hold both
pkg-1.0.dist-info (restored) and pkg-2.0.dist-info (left behind). Which one
wins is then down to directory iteration order, and importlib.metadata can
report either.

Two narrower cases of the same gap:

  • findPackageEntries() locates .dist-info only, so a package installed with
    legacy .egg-info / .egg-link metadata gets an empty backup and nothing is
    restored for it at all.
  • A package's file set can shrink between versions; files the old version did not
    have are not removed on rollback.

Why it is filed separately

This is not specific to any one restore path — it applies to every
version-changed package and predates the recent revert work. Fixing it properly
means capturing a pre-install manifest of each affected package's entries and, on
rollback, removing entries absent from that manifest before restoring the saved
ones. That is a change to the backup mechanism itself, which did not belong
inside a data-loss fix.

Current mitigation

The revert no longer claims to have succeeded in these cases: it reports the
packages it captured no backup for and marks itself incomplete, so the failure
message does not assert a rollback that did not fully happen.

Suggested fix

  1. Record a manifest of every affected package's site-packages entries before the
    install step, including legacy metadata forms.
  2. On rollback, delete entries present now but absent from the manifest, then
    restore the saved entries.
  3. Regression tests for: a version change leaving the new .dist-info behind, and
    a package whose only metadata is .egg-info / .egg-link.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions