From e19d62fc02a0cdce2d17365243a05ff2c139aad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 25 Dec 2020 17:29:44 +0100 Subject: [PATCH 1/6] use_flake: add gcroot for inputs --- README.md | 4 +++- direnvrc | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 86d1d9ed..cc5e76c6 100644 --- a/README.md +++ b/README.md @@ -134,11 +134,13 @@ $ echo "use nix" >> .envrc $ direnv allow ``` -## Experimental flakes support +## Flakes support nix-direnv also comes with a flake alternative. The code is tested and works however since future nix versions might change their api regarding this feature we cannot guarantee stability after an nix upgrade. +Likewise `use_nix` the `use_flake` implementation will prevent garbage +collection of downloaded packages and also for flake inputs. Save this file as `flake.nix`: diff --git a/direnvrc b/direnvrc index 59cb14de..8c3055a8 100644 --- a/direnvrc +++ b/direnvrc @@ -55,6 +55,7 @@ use_flake() { watch_file flake.lock local profile="$(direnv_layout_dir)/flake-profile" + local flake="$(direnv_layout_dir)/flake" local profile_rc="${profile}.rc" if [[ ! -e "$profile" @@ -72,6 +73,11 @@ use_flake() { echo "$tmp_profile_rc" > "$profile_rc" rm -f "$tmp_profile" "$tmp_profile"* _nix_add_gcroot "$drv" "$profile" + + # also add garbage collection root for source + local flake_source=$(nix eval --impure --raw --expr 'builtins.getFlake (toString ./.)') + _nix_add_gcroot "$flake_source" "$flake" + log_status renewed cache else log_status using cached dev shell From 5dd5a26ccf654b2e5d6d7e2879b6bbdf2197d35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 25 Dec 2020 17:59:48 +0100 Subject: [PATCH 2/6] direnv: fix updating gcroots if store path is a directory --- direnvrc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/direnvrc b/direnvrc index 8c3055a8..8c56f708 100644 --- a/direnvrc +++ b/direnvrc @@ -46,8 +46,8 @@ _nix_add_gcroot() { local stripped_pwd=${PWD/\//} local escaped_pwd=${stripped_pwd//-/--} local escaped_pwd=${escaped_pwd//\//-} - ln -fs "$storepath" "$symlink" - ln -fs "$symlink" "/nix/var/nix/gcroots/per-user/$USER/$escaped_pwd" + ln -fsn "$storepath" "$symlink" + ln -fsn "$symlink" "/nix/var/nix/gcroots/per-user/$USER/$escaped_pwd" } use_flake() { From 47da3c88c788980b15c74eaf7360a6c5b7a2b9c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 25 Dec 2020 18:24:10 +0100 Subject: [PATCH 3/6] tests: fix flake feature check --- tests/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test.py b/tests/test.py index d97592ba..c018ee10 100644 --- a/tests/test.py +++ b/tests/test.py @@ -24,10 +24,10 @@ def support_flakes() -> bool: "--json", "--eval", "--expr", - '(builtins.compareVersions "2.4" builtins.nixVersion) == 1', + "builtins ? getFlake", ] proc = subprocess.run(cmd, text=True, capture_output=True, check=True) - return proc.stdout != "true" + return proc.stdout == "true" class IntegrationTest(unittest.TestCase): From 4aad17c4a159b18b547b9082443eae410ae231e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 25 Dec 2020 18:29:06 +0100 Subject: [PATCH 4/6] tests: extend use_flake tests --- tests/test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test.py b/tests/test.py index c018ee10..ab9887fc 100644 --- a/tests/test.py +++ b/tests/test.py @@ -97,7 +97,10 @@ def test_nix_flake(self) -> None: text=True, ) sys.stderr.write(out2.stderr) + # check if gcroot symlink has been created and is still valid + self.assertTrue(self.testenv.joinpath(".direnv/flake").is_dir()) self.assertIn("using cached dev shell", out2.stderr) + self.assertEqual(out2.returncode, 0) def tearDown(self) -> None: From f79469890a2117308e5311c7b4be27cf260c0c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 25 Dec 2020 18:59:56 +0100 Subject: [PATCH 5/6] use perl on macos to emulate realpath readlink without -f breaks with use_flakes --- direnvrc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/direnvrc b/direnvrc index 8c56f708..3f82be12 100644 --- a/direnvrc +++ b/direnvrc @@ -69,7 +69,12 @@ use_flake() { local tmp_profile="$(direnv_layout_dir)/flake-profile.$$" [[ -d "$(direnv_layout_dir)" ]] || mkdir -p "$(direnv_layout_dir)" local tmp_profile_rc=$(nix print-dev-env --profile "$tmp_profile") - drv=$(readlink "$tmp_profile") + # macos does not have realpath + if command -v realpath >/dev/null; then + drv=$(realpath "$tmp_profile") + else + drv=$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$tmp_profile") + fi echo "$tmp_profile_rc" > "$profile_rc" rm -f "$tmp_profile" "$tmp_profile"* _nix_add_gcroot "$drv" "$profile" From 6833ac21727ba0e2296de4faa056c8f479b1ca4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 25 Dec 2020 19:20:19 +0100 Subject: [PATCH 6/6] fix path collision with multiple gcroots in same dir --- direnvrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/direnvrc b/direnvrc index 3f82be12..6a04b87f 100644 --- a/direnvrc +++ b/direnvrc @@ -43,7 +43,7 @@ _nix_add_gcroot() { local storepath=$1 local symlink=$2 - local stripped_pwd=${PWD/\//} + local stripped_pwd=${2/\//} local escaped_pwd=${stripped_pwd//-/--} local escaped_pwd=${escaped_pwd//\//-} ln -fsn "$storepath" "$symlink"