Skip to content

The drvOutputId->OutputPath link is lost for CA derivations when the drv file is deleted #4138

@thufschmitt

Description

@thufschmitt

Describe the bug

The sqlite database keeps a mapping between derivations output − a tuple (derivationFile, outputName) − and their actual output path as this one can't be inferred from the derivation file itself when CA derivations come into play.
However, this mapping is actually (pathIdx, outputName) -> outputPath where pathIdx is the index of the entry representing the derivation file in the db. In practice, this means that once the drv file is garbage-collected this index doesn't have any meaning anymore, so this mapping if effectively lost (there's even an sql rule saying that it should be deleted when the drv file is garbage-collected). So Nix won't be aware anymore of the fact that the derivation has been built, and the next nix-build call will have to rebuild it.

Steps To Reproduce

From a recent-enough Nix, apply the following patch and run make install && make tests/content-addressed.sh.test

diff --git a/tests/content-addressed.sh b/tests/content-addressed.sh
index 61ec03fe3..82a979b2a 100644
--- a/tests/content-addressed.sh
+++ b/tests/content-addressed.sh
@@ -5,6 +5,15 @@ source common.sh
 drv=$(nix-instantiate --experimental-features ca-derivations ./content-addressed.nix -A rootCA --arg seed 1)
 nix --experimental-features 'nix-command ca-derivations' show-derivation --derivation "$drv" --arg seed 1
 
+# Build the derivation a first time and add a gc root for the output path
+nix-build --experimental-features ca-derivations ./content-addressed.nix -A rootCA --arg seed 1 -o $TEST_ROOT/var/nix/gcroots/caRoot
+# Run the gc to remove the drv file
+nix-store --gc
+# Try buinding it again with `-j0`. This should succeed as the output path is
+# still here, but will fail because we lost that knowledge when removing the
+# drv file
+nix-build --experimental-features ca-derivations ./content-addressed.nix -A rootCA --arg seed 1 -o $TEST_ROOT/var/nix/gcroots/caRoot -j0
+
 testDerivation () {
     local derivationPath=$1
     local commonArgs=("--experimental-features" "ca-derivations" "./content-addressed.nix" "-A" "$derivationPath" "--no-out-link")

Expected behavior

The above should work.
More generally, one should be able to register a drvOutputId -> outputPath mapping without having the drv file around

cc @edolstra @Ericson2314

Metadata

Metadata

Assignees

Labels

bugca-derivationsDerivations with content addressed outputs

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions