diff --git a/lix/libstore/build/local-derivation-goal.cc b/lix/libstore/build/local-derivation-goal.cc index 0e4932949..5e35ebdb5 100644 --- a/lix/libstore/build/local-derivation-goal.cc +++ b/lix/libstore/build/local-derivation-goal.cc @@ -663,7 +663,17 @@ try { if (needsHashRewrite() && pathExists(homeDir)) throw Error("home directory '%1%' exists; please remove it to assure purity of builds without sandboxing", homeDir); - if (useChroot && settings.preBuildHook != "" && dynamic_cast(drv.get())) { + // Note that the derivation may or may not exist when running the + // pre-build-hook. In the past this was *supposed* to not run the + // hook in such cases, but at some intermediate point (since this->drv + // became always an instance of Derivation rather than BasicDerivation), it + // started being run in all cases on systems using the sandbox. + // https://git.lix.systems/lix-project/lix/commit/7f5b750b401e98e9e2a346552aba5bd2e0a9203f + // + // As such, we just run it every time. It might be reasonable (and more + // helpful behaviour for users) in the future to write out the derivation + // to disk if pre-build-hook is in use. + if (settings.preBuildHook != "") { printMsg(lvlChatty, "executing pre-build hook '%1%'", settings.preBuildHook); auto drvPathPretty = worker.store.printStorePath(drvPath); auto args = useChroot ? Strings({ drvPathPretty, chrootRootDir}) : diff --git a/lix/libstore/settings/pre-build-hook.md b/lix/libstore/settings/pre-build-hook.md index c3f1a0482..0e3be6059 100644 --- a/lix/libstore/settings/pre-build-hook.md +++ b/lix/libstore/settings/pre-build-hook.md @@ -9,6 +9,8 @@ settings for this system. This is used for settings that can't be captured by the derivation model itself and are too variable between different versions of the same system to be hard-coded into nix. +At the time of running the hook, the derivation may or may not exist on disk (and, e.g. won't exist in the case of many remote builds). + The hook is passed the derivation path and, if sandboxes are enabled, the sandbox directory. It can then modify the sandbox and send a series of commands to modify various settings to stdout. The diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 2d905d79f..187841959 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -163,6 +163,7 @@ functional_tests_scripts = [ 'compression-levels.sh', 'nix-copy-ssh.sh', 'nix-copy-ssh-ng.sh', + 'pre-hook.sh', 'post-hook.sh', 'function-trace.sh', 'flakes/config.sh', diff --git a/tests/functional/pre-hook.sh b/tests/functional/pre-hook.sh new file mode 100644 index 000000000..82e2dc456 --- /dev/null +++ b/tests/functional/pre-hook.sh @@ -0,0 +1,31 @@ +source common.sh + +clearStore + +rm -f "$TEST_ROOT/result" + +cat > "$TEST_ROOT/pre-hook.sh" <<-'EOF' +#!/bin/sh + +# log the drvs that have been pre-hooked +echo "$1" >> "$(dirname "$0")"/drvs.txt +# sandbox: we have a sandbox path as second arg +if [[ $# == 2 ]]; then + # FIXME: verify this is actually present inside the derivation builder + # where sandbox is available. + echo extra-sandbox-paths + echo /foo=/bin/sh + echo +else + echo +fi +EOF + +chmod +x "$TEST_ROOT/pre-hook.sh" +drvPath="$(nix eval --raw -f dependencies.nix drvPath)" +nix-store -r "$drvPath" --pre-build-hook "$TEST_ROOT/pre-hook.sh" + +# We expect that the pre build hook got called on all the derivations in the closure we built +numDrvs="$(nix-store --query --requisites "$drvPath" | grep -c '\.drv$')" +[[ "$numDrvs" -gt 1 ]] +[[ "$numDrvs" == "$(< "$TEST_ROOT/drvs.txt" wc -l)" ]]