diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2021-07-09 00:47:57 +0200 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2021-07-09 01:18:37 +0200 |
commit | b1f1347ade81d1f04f2d490baceefb3c4de0b4e3 (patch) | |
tree | 754842669bbb8749ef6c1a0e071500bcf23e21db /src/nix/get-env.sh | |
parent | b1cfe8f984145c836c1dab229c1117d6396a4305 (diff) |
nix develop: Don't parse bash environment with regexes
Instead have get-env.sh dump the bash environment as JSON. This should
be a lot less error-prone.
Fixes #4992.
Diffstat (limited to 'src/nix/get-env.sh')
-rw-r--r-- | src/nix/get-env.sh | 92 |
1 files changed, 90 insertions, 2 deletions
diff --git a/src/nix/get-env.sh b/src/nix/get-env.sh index 091c0f573..834b84e35 100644 --- a/src/nix/get-env.sh +++ b/src/nix/get-env.sh @@ -8,10 +8,98 @@ if [[ -n $stdenv ]]; then source $stdenv/setup fi +# Better to use compgen, but stdenv bash doesn't have it. +__vars="$(declare -p)" +__functions="$(declare -F)" + +__dumpEnv() { + printf '{\n' + + printf ' "bashFunctions": {\n' + local __first=1 + while read __line; do + if ! [[ $__line =~ ^declare\ -f\ (.*) ]]; then continue; fi + __fun_name="${BASH_REMATCH[1]}" + __fun_body="$(type $__fun_name)" + if [[ $__fun_body =~ \{(.*)\} ]]; then + if [[ -z $__first ]]; then printf ',\n'; else __first=; fi + __fun_body="${BASH_REMATCH[1]}" + printf " " + __escapeString "$__fun_name" + printf ':' + __escapeString "$__fun_body" + else + printf "Cannot parse definition of function '%s'.\n" "$__fun_name" >&2 + return 1 + fi + done < <(printf "%s\n" "$__functions") + printf '\n },\n' + + printf ' "variables": {\n' + local __first=1 + while read __line; do + if ! [[ $__line =~ ^declare\ (-[^ ])\ ([^=]*) ]]; then continue; fi + local type="${BASH_REMATCH[1]}" + local __var_name="${BASH_REMATCH[2]}" + + if [[ -z $__first ]]; then printf ',\n'; else __first=; fi + + printf " " + __escapeString "$__var_name" + printf ': {' + + # FIXME: handle -i, -r, -n. + if [[ $type == -x ]]; then + printf '"type": "exported", "value": ' + __escapeString "${!__var_name}" + elif [[ $type == -- ]]; then + printf '"type": "var", "value": ' + __escapeString "${!__var_name}" + elif [[ $type == -a ]]; then + printf '"type": "array", "value": [' + local __first2=1 + __var_name="$__var_name[@]" + for __i in "${!__var_name}"; do + if [[ -z $__first2 ]]; then printf ', '; else __first2=; fi + __escapeString "$__i" + printf ' ' + done + printf ']' + elif [[ $type == -A ]]; then + printf '"type": "associative", "value": {\n' + local __first2=1 + declare -n __var_name2="$__var_name" + for __i in "${!__var_name2[@]}"; do + if [[ -z $__first2 ]]; then printf ',\n'; else __first2=; fi + printf " " + __escapeString "$__i" + printf ": " + __escapeString "${__var_name2[$__i]}" + done + printf '\n }' + else + printf '"type": "unknown"' + fi + + printf "}" + done < <(printf "%s\n" "$__vars") + printf '\n }\n}' +} + +__escapeString() { + local __s="$1" + __s="${__s//\\/\\\\}" + __s="${__s//\"/\\\"}" + __s="${__s//$'\n'/\\n}" + __s="${__s//$'\r'/\\r}" + __s="${__s//$'\t'/\\t}" + printf '"%s"' "$__s" +} + +# Dump the bash environment as JSON. for __output in $outputs; do if [[ -z $__done ]]; then - export > ${!__output} - set >> ${!__output} + __dumpEnv > ${!__output} __done=1 else echo -n >> ${!__output} |