From b94763c7f52dbbcc9920b4216d53fd8109e434c9 Mon Sep 17 00:00:00 2001 From: Marek Blaha 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)