From d31f0fee089eb0883c7b48faabee4c47d80cbdf8 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Sun, 24 Dec 2023 10:40:57 -0800 Subject: bindbapi: Update state for package remove in aux_update When removing a signed gpkg in aux_update, update internal state including $PKGDIR/Packages (important especially for FEATURES=pkgdir-index-trusted). Bug: https://bugs.gentoo.org/920095 Fixes: a7bbb4fc4d38 ("Fix move_ent with signed binpkg") Signed-off-by: Zac Medico --- lib/portage/dbapi/bintree.py | 61 +++++++++++++++++++++---- lib/portage/tests/update/test_move_slot_ent.py | 19 +++++--- lib/portage/tests/update/test_update_dbentry.py | 13 ++++-- 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/lib/portage/dbapi/bintree.py b/lib/portage/dbapi/bintree.py index 9c9ac6633..b9f8d6795 100644 --- a/lib/portage/dbapi/bintree.py +++ b/lib/portage/dbapi/bintree.py @@ -302,15 +302,7 @@ class bindbapi(fakedbapi): "the file will be removed.", ) ) - try: - os.remove(binpkg_path) - except OSError as err: - writemsg( - colorize( - "WARN", - f"Failed to remove moved signed package: {binpkg_path} {str(err)}", - ) - ) + self.bintree.remove(cpv) return encoding_key = False else: @@ -1789,6 +1781,57 @@ class binarytree: return cpv + def remove(self, cpv: portage.versions._pkg_str) -> None: + """ + Remove a package instance and update internal state including + the package index. This will raise a KeyError if cpv is not + found in the internal state. It will display a warning message + if the package file was not found on disk, since it could have + been removed by another process before this method could + acquire a lock. + + @param cpv: The cpv of the existing package to remove + @type cpv: portage.versions._pkg_str + @rtype: None + @return: None + @raise KeyError: If cpv does not exist in the internal state + """ + if not self.populated: + self.populate() + os.makedirs(self.pkgdir, exist_ok=True) + pkgindex_lock = lockfile(self._pkgindex_file, wantnewlockfile=1) + try: + # Will raise KeyError if the package is not found. + instance_key = self.dbapi._instance_key(cpv) + pkg_path = self.getname(cpv) + self.dbapi.cpv_remove(cpv) + self._pkg_paths.pop(instance_key, None) + if self._remotepkgs is not None: + self._remotepkgs.pop(instance_key, None) + pkgindex = self._load_pkgindex() + if not self._pkgindex_version_supported(pkgindex): + pkgindex = self._new_pkgindex() + + path = pkg_path[len(self.pkgdir) + 1 :] + for i in range(len(pkgindex.packages) - 1, -1, -1): + d = pkgindex.packages[i] + if cpv == d.get("CPV"): + if path == d.get("PATH", ""): + del pkgindex.packages[i] + + self._pkgindex_write(pkgindex) + try: + os.remove(pkg_path) + except OSError as err: + writemsg( + colorize( + "WARN", + f"Failed to remove package: {binpkg_path} {str(err)}", + ) + ) + finally: + unlockfile(pkgindex_lock) + def _read_metadata(self, filename, st, keys=None, binpkg_format=None): """ Read metadata from a binary package. The returned metadata diff --git a/lib/portage/tests/update/test_move_slot_ent.py b/lib/portage/tests/update/test_move_slot_ent.py index caefdb4c9..62b5c3544 100644 --- a/lib/portage/tests/update/test_move_slot_ent.py +++ b/lib/portage/tests/update/test_move_slot_ent.py @@ -1,4 +1,4 @@ -# Copyright 2012-2019 Gentoo Authors +# Copyright 2012-2023 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 import sys @@ -277,17 +277,24 @@ class MoveSlotEntTestCase(TestCase): self.assertEqual( "2/2.30", vardb.aux_get("dev-libs/A-1", ["SLOT"])[0] ) - self.assertEqual( - "0/2.30", bindb.aux_get("dev-libs/A-1", ["SLOT"])[0] - ) + + # Stale signed packages removed since a7bbb4fc4d38. + self.assertRaises(KeyError, bindb.aux_get, "dev-libs/A-1", ["SLOT"]) + # self.assertEqual( + # "0/2.30", bindb.aux_get("dev-libs/A-1", ["SLOT"])[0] + # ) # 0 -> 1 self.assertEqual("1", vardb.aux_get("dev-libs/B-1", ["SLOT"])[0]) - self.assertEqual("0", bindb.aux_get("dev-libs/B-1", ["SLOT"])[0]) + # Stale signed packages removed since a7bbb4fc4d38. + self.assertRaises(KeyError, bindb.aux_get, "dev-libs/B-1", ["SLOT"]) + # self.assertEqual("0", bindb.aux_get("dev-libs/B-1", ["SLOT"])[0]) # 0/1 -> 1 (equivalent to 1/1) self.assertEqual("1", vardb.aux_get("dev-libs/C-1", ["SLOT"])[0]) - self.assertEqual("0/1", bindb.aux_get("dev-libs/C-1", ["SLOT"])[0]) + # Stale signed packages removed since a7bbb4fc4d38. + self.assertRaises(KeyError, bindb.aux_get, "dev-libs/C-1", ["SLOT"]) + # self.assertEqual("0/1", bindb.aux_get("dev-libs/C-1", ["SLOT"])[0]) # dont_apply_updates self.assertEqual( diff --git a/lib/portage/tests/update/test_update_dbentry.py b/lib/portage/tests/update/test_update_dbentry.py index 4e6554496..a3c9a37e8 100644 --- a/lib/portage/tests/update/test_update_dbentry.py +++ b/lib/portage/tests/update/test_update_dbentry.py @@ -1,4 +1,4 @@ -# Copyright 2012-2013 Gentoo Foundation +# Copyright 2012-2023 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 import sys @@ -432,10 +432,13 @@ class UpdateDbentryTestCase(TestCase): rdepend = vardb.aux_get("dev-libs/A-1", ["RDEPEND"])[0] self.assertTrue(old_pattern.search(rdepend) is None) self.assertTrue("dev-libs/M-moved" in rdepend) - rdepend = bindb.aux_get("dev-libs/A-1", ["RDEPEND"])[0] - print(old_pattern.search(rdepend) is None) - self.assertFalse(old_pattern.search(rdepend) is None) - self.assertFalse("dev-libs/M-moved" in rdepend) + # Stale signed packages removed since a7bbb4fc4d38. + self.assertRaises( + KeyError, bindb.aux_get, "dev-libs/A-1", ["RDEPEND"] + ) + # rdepend = bindb.aux_get("dev-libs/A-1", ["RDEPEND"])[0] + # self.assertFalse(old_pattern.search(rdepend) is None) + # self.assertFalse("dev-libs/M-moved" in rdepend) rdepend = vardb.aux_get("dev-libs/B-1", ["RDEPEND"])[0] self.assertTrue(old_pattern.search(rdepend) is None) self.assertTrue("dev-libs/M-moved" in rdepend) -- cgit v1.2.3-65-gdbad