ubuntu-release-upgrade: rework DistUpgradeQuirks for different Trisquel flavors.
This commit is contained in:
parent
715877a0b0
commit
a12c2b558e
8 changed files with 278 additions and 33 deletions
|
|
@ -10,40 +10,56 @@ index f7427ac2..51f85b32 100644
|
|||
self._protect_essential_gui()
|
||||
self._maybe_remove_gpg_wks_server()
|
||||
self._install_t64_replacement_packages()
|
||||
@@ -205,6 +206,37 @@ class DistUpgradeQuirks(object):
|
||||
@@ -205,6 +206,53 @@ class DistUpgradeQuirks(object):
|
||||
self._disable_cloud_init()
|
||||
|
||||
# helpers
|
||||
+ def _t64_transition_helper(self):
|
||||
+ """
|
||||
+ Provides a minimal t64 transition focused on GLib and Qt5Core.
|
||||
+ Marks the t64 variants for installation if the older packages are
|
||||
+ installed. Idempotent and conservative for initial testing.
|
||||
+ Help the resolver by preferring t64 variants for commonly-blocking libs.
|
||||
+ Safe to run multiple times.
|
||||
+ """
|
||||
+ cache = self.controller.cache
|
||||
+ log = logging.getLogger("DistUpgrade")
|
||||
+
|
||||
+ # Run only if at least one of the target t64 packages is in the cache.
|
||||
+ if "libglib2.0-0t64" not in cache and "libqt5core5t64" not in cache:
|
||||
+ log.debug("t64-helper: no target t64 packages in cache; skipping")
|
||||
+ cache = getattr(self.controller, "cache", None)
|
||||
+ if cache is None:
|
||||
+ return
|
||||
+ log = logging.getLogger("DistUpgrade")
|
||||
+
|
||||
+ pairs = [
|
||||
+ ("libglib2.0-0", "libglib2.0-0t64"),
|
||||
+ ("libqt5core5a", "libqt5core5t64"),
|
||||
+ ("libelf1", "libelf1t64"),
|
||||
+ ("libssl3", "libssl3t64"),
|
||||
+ ("libpsl5", "libpsl5t64"),
|
||||
+ ("libdb5.3", "libdb5.3t64"),
|
||||
+ ("libgdbm6", "libgdbm6t64"),
|
||||
+ ("libpng16-16", "libpng16-16t64"),
|
||||
+ ("libtevent0", "libtevent0t64"),
|
||||
+ ("libmtdev1", "libmtdev1t64"),
|
||||
+ ("libts0", "libts0t64"),
|
||||
+ ("libtirpc3", "libtirpc3t64"),
|
||||
+ ("libqt6core6", "libqt6core6t64"),
|
||||
+ ("libqt6dbus6", "libqt6dbus6t64"),
|
||||
+ ("libparted2", "libparted2t64"),
|
||||
+ ]
|
||||
+
|
||||
+ # Run only if at least one of the target t64 packages is in the cache.
|
||||
+ if not any(new in cache for _, new in pairs):
|
||||
+ log.debug("t64-helper: no target t64 packages in cache; skipping")
|
||||
+ return
|
||||
+
|
||||
+ touched = []
|
||||
+ for old, new in pairs:
|
||||
+ try:
|
||||
+ if old in cache and cache[old].is_installed and new in cache:
|
||||
+ cache[new].mark_install(True, True, False)
|
||||
+ touched.append(f"{old}->{new}")
|
||||
+ except Exception as e:
|
||||
+ log.warning("t64-helper: error marking %s->%s: %s", old, new, e)
|
||||
+ for old, newpkg in pairs:
|
||||
+ if old in cache and newpkg in cache:
|
||||
+ try:
|
||||
+ if getattr(cache[old], "is_installed", False) or getattr(cache[old], "marked_install", False):
|
||||
+ cache[newpkg].mark_install(from_user=True, auto_fix=True)
|
||||
+ touched.append(newpkg)
|
||||
+ except Exception as e:
|
||||
+ log.debug("t64-helper: mark_install(%s) failed: %s", newpkg, e)
|
||||
+
|
||||
+ if touched:
|
||||
+ log.info("t64-helper: touched=%s", ", ".join(touched))
|
||||
+ log.info("t64-helper: forced %s", ", ".join(touched))
|
||||
+
|
||||
+
|
||||
def _is_lxde_system(self):
|
||||
"""Return True if LXDE (trisquel-mini) is detected as installed."""
|
||||
|
|
|
|||
|
|
@ -2,15 +2,25 @@ diff --git a/DistUpgrade/DistUpgradeQuirks.py b/DistUpgrade/DistUpgradeQuirks.py
|
|||
index 243efc14..a63db6bb 100644
|
||||
--- a/DistUpgrade/DistUpgradeQuirks.py
|
||||
+++ b/DistUpgrade/DistUpgradeQuirks.py
|
||||
@@ -196,6 +196,8 @@ class DistUpgradeQuirks(object):
|
||||
self._install_t64_replacement_packages()
|
||||
self._install_pipewire_audio_on_ubuntu_studio()
|
||||
self._handle_ufw_breaks()
|
||||
@@ -189,6 +189,18 @@ class DistUpgradeQuirks(object):
|
||||
def PreDistUpgradeCache(self):
|
||||
""" run right before calculating the dist-upgrade """
|
||||
logging.debug("running Quirks.PreDistUpgradeCache")
|
||||
+
|
||||
+ cache = self._get_cache()
|
||||
+ self.__resolver = None
|
||||
+ # Ensure recommends are ON for desktops, avoids resolver dead-ends
|
||||
+ try:
|
||||
+ self.ensure_recommends_are_installed_on_desktops()
|
||||
+ except Exception as e:
|
||||
+ logging.debug("ensure_recommends skipped: %s", e)
|
||||
+
|
||||
+ # Prefer Ecne-style candidates before marking transitions
|
||||
+ self._prefer_ecne_suffix(cache)
|
||||
|
||||
# individual quirks handler that run *after* the dist-upgrade was
|
||||
# calculated in the cache
|
||||
+
|
||||
# self._install_python_is_python2()
|
||||
self._t64_transition_helper()
|
||||
self._protect_essential_gui()
|
||||
@@ -206,6 +208,88 @@ class DistUpgradeQuirks(object):
|
||||
self._disable_cloud_init()
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ index a63db6bb..c91dff31 100644
|
|||
|
||||
# run right before the first packages get installed
|
||||
def StartUpgrade(self):
|
||||
@@ -186,13 +191,24 @@ class DistUpgradeQuirks(object):
|
||||
@@ -193,6 +193,15 @@ class DistUpgradeQuirks(object):
|
||||
|
||||
# individual quirks handler that run *right before* the dist-upgrade
|
||||
# is calculated in the cache
|
||||
|
|
@ -57,6 +57,9 @@ index a63db6bb..c91dff31 100644
|
|||
def PreDistUpgradeCache(self):
|
||||
""" run right before calculating the dist-upgrade """
|
||||
logging.debug("running Quirks.PreDistUpgradeCache")
|
||||
@@ -209,9 +218,11 @@ class DistUpgradeQuirks(object):
|
||||
self._prefer_ecne_suffix(cache)
|
||||
|
||||
# self._install_python_is_python2()
|
||||
+ self._wks_purge_from_cache()
|
||||
+ self._mta_cancel_selection()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
diff --git a/DistUpgrade/DistUpgradeQuirks.py b/DistUpgrade/DistUpgradeQuirks.py
|
||||
index f1337e12..9250dd3a 100644
|
||||
--- a/DistUpgrade/DistUpgradeQuirks.py
|
||||
+++ b/DistUpgrade/DistUpgradeQuirks.py
|
||||
@@ -209,6 +209,7 @@ class DistUpgradeQuirks(object):
|
||||
self._wks_purge_from_cache()
|
||||
self._mta_cancel_selection()
|
||||
self._t64_transition_helper()
|
||||
+ self._ensure_trisquel_meta_selected()
|
||||
self._protect_essential_gui()
|
||||
# self._maybe_remove_gpg_wks_server()
|
||||
self._install_t64_replacement_packages()
|
||||
@@ -476,6 +477,36 @@ class DistUpgradeQuirks(object):
|
||||
else:
|
||||
logging.debug("prefer-ecne-suffix: no candidates changed")
|
||||
|
||||
+ def _ensure_trisquel_meta_selected(self):
|
||||
+ """
|
||||
+ Ensure base Trisquel meta-packages are explicitly selected for installation/upgrade.
|
||||
+ This nudges APT's resolver to plan the transition (e.g., PipeWire replacing PulseAudio)
|
||||
+ in the same run, instead of deferring meta-packages as "Not Upgrading".
|
||||
+ """
|
||||
+ # Get the apt cache from the controller (attribute name varies across releases)
|
||||
+ cache = getattr(self.controller, "cache", None) or getattr(self.controller, "_cache", None)
|
||||
+ if cache is None:
|
||||
+ # Best effort: nothing to do if cache is not yet attached here
|
||||
+ return
|
||||
+
|
||||
+ # Root meta-packages by flavour plus the common desktop pivot
|
||||
+ roots = [
|
||||
+ "trisquel", "triskel", "trisquel-mini", "trisquel-gnome", "trisquel-sugar",
|
||||
+ "trisquel-desktop-common",
|
||||
+ ]
|
||||
+ for name in roots:
|
||||
+ try:
|
||||
+ pkg = cache[name]
|
||||
+ except KeyError:
|
||||
+ continue # package not present in this flavour
|
||||
+ if getattr(pkg, "is_installed", False):
|
||||
+ try:
|
||||
+ # Mark as user-requested so the resolver upgrades it with its peers
|
||||
+ pkg.mark_install(from_user=True)
|
||||
+ except Exception:
|
||||
+ # Non-fatal: keep going
|
||||
+ pass
|
||||
+
|
||||
def _t64_transition_helper(self):
|
||||
"""
|
||||
Provides a minimal t64 transition focused on GLib and Qt5Core.
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
diff --git a/DistUpgrade/DistUpgradeQuirks.py b/DistUpgrade/DistUpgradeQuirks.py
|
||||
index 35ed55bd..b70a8899 100644
|
||||
--- a/DistUpgrade/DistUpgradeQuirks.py
|
||||
+++ b/DistUpgrade/DistUpgradeQuirks.py
|
||||
@@ -209,6 +209,7 @@ class DistUpgradeQuirks(object):
|
||||
self._wks_purge_from_cache()
|
||||
self._mta_cancel_selection()
|
||||
self._t64_transition_helper()
|
||||
+ self._ensure_pipewire_stack()
|
||||
self._ensure_trisquel_meta_selected()
|
||||
self._protect_essential_gui()
|
||||
# self._maybe_remove_gpg_wks_server()
|
||||
@@ -605,6 +606,51 @@ class DistUpgradeQuirks(object):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
+ def _ensure_pipewire_stack(self):
|
||||
+ """
|
||||
+ Nudge APT to pick the PipeWire stack so desktop metas can upgrade.
|
||||
+ Also remove PulseAudio family to resolve Conflicts/Breaks with pipewire-audio.
|
||||
+ """
|
||||
+ cache = getattr(self.controller, "cache", None)
|
||||
+ if cache is None:
|
||||
+ return
|
||||
+ log = logging.getLogger("DistUpgrade")
|
||||
+
|
||||
+ touched_i, touched_d = [], []
|
||||
+
|
||||
+ # Full PipeWire stack
|
||||
+ for n in ("pipewire-audio", "pipewire-alsa", "pipewire-pulse", "gstreamer1.0-pipewire", "wireplumber"):
|
||||
+ if self._apt_mark_install(n, protect=True): touched_i.append(n)
|
||||
+
|
||||
+ # Remove PulseAudio family to avoid conflicts
|
||||
+ for n in ("pulseaudio", "pulseaudio-module-bluetooth", "pulseaudio-module-gsettings", "pulseaudio-module-jack", "pulseaudio-utils"):
|
||||
+ if self._apt_mark_delete(n): touched_d.append(n)
|
||||
+
|
||||
+ if touched_i or touched_d:
|
||||
+ log.info("pipewire-helper: install=%s remove=%s",
|
||||
+ ", ".join(touched_i) if touched_i else "-",
|
||||
+ ", ".join(touched_d) if touched_d else "-")
|
||||
+
|
||||
+
|
||||
+ def mark(name):
|
||||
+ if name in cache and getattr(cache[name], "candidate", None):
|
||||
+ try:
|
||||
+ cache[name].mark_install(from_user=True)
|
||||
+ return True
|
||||
+ except Exception:
|
||||
+ pass
|
||||
+ return False
|
||||
+
|
||||
+ touched = []
|
||||
+ for n in ("pipewire-alsa", "pipewire-audio", "gstreamer1.0-pipewire"):
|
||||
+ if mark(n):
|
||||
+ touched.append(n)
|
||||
+
|
||||
+ if touched:
|
||||
+ logging.getLogger("DistUpgrade").info(
|
||||
+ "pipewire-helper: preselected %s", ", ".join(touched)
|
||||
+ )
|
||||
+
|
||||
def _get_pci_ids(self):
|
||||
""" return a set of pci ids of the system (using lspci -n) """
|
||||
lspci = set()
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
diff --git a/DistUpgrade/DistUpgradeQuirks.py b/DistUpgrade/DistUpgradeQuirks.py
|
||||
index 484ceaae..c390003a 100644
|
||||
--- a/DistUpgrade/DistUpgradeQuirks.py
|
||||
+++ b/DistUpgrade/DistUpgradeQuirks.py
|
||||
@@ -209,6 +209,7 @@ class DistUpgradeQuirks(object):
|
||||
self._wks_purge_from_cache()
|
||||
self._mta_cancel_selection()
|
||||
self._t64_transition_helper()
|
||||
+ self._parted_transition_helper()
|
||||
self._ensure_pipewire_stack()
|
||||
self._ensure_trisquel_meta_selected()
|
||||
self._protect_essential_gui()
|
||||
@@ -618,6 +624,44 @@ class DistUpgradeQuirks(object):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
+
|
||||
+ def _parted_transition_helper(self):
|
||||
+ """
|
||||
+ Handle libparted/udisks2 transition seen in logs:
|
||||
+ - Remove libparted-fs-resize0 (obsolete transitional)
|
||||
+ - Prefer libparted2t64 when available, else libparted2
|
||||
+ - Protect libblockdev-fs2 and udisks2 from accidental removal
|
||||
+ """
|
||||
+ cache = getattr(self.controller, "cache", None)
|
||||
+ if cache is None:
|
||||
+ return
|
||||
+ log = logging.getLogger("DistUpgrade")
|
||||
+
|
||||
+ touched_i, touched_d = [], []
|
||||
+
|
||||
+ if self._apt_mark_delete("libparted-fs-resize0"):
|
||||
+ touched_d.append("libparted-fs-resize0")
|
||||
+
|
||||
+ # Prefer t64 if present
|
||||
+ if "libparted2t64" in cache:
|
||||
+ if self._apt_mark_install("libparted2t64"):
|
||||
+ touched_i.append("libparted2t64")
|
||||
+ else:
|
||||
+ if self._apt_mark_install("libparted2"):
|
||||
+ touched_i.append("libparted2")
|
||||
+
|
||||
+ # Keep storage stack in place
|
||||
+ for keep in ("libblockdev-fs2", "udisks2"):
|
||||
+ try:
|
||||
+ if keep in cache and (getattr(cache[keep], "is_installed", False) or getattr(cache[keep], "marked_install", False)):
|
||||
+ if self._resolver(): self._resolver().protect(cache[keep])
|
||||
+ except Exception: pass
|
||||
+
|
||||
+ if touched_i or touched_d:
|
||||
+ log.info("parted-helper: install=%s remove=%s",
|
||||
+ ", ".join(touched_i) if touched_i else "-",
|
||||
+ ", ".join(touched_d) if touched_d else "-")
|
||||
+
|
||||
def _ensure_pipewire_stack(self):
|
||||
"""
|
||||
Nudge APT to pick the PipeWire stack so desktop metas can upgrade.
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
diff --git a/DistUpgrade/DistUpgradeQuirks.py b/DistUpgrade/DistUpgradeQuirks.py
|
||||
index 4c599207..2c3fd680 100644
|
||||
--- a/DistUpgrade/DistUpgradeQuirks.py
|
||||
+++ b/DistUpgrade/DistUpgradeQuirks.py
|
||||
@@ -202,6 +202,41 @@ class DistUpgradeQuirks(object):
|
||||
# --- MTA hard-block config (postfix only, temporary during upgrade) ---
|
||||
MTA_BLOCK_PREF = "/etc/apt/preferences.d/zz-urug-block-mta-postfix.pref"
|
||||
|
||||
+ def _resolver(self):
|
||||
+ # use only one ProblemResolver per stage
|
||||
+ if not hasattr(self, "__resolver") or self.__resolver is None:
|
||||
+ try:
|
||||
+ import apt
|
||||
+ self.__resolver = apt.ProblemResolver(self._get_cache())
|
||||
+ except Exception:
|
||||
+ self.__resolver = None
|
||||
+ return self.__resolver
|
||||
+
|
||||
+ def _apt_mark_install(self, name, protect=False, auto_fix=True, from_user=True):
|
||||
+ cache = self._get_cache()
|
||||
+ if cache and name in cache and getattr(cache[name], "candidate", None):
|
||||
+ try:
|
||||
+ cache[name].mark_install(from_user=from_user, auto_fix=auto_fix)
|
||||
+ if protect and self._resolver():
|
||||
+ try: self._resolver().protect(cache[name])
|
||||
+ except Exception: pass
|
||||
+ return True
|
||||
+ except Exception:
|
||||
+ return False
|
||||
+ return False
|
||||
+
|
||||
+ def _apt_mark_delete(self, name, purge=False):
|
||||
+ cache = self._get_cache()
|
||||
+ if cache and name in cache:
|
||||
+ pkg = cache[name]
|
||||
+ if getattr(pkg, "is_installed", False) or getattr(pkg, "marked_install", False):
|
||||
+ try:
|
||||
+ pkg.mark_delete(auto_fix=False)
|
||||
+ return True
|
||||
+ except Exception:
|
||||
+ return False
|
||||
+ return False
|
||||
+
|
||||
def PreDistUpgradeCache(self):
|
||||
""" run right before calculating the dist-upgrade """
|
||||
logging.debug("running Quirks.PreDistUpgradeCache")
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
# Also, don't forget to update the meta-release files at archive and packages.t.i
|
||||
# The "obsoletes" list from ubuntu has been removed
|
||||
|
||||
VERSION=19
|
||||
VERSION=20
|
||||
|
||||
. ./config
|
||||
# Previous upstream release name, update for each release.
|
||||
|
|
@ -213,12 +213,12 @@ perl $DATA/parsewiki DistUpgrade/DevelReleaseAnnouncement > DistUpgrade/DevelRel
|
|||
|
||||
cat <<EOF > data/removal_denylist.cfg
|
||||
# list of packages that should never be removed
|
||||
trisquel-base
|
||||
trisquel-minimal
|
||||
trisquel-desktop-common
|
||||
trisquel-mini
|
||||
triskel
|
||||
trisquel-sugar
|
||||
^trisquel-base$
|
||||
^trisquel-minimal$
|
||||
^trisquel-desktop-common$
|
||||
^trisquel-mini$
|
||||
^triskel$
|
||||
^trisquel-sugar$
|
||||
# update-manager should not remove itself
|
||||
update-manager
|
||||
update-manager-core
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue