-
Notifications
You must be signed in to change notification settings - Fork 349
/
direnvrc
222 lines (188 loc) · 6.04 KB
/
direnvrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# shellcheck shell=bash
# adapted from https://github.com/nix-community/nix-direnv/blob/master/direnvrc
REQUIRED_DIRENV_VERSION="2.21.3"
_nix_direnv_preflight () {
if [[ -z "$direnv" ]]; then
printf '%s\n' "\$direnv environment variable was not defined. Was this script run inside direnv?"
exit 1
fi
if [[ -z ${DEVENV_BIN:-} ]]; then
DEVENV_BIN=$(command -v devenv)
if [[ -z "${DEVENV_BIN}" ]]; then
log_error "command not found: devenv, see https://devenv.sh/getting-started/"
exit 1
fi
fi
if ! has direnv_version || ! direnv_version "$REQUIRED_DIRENV_VERSION" 2>/dev/null; then
log_error "base direnv version is older than the required v$REQUIRED_DIRENV_VERSION."
exit 1
fi
local layout_dir
layout_dir=$(direnv_layout_dir)
if [[ ! -d "$layout_dir" ]]; then
mkdir -p "$layout_dir"
fi
export DEVENV_DIRENVRC_VERSION=1
export DEVENV_DIRENVRC_ROLLING_UPGRADE=0
}
_nix_export_or_unset() {
local key=$1 value=$2
if [[ "$value" == __UNSET__ ]]; then
unset "$key"
else
export "$key=$value"
fi
}
_nix_import_env() {
local profile_rc=$1
# Note which environments are active, but make sure we don't repeat them
if [[ ! "''${DIRENV_ACTIVE-}" =~ (^|:)"$PWD"(:|$) ]]; then
export DIRENV_ACTIVE="$PWD:''${DIRENV_ACTIVE-}"
fi
local old_nix_build_top=${NIX_BUILD_TOP:-__UNSET__}
local old_tmp=${TMP:-__UNSET__}
local old_tmpdir=${TMPDIR:-__UNSET__}
local old_temp=${TEMP:-__UNSET__}
local old_tempdir=${TEMPDIR:-__UNSET__}
local old_xdg_data_dirs=${XDG_DATA_DIRS:-}
eval "$(< "$profile_rc")"
# `nix print-dev-env` will create a temporary directory and use it as TMPDIR
# 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.
if [[ -n "${NIX_BUILD_TOP+x}" && "$NIX_BUILD_TOP" == */nix-shell.* && -d "$NIX_BUILD_TOP" ]]; then
rm -rf "$NIX_BUILD_TOP"
fi
_nix_export_or_unset NIX_BUILD_TOP "$old_nix_build_top"
_nix_export_or_unset TMP "$old_tmp"
_nix_export_or_unset TMPDIR "$old_tmpdir"
_nix_export_or_unset TEMP "$old_temp"
_nix_export_or_unset TEMPDIR "$old_tempdir"
local new_xdg_data_dirs=${XDG_DATA_DIRS:-}
export XDG_DATA_DIRS=
local IFS=:
for dir in $new_xdg_data_dirs${old_xdg_data_dirs:+:}$old_xdg_data_dirs; do
dir="${dir%/}" # remove trailing slashes
if [[ :$XDG_DATA_DIRS: = *:$dir:* ]]; then
continue # already present, skip
fi
XDG_DATA_DIRS="$XDG_DATA_DIRS${XDG_DATA_DIRS:+:}$dir"
done
}
_nix_argsum_suffix() {
local out checksum content
args=("$@")
sorted_args=$(printf "%s\n" "${args[@]}" | sort -u)
content=$(cat "${sorted_args[@]}" 2>/dev/null)
if has sha1sum; then
out=$(sha1sum <<< "$content")
elif has shasum; then
out=$(shasum <<< "$content")
else
log_status "not hashing your cache, please install sha1sum"
# degrate gracefully both tools are not present
return
fi
read -r checksum _ <<< "$out"
echo "-$checksum"
}
nix_direnv_watch_file() {
log_error "nix_direnv_watch_file is deprecated. Use watch_file instead."
watch_file "$@"
}
_nix_direnv_watches() {
local -n _watches=$1
if [[ -z ${DIRENV_WATCHES-} ]]; then
return
fi
while IFS= read -r line; do
local regex='"[Pp]ath": "(.+)"$'
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}")
}
_devenv_watches() {
local path=$1
local -n _watches=$2
if [[ -f "$path" ]]; then
while IFS= read -r file; do
file=$(printf "$file")
_watches+=("$file")
done < "$path"
fi
}
_devenv_profile_rc() {
local -n _watches=$1
local layout_dir profile
layout_dir=$(direnv_layout_dir)
profile="${layout_dir}/devenv-profile$(_nix_argsum_suffix "${_watches[@]}")"
echo "${profile}.rc"
}
use_devenv() {
_nix_direnv_preflight
flake_expr="${1:-.}"
flake_dir="${flake_expr%#*}"
env_deps_path="$flake_dir/.devenv/input-paths.txt"
local default_watches
default_watches=(".envrc" "$HOME/.direnvrc" "$HOME/.config/direnv/direnvrc")
if [[ -d "$flake_dir" ]]; then
default_watches+=("$flake_dir/devenv.nix" "$flake_dir/devenv.lock" "$flake_dir/devenv.yaml" "$flake_dir/devenv.local.nix")
if [[ -f "$flake_dir/devenv.yaml" ]]; then
if ! devenv assemble; then
log_error "$(devenv version) failed to parse devenv.yaml, make sure to use version 0.6 or newer and fix the errors above."
exit 0
fi
fi
fi
# Watch the default files
watch_file "${default_watches[@]}"
# Fetch and watch files that affect the env
local env_watches
_devenv_watches "$env_deps_path" env_watches
watch_file "${env_watches[@]}"
# Fetch all files that direnv is currently watching
local watches
_nix_direnv_watches watches
profile_rc=$(_devenv_profile_rc watches)
local need_update=0
local file=
for file in "${watches[@]}"; do
if [[ "$file" -nt "$profile_rc" ]]; then
need_update=1
log_status "$file changed, reloading"
break
fi
done
if [[ ! -e "$profile_rc" || "$need_update" == "1" ]];
then
# We need to update our cache
local env
if ! env=$("${DEVENV_BIN}" print-dev-env); then
log_error "failed to build the devenv environment. devenv.nix may contain errors. see above."
exit 0
fi
# Re-watch files that affect the env
local env_watches
_devenv_watches "$env_deps_path" env_watches
watch_file "${env_watches[@]}"
# Fetch the final watches and compute the new profile_rc
local watches
_nix_direnv_watches watches
profile_rc=$(_devenv_profile_rc watches)
echo "$env" > "$profile_rc"
log_status "updated devenv shell cache"
_nix_import_env "$profile_rc"
else
log_status "using cached devenv shell"
_nix_import_env "$profile_rc"
fi
}