Public bug reported:

When migrateToDeb822Sources() cannot migrate any of the remaining .list
files (for example because every one uses [signed-by=], bug 2167655),
aborting the upgrade afterwards loses those sources. The original .list
files and their .migrate backups are both deleted, and only the
commented-out .list.disabled stubs remain, so the repositories stay
disabled on the release that is still installed.

Version: ubuntu-release-upgrader 26.10.11 (26.04.1 to 26.10),
python3-apt 3.1.0ubuntu1.1.

Steps to reproduce
1. On 26.04, with the Ubuntu sources in deb822 format, add a third-party source 
as a one-line .list file that uses signed-by, for example 
/etc/apt/sources.list.d/dbeaver.list containing:
   deb [signed-by=/usr/share/keyrings/dbeaver.gpg.key] 
https://dbeaver.io/debs/dbeaver-ce /
2. Run do-release-upgrade and abort once the sources have been rewritten, for 
example by declining "Do you want to start the upgrade?". Here the abort 
followed apt update failing on the Ubuntu Pro ESM sources (bug 2084208).
3. List /etc/apt/sources.list.d.

Expected: dbeaver.list is back as it was, and dbeaver.list.disabled is
gone.

Actual: dbeaver.list and dbeaver.list.migrate are both gone, and
dbeaver.list.disabled holds the entry commented out. main.log,
timestamps trimmed:

    DEBUG migrateToDeb822Sources()
    DEBUG Could not migrate deb [arch=amd64,arm64 
signed-by=/usr/share/keyrings/claude-desktop-archive-keyring.asc] 
https://downloads.claude.ai/claude-desktop/apt/stable stable main from 
/etc/apt/sources.list.d/claude-desktop.list, disabling instead.
    DEBUG Could not migrate deb [signed-by=/usr/share/keyrings/dbeaver.gpg.key] 
https://dbeaver.io/debs/dbeaver-ce / from /etc/apt/sources.list.d/dbeaver.list, 
disabling instead.
    ...
    DEBUG abort called

Cause
migrateToDeb822Sources() backs every file up as *.migrate, writes 
<file>.disabled for entries python-apt marks invalid, and removes the original 
.list files. abort() then calls restoreMigratedSources() and 
cleanBackupSources(). restoreMigratedSources() returns immediately when no 
.sources file was generated:

    def restoreMigratedSources(self):
        if not self._generated_sources_files:
            return

When every .list entry was invalid, nothing was generated, so the *.migrate 
files are never renamed back, and cleanBackupSources() then deletes them. The 
.disabled stubs stay. ubuntu/main at d09d661750e4 has the same code:
https://git.launchpad.net/ubuntu-release-upgrader/tree/DistUpgrade/DistUpgradeController.py?id=d09d661750e42d2cb6da3c9ada3d772f22e2bbb3#n768

Suggested fix: in restoreMigratedSources(), rename the *.migrate files
back whether or not any .sources files were generated, and remove the
.disabled files this run wrote.

Related: bug 2167655 (signed-by sources are never migrated), bug 2130273
(the same files deleted at the end of a completed upgrade, where a
maintainer noted that the upgrader does not restore the original), and
bug 2166117 (abort leaves sources unrestored in a different case).

_Drafted by Claude (Anthropic AI assistant)._

** Affects: ubuntu-release-upgrader (Ubuntu)
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2171068

Title:
  Aborting a release upgrade deletes .list sources that could not be
  migrated to deb822

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/ubuntu-release-upgrader/+bug/2171068/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to