From 6997988d1bdcbb0558d6239d1b83294d9472f53a Mon Sep 17 00:00:00 2001 From: Arthur Noel Date: Thu, 23 Nov 2023 20:37:03 +0000 Subject: [PATCH 1/4] drop nix_direnv_watch_file - instead parse DIRENV_WATCHES fixes #408 --- README.md | 8 ++++---- default.nix | 6 ++++-- direnvrc | 45 ++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 113b7e91..a9149e9d 100644 --- a/README.md +++ b/README.md @@ -314,23 +314,23 @@ when deciding to update its cache. * `flake.lock` * `devshell.toml` if it exists -To add more files to be checked use `nix_direnv_watch_file` like this +To add more files to be checked use `watch_file` like this ```shell -nix_direnv_watch_file your-file.nix +watch_file your-file.nix use nix # or use flake ``` Or - if you don't mind the overhead (runtime and conceptual) of watching all nix-files: ```shell -nix_direnv_watch_file $(find . -name "*.nix" -printf '"%p" ') +watch_file $(find . -name "*.nix" -printf '"%p" ') ``` Note that this will re-execute direnv for any nix change, regardless of whether that change is meaningful for the devShell in use. -`nix_direnv_watch_file` must be invoked before either `use flake` or `use nix` to take effect. +`watch_file` must be invoked before either `use flake` or `use nix` to take effect. ## General direnv tips diff --git a/default.nix b/default.nix index b287a36d..fffb0eba 100644 --- a/default.nix +++ b/default.nix @@ -1,4 +1,4 @@ -{ stdenv, nix, gnugrep, lib }: +{ stdenv, nix, gnugrep, gzip, jq, lib }: stdenv.mkDerivation { name = "nix-direnv"; @@ -8,7 +8,9 @@ stdenv.mkDerivation { postPatch = '' sed -i "2iNIX_BIN_PREFIX=${nix}/bin/" direnvrc substituteInPlace direnvrc \ - --replace "grep" "${gnugrep}/bin/grep" + --replace "grep" "${gnugrep}/bin/grep" \ + --replace gzip "${gzip}/bin/gzip" \ + --replace JQ= "JQ=${jq}/bin/jq" ''; installPhase = '' diff --git a/direnvrc b/direnvrc index 6e622ea6..02485f9e 100644 --- a/direnvrc +++ b/direnvrc @@ -197,8 +197,39 @@ _nix_argsum_suffix() { } nix_direnv_watch_file() { + # shellcheck disable=2016 + log_error '`nix_direnv_watch_file` is deprecated - use `watch_file`' watch_file "$@" - nix_watches+=("$@") +} + +# set by nix build - see ./default.nix +JQ= + +_jq() { + if [[ -n $JQ ]] + then + $JQ "$@" + elif has jq + then + jq "$@" + else + nix-shell --packages jq --run "$(join_args jq "$@")" + fi +} + +_nix_direnv_watches() { + local -n _watches=$1 + # DIRENV_WATCHES is json | gzip (without header and trailer) | base64url + # allow files under $XDG_DATA_HOME/direenv/allow are filtered out as not relevant + # gzip header: https://datatracker.ietf.org/doc/html/rfc1952#page-6 + mapfile -td "" _watches < <( + # shellcheck disable=2016 + tr -- "-_" "+/" <<< "$DIRENV_WATCHES" \ + | base64 --decode \ + | (echo -ne "\x1f\x8b\x08\x00\x00\x00\x00\x00"; cat /dev/stdin) \ + | (gzip --decompress 2>/dev/null || true) \ + | _jq --join-output '.[] | select(.Exists ) | .Path | select(. | test($ENV.XDG_DATA_HOME + "/direnv/allow") | not) | (. + "\u0000")' + ) } _nix_direnv_manual_reload=0 @@ -229,7 +260,7 @@ use_flake() { files_to_watch+=("$flake_dir/flake.nix" "$flake_dir/flake.lock" "$flake_dir/devshell.toml") fi - nix_direnv_watch_file "${files_to_watch[@]}" + watch_file "${files_to_watch[@]}" local layout_dir profile layout_dir=$(direnv_layout_dir) @@ -238,8 +269,10 @@ use_flake() { local flake_inputs="${layout_dir}/flake-inputs/" local need_update=0 + local watches + _nix_direnv_watches watches local file= - for file in "${nix_watches[@]}"; do + for file in "${watches[@]}"; do if [[ "$file" -nt "$profile_rc" ]]; then need_update=1 break @@ -388,11 +421,13 @@ use_nix() { esac done - nix_direnv_watch_file "$HOME/.direnvrc" "$HOME/.config/direnv/direnvrc" ".envrc" "shell.nix" "default.nix" + watch_file "$HOME/.direnvrc" "$HOME/.config/direnv/direnvrc" ".envrc" "shell.nix" "default.nix" local need_update=0 + local watches + _nix_direnv_watches watches local file= - for file in "${nix_watches[@]}"; do + for file in "${watches[@]}"; do if [[ "$file" -nt "$profile_rc" ]]; then need_update=1 break From 433948e9ad48fa2c551383e41b45c2925513ec06 Mon Sep 17 00:00:00 2001 From: Arthur Noel Date: Thu, 23 Nov 2023 20:37:42 +0000 Subject: [PATCH 2/4] fix typos --- direnvrc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/direnvrc b/direnvrc index 02485f9e..faab6916 100644 --- a/direnvrc +++ b/direnvrc @@ -139,7 +139,7 @@ _nix_import_env() { eval "$(< "$profile_rc")" # `nix print-dev-env` will create a temporary directory and use it as TMPDIR - # We cannot rely on this directory being availble at all times, + # We cannot rely on this directory being available at all times, # as it may be garbage collected. # Instead - just remove it immediately. # Use recursive & force as it may not be empty. @@ -188,7 +188,7 @@ _nix_argsum_suffix() { elif has shasum; then out=$(shasum <<< "$1") else - # degrate gracefully both tools are not present + # degrade gracefully both tools are not present return fi read -r checksum _ <<< "$out" From 4248f7735b684f9291f05b32d22f84b510a98f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 26 Nov 2023 13:15:37 +0100 Subject: [PATCH 3/4] use direnv show_dump to extract direnv watches --- default.nix | 1 - direnvrc | 16 ++++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/default.nix b/default.nix index fffb0eba..a5624267 100644 --- a/default.nix +++ b/default.nix @@ -9,7 +9,6 @@ stdenv.mkDerivation { sed -i "2iNIX_BIN_PREFIX=${nix}/bin/" direnvrc substituteInPlace direnvrc \ --replace "grep" "${gnugrep}/bin/grep" \ - --replace gzip "${gzip}/bin/gzip" \ --replace JQ= "JQ=${jq}/bin/jq" ''; diff --git a/direnvrc b/direnvrc index faab6916..359a6e3c 100644 --- a/direnvrc +++ b/direnvrc @@ -206,11 +206,9 @@ nix_direnv_watch_file() { JQ= _jq() { - if [[ -n $JQ ]] - then + if [[ -n $JQ ]]; then $JQ "$@" - elif has jq - then + elif has jq; then jq "$@" else nix-shell --packages jq --run "$(join_args jq "$@")" @@ -219,15 +217,10 @@ _jq() { _nix_direnv_watches() { local -n _watches=$1 - # DIRENV_WATCHES is json | gzip (without header and trailer) | base64url - # allow files under $XDG_DATA_HOME/direenv/allow are filtered out as not relevant - # gzip header: https://datatracker.ietf.org/doc/html/rfc1952#page-6 + # allow files under $XDG_DATA_HOME/direnv/allow are filtered out as not relevant mapfile -td "" _watches < <( # shellcheck disable=2016 - tr -- "-_" "+/" <<< "$DIRENV_WATCHES" \ - | base64 --decode \ - | (echo -ne "\x1f\x8b\x08\x00\x00\x00\x00\x00"; cat /dev/stdin) \ - | (gzip --decompress 2>/dev/null || true) \ + direnv show_dump "${DIRENV_WATCHES}" \ | _jq --join-output '.[] | select(.Exists ) | .Path | select(. | test($ENV.XDG_DATA_HOME + "/direnv/allow") | not) | (. + "\u0000")' ) } @@ -237,7 +230,6 @@ nix_direnv_manual_reload() { _nix_direnv_manual_reload=1 } - use_flake() { _nix_direnv_preflight From a20b32d9cd24a671fc47f83b0b849f565767ade1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 26 Nov 2023 13:56:34 +0100 Subject: [PATCH 4/4] drop dependency on jq --- default.nix | 5 ++--- direnvrc | 35 ++++++++++++++--------------------- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/default.nix b/default.nix index a5624267..b287a36d 100644 --- a/default.nix +++ b/default.nix @@ -1,4 +1,4 @@ -{ stdenv, nix, gnugrep, gzip, jq, lib }: +{ stdenv, nix, gnugrep, lib }: stdenv.mkDerivation { name = "nix-direnv"; @@ -8,8 +8,7 @@ stdenv.mkDerivation { postPatch = '' sed -i "2iNIX_BIN_PREFIX=${nix}/bin/" direnvrc substituteInPlace direnvrc \ - --replace "grep" "${gnugrep}/bin/grep" \ - --replace JQ= "JQ=${jq}/bin/jq" + --replace "grep" "${gnugrep}/bin/grep" ''; installPhase = '' diff --git a/direnvrc b/direnvrc index 359a6e3c..60dafc13 100644 --- a/direnvrc +++ b/direnvrc @@ -202,27 +202,21 @@ nix_direnv_watch_file() { watch_file "$@" } -# set by nix build - see ./default.nix -JQ= - -_jq() { - if [[ -n $JQ ]]; then - $JQ "$@" - elif has jq; then - jq "$@" - else - nix-shell --packages jq --run "$(join_args jq "$@")" - fi -} - _nix_direnv_watches() { local -n _watches=$1 - # allow files under $XDG_DATA_HOME/direnv/allow are filtered out as not relevant - mapfile -td "" _watches < <( - # shellcheck disable=2016 - direnv show_dump "${DIRENV_WATCHES}" \ - | _jq --join-output '.[] | select(.Exists ) | .Path | select(. | test($ENV.XDG_DATA_HOME + "/direnv/allow") | not) | (. + "\u0000")' - ) + while IFS= read -r line; do + local regex='"path": "(.+)"$' + if [[ "$line" =~ $regex ]]; then + local path="${BASH_REMATCH[1]}" + if [[ "$path" == "${XDG_DATA_HOME:-${HOME:-/var/empty}/.local/share}/direnv/allow/"* ]]; then + continue + fi + # expand new lines and other json escapes + # shellcheck disable=2059 + path=$(printf "$path") + _watches+=("$path") + fi + done < <(direnv show_dump "${DIRENV_WATCHES}") } _nix_direnv_manual_reload=0 @@ -477,7 +471,6 @@ use_nix() { if [[ "$#" == 0 ]]; then - watch_file default.nix - watch_file shell.nix + watch_file default.nix shell.nix fi }