diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc index 01546f9a0..62745b681 100644 --- a/src/libcmd/common-eval-args.cc +++ b/src/libcmd/common-eval-args.cc @@ -11,6 +11,8 @@ #include "command.hh" #include "tarball.hh" #include "fetch-to-store.hh" +#include "compatibility-settings.hh" +#include "eval-settings.hh" namespace nix { @@ -33,6 +35,11 @@ EvalSettings evalSettings { static GlobalConfig::Register rEvalSettings(&evalSettings); +CompatibilitySettings compatibilitySettings {}; + +static GlobalConfig::Register rCompatibilitySettings(&compatibilitySettings); + + MixEvalArgs::MixEvalArgs() { addFlag({ diff --git a/src/libcmd/common-eval-args.hh b/src/libcmd/common-eval-args.hh index 189abf0ed..8d303ee7c 100644 --- a/src/libcmd/common-eval-args.hh +++ b/src/libcmd/common-eval-args.hh @@ -13,6 +13,7 @@ namespace nix { class Store; class EvalState; struct EvalSettings; +struct CompatibilitySettings; class Bindings; struct SourcePath; @@ -21,6 +22,11 @@ struct SourcePath; */ extern EvalSettings evalSettings; +/** + * Settings that control behaviors that have changed since Nix 2.3. + */ +extern CompatibilitySettings compatibilitySettings; + struct MixEvalArgs : virtual Args, virtual MixRepair { static constexpr auto category = "Common evaluation options"; diff --git a/src/libcmd/meson.build b/src/libcmd/meson.build index d9a90508a..2c8a9fa33 100644 --- a/src/libcmd/meson.build +++ b/src/libcmd/meson.build @@ -97,6 +97,7 @@ headers = [config_h] + files( 'command-installable-value.hh', 'command.hh', 'common-eval-args.hh', + 'compatibility-settings.hh', 'editor-for.hh', 'installable-attr-path.hh', 'installable-derived-path.hh', diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 30cc86456..d37b16bdc 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -26,6 +26,7 @@ #include "legacy.hh" #include "users.hh" #include "network-proxy.hh" +#include "compatibility-settings.hh" using namespace nix; using namespace std::string_literals; @@ -100,7 +101,13 @@ static SourcePath resolveShellExprPath(SourcePath path) auto resolvedOrDir = resolveExprPath(path, false); if (resolvedOrDir.resolveSymlinks().lstat().type == SourceAccessor::tDirectory) { if ((resolvedOrDir / "shell.nix").pathExists()) { - return resolvedOrDir / "shell.nix"; + if (compatibilitySettings.nixShellAlwaysLooksForShellNix) { + return resolvedOrDir / "shell.nix"; + } else { + warn("Skipping '%1%', because the setting '%2%' is disabled. This is a deprecated behavior. Consider enabling '%2%'.", + resolvedOrDir / "shell.nix", + "nix-shell-always-looks-for-shell-nix"); + } } if ((resolvedOrDir / "default.nix").pathExists()) { return resolvedOrDir / "default.nix"; @@ -302,11 +309,17 @@ static void main_nix_build(int argc, char * * argv) fromArgs = true; remainingArgs = {joined.str()}; } else if (!fromArgs && remainingArgs.empty()) { - remainingArgs = {"."}; + if (isNixShell && !compatibilitySettings.nixShellAlwaysLooksForShellNix && std::filesystem::exists("shell.nix")) { + // If we're in 2.3 compatibility mode, we need to look for shell.nix + // now, because it won't be done later. + remainingArgs = {"shell.nix"}; + } else { + remainingArgs = {"."}; - // Instead of letting it throw later, we throw here to give a more relevant error message - if (isNixShell && !std::filesystem::exists("shell.nix") && !std::filesystem::exists("default.nix")) - throw Error("no argument specified and no '%s' or '%s' file found in the working directory", "shell.nix", "default.nix"); + // Instead of letting it throw later, we throw here to give a more relevant error message + if (isNixShell && !std::filesystem::exists("shell.nix") && !std::filesystem::exists("default.nix")) + throw Error("no argument specified and no '%s' or '%s' file found in the working directory", "shell.nix", "default.nix"); + } } if (isNixShell) diff --git a/tests/functional/nix-shell.sh b/tests/functional/nix-shell.sh index b7a7db27c..2a1d556dd 100755 --- a/tests/functional/nix-shell.sh +++ b/tests/functional/nix-shell.sh @@ -21,6 +21,10 @@ output=$(nix-shell --pure "$shellDotNix" -A shellDrv --run \ [ "$output" = " - foo - bar - true" ] +output=$(nix-shell --pure "$shellDotNix" -A shellDrv --option nix-shell-always-looks-for-shell-nix false --run \ + 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') +[ "$output" = " - foo - bar - true" ] + # Test --keep output=$(nix-shell --pure --keep SELECTED_IMPURE_VAR "$shellDotNix" -A shellDrv --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $SELECTED_IMPURE_VAR"') @@ -101,6 +105,11 @@ nix-shell $TEST_ROOT/lookup-test -A shellDrv --run 'echo "it works"' | grepQuiet # https://github.com/NixOS/nix/issues/4529 nix-shell -I "testRoot=$TEST_ROOT" '' -A shellDrv --run 'echo "it works"' | grepQuiet "it works" +expectStderr 1 nix-shell $TEST_ROOT/lookup-test -A shellDrv --run 'echo "it works"' --option nix-shell-always-looks-for-shell-nix false \ + | grepQuiet -F "do not load default.nix!" # we did, because we chose to enable legacy behavior +expectStderr 1 nix-shell $TEST_ROOT/lookup-test -A shellDrv --run 'echo "it works"' --option nix-shell-always-looks-for-shell-nix false \ + | grepQuiet "Skipping .*lookup-test/shell\.nix.*, because the setting .*nix-shell-always-looks-for-shell-nix.* is disabled. This is a deprecated behavior\. Consider enabling .*nix-shell-always-looks-for-shell-nix.*" + ( cd $TEST_ROOT/empty; expectStderr 1 nix-shell | \