Merge pull request #605 from nix-community/disallow_fallback

Disallow fallback
This commit is contained in:
Jörg Thalheim 2025-08-29 18:49:15 +00:00 committed by GitHub
commit 8a5cf83e26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 72 additions and 36 deletions

3
.envrc
View file

@ -6,4 +6,7 @@ watch_file direnvrc
# shellcheck disable=SC2046 # shellcheck disable=SC2046
watch_file $(find . -name "*.nix") 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 use flake

View file

@ -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 Currently, all single-word arguments and some well-known double arguments will
be interpreted or passed along. 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 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 nix-direnv in the "manual reload" mode. nix-direnv will then tell you when the

View file

@ -244,6 +244,12 @@ nix_direnv_manual_reload() {
_nix_direnv_manual_reload=1 _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() { _nix_direnv_warn_manual_reload() {
if [[ -e $1 ]]; then if [[ -e $1 ]]; then
_nix_direnv_warning 'cache is out of date. use "nix-direnv-reload" to reload' _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, # but there is already a prior profile_rc,
# which is probably more useful than nothing. # which is probably more useful than nothing.
# Fallback to use that (which means just leaving profile_rc alone!) # Fallback to use that (which means just leaving profile_rc alone!)
_nix_direnv_warning "Evaluating current devShell failed. Falling back to previous environment!" if [[ $_nix_direnv_allow_fallback -eq 1 ]]; then
export NIX_DIRENV_DID_FALLBACK=1 _nix_direnv_warning "Evaluating current devShell failed. Falling back to previous environment!"
export NIX_DIRENV_DID_FALLBACK=1
else
return 1
fi
fi fi
fi fi
else else
@ -493,8 +503,13 @@ use_nix() {
rm -f "$tmp_profile" "$tmp_profile"* rm -f "$tmp_profile" "$tmp_profile"*
_nix_direnv_info "Renewed cache" _nix_direnv_info "Renewed cache"
else else
_nix_direnv_warning "Evaluating current nix shell failed. Falling back to previous environment!" if [[ $_nix_direnv_allow_fallback -eq 1 ]]; then
export NIX_DIRENV_DID_FALLBACK=1 _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
fi fi
else else
@ -502,6 +517,7 @@ use_nix() {
_nix_direnv_info "Using cached dev shell" _nix_direnv_info "Using cached dev shell"
else else
_nix_direnv_error "use_nix failed - Is your nix shell working?" _nix_direnv_error "use_nix failed - Is your nix shell working?"
unset IN_NIX_SHELL
return 1 return 1
fi fi
fi fi

View file

@ -9,7 +9,6 @@ let
in in
pkgs.mkShell { pkgs.mkShell {
DIRENV_STDLIB = "${test_pkgs.direnv-stdlib}"; DIRENV_STDLIB = "${test_pkgs.direnv-stdlib}";
DIRENVRC = "${nix-direnv}/share/nix-direnv/direnvrc";
BATS_LIB_PATH = lib.strings.makeSearchPath "" ( BATS_LIB_PATH = lib.strings.makeSearchPath "" (
with test_pkgs; with test_pkgs;
[ [

View file

@ -7,6 +7,7 @@
fetchurl, fetchurl,
findutils, findutils,
gnugrep, gnugrep,
gnused,
lib, lib,
nix-direnv, nix-direnv,
nixVersions, nixVersions,
@ -31,6 +32,7 @@ let
coreutils coreutils
findutils findutils
gnugrep gnugrep
gnused
] ]
} }
export DIRENV_STDLIB=${direnv-stdlib} export DIRENV_STDLIB=${direnv-stdlib}
@ -38,7 +40,7 @@ let
export BATS_LIB_PATH="${bats-support}:${bats-assert}" export BATS_LIB_PATH="${bats-support}:${bats-assert}"
echo run unittest echo run unittest
${lib.getExe' bats "bats"} -x --verbose-run tests/ ${lib.getExe' bats "bats"} tests/
''; '';
test-runner-stable = mkTestRunner "stable"; test-runner-stable = mkTestRunner "stable";
test-runner-latest = mkTestRunner "latest"; test-runner-latest = mkTestRunner "latest";

32
tests/test_fallback.bats Normal file
View file

@ -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"
}

View file

@ -44,13 +44,6 @@ function assert_use_flake_layout_dir_shape {
} }
# tests =================================== # 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 function use_nix_strict { # @test
write_envrc "strict_env\nuse nix" write_envrc "strict_env\nuse nix"
assert_run_output assert_run_output
@ -58,13 +51,6 @@ function use_nix_strict { # @test
assert_use_nix_layout_dir_shape 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 function use_flake_strict { # @test
write_envrc "strict_env\nuse flake" write_envrc "strict_env\nuse flake"
assert_run_output assert_run_output

View file

@ -17,13 +17,6 @@ function use_nix_attrs_strict { # @test
assert_output -e "subshell: OK$" 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 function use_nix_no_nix_path_strict { # @test
unset NIX_PATH unset NIX_PATH
write_envrc "strict_env\nuse nix --argstr someArg OK" 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$" 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 function use_nix_no_files { # @test
write_envrc "use nix -p hello" write_envrc "use nix -p hello"
( (