]> Sergey Matveev's repositories - zsh-autoenv.git/blob - autoenv.zsh
Various improvements
[zsh-autoenv.git] / autoenv.zsh
1 # Stolen from
2 # https://github.com/joshuaclayton/dotfiles/blob/master/zsh_profile.d/autoenv.zsh
3
4 # TODO: move this to DOTENV_*?!
5 export ENV_AUTHORIZATION_FILE=$HOME/.env_auth
6
7 : ${DOTENV_FILE_ENTER:=.env}
8 : ${DOTENV_FILE_LEAVE:=.env.leave}
9
10 # Look for .env in parent dirs?
11 : ${DOTENV_LOOK_UPWARDS:=0}
12
13 # Handle leave events, when leaving ?
14 : ${DOTENV_HANDLE_LEAVE:=1}
15
16
17 _dotenv_hash_pair() {
18   local env_file=$1
19   env_shasum=$(shasum $env_file | cut -d' ' -f1)
20   echo "$env_file:$env_shasum"
21 }
22
23 _dotenv_authorized_env_file() {
24   local env_file=$1
25   local pair=$(_dotenv_hash_pair $env_file)
26   touch $ENV_AUTHORIZATION_FILE
27   \grep -Gq $pair $ENV_AUTHORIZATION_FILE
28 }
29
30 _dotenv_authorize() {
31   local env_file=$1
32   _dotenv_deauthorize $env_file
33   _dotenv_hash_pair $env_file >> $ENV_AUTHORIZATION_FILE
34 }
35
36 _dotenv_deauthorize() {
37   local env_file=$1
38   echo $(\grep -Gv $env_file $ENV_AUTHORIZATION_FILE) > $ENV_AUTHORIZATION_FILE
39 }
40
41 _dotenv_print_unauthorized_message() {
42   echo "Attempting to load unauthorized env file: $1"
43   echo ""
44   echo "**********************************************"
45   echo ""
46   cat $1
47   echo ""
48   echo "**********************************************"
49   echo ""
50   echo -n "Would you like to authorize it? [y/N] "
51 }
52
53 # This function can be mocked in tests
54 _dotenv_read_answer() {
55   local answer
56   read -q answer
57   echo $answer
58 }
59
60 _dotenv_check_authorized_env_file() {
61   if ! _dotenv_authorized_env_file $1; then
62     _dotenv_print_unauthorized_message $1
63
64     local answer=$(_dotenv_read_answer)
65     echo
66     if [[ $answer != 'y' ]]; then
67       return 1
68     fi
69
70     _dotenv_authorize $1
71   fi
72   return 0
73 }
74
75 _dotenv_stack_entered=()
76
77 _dotenv_chpwd_handler() {
78   local env_file="$PWD/$DOTENV_FILE_ENTER"
79
80   # Handle leave event for previously sourced env files.
81   if [[ $DOTENV_HANDLE_LEAVE == 1 ]] && (( $#_dotenv_stack_entered )); then
82     for prev_dir in ${_dotenv_stack_entered}; do
83       if ! [[ ${PWD}/ == ${prev_dir}/* ]]; then
84         local env_file_leave=$prev_dir/$DOTENV_FILE_LEAVE
85         if _dotenv_check_authorized_env_file $env_file_leave; then
86           _dotenv_event=leave
87           source $env_file_leave
88           unset _dotenv_event
89         fi
90         # Remove this entry from the stack.
91         _dotenv_stack_entered=(${_dotenv_stack_entered#$prev_dir})
92       fi
93     done
94   fi
95
96   if ! [[ -f $env_file ]] && [[ $DOTENV_LOOK_UPWARDS == 1 ]]; then
97     setopt localoptions extendedglob
98     local m
99     m=((../)#${DOTENV_FILE_ENTER}(N))
100     if (( $#m )); then
101       env_file=$m[1]
102     fi
103   fi
104
105   if ! [[ -f $env_file ]]; then
106     return
107   fi
108
109   if ! _dotenv_check_authorized_env_file $env_file; then
110     return
111   fi
112
113   # Load the env file only once.
114   if (( ${+_dotenv_stack_entered[(r)${env_file:A:h}]} )); then
115     return
116   fi
117
118   _dotenv_stack_entered+=(${env_file:A:h})
119
120   _dotenv_event=enter
121   source $env_file
122   unset _dotenv_event
123 }
124
125 autoload -U add-zsh-hook
126 add-zsh-hook chpwd _dotenv_chpwd_handler
127
128 # Look in current directory already.
129 _dotenv_chpwd_handler