From b94763c7f52dbbcc9920b4216d53fd8109e434c9 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Wed, 17 Jun 2020 15:49:50 +0200
Subject: [PATCH] Fix debug-restore command
- correctly work with install-only packages (BZ#1844533)
- do not remove current versions of packages that are supposed to be
replaced (downgraded / upgraded)
---
plugins/debug.py | 108 ++++++++++++++++++++++++-----------------------
1 file changed, 56 insertions(+), 52 deletions(-)
diff --git a/plugins/debug.py b/plugins/debug.py
index 6d00613d..29c5bf78 100644
--- a/plugins/debug.py
+++ b/plugins/debug.py
@@ -201,10 +201,9 @@ def run(self):
self.opts.filter_types = set(
self.opts.filter_types.replace(",", " ").split())
- installed = self.base.sack.query().installed()
dump_pkgs = self.read_dump_file(self.opts.filename[0])
- self.process_installed(installed, dump_pkgs, self.opts)
+ self.process_installed(dump_pkgs, self.opts)
self.process_dump(dump_pkgs, self.opts)
@@ -212,56 +211,63 @@ def run(self):
self.base.resolve()
self.base.do_transaction()
- def process_installed(self, installed, dump_pkgs, opts):
- for pkg in sorted(installed):
- filtered = False
+ def process_installed(self, dump_pkgs, opts):
+ installed = self.base.sack.query().installed()
+ installonly_pkgs = self.base._get_installonly_query(installed)
+ for pkg in installed:
+ pkg_remove = False
spec = pkgspec(pkg)
- action, dn, da, de, dv, dr = dump_pkgs.get((pkg.name, pkg.arch),
- [None, None, None,
- None, None, None])
- dump_naevr = (dn, da, de, dv, dr)
- if pkg.pkgtup == dump_naevr:
- # package unchanged
- del dump_pkgs[(pkg.name, pkg.arch)]
- else:
- if action == "install":
- # already have some version
- dump_pkgs[(pkg.name, pkg.arch)][0] = "replace"
- if "replace" not in opts.filter_types:
- filtered = True
+ dumped_versions = dump_pkgs.get((pkg.name, pkg.arch), None)
+ if dumped_versions is not None:
+ evr = (pkg.epoch, pkg.version, pkg.release)
+ if evr in dumped_versions:
+ # the correct version is already installed
+ dumped_versions[evr] = 'skip'
else:
- if "remove" not in opts.filter_types:
- filtered = True
- if not filtered:
- if opts.output:
- print("remove %s" % spec)
+ # other version is currently installed
+ if pkg in installonly_pkgs:
+ # package is install-only, should be removed
+ pkg_remove = True
else:
- self.base.package_remove(pkg)
-
- def process_dump(self, dump_pkgs, opts):
- for (action, n, a, e, v, r) in sorted(dump_pkgs.values()):
- filtered = False
- if opts.ignore_arch:
- arch = ""
- else:
- arch = "." + a
- if opts.install_latest and action == "install":
- pkg_spec = "%s%s" % (n, arch)
- if "install" not in opts.filter_types:
- filtered = True
+ # package should be upgraded / downgraded
+ if "replace" in opts.filter_types:
+ action = 'replace'
+ else:
+ action = 'skip'
+ for d_evr in dumped_versions.keys():
+ dumped_versions[d_evr] = action
else:
- pkg_spec = pkgtup2spec(n, arch, e, v, r)
- if (action == "replace" and
- "replace" not in opts.filter_types):
- filtered = True
- if not filtered:
+ # package should not be installed
+ pkg_remove = True
+ if pkg_remove and "remove" in opts.filter_types:
if opts.output:
- print("install %s" % pkg_spec)
+ print("remove %s" % spec)
else:
- try:
- self.base.install(pkg_spec)
- except dnf.exceptions.MarkingError:
- logger.error(_("Package %s is not available"), pkg_spec)
+ self.base.package_remove(pkg)
+
+ def process_dump(self, dump_pkgs, opts):
+ for (n, a) in sorted(dump_pkgs.keys()):
+ dumped_versions = dump_pkgs[(n, a)]
+ for (e, v, r) in sorted(dumped_versions.keys()):
+ action = dumped_versions[(e, v, r)]
+ if action == 'skip':
+ continue
+ if opts.ignore_arch:
+ arch = ""
+ else:
+ arch = "." + a
+ if opts.install_latest and action == "install":
+ pkg_spec = "%s%s" % (n, arch)
+ else:
+ pkg_spec = pkgtup2spec(n, arch, e, v, r)
+ if action in opts.filter_types:
+ if opts.output:
+ print("%s %s" % (action, pkg_spec))
+ else:
+ try:
+ self.base.install(pkg_spec)
+ except dnf.exceptions.MarkingError:
+ logger.error(_("Package %s is not available"), pkg_spec)
@staticmethod
def read_dump_file(filename):
@@ -288,11 +294,9 @@ def read_dump_file(filename):
pkg_spec = line.strip()
nevra = hawkey.split_nevra(pkg_spec)
- pkgs[(nevra.name, nevra.arch)] = ["install", ucd(nevra.name),
- ucd(nevra.arch),
- ucd(nevra.epoch),
- ucd(nevra.version),
- ucd(nevra.release)]
+ # {(name, arch): {(epoch, version, release): action}}
+ pkgs.setdefault((nevra.name, nevra.arch), {})[
+ (nevra.epoch, nevra.version, nevra.release)] = "install"
return pkgs
@@ -321,6 +325,6 @@ def pkgspec(pkg):
def pkgtup2spec(name, arch, epoch, version, release):
- a = "" if not arch else ".%s" % arch
+ a = "" if not arch else ".%s" % arch.lstrip('.')
e = "" if epoch in (None, "") else "%s:" % epoch
return "%s-%s%s-%s%s" % (name, e, version, release, a)