[Merge] ~enr0n/ubuntu-release-upgrader:t64-replacements into ubuntu-release-upgrader:ubuntu/main
Julian Andres Klode
mp+464340 at code.launchpad.net
Mon Apr 15 17:11:44 UTC 2024
Review: Approve
This seems to work for me but could be made faster by using APT's rev_depends_list and provides_list of the apt_pkg.Package object.
Diff comments:
> diff --git a/DistUpgrade/DistUpgradeQuirks.py b/DistUpgrade/DistUpgradeQuirks.py
> index 986f88d..9d7b6d6 100644
> --- a/DistUpgrade/DistUpgradeQuirks.py
> +++ b/DistUpgrade/DistUpgradeQuirks.py
> @@ -1726,3 +1736,75 @@ class DistUpgradeQuirks(object):
> ) + updates_end_msg,
> )
> self.controller.abort()
> +
> + def _install_t64_replacement_packages(self):
> + """
> + LP: #2061175
> + """
> + for package in self.controller.cache:
> + if not package.is_installed:
> + continue
> +
> + if package.candidate and package.candidate.downloadable:
> + continue
> +
> + # If we get here, then it means that this package is installed
> + # and its candidate version is obsolete (i.e. not downloadable).
> + # Now, we need to find a replacement for it.
> + logging.debug(f'Searching for replacement for {package.name}')
> +
> + replacement = None
> + for p in self.controller.cache:
This seems very slow, could you use use package._pkg.reverse_depends_list to query just the reverse depends? For example, you can do:
rdeps = [(dep.parent_ver, dep.dep_type_untranslated) for dep in package._pkg.rev_depends_list]
prvs = [providing_ver for _, _, providing_ver in package._pkg.provides_list]
To get the reverse depends as tuples (apt_pkg.Version, str) and providers of the package. as (apt_pkg.Version). Then you can check if any of the providers also Conflicts or Breaks, and Replaces it:
replacements = [prv for prv in prvs if ((prv, "Breaks") in rdeps or (prv, "Conflicts") in rdeps) and (prv, "Replaces") in rdeps]
Then you can construct the apt.Package for the replacement's parent_pkg (apt_pkg.Package):
for replacement_cand in replacements:
replacement_package = apt.Package(cache, replacement_cand.parent_pkg)
if replacement_package.candidate._cand == replacement_cand:
break
else:
print("No replacement found")
continue
The temporary replacements array being a bit unreadable perhaps, the loop could also just iterate over the providers and add an if continue.
> + depends_list = p.candidate._cand.depends_list_str
> +
> + replaces = False
> + for replace_list in depends_list.get('Replaces', []):
> + if package.name in [
> + name for (name, _, _) in replace_list
> + ]:
> + replaces = True
> + break
> +
> + if not replaces:
> + continue
> +
> + conflicts_or_breaks = False
> + for conflict_list in depends_list.get('Conflicts', []):
> + if package.name in [
> + name for (name, _, _) in conflict_list
> + ]:
> + conflicts_or_breaks = True
> + break
> +
> + if not conflicts_or_breaks:
> + for break_list in depends_list.get('Breaks', []):
> + if package.name in [
> + name for (name, _, _) in break_list
> + ]:
> + conflicts_or_breaks = True
> + break
> +
> + if not conflicts_or_breaks:
> + continue
> +
> + if package.name not in [
> + name for (name, _, _) in p.candidate._cand.provides_list
> + ]:
> + continue
> +
> + # Cool, we found a replacement.
> + replacement = p
> + break
> +
> + if replacement is not None:
> + logging.debug(
> + f'Found replacement {replacement.name} for {package.name}'
> + )
> +
> + replacement.mark_install(auto_fix=False, auto_inst=False)
> + package.mark_delete(auto_fix=False)
> + apt.ProblemResolver(self.controller.cache).protect(package)
I see this is needed because upgrader will call MarkInstall on each installed package even if it has no upgrade available. APT is weird.
> + else:
> + logging.debug(
> + f'Failed to find a replacement for {package.name}'
> + )
--
https://code.launchpad.net/~enr0n/ubuntu-release-upgrader/+git/ubuntu-release-upgrader/+merge/464340
Your team Ubuntu Core Development Team is subscribed to branch ubuntu-release-upgrader:ubuntu/main.
More information about the Ubuntu-reviews
mailing list