use lorri for envrc, faster better
This commit is contained in:
parent
4ebfda2215
commit
eefd8e1210
154
.envrc
154
.envrc
|
@ -1,153 +1 @@
|
||||||
# Usage: use_nix [...]
|
eval "$(lorri direnv)"
|
||||||
#
|
|
||||||
# Load environment variables from `nix-shell`.
|
|
||||||
# If you have a `default.nix` or `shell.nix` one of these will be used and
|
|
||||||
# the derived environment will be stored at ./.direnv/env-<hash>
|
|
||||||
# and symlink to it will be created at ./.direnv/default.
|
|
||||||
# Dependencies are added to the GC roots, such that the environment remains persistent.
|
|
||||||
#
|
|
||||||
# The resulting environment is cached for better performance.
|
|
||||||
#
|
|
||||||
# To trigger switch to a different environment:
|
|
||||||
# `rm -f .direnv/default`
|
|
||||||
#
|
|
||||||
# To derive a new environment:
|
|
||||||
# `rm -rf .direnv/env-$(md5sum {shell,default}.nix 2> /dev/null | cut -c -32)`
|
|
||||||
#
|
|
||||||
# To remove cache:
|
|
||||||
# `rm -f .direnv/dump-*`
|
|
||||||
#
|
|
||||||
# To remove all environments:
|
|
||||||
# `rm -rf .direnv/env-*`
|
|
||||||
#
|
|
||||||
# To remove only old environments:
|
|
||||||
# `find .direnv -name 'env-*' -and -not -name `readlink .direnv/default` -exec rm -rf {} +`
|
|
||||||
#
|
|
||||||
|
|
||||||
set -eo pipefail
|
|
||||||
|
|
||||||
use_nix() {
|
|
||||||
# define all local variables
|
|
||||||
local shell f env_hash dir default wd drv dump path_backup
|
|
||||||
local files_to_watch=()
|
|
||||||
|
|
||||||
declare opt
|
|
||||||
declare OPTARG
|
|
||||||
declare OPTIND
|
|
||||||
|
|
||||||
while getopts ":s:w:" opt; do
|
|
||||||
case "${opt}" in
|
|
||||||
s)
|
|
||||||
shell="${OPTARG}"
|
|
||||||
files_to_watch=("${files_to_watch[@]}" "${shell}")
|
|
||||||
;;
|
|
||||||
w)
|
|
||||||
files_to_watch=("${files_to_watch[@]}" "${OPTARG}")
|
|
||||||
;;
|
|
||||||
:)
|
|
||||||
>&2 echo "Invalid option: $OPTARG requires an argument"
|
|
||||||
;;
|
|
||||||
\?)
|
|
||||||
>&2 echo "Invalid option: $OPTARG"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
shift $((OPTIND -1))
|
|
||||||
|
|
||||||
if [[ -z "${shell}" ]]; then
|
|
||||||
>&2 echo "ERR: no shell was given"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
for f in "${files_to_watch[@]}"; do
|
|
||||||
if ! [[ -f "${f}" ]]; then
|
|
||||||
>&2 echo "cannot watch file ${f} because it does not exist"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# compute the hash of all the files that makes up the development environment
|
|
||||||
env_hash="$(hashContents "${files_to_watch[@]}")"
|
|
||||||
|
|
||||||
dir="$(direnv_layout_dir)"
|
|
||||||
default="${dir}/default"
|
|
||||||
if [[ ! -L "${default}" ]] || [[ ! -d $(readlink "${default}") ]]; then
|
|
||||||
wd="${dir}/env-${env_hash}"
|
|
||||||
mkdir -p "${wd}"
|
|
||||||
|
|
||||||
drv="${wd}/env.drv"
|
|
||||||
if [[ ! -f "${drv}" ]]; then
|
|
||||||
log_status "use nix: deriving new environment"
|
|
||||||
IN_NIX_SHELL=1 nix-instantiate --add-root "${drv}" --indirect "${shell}" > /dev/null
|
|
||||||
nix-store -r $(nix-store --query --references "${drv}") --add-root "${wd}/dep" --indirect > /dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f "${default}"
|
|
||||||
ln -s $(basename "${wd}") "${default}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
drv=$(readlink "${default}/env.drv")
|
|
||||||
dump="${dir}/dump-$(hashFile ".envrc")-$(hashFile ${drv})"
|
|
||||||
|
|
||||||
if [[ ! -f "${dump}" ]] || [[ "${XDG_CONFIG_DIR}/direnv/direnvrc" -nt "${dump}" ]]; then
|
|
||||||
log_status "use nix: updating cache"
|
|
||||||
|
|
||||||
old=$(find "${dir}" -name 'dump-*')
|
|
||||||
nix-shell --pure "${drv}" --show-trace --run "$(join_args "$direnv" dump bash)" > "${dump}"
|
|
||||||
rm -f ${old}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# evaluate the dump created by nix-shell earlier, but have to merge the PATH
|
|
||||||
# with the current PATH
|
|
||||||
# NOTE: we eval the dump here as opposed to direnv_load it because we don't
|
|
||||||
# want to persist environment variables coming from the shell at the time of
|
|
||||||
# the dump. See https://github.com/direnv/direnv/issues/405 for context.
|
|
||||||
path_backup="${PATH}"
|
|
||||||
eval $(cat "${dump}")
|
|
||||||
export PATH="${PATH}:${path_backup}"
|
|
||||||
|
|
||||||
for f in "${files_to_watch[@]}"; do
|
|
||||||
watch_file "${f}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
hashContents() {
|
|
||||||
if has md5sum; then
|
|
||||||
cat "${@}" | md5sum | cut -c -32
|
|
||||||
elif has md5; then
|
|
||||||
cat "${@}" | md5 -q
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
hashFile() {
|
|
||||||
if has md5sum; then
|
|
||||||
md5sum "${@}" | cut -c -32
|
|
||||||
elif has md5; then
|
|
||||||
md5 -q "${@}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
log_error "${@}"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
validateVersion() {
|
|
||||||
local version="$("${direnv}" version)"
|
|
||||||
local major="$(echo "${version}" | cut -d. -f1)"
|
|
||||||
local minor="$(echo "${version}" | cut -d. -f2)"
|
|
||||||
local patch="$(echo "${version}" | cut -d. -f3)"
|
|
||||||
|
|
||||||
if [[ "${major}" -gt 2 ]]; then return 0; fi
|
|
||||||
if [[ "${major}" -eq 2 ]] && [[ "${minor}" -gt 18 ]]; then return 0; fi
|
|
||||||
if [[ "${major}" -eq 2 ]] && [[ "${minor}" -eq 18 ]] && [[ "${patch}" -ge 2 ]]; then return 0; fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if ! validateVersion; then
|
|
||||||
echo "This .envrc requires direnv version 2.18.2 or above."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
use_nix -s shell.nix
|
|
||||||
|
|
Loading…
Reference in a new issue