Populate repo with initial version
This commit is contained in:
parent
86140610dd
commit
cd10903ba1
58
README.md
58
README.md
@ -1,2 +1,60 @@
|
|||||||
# direnv-cache
|
# direnv-cache
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
direnv-cache consists of two components: the direnv-cache script and an
|
||||||
|
extension to direnv's stdlib.
|
||||||
|
|
||||||
|
To set up direnv-cache, make direnv read the provided direnvrc, eg. via
|
||||||
|
|
||||||
|
cp direnvrc ~/.config/direnv/direnvrc
|
||||||
|
|
||||||
|
and install direnv-cache somewhere in your PATH.
|
||||||
|
|
||||||
|
If you use home-manager, you can add the following to your configuration
|
||||||
|
|
||||||
|
...
|
||||||
|
let
|
||||||
|
direnv-cache = pkgs.callPackage ./path/to/this/repo {};
|
||||||
|
in
|
||||||
|
...
|
||||||
|
|
||||||
|
home.packages = [ ... direnv-cache ... ];
|
||||||
|
programs.direnv = {
|
||||||
|
enable = true;
|
||||||
|
enableBashIntegration = true;
|
||||||
|
stdlib = builtins.readFile direnv-cache.direnvrc;
|
||||||
|
};
|
||||||
|
...
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The following assumes a working direnv setup.
|
||||||
|
|
||||||
|
Use the cache function in your `.envrc` files, eg.
|
||||||
|
|
||||||
|
cache <<EOF
|
||||||
|
# everything in here will be cached
|
||||||
|
use nix -p hello
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# you can also have stuff outside the cached region
|
||||||
|
export PATH=/some/other/path:$PATH
|
||||||
|
|
||||||
|
If you now enter the directory, direnv will tell you that the environment
|
||||||
|
is not yet cached. We can fix that by running `direnv-cache reload`. This
|
||||||
|
will also tell direnv to reload. From now on, if you enter the directory,
|
||||||
|
direnv will load the cached environment.
|
||||||
|
|
||||||
|
Re-run `direnv-cache reload` whenever your `.envrc` or other dependencies change
|
||||||
|
to update the cache.
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|
Everything piped into the `cache` function is stored in a recipe file in
|
||||||
|
direnv-cache's cache directory when the `.envrc` is evaluated. Then, if the
|
||||||
|
environment cache exists, it is sourced.
|
||||||
|
|
||||||
|
When `direnv-cache reload` is called, it looks for a recipe file for the
|
||||||
|
current directory, and runs it. A diff of the environments before and after the
|
||||||
|
recipe is run is written to the directory-specific cache file.
|
||||||
|
3
default.nix
Normal file
3
default.nix
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
|
(pkgs.writers.writeBashBin "direnv-cache" ./direnv-cache).overrideAttrs
|
||||||
|
(o: { passthru = { direnvrc = ./direnvrc; }; })
|
106
direnv-cache
Executable file
106
direnv-cache
Executable file
@ -0,0 +1,106 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Dumps all environment variables sorted alphabetically. Uses zero byte as a
|
||||||
|
# delimiter since bash variables can not contain '\0'.
|
||||||
|
dumpEnv() {
|
||||||
|
env -0 | sort -z
|
||||||
|
}
|
||||||
|
|
||||||
|
# Retrieves the value of variable name passed as $1 in dumped environment
|
||||||
|
# passed as $2 (see dumpEnv)
|
||||||
|
getByName() {
|
||||||
|
local name="$1"
|
||||||
|
local envFile="$2"
|
||||||
|
grep -z "^${name}=" $envFile | cut -z -f2- -d '=' | tr -d '\0'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Produces a diff of two given environment dumps, suitable for consumption by
|
||||||
|
# bash. Given environment dumps A and B (both generated by dumpEnv),
|
||||||
|
#
|
||||||
|
# source A; source <(diffEnvs A B)
|
||||||
|
#
|
||||||
|
# shall be equivalent to
|
||||||
|
#
|
||||||
|
# source B
|
||||||
|
#
|
||||||
|
diffEnvs() {
|
||||||
|
local name
|
||||||
|
local old="$1"
|
||||||
|
local new="$2"
|
||||||
|
|
||||||
|
while read -r -d '' line; do
|
||||||
|
name=$(tr -d '\0' <<<"$line" | head -n1 | cut -f1 -d'=')
|
||||||
|
if ! getByName "$name" "$new" >/dev/null; then
|
||||||
|
echo "export -n '${name}'"
|
||||||
|
fi
|
||||||
|
done <"$old"
|
||||||
|
|
||||||
|
while read -rd $'\0' line; do
|
||||||
|
name=$(tr -d '\0' <<<"$line" | head -n1 | cut -f1 -d'=')
|
||||||
|
if getByName "$name" "$old" >/dev/null; then
|
||||||
|
# found in old env, check if values match
|
||||||
|
if ! grep -z "^${line}\$" "$old" >/dev/null; then
|
||||||
|
# variable has changed
|
||||||
|
echo "export ${line@Q}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# variable is new
|
||||||
|
echo "export ${line@Q}"
|
||||||
|
fi
|
||||||
|
done <"$new"
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "${BASH_SOURCE[0]} COMMAND"
|
||||||
|
echo
|
||||||
|
echo "Commands:"
|
||||||
|
echo -e "\tstatus,s: Show cache status"
|
||||||
|
echo -e "\treload,r: Recreate cache from .envrc"
|
||||||
|
echo -e "\tclear,c: Remove cache file for current directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
getCacheFilePath() {
|
||||||
|
local cacheDir="${XDG_CACHE_HOME:-$HOME/.cache}/direnv-cache"
|
||||||
|
echo "${cacheDir}/$(pwd | sha1sum | tr -d ' -')"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd="$1"
|
||||||
|
|
||||||
|
if ! [[ -e .envrc ]]; then
|
||||||
|
echo "Error, no .envrc found in current directory"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cacheFile=$(getCacheFilePath)
|
||||||
|
|
||||||
|
case $cmd in
|
||||||
|
reload|r)
|
||||||
|
echo "Re-creating cache"
|
||||||
|
mkdir -p "$(dirname ${cacheFile})"
|
||||||
|
dumpEnv > "${cacheFile}.pre"
|
||||||
|
source <(direnv stdlib)
|
||||||
|
if [[ .envrc -nt ${cacheFile}.recipe ]]; then
|
||||||
|
direnv exec . true > /dev/null
|
||||||
|
fi
|
||||||
|
source "${cacheFile}.recipe"
|
||||||
|
dumpEnv > "${cacheFile}.post"
|
||||||
|
diffEnvs "${cacheFile}.pre" "${cacheFile}.post" > "$cacheFile"
|
||||||
|
rm "${cacheFile}.pre" "${cacheFile}.post"
|
||||||
|
echo "Environment cached in $cacheFile, telling direnv to reload"
|
||||||
|
direnv reload
|
||||||
|
;;
|
||||||
|
status|s)
|
||||||
|
shift
|
||||||
|
ls "$cacheFile" "$@"
|
||||||
|
;;
|
||||||
|
clear|c)
|
||||||
|
if [[ -e "$cacheFile" ]]; then
|
||||||
|
rm "$cacheFile"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
esac
|
17
direnvrc
Normal file
17
direnvrc
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# -*- mode: sh -*-
|
||||||
|
|
||||||
|
cache() {
|
||||||
|
|
||||||
|
local cacheDir="${XDG_CACHE_HOME:-$HOME/.cache}/direnv-cache"
|
||||||
|
mkdir -p "$cacheDir"
|
||||||
|
local cacheFile
|
||||||
|
cacheFile="${cacheDir}/$(pwd | sha1sum | tr -d ' -')"
|
||||||
|
cat - > "${cacheFile}.recipe"
|
||||||
|
if [[ -e "$cacheFile" ]]; then
|
||||||
|
echo "Using cached environment from $cacheFile"
|
||||||
|
. $cacheFile
|
||||||
|
else
|
||||||
|
echo "Environment not cached"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user