# Stolen from
# https://github.com/joshuaclayton/dotfiles/blob/master/zsh_profile.d/autoenv.zsh
+# TODO: move this to DOTENV_*?!
export ENV_AUTHORIZATION_FILE=$HOME/.env_auth
+: ${DOTENV_FILE_ENTER:=.env}
+: ${DOTENV_FILE_LEAVE:=.env.leave}
+
+# Look for .env in parent dirs?
+: ${DOTENV_LOOK_UPWARDS:=0}
+
+# Handle leave events, when leaving ?
+: ${DOTENV_HANDLE_LEAVE:=1}
+
+
_dotenv_hash_pair() {
local env_file=$1
env_shasum=$(shasum $env_file | cut -d' ' -f1)
}
_dotenv_print_unauthorized_message() {
- echo "Attempting to load unauthorized env: $1"
+ echo "Attempting to load unauthorized env file: $1"
echo ""
echo "**********************************************"
echo ""
echo ""
echo "**********************************************"
echo ""
- echo "Would you like to authorize it? (y/n)"
+ echo -n "Would you like to authorize it? [y/N] "
}
# This function can be mocked in tests
_dotenv_read_answer() {
- read answer
+ local answer
+ read -q answer
+ echo $answer
}
-_dotenv_source_env() {
- local env_file="$PWD/.env"
+_dotenv_check_authorized_env_file() {
+ if ! _dotenv_authorized_env_file $1; then
+ _dotenv_print_unauthorized_message $1
- if [[ -f $env_file ]]
- then
- if _dotenv_authorized_env_file $env_file
- then
- source $env_file
- return 0
+ local answer=$(_dotenv_read_answer)
+ echo
+ if [[ $answer != 'y' ]]; then
+ return 1
fi
- _dotenv_print_unauthorized_message $env_file
+ _dotenv_authorize $1
+ fi
+ return 0
+}
+
+_dotenv_stack_entered=()
- _dotenv_read_answer
+_dotenv_chpwd_handler() {
+ local env_file="$PWD/$DOTENV_FILE_ENTER"
+
+ # Handle leave event for previously sourced env files.
+ if [[ $DOTENV_HANDLE_LEAVE == 1 ]] && (( $#_dotenv_stack_entered )); then
+ for prev_dir in ${_dotenv_stack_entered}; do
+ if ! [[ ${PWD}/ == ${prev_dir}/* ]]; then
+ local env_file_leave=$prev_dir/$DOTENV_FILE_LEAVE
+ if _dotenv_check_authorized_env_file $env_file_leave; then
+ _dotenv_event=leave
+ source $env_file_leave
+ unset _dotenv_event
+ fi
+ # Remove this entry from the stack.
+ _dotenv_stack_entered=(${_dotenv_stack_entered#$prev_dir})
+ fi
+ done
+ fi
- if [[ $answer == 'y' ]]
- then
- _dotenv_authorize $env_file
- source $env_file
+ if ! [[ -f $env_file ]] && [[ $DOTENV_LOOK_UPWARDS == 1 ]]; then
+ setopt localoptions extendedglob
+ local m
+ m=((../)#${DOTENV_FILE_ENTER}(N))
+ if (( $#m )); then
+ env_file=$m[1]
fi
fi
+
+ if ! [[ -f $env_file ]]; then
+ return
+ fi
+
+ if ! _dotenv_check_authorized_env_file $env_file; then
+ return
+ fi
+
+ # Load the env file only once.
+ if (( ${+_dotenv_stack_entered[(r)${env_file:A:h}]} )); then
+ return
+ fi
+
+ _dotenv_stack_entered+=(${env_file:A:h})
+
+ _dotenv_event=enter
+ source $env_file
+ unset _dotenv_event
}
-chpwd_functions=($chpwd_functions _dotenv_source_env)
+autoload -U add-zsh-hook
+add-zsh-hook chpwd _dotenv_chpwd_handler
+
+# Look in current directory already.
+_dotenv_chpwd_handler
Lets set a simple .env action
- $ echo 'echo blah' >> .env
+ $ echo 'echo ENTERED' >> .env
Manually create auth file
- $ echo "$PWD/.env:$(echo echo blah | shasum)" > $ENV_AUTHORIZATION_FILE
+ $ echo "$PWD/.env:$(echo echo ENTERED | shasum)" > $ENV_AUTHORIZATION_FILE
$ cd .
- blah
+ ENTERED
Now try to make it accept it
+ $ unset _dotenv_stack_entered
$ rm $ENV_AUTHORIZATION_FILE
- $ _dotenv_read_answer() { answer='y' }
+ $ _dotenv_read_answer() { echo 'y' }
$ cd .
- Attempting to load unauthorized env: /tmp/cramtests-??????/autoenv.t/.env (glob)
+ Attempting to load unauthorized env file: /tmp/cramtests-??????/autoenv.t/.env (glob)
**********************************************
- echo blah
+ echo ENTERED
**********************************************
- Would you like to authorize it? (y/n)
- blah
+ Would you like to authorize it? [y/N]
+ ENTERED
-The last "blah" is because it executed the command
+The last "ENTERED" is because it executed the command
Now lets see that it actually checks the shasum value
+ $ unset _dotenv_stack_entered
$ cd .
- blah
+ ENTERED
+
+ $ unset _dotenv_stack_entered
$ rm $ENV_AUTHORIZATION_FILE
$ echo "$PWD/.env:$(echo mischief | shasum)" > $ENV_AUTHORIZATION_FILE
$ cd .
- Attempting to load unauthorized env: /tmp/cramtests-??????/autoenv.t/.env (glob)
+ Attempting to load unauthorized env file: /tmp/cramtests-??????/autoenv.t/.env (glob)
**********************************************
- echo blah
+ echo ENTERED
**********************************************
- Would you like to authorize it? (y/n)
- blah
+ Would you like to authorize it? [y/N]
+ ENTERED
Now, will it take no for an answer?
+ $ unset _dotenv_stack_entered
$ rm $ENV_AUTHORIZATION_FILE
- $ _dotenv_read_answer() { answer='n' }
+ $ _dotenv_read_answer() { echo 'n' }
$ cd .
- Attempting to load unauthorized env: /tmp/cramtests-??????/autoenv.t/.env (glob)
+ Attempting to load unauthorized env file: /tmp/cramtests-??????/autoenv.t/.env (glob)
**********************************************
- echo blah
+ echo ENTERED
**********************************************
- Would you like to authorize it? (y/n)
+ Would you like to authorize it? [y/N]
Lets also try one more time to ensure it didnt add it
$ cd .
- Attempting to load unauthorized env: /tmp/cramtests-??????/autoenv.t/.env (glob)
+ Attempting to load unauthorized env file: /tmp/cramtests-??????/autoenv.t/.env (glob)
**********************************************
- echo blah
+ echo ENTERED
**********************************************
- Would you like to authorize it? (y/n)
+ Would you like to authorize it? [y/N]
--- /dev/null
+Ensure we have our mocked out ENV_AUTHORIZATION_FILE
+
+ $ [[ $ENV_AUTHORIZATION_FILE[0,4] == '/tmp' ]] || return 1
+
+
+Lets set a simple .env action
+
+ $ mkdir sub
+ $ cd sub
+ $ echo 'echo ENTERED' >> .env
+ $ echo 'echo LEFT' >> .env.leave
+
+Change to the directory.
+
+ $ _dotenv_read_answer() { echo 'y' }
+ $ cd .
+ Attempting to load unauthorized env file: /tmp/cramtests-??????/leave.t/sub/.env (glob)
+
+ **********************************************
+
+ echo ENTERED
+
+ **********************************************
+
+ Would you like to authorize it? [y/N]
+ ENTERED
+
+
+Leave the directory and answer "no".
+
+ $ _dotenv_read_answer() { echo 'n' }
+ $ cd ..
+ Attempting to load unauthorized env file: /tmp/cramtests-??????/leave.t/sub/.env.leave (glob)
+
+ **********************************************
+
+ echo LEFT
+
+ **********************************************
+
+ Would you like to authorize it? [y/N]
+
+
+ $ cd sub
+ ENTERED
+ $ _dotenv_read_answer() { echo 'y' }
+ $ cd ..
+ Attempting to load unauthorized env file: /tmp/cramtests-??????/leave.t/sub/.env.leave (glob)
+
+ **********************************************
+
+ echo LEFT
+
+ **********************************************
+
+ Would you like to authorize it? [y/N]
+ LEFT
+
+
+Now check with subdirs, looking upwards.
+
+ $ DOTENV_LOOK_UPWARDS=1
+ $ mkdir sub/child
+ $ cd sub/child
+ ENTERED
+ $ cd .
+ $ cd ..
+ $ cd ..
+ LEFT
+
+
+Now check with subdirs, not looking at parent dirs.
+
+ $ DOTENV_LOOK_UPWARDS=0
+ $ cd sub/child
+ $ cd ..
+ ENTERED
+ $ cd child
+ $ cd ../..
+ LEFT