Skip to content

Commit

Permalink
bindbapi: Update state for package remove in aux_update
Browse files Browse the repository at this point in the history
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: a7bbb4f ("Fix move_ent with signed binpkg")
Signed-off-by: Zac Medico <zmedico@gentoo.org>
  • Loading branch information
zmedico committed Dec 24, 2023
1 parent b39e1ed commit 1c3af79
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 20 deletions.
66 changes: 57 additions & 9 deletions lib/portage/dbapi/bintree.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,15 +302,7 @@ def aux_update(self, cpv, values):
"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:
Expand Down Expand Up @@ -1789,6 +1781,62 @@ def inject(self, cpv, current_pkg_path=None, allocated_pkg_path=None):

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 display a warning message if the
package was not found, 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
"""
os.makedirs(self.pkgdir, exist_ok=True)
pkgindex_lock = lockfile(self._pkgindex_file, wantnewlockfile=1)
try:
try:
instance_key = self.dbapi._instance_key(cpv)
except KeyError as err:
# Another process may have removed
# it before we acquired the lock.
writemsg(
colorize(
"WARN",
f"Failed to remove package: {cpv} {str(err)}",
)
)
return
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
Expand Down
19 changes: 13 additions & 6 deletions lib/portage/tests/update/test_move_slot_ent.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -277,17 +277,24 @@ def testMoveSlotEntWithSignature(self):
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(
Expand Down
13 changes: 8 additions & 5 deletions lib/portage/tests/update/test_update_dbentry.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -432,10 +432,13 @@ def testUpdateDbentryDbapiTestCaseWithSignature(self):
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)
Expand Down

0 comments on commit 1c3af79

Please sign in to comment.