diff --git a/.envrc b/.envrc index 1639dfc..1bb3edd 100644 --- a/.envrc +++ b/.envrc @@ -6,4 +6,7 @@ watch_file direnvrc # shellcheck disable=SC2046 watch_file $(find . -name "*.nix") +# This is not in shell.nix because accessing the working path requires impure eval +export DIRENVRC="$PWD/direnvrc" + use flake diff --git a/README.md b/README.md index 13f805f..655b436 100644 --- a/README.md +++ b/README.md @@ -250,7 +250,20 @@ This leads to some limitations in what we can reasonably parse. Currently, all single-word arguments and some well-known double arguments will be interpreted or passed along. -#### Manual reload of the nix environment +#### Fine-grained behavior control + +##### Disabling devShell fallback + +By default, nix-direnv will reload a previously working devShell if it discovers +that a new verison does not evaluate. This can be disabled by calling +`nix_direnv_disallow_fallback` in `.envrc`, like so: + +```shell +nix_direnv_disallow_fallback +use nix # or use flake +``` + +##### Manual reload of the nix environment To avoid delays and time consuming rebuilds at unexpected times, you can use nix-direnv in the "manual reload" mode. nix-direnv will then tell you when the diff --git a/direnvrc b/direnvrc index cad58f7..c68edf6 100644 --- a/direnvrc +++ b/direnvrc @@ -244,6 +244,12 @@ nix_direnv_manual_reload() { _nix_direnv_manual_reload=1 } +: "${_nix_direnv_allow_fallback:=1}" +nix_direnv_disallow_fallback() { + _nix_direnv_info "Fallback disallowed" + _nix_direnv_allow_fallback=0 +} + _nix_direnv_warn_manual_reload() { if [[ -e $1 ]]; then _nix_direnv_warning 'cache is out of date. use "nix-direnv-reload" to reload' @@ -336,8 +342,12 @@ use_flake() { # but there is already a prior profile_rc, # which is probably more useful than nothing. # Fallback to use that (which means just leaving profile_rc alone!) - _nix_direnv_warning "Evaluating current devShell failed. Falling back to previous environment!" - export NIX_DIRENV_DID_FALLBACK=1 + if [[ $_nix_direnv_allow_fallback -eq 1 ]]; then + _nix_direnv_warning "Evaluating current devShell failed. Falling back to previous environment!" + export NIX_DIRENV_DID_FALLBACK=1 + else + return 1 + fi fi fi else @@ -493,8 +503,13 @@ use_nix() { rm -f "$tmp_profile" "$tmp_profile"* _nix_direnv_info "Renewed cache" else - _nix_direnv_warning "Evaluating current nix shell failed. Falling back to previous environment!" - export NIX_DIRENV_DID_FALLBACK=1 + if [[ $_nix_direnv_allow_fallback -eq 1 ]]; then + _nix_direnv_warning "Evaluating current nix shell failed. Falling back to previous environment!" + export NIX_DIRENV_DID_FALLBACK=1 + else + unset IN_NIX_SHELL + return 1 + fi fi fi else @@ -502,6 +517,7 @@ use_nix() { _nix_direnv_info "Using cached dev shell" else _nix_direnv_error "use_nix failed - Is your nix shell working?" + unset IN_NIX_SHELL return 1 fi fi diff --git a/shell.nix b/shell.nix index 409fd63..1c7f3f8 100644 --- a/shell.nix +++ b/shell.nix @@ -9,7 +9,6 @@ let in pkgs.mkShell { DIRENV_STDLIB = "${test_pkgs.direnv-stdlib}"; - DIRENVRC = "${nix-direnv}/share/nix-direnv/direnvrc"; BATS_LIB_PATH = lib.strings.makeSearchPath "" ( with test_pkgs; [ diff --git a/tests/default.nix b/tests/default.nix index 77a7607..b0975fb 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -7,6 +7,7 @@ fetchurl, findutils, gnugrep, + gnused, lib, nix-direnv, nixVersions, @@ -31,6 +32,7 @@ let coreutils findutils gnugrep + gnused ] } export DIRENV_STDLIB=${direnv-stdlib} @@ -38,7 +40,7 @@ let export BATS_LIB_PATH="${bats-support}:${bats-assert}" echo run unittest - ${lib.getExe' bats "bats"} -x --verbose-run tests/ + ${lib.getExe' bats "bats"} tests/ ''; test-runner-stable = mkTestRunner "stable"; test-runner-latest = mkTestRunner "latest"; diff --git a/tests/test_fallback.bats b/tests/test_fallback.bats new file mode 100644 index 0000000..29372b9 --- /dev/null +++ b/tests/test_fallback.bats @@ -0,0 +1,32 @@ +# -*- mode: bash-ts -*- + +function setup { + load "util" + + _common_setup +} + +function teardown { + _common_teardown +} + +function test_fallback_allowed() { # @test + write_envrc "strict_env\nwatch_file shell.nix\nuse flake" + run_in_direnv 'hello' + + sed -i.bk 's|inherit shellHook|inherit doesntExist|' "$TESTDIR/shell.nix" + + run --separate-stderr direnv exec "$TESTDIR" "hello" + assert_stderr -p "Falling back to previous environment" + +} + +function test_fallback_disallowed() { # @test + write_envrc "strict_env\nwatch_file shell.nix\nnix_direnv_disallow_fallback\nuse flake" + run_in_direnv 'hello' + + sed -i.bk 's|inherit shellHook|inherit doesntExist|' "$TESTDIR/shell.nix" + + run --separate-stderr direnv exec "$TESTDIR" "hello" + refute_stderr -p "Falling back to previous environment" +} diff --git a/tests/test_gc.bats b/tests/test_gc.bats index 29d8cc6..761e89f 100644 --- a/tests/test_gc.bats +++ b/tests/test_gc.bats @@ -44,13 +44,6 @@ function assert_use_flake_layout_dir_shape { } # tests =================================== -function use_nix_no_strict { # @test - write_envrc "use nix" - assert_run_output - assert_gcroot - assert_use_nix_layout_dir_shape -} - function use_nix_strict { # @test write_envrc "strict_env\nuse nix" assert_run_output @@ -58,13 +51,6 @@ function use_nix_strict { # @test assert_use_nix_layout_dir_shape } -function use_flake_no_strict { # @test - write_envrc "use flake" - assert_run_output - assert_gcroot - assert_use_flake_layout_dir_shape -} - function use_flake_strict { # @test write_envrc "strict_env\nuse flake" assert_run_output diff --git a/tests/test_use_nix.bats b/tests/test_use_nix.bats index 164fadc..2950dd7 100644 --- a/tests/test_use_nix.bats +++ b/tests/test_use_nix.bats @@ -17,13 +17,6 @@ function use_nix_attrs_strict { # @test assert_output -e "subshell: OK$" } -function use_nix_attrs_no_strict { # @test - write_envrc "use nix -A subshell" - # shellcheck disable=SC2016 - run_in_direnv 'echo "subshell: $THIS_IS_A_SUBSHELL"' - assert_output -e "subshell: OK$" -} - function use_nix_no_nix_path_strict { # @test unset NIX_PATH write_envrc "strict_env\nuse nix --argstr someArg OK" @@ -32,14 +25,6 @@ function use_nix_no_nix_path_strict { # @test assert_output -e "someArg: OK$" } -function use_nix_no_nix_path_no_strict { # @test - unset NIX_PATH - write_envrc "use nix --argstr someArg OK" - # shellcheck disable=SC2016 - run_in_direnv 'echo "someArg: $SHOULD_BE_SET"' - assert_output -e "someArg: OK$" -} - function use_nix_no_files { # @test write_envrc "use nix -p hello" (