libstore/gc: restore deletion of referrers

Fixes: 8614cf1334
Fixes #495

Change-Id: I4d8d655c6254786ba1222a5b37551c68d9e370ee
This commit is contained in:
Linus Heckemann
2025-03-09 22:15:12 +01:00
parent 93c3ca4e92
commit d6c871eb2d
3 changed files with 32 additions and 15 deletions
+13
View File
@@ -0,0 +1,13 @@
---
synopsis: "Fix nix-store --delete on paths with remaining referrers"
cls: [2783]
category: "Fixes"
credits: lheckemann
---
Nix 2.5 introduced a regression whereby `nix-store --delete` and `nix
store delete` started to fail when trying to delete a path that was
still referenced by other paths, even if the referrers were not
reachable from any GC roots. The old behaviour, where attempting to
delete a store path would also delete its referrer closure, is now
restored.
-4
View File
@@ -749,10 +749,6 @@ try {
co_return result::success();
}
if (options.action == GCOptions::gcDeleteSpecific
&& !options.pathsToDelete.count(*path))
co_return result::success();
if (!gcServer.markPendingIfPresent(std::string(path->hashPart()))) {
debug("cannot delete '%s' because it's a temporary root", printStorePath(*path));
TRY_AWAIT(markAlive());
+19 -11
View File
@@ -2,12 +2,16 @@ source common.sh
clearStore
drvPath=$(nix-instantiate dependencies.nix)
outPath=$(nix-store -rvv "$drvPath")
createAndRootPaths() {
drvPath=$(nix-instantiate dependencies.nix)
outPath=$(nix-store -rvv "$drvPath")
# Set a GC root.
rm -f "$NIX_STATE_DIR"/gcroots/foo
ln -sf $outPath "$NIX_STATE_DIR"/gcroots/foo
# Set a GC root.
rm -f "$NIX_STATE_DIR"/gcroots/foo
ln -sf $outPath "$NIX_STATE_DIR"/gcroots/foo
}
createAndRootPaths
[ "$(nix-store -q --roots $outPath)" = "$NIX_STATE_DIR/gcroots/foo -> $outPath" ]
@@ -18,9 +22,9 @@ if nix-store --gc --print-dead | grep -E $outPath$; then false; fi
nix-store --gc --print-dead
inUse=$(readLink $outPath/reference-to-input-2)
if nix-store --delete $inUse; then false; fi
test -e $inUse
input2=$(readLink $outPath/reference-to-input-2)
if nix-store --delete $input2; then false; fi
test -e $input2
if nix-store --delete $outPath; then false; fi
test -e $outPath
@@ -42,10 +46,14 @@ if test -e $drvPath; then false; fi
rm "$NIX_STATE_DIR"/gcroots/foo
nix-collect-garbage
# Deleting the dependency should now be possible, and delete the referrer as well
nix-store --delete $input2
! test -e $outPath
! test -e $input2
# Check that the output has been GC'd.
if test -e $outPath/foobar; then false; fi
createAndRootPaths
rm "$NIX_STATE_DIR"/gcroots/foo
nix-collect-garbage
# Check that the store is empty.
rmdir $NIX_STORE_DIR/.links