diff --git a/direnvrc b/direnvrc index 81fcd90..8683cf5 100644 --- a/direnvrc +++ b/direnvrc @@ -112,15 +112,33 @@ _nix_import_env() { export XDG_DATA_DIRS=$XDG_DATA_DIRS${old_xdg_data_dirs:+":"}$old_xdg_data_dirs } +_nix_strip_escape_path() { + local stripped_path=${1/\//} + local escaped_path=${stripped_path//-/--} + local escaped_path=${escaped_path//\//-} + + echo "$escaped_path" +} + _nix_add_gcroot() { local storepath=$1 local symlink=$2 + local escaped_symlink + escaped_symlink=$(_nix_strip_escape_path "$symlink") - local stripped_pwd=${2/\//} - local escaped_pwd=${stripped_pwd//-/--} - local escaped_pwd=${escaped_pwd//\//-} ln -fsn "$storepath" "$symlink" - ln -fsn "$symlink" "/nix/var/nix/gcroots/per-user/$USER/$escaped_pwd" + ln -fsn "$symlink" "/nix/var/nix/gcroots/per-user/$USER/$escaped_symlink" +} + +_nix_clean_old_gcroots() { + local layout_dir=$1 + local escaped_layout_dir + escaped_layout_dir=$(_nix_strip_escape_path "$layout_dir") + + rm -rfv "$layout_dir/flake-inputs/" + rm -fv "$layout_dir"/{nix,flake}-profile* + rm -fv "/nix/var/nix/gcroots/per-user/$USER/$escaped_layout_dir"-flake--inputs* + rm -fv "/nix/var/nix/gcroots/per-user/$USER/$escaped_layout_dir"-{nix,flake}--profile* } _nix_argsum_suffix() { @@ -180,6 +198,8 @@ use_flake() { || "$need_update" == "1" ]]; then + _nix_clean_old_gcroots "$layout_dir" + # We need to update our cache local tmp_profile="${layout_dir}/flake-profile.$$" local tmp_profile_rc @@ -196,7 +216,6 @@ use_flake() { # also add garbage collection root for source local flake_input_paths - rm -rf "$flake_inputs" mkdir "$flake_inputs" flake_input_paths=$("${NIX_BIN_PREFIX}nix" flake archive \ --json \ @@ -322,6 +341,8 @@ use_nix() { || "$need_update" -eq "1" ]]; then + _nix_clean_old_gcroots "$layout_dir" + local tmp_profile="${layout_dir}/flake-profile.$$" local tmp_profile_rc diff --git a/tests/test_gc.py b/tests/test_gc.py index c951f62..fefda77 100644 --- a/tests/test_gc.py +++ b/tests/test_gc.py @@ -38,10 +38,37 @@ def common_test(direnv_project: DirenvProject) -> None: assert "Executing shellHook." in out2.stderr +def common_test_clean(direnv_project: DirenvProject) -> None: + testenv = str(direnv_project.dir) + + out3 = run( + ["direnv", "exec", testenv, "hello"], + stderr=subprocess.PIPE, + check=False, + cwd=direnv_project.dir, + ) + sys.stderr.write(out3.stderr) + + files = [ + path for path in (direnv_project.dir / ".direnv").iterdir() if path.is_file() + ] + rcs = [f for f in files if f.match("*.rc")] + profiles = [f for f in files if not f.match("*.rc")] + if len(rcs) != 1 or len(profiles) != 1: + print(files) + assert len(rcs) == 1 + assert len(profiles) == 1 + + def test_use_nix(direnv_project: DirenvProject) -> None: direnv_project.setup_envrc("use nix") common_test(direnv_project) + direnv_project.setup_envrc( + "use nix --argstr shellHook 'echo Executing hijacked shellHook.'" + ) + common_test_clean(direnv_project) + def test_use_flake(direnv_project: DirenvProject) -> None: direnv_project.setup_envrc("use flake") @@ -55,6 +82,9 @@ def test_use_flake(direnv_project: DirenvProject) -> None: for symlink in inputs: assert symlink.is_dir() + direnv_project.setup_envrc("use flake --impure") + common_test_clean(direnv_project) + if __name__ == "__main__": unittest.main() diff --git a/tests/testenv/shell.nix b/tests/testenv/shell.nix index c5c9d85..05d0a7a 100644 --- a/tests/testenv/shell.nix +++ b/tests/testenv/shell.nix @@ -1,14 +1,11 @@ -{ pkgs ? import {}, someArg ? null }: +{ pkgs ? import { }, someArg ? null, shellHook ? '' + echo "Executing shellHook." +'' }: pkgs.mkShellNoCC { + inherit shellHook; + nativeBuildInputs = [ pkgs.hello ]; - shellHook = '' - echo "Executing shellHook." - ''; SHOULD_BE_SET = someArg; - passthru = { - subshell = pkgs.mkShellNoCC { - THIS_IS_A_SUBSHELL = "OK"; - }; - }; + passthru = { subshell = pkgs.mkShellNoCC { THIS_IS_A_SUBSHELL = "OK"; }; }; }