mirror of
https://github.com/Tarrasch/zsh-autoenv.git
synced 2024-11-22 15:30:59 +02:00
Merge pull request #8 from blueyed/next
Next: varstash integration, tests refactoring, s/dotenv/autoenv/ and some more
This commit is contained in:
commit
c2a3009d4a
14
Makefile
14
Makefile
@ -1,7 +1,17 @@
|
|||||||
.PHONY: itest test
|
.PHONY: itest test
|
||||||
|
|
||||||
|
test:
|
||||||
|
ZDOTDIR="${PWD}/tests" cram --shell=zsh -v tests
|
||||||
|
|
||||||
itest:
|
itest:
|
||||||
ZDOTDIR="${PWD}/tests" cram -i --shell=zsh tests
|
ZDOTDIR="${PWD}/tests" cram -i --shell=zsh tests
|
||||||
|
|
||||||
test:
|
# Define targets for test files, with relative and abolute path.
|
||||||
ZDOTDIR="${PWD}/tests" cram --shell=zsh tests
|
# Use verbose output, which is useful with Vim's 'errorformat'.
|
||||||
|
TESTS:=$(wildcard tests/*.t)
|
||||||
|
|
||||||
|
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
|
||||||
|
_TESTS_REL_AND_ABS:=$(call uniq,$(abspath $(TESTS)) $(TESTS))
|
||||||
|
$(_TESTS_REL_AND_ABS):
|
||||||
|
ZDOTDIR="${PWD}/tests" cram --shell=zsh -v $@
|
||||||
|
.PHONY: $(_TESTS_REL_AND_ABS)
|
||||||
|
298
autoenv.zsh
298
autoenv.zsh
@ -1,68 +1,177 @@
|
|||||||
# Initially based on
|
# Initially based on
|
||||||
# https://github.com/joshuaclayton/dotfiles/blob/master/zsh_profile.d/autoenv.zsh
|
# https://github.com/joshuaclayton/dotfiles/blob/master/zsh_profile.d/autoenv.zsh
|
||||||
|
|
||||||
# TODO: move this to DOTENV_*?!
|
export AUTOENV_ENV_FILENAME=$HOME/.env_auth
|
||||||
export ENV_AUTHORIZATION_FILE=$HOME/.env_auth
|
|
||||||
|
|
||||||
# Name of file to look for when entering directories.
|
# Name of file to look for when entering directories.
|
||||||
: ${DOTENV_FILE_ENTER:=.env}
|
: ${AUTOENV_FILE_ENTER:=.env}
|
||||||
|
|
||||||
# Name of file to look for when leaving directories.
|
# Name of file to look for when leaving directories.
|
||||||
# Requires DOTENV_HANDLE_LEAVE=1.
|
# Requires AUTOENV_HANDLE_LEAVE=1.
|
||||||
: ${DOTENV_FILE_LEAVE:=.env.leave}
|
: ${AUTOENV_FILE_LEAVE:=.env.leave}
|
||||||
|
|
||||||
# Look for .env in parent dirs?
|
# Look for .env in parent dirs?
|
||||||
: ${DOTENV_LOOK_UPWARDS:=1}
|
: ${AUTOENV_LOOK_UPWARDS:=1}
|
||||||
|
|
||||||
# Handle leave events when changing away from a subtree, where an "enter"
|
# Handle leave events when changing away from a subtree, where an "enter"
|
||||||
# event was handled?
|
# event was handled?
|
||||||
: ${DOTENV_HANDLE_LEAVE:=1}
|
: ${AUTOENV_HANDLE_LEAVE:=1}
|
||||||
|
|
||||||
|
# Enable debugging. Multiple levels are supported (max 2).
|
||||||
|
: ${AUTOENV_DEBUG:=0}
|
||||||
|
|
||||||
# Internal: stack of entered (and handled) directories.
|
# Public helper functions, which can be used from your .env files:
|
||||||
_dotenv_stack_entered=()
|
#
|
||||||
|
# Source the next .env file from parent directories.
|
||||||
|
# This is useful if you want to use a base .env file for a directory subtree.
|
||||||
|
autoenv_source_parent() {
|
||||||
|
local parent_env_file=$(_autoenv_get_file_upwards $PWD)
|
||||||
|
|
||||||
|
if [[ -n $parent_env_file ]] \
|
||||||
|
&& _autoenv_check_authorized_env_file $parent_env_file; then
|
||||||
|
_autoenv_debug "Calling autoenv_source_parent: parent_env_file:$parent_env_file"
|
||||||
|
|
||||||
_dotenv_hash_pair() {
|
local parent_env_dir=${parent_env_file:A:h}
|
||||||
local env_file=$1
|
|
||||||
env_shasum=$(shasum $env_file | cut -d' ' -f1)
|
_autoenv_stack_entered_add $parent_env_file
|
||||||
echo "$env_file:$env_shasum"
|
|
||||||
|
_autoenv_source $parent_env_file enter $parent_env_dir
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_dotenv_authorized_env_file() {
|
# Internal functions. {{{
|
||||||
|
# Internal: stack of entered (and handled) directories. {{{
|
||||||
|
_autoenv_stack_entered=()
|
||||||
|
typeset -A _autoenv_stack_entered_mtime
|
||||||
|
_autoenv_stack_entered_mtime=()
|
||||||
|
|
||||||
|
# Add an entry to the stack, and remember its mtime.
|
||||||
|
_autoenv_stack_entered_add() {
|
||||||
local env_file=$1
|
local env_file=$1
|
||||||
local pair=$(_dotenv_hash_pair $env_file)
|
|
||||||
test -f $ENV_AUTHORIZATION_FILE \
|
_autoenv_debug "[stack] adding: $env_file" 2
|
||||||
&& \grep -qF $pair $ENV_AUTHORIZATION_FILE
|
|
||||||
|
# Remove any existing entry.
|
||||||
|
_autoenv_stack_entered_remove $env_file
|
||||||
|
|
||||||
|
# Append it to the stack, and remember its mtime.
|
||||||
|
_autoenv_stack_entered+=($env_file)
|
||||||
|
_autoenv_stack_entered_mtime[$env_file]=$(_autoenv_get_file_mtime $env_file)
|
||||||
}
|
}
|
||||||
|
|
||||||
_dotenv_authorize() {
|
_autoenv_get_file_mtime() {
|
||||||
local env_file=$1
|
if [[ -f $1 ]]; then
|
||||||
_dotenv_deauthorize $env_file
|
zstat +mtime $1
|
||||||
_dotenv_hash_pair $env_file >> $ENV_AUTHORIZATION_FILE
|
else
|
||||||
|
echo 0
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_dotenv_deauthorize() {
|
# Remove an entry from the stack.
|
||||||
|
_autoenv_stack_entered_remove() {
|
||||||
local env_file=$1
|
local env_file=$1
|
||||||
if [[ -f $ENV_AUTHORIZATION_FILE ]]; then
|
_autoenv_debug "[stack] removing: $env_file" 2
|
||||||
echo $(\grep -vF $env_file $ENV_AUTHORIZATION_FILE) > $ENV_AUTHORIZATION_FILE
|
_autoenv_stack_entered[$_autoenv_stack_entered[(i)$env_file]]=()
|
||||||
|
_autoenv_stack_entered_mtime[$env_file]=
|
||||||
|
}
|
||||||
|
|
||||||
|
# Is the given entry already in the stack?
|
||||||
|
_autoenv_stack_entered_contains() {
|
||||||
|
local env_file=$1
|
||||||
|
if (( ${+_autoenv_stack_entered[(r)${env_file}]} )); then
|
||||||
|
# Entry is in stack.
|
||||||
|
if [[ $_autoenv_stack_entered_mtime[$env_file] == $(_autoenv_get_file_mtime $env_file) ]]; then
|
||||||
|
# Entry has the expected mtime.
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
# Internal function for debug output. {{{
|
||||||
|
_autoenv_debug() {
|
||||||
|
local msg=$1
|
||||||
|
local level=${2:-1}
|
||||||
|
if [[ $AUTOENV_DEBUG -lt $level ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# Load zsh color support.
|
||||||
|
if [[ -z $colors ]]; then
|
||||||
|
autoload colors
|
||||||
|
colors
|
||||||
|
fi
|
||||||
|
# Build $indent prefix.
|
||||||
|
local indent=
|
||||||
|
if [[ $_autoenv_debug_indent -gt 0 ]]; then
|
||||||
|
for i in {1..${_autoenv_debug_indent}}; do
|
||||||
|
indent=" $indent"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Split $msg by \n (not newline).
|
||||||
|
lines=(${(ps:\\n:)msg})
|
||||||
|
for line in $lines; do
|
||||||
|
echo -n "${fg_bold[blue]}[autoenv]${fg_no_bold[default]} " >&2
|
||||||
|
echo ${indent}${line} >&2
|
||||||
|
done
|
||||||
|
}
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
# Load zstat module, but only its builtin `zstat`.
|
||||||
|
zmodload -F zsh/stat b:zstat
|
||||||
|
|
||||||
|
|
||||||
|
_autoenv_hash_pair() {
|
||||||
|
local env_file=${1:A}
|
||||||
|
local env_shasum
|
||||||
|
if [[ -n $2 ]]; then
|
||||||
|
env_shasum=$2
|
||||||
|
else
|
||||||
|
env_shasum=$(shasum $env_file | cut -d' ' -f1)
|
||||||
|
fi
|
||||||
|
echo "$env_file:$env_shasum:1"
|
||||||
|
}
|
||||||
|
|
||||||
|
_autoenv_authorized_env_file() {
|
||||||
|
local env_file=$1
|
||||||
|
local pair=$(_autoenv_hash_pair $env_file)
|
||||||
|
test -f $AUTOENV_ENV_FILENAME \
|
||||||
|
&& \grep -qF $pair $AUTOENV_ENV_FILENAME
|
||||||
|
}
|
||||||
|
|
||||||
|
_autoenv_authorize() {
|
||||||
|
local env_file=$1
|
||||||
|
_autoenv_deauthorize $env_file
|
||||||
|
_autoenv_hash_pair $env_file >> $AUTOENV_ENV_FILENAME
|
||||||
|
}
|
||||||
|
|
||||||
|
_autoenv_deauthorize() {
|
||||||
|
local env_file=$1
|
||||||
|
if [[ -f $AUTOENV_ENV_FILENAME ]]; then
|
||||||
|
echo $(\grep -vF $env_file $AUTOENV_ENV_FILENAME) > $AUTOENV_ENV_FILENAME
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function can be mocked in tests
|
# This function can be mocked in tests
|
||||||
_dotenv_read_answer() {
|
_autoenv_ask_for_yes() {
|
||||||
local answer
|
local answer
|
||||||
read -q answer
|
read answer
|
||||||
echo $answer
|
if [[ $answer == "yes" ]]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Args: 1: absolute path to env file (resolved symlinks).
|
# Args: 1: absolute path to env file (resolved symlinks).
|
||||||
_dotenv_check_authorized_env_file() {
|
_autoenv_check_authorized_env_file() {
|
||||||
if ! [[ -f $1 ]]; then
|
if ! [[ -f $1 ]]; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
if ! _dotenv_authorized_env_file $1; then
|
if ! _autoenv_authorized_env_file $1; then
|
||||||
echo "Attempting to load unauthorized env file: $1"
|
echo "Attempting to load unauthorized env file!"
|
||||||
|
command ls -l $1
|
||||||
echo ""
|
echo ""
|
||||||
echo "**********************************************"
|
echo "**********************************************"
|
||||||
echo ""
|
echo ""
|
||||||
@ -70,78 +179,133 @@ _dotenv_check_authorized_env_file() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo "**********************************************"
|
echo "**********************************************"
|
||||||
echo ""
|
echo ""
|
||||||
echo -n "Would you like to authorize it? [y/N] "
|
echo -n "Would you like to authorize it? (type 'yes') "
|
||||||
|
|
||||||
local answer=$(_dotenv_read_answer)
|
if ! _autoenv_ask_for_yes; then
|
||||||
echo
|
|
||||||
if [[ $answer != 'y' ]]; then
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_dotenv_authorize $1
|
_autoenv_authorize $1
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
_dotenv_source() {
|
# Get directory of this file (absolute, with resolved symlinks).
|
||||||
|
_autoenv_source_dir=${0:A:h}
|
||||||
|
|
||||||
|
_autoenv_source() {
|
||||||
local env_file=$1
|
local env_file=$1
|
||||||
_dotenv_event=$2
|
_autoenv_event=$2
|
||||||
_dotenv_cwd=$PWD
|
local _autoenv_envfile_dir=${3:-${1:A:h}}
|
||||||
|
|
||||||
builtin cd -q ${env_file:h}
|
_autoenv_from_dir=$_autoenv_chpwd_prev_dir
|
||||||
|
_autoenv_to_dir=$PWD
|
||||||
|
|
||||||
|
# Source varstash library once.
|
||||||
|
if [[ -z "$functions[(I)autostash]" ]]; then
|
||||||
|
source $_autoenv_source_dir/lib/varstash
|
||||||
|
# NOTE: Varstash uses $PWD as default for varstash_dir, we might set it to
|
||||||
|
# ${env_file:h}.
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Change to directory of env file, source it and cd back.
|
||||||
|
local new_dir=$PWD
|
||||||
|
builtin cd -q $_autoenv_envfile_dir
|
||||||
|
_autoenv_debug "== SOURCE: ${bold_color}$env_file${reset_color}\n PWD: $PWD"
|
||||||
|
(( _autoenv_debug_indent++ ))
|
||||||
source $env_file
|
source $env_file
|
||||||
builtin cd -q $_dotenv_cwd
|
(( _autoenv_debug_indent-- ))
|
||||||
|
_autoenv_debug "== END SOURCE =="
|
||||||
|
builtin cd -q $new_dir
|
||||||
|
|
||||||
unset _dotenv_event _dotenv_cwd
|
# Unset vars set for enter/leave scripts.
|
||||||
|
# This should not get done for recursion (via autoenv_source_parent),
|
||||||
|
# and can be useful to have in general after autoenv was used.
|
||||||
|
# unset _autoenv_event _autoenv_from_dir _autoenv_to_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
_dotenv_chpwd_handler() {
|
_autoenv_get_file_upwards() {
|
||||||
local env_file="$PWD/$DOTENV_FILE_ENTER"
|
local look_from=${1:-$PWD}
|
||||||
|
local look_for=${2:-$AUTOENV_FILE_ENTER}
|
||||||
|
|
||||||
|
# Manually look in parent dirs. An extended Zsh glob should use Y1 for
|
||||||
|
# performance reasons, which is only available in zsh-5.0.5-146-g9381bb6.
|
||||||
|
local last
|
||||||
|
local parent_dir="$look_from/.."
|
||||||
|
while true; do
|
||||||
|
parent_dir=${parent_dir:A}
|
||||||
|
if [[ $parent_dir == $last ]]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
parent_file="${parent_dir}/${look_for}"
|
||||||
|
|
||||||
|
if [[ -f $parent_file ]]; then
|
||||||
|
echo $parent_file
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
last=$parent_dir
|
||||||
|
parent_dir="${parent_dir}/.."
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_autoenv_chpwd_prev_dir=$PWD
|
||||||
|
_autoenv_chpwd_handler() {
|
||||||
|
local env_file="$PWD/$AUTOENV_FILE_ENTER"
|
||||||
|
|
||||||
|
_autoenv_debug "Calling chpwd handler: PWD=$PWD"
|
||||||
|
|
||||||
# Handle leave event for previously sourced env files.
|
# Handle leave event for previously sourced env files.
|
||||||
if [[ $DOTENV_HANDLE_LEAVE == 1 ]] && (( $#_dotenv_stack_entered )); then
|
if [[ $AUTOENV_HANDLE_LEAVE == 1 ]] && (( $#_autoenv_stack_entered )); then
|
||||||
for prev_dir in ${_dotenv_stack_entered}; do
|
local prev_file prev_dir
|
||||||
|
for prev_file in ${_autoenv_stack_entered}; do
|
||||||
|
prev_dir=${prev_file:A:h}
|
||||||
if ! [[ ${PWD}/ == ${prev_dir}/* ]]; then
|
if ! [[ ${PWD}/ == ${prev_dir}/* ]]; then
|
||||||
local env_file_leave=$prev_dir/$DOTENV_FILE_LEAVE
|
local env_file_leave=$prev_dir/$AUTOENV_FILE_LEAVE
|
||||||
if _dotenv_check_authorized_env_file $env_file_leave; then
|
if _autoenv_check_authorized_env_file $env_file_leave; then
|
||||||
_dotenv_source $env_file_leave leave
|
_autoenv_source $env_file_leave leave $prev_dir
|
||||||
fi
|
fi
|
||||||
# Remove this entry from the stack.
|
_autoenv_stack_entered_remove $prev_file
|
||||||
_dotenv_stack_entered=(${_dotenv_stack_entered#$prev_dir})
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! [[ -f $env_file ]] && [[ $DOTENV_LOOK_UPWARDS == 1 ]]; then
|
if ! [[ -f $env_file ]] && [[ $AUTOENV_LOOK_UPWARDS == 1 ]]; then
|
||||||
# Look for files in parent dirs, using an extended Zsh glob.
|
env_file=$(_autoenv_get_file_upwards $PWD)
|
||||||
setopt localoptions extendedglob
|
if [[ -z $env_file ]]; then
|
||||||
local m
|
_autoenv_chpwd_prev_dir=$PWD
|
||||||
m=((../)#${DOTENV_FILE_ENTER}(N))
|
|
||||||
if (( $#m )); then
|
|
||||||
env_file=${${m[1]}:A}
|
|
||||||
else
|
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! _dotenv_check_authorized_env_file $env_file; then
|
# Load the env file only once: check if $env_file is in the stack of entered
|
||||||
|
# directories.
|
||||||
|
if _autoenv_stack_entered_contains $env_file; then
|
||||||
|
_autoenv_debug "Already in stack: $env_file"
|
||||||
|
_autoenv_chpwd_prev_dir=$PWD
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Load the env file only once: check if $env_file's parent
|
if ! _autoenv_check_authorized_env_file $env_file; then
|
||||||
# is in $_dotenv_stack_entered.
|
_autoenv_chpwd_prev_dir=$PWD
|
||||||
local env_file_dir=${env_file:A:h}
|
|
||||||
if (( ${+_dotenv_stack_entered[(r)${env_file_dir}]} )); then
|
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_dotenv_stack_entered+=(${env_file_dir})
|
_autoenv_stack_entered_add $env_file
|
||||||
|
|
||||||
_dotenv_source $env_file enter
|
# Source the enter env file.
|
||||||
|
_autoenv_debug "Sourcing from chpwd handler: $env_file"
|
||||||
|
_autoenv_source $env_file enter
|
||||||
|
|
||||||
|
_autoenv_chpwd_prev_dir=$PWD
|
||||||
|
|
||||||
|
(( _autoenv_debug_indent++ ))
|
||||||
}
|
}
|
||||||
|
# }}}
|
||||||
|
|
||||||
autoload -U add-zsh-hook
|
autoload -U add-zsh-hook
|
||||||
add-zsh-hook chpwd _dotenv_chpwd_handler
|
add-zsh-hook chpwd _autoenv_chpwd_handler
|
||||||
|
|
||||||
# Look in current directory already.
|
# Look in current directory already.
|
||||||
_dotenv_chpwd_handler
|
_autoenv_chpwd_handler
|
||||||
|
343
lib/varstash
Normal file
343
lib/varstash
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
################################################################################
|
||||||
|
# Stash/unstash support for per-directory variables
|
||||||
|
#
|
||||||
|
# Adopted for zsh-autoenv.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2009,2012 Dave Olszewski <cxreg@pobox.com>
|
||||||
|
# http://github.com/cxreg/smartcd
|
||||||
|
#
|
||||||
|
# This code is released under GPL v2 and the Artistic License, and
|
||||||
|
# may be redistributed under the terms of either.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# This library allows you to save the current value of a given environment
|
||||||
|
# variable in a temporary location, so that you can modify it, and then
|
||||||
|
# later restore its original value.
|
||||||
|
#
|
||||||
|
# Note that you will need to be in the same directory you were in when you
|
||||||
|
# stashed in order to successfully unstash. This is because the temporary
|
||||||
|
# variable is derived from your current working directory's path.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# stash PATH
|
||||||
|
# export PATH=/something/else
|
||||||
|
# [...]
|
||||||
|
# unstash PATH
|
||||||
|
#
|
||||||
|
# Note that this was written for use with, and works very well with,
|
||||||
|
# smartcd. See the documentation there for examples.
|
||||||
|
#
|
||||||
|
# An alternate usage is `autostash' which will trigger autounstash when
|
||||||
|
# leaving the directory, if combined with smartcd. This reduces the amount
|
||||||
|
# of explicit configuration you need to provide:
|
||||||
|
#
|
||||||
|
# autostash PATH
|
||||||
|
# export PATH=/something/else
|
||||||
|
#
|
||||||
|
# You may also do both operations on line line, leaving only the very succinct
|
||||||
|
#
|
||||||
|
# autostash PATH=/something/else
|
||||||
|
#
|
||||||
|
# If you attempt to stash the same value twice, a warning will be displayed
|
||||||
|
# and the second stash will not occur. To make it happen anyway, pass -f
|
||||||
|
# as the first argument to stash.
|
||||||
|
#
|
||||||
|
# $ stash FOO
|
||||||
|
# $ stash FOO
|
||||||
|
# You have already stashed FOO, please specify "-f" if you want to overwrite another stashed value
|
||||||
|
# $ stash -f FOO
|
||||||
|
# $
|
||||||
|
#
|
||||||
|
# This rule is a bit different if you are assigning a value and the variable
|
||||||
|
# has already been stashed. In that case, the new value will be assigned, but
|
||||||
|
# the stash will not be overwritten. This allows for non-conflicting chained
|
||||||
|
# stash-assign rules.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
# Library functions, from smartcd's lib/core/arrays. {{{
|
||||||
|
function apush() {
|
||||||
|
local var=$1; shift
|
||||||
|
eval "$var=(\${$var[@]} \"\$@\")"
|
||||||
|
}
|
||||||
|
|
||||||
|
function alen() {
|
||||||
|
local var=$1
|
||||||
|
|
||||||
|
if [[ -n $var ]]; then
|
||||||
|
eval "echo \${#$var[@]}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function afirst() {
|
||||||
|
setopt localoptions && setopt ksharrays
|
||||||
|
local var=$1
|
||||||
|
|
||||||
|
if [[ -n $var ]] && (( $(eval "echo \${#$var[@]}") >= 1 )); then
|
||||||
|
eval "echo \"\${$var""[0]}\""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function ashift() {
|
||||||
|
setopt localoptions && setopt ksharrays
|
||||||
|
local var=$1
|
||||||
|
|
||||||
|
local _ashift_return=
|
||||||
|
|
||||||
|
if [[ -n $var ]] && (( $(eval "echo \${#$var[@]}") >= 1 )); then
|
||||||
|
eval "_ashift_return=\"\${$var""[0]}\""
|
||||||
|
eval "$var""[0]=()"
|
||||||
|
|
||||||
|
echo "$_ashift_return"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
function stash() {
|
||||||
|
if [[ $1 == "-f" ]]; then
|
||||||
|
local force=1; shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
while [[ -n $1 ]]; do
|
||||||
|
if [[ $1 == "alias" && $2 =~ "=" ]]; then
|
||||||
|
shift
|
||||||
|
local _stashing_alias_assign=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
local stash_expression=$1
|
||||||
|
local stash_which=${stash_expression%%'='*}
|
||||||
|
local stash_name=$(_mangle_var $stash_which)
|
||||||
|
|
||||||
|
# Extract the value and make it double-quote safe
|
||||||
|
local stash_value=${stash_expression#*'='}
|
||||||
|
stash_value=${stash_value//\\/\\\\}
|
||||||
|
stash_value=${stash_value//\"/\\\"}
|
||||||
|
stash_value=${stash_value//\`/\\\`}
|
||||||
|
stash_value=${stash_value//\$/\\\$}
|
||||||
|
|
||||||
|
if [[ ( -n "$(eval echo '$__varstash_alias__'$stash_name)" ||
|
||||||
|
-n "$(eval echo '$__varstash_function__'$stash_name)" ||
|
||||||
|
-n "$(eval echo '$__varstash_array__'$stash_name)" ||
|
||||||
|
-n "$(eval echo '$__varstash_export__'$stash_name)" ||
|
||||||
|
-n "$(eval echo '$__varstash_variable__'$stash_name)" ||
|
||||||
|
-n "$(eval echo '$__varstash_nostash__'$stash_name)" )
|
||||||
|
&& -z $force ]]; then
|
||||||
|
|
||||||
|
if [[ -z $already_stashed && ${already_stashed-_} == "_" ]]; then
|
||||||
|
local already_stashed=1
|
||||||
|
else
|
||||||
|
already_stashed=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $stash_which == $stash_expression ]]; then
|
||||||
|
if [[ -z $run_from_smartcd ]]; then
|
||||||
|
echo "You have already stashed $stash_which, please specify \"-f\" if you want to overwrite another stashed value"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip remaining work if we're not doing an assignment
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle any alias that may exist under this name
|
||||||
|
if [[ -z $already_stashed ]]; then
|
||||||
|
local alias_def="$(eval alias $stash_which 2>/dev/null)"
|
||||||
|
if [[ -n $alias_def ]]; then
|
||||||
|
alias_def=${alias_def#alias }
|
||||||
|
eval "__varstash_alias__$stash_name=\"$alias_def\""
|
||||||
|
local stashed=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ $stash_which != $stash_expression && -n $_stashing_alias_assign ]]; then
|
||||||
|
eval "alias $stash_which=\"$stash_value\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle any function that may exist under this name
|
||||||
|
if [[ -z $already_stashed ]]; then
|
||||||
|
local function_def="$(declare -f $stash_which)"
|
||||||
|
if [[ -n $function_def ]]; then
|
||||||
|
# make function definition quote-safe. because we are going to evaluate the
|
||||||
|
# source with "echo -e", we need to double-escape the backslashes (so 1 -> 4)
|
||||||
|
function_def=${function_def//\\/\\\\\\\\}
|
||||||
|
function_def=${function_def//\"/\\\"}
|
||||||
|
function_def=${function_def//\`/\\\`}
|
||||||
|
function_def=${function_def//\$/\\\$}
|
||||||
|
eval "__varstash_function__$stash_name=\"$function_def\""
|
||||||
|
local stashed=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle any variable that may exist under this name
|
||||||
|
local vartype="$(declare -p $stash_which 2>/dev/null)"
|
||||||
|
if [[ -n $vartype ]]; then
|
||||||
|
if [[ -n $ZSH_VERSION ]]; then
|
||||||
|
local pattern="^typeset"
|
||||||
|
else
|
||||||
|
local pattern="^declare"
|
||||||
|
fi
|
||||||
|
if [[ $vartype =~ $pattern" -a" ]]; then
|
||||||
|
# varible is an array
|
||||||
|
if [[ -z $already_stashed ]]; then
|
||||||
|
eval "__varstash_array__$stash_name=(\"\${$stash_which""[@]}\")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [[ $vartype =~ $pattern" -x" ]]; then
|
||||||
|
# variable is exported
|
||||||
|
if [[ -z $already_stashed ]]; then
|
||||||
|
eval "__varstash_export__$stash_name=\"\$$stash_which\""
|
||||||
|
fi
|
||||||
|
if [[ $stash_which != $stash_expression && -z $_stashing_alias_assign ]]; then
|
||||||
|
eval "export $stash_which=\"$stash_value\""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# regular variable
|
||||||
|
if [[ -z $already_stashed ]]; then
|
||||||
|
eval "__varstash_variable__$stash_name=\"\$$stash_which\""
|
||||||
|
fi
|
||||||
|
if [[ $stash_which != $stash_expression && -z $_stashing_alias_assign ]]; then
|
||||||
|
eval "$stash_which=\"$stash_value\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
local stashed=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $stashed ]]; then
|
||||||
|
# Nothing in the variable we're stashing, but make a note that we stashed so we
|
||||||
|
# do the right thing when unstashing. Without this, we take no action on unstash
|
||||||
|
|
||||||
|
# Zsh bug sometimes caues
|
||||||
|
# (eval):1: command not found: __varstash_nostash___tmp__home_dolszewski_src_smartcd_RANDOM_VARIABLE=1
|
||||||
|
# fixed in zsh commit 724fd07a67f, version 4.3.14
|
||||||
|
if [[ -z $already_stashed ]]; then
|
||||||
|
eval "__varstash_nostash__$stash_name=1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# In the case of a previously unset variable that we're assigning too, export it
|
||||||
|
if [[ $stash_which != $stash_expression && -z $_stashing_alias_assign ]]; then
|
||||||
|
eval "export $stash_which=\"$stash_value\""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
shift
|
||||||
|
unset -v _stashing_alias_assign
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function autostash() {
|
||||||
|
local run_from_autostash=1
|
||||||
|
while [[ -n $1 ]]; do
|
||||||
|
if [[ $1 == "alias" && $2 =~ "=" ]]; then
|
||||||
|
shift
|
||||||
|
local _stashing_alias_assign=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local already_stashed=
|
||||||
|
stash "$1"
|
||||||
|
if [[ -z $already_stashed ]]; then
|
||||||
|
local autostash_name=$(_mangle_var AUTOSTASH)
|
||||||
|
local varname=${1%%'='*}
|
||||||
|
apush $autostash_name "$varname"
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
unset -v _stashing_alias_assign
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function unstash() {
|
||||||
|
while [[ -n $1 ]]; do
|
||||||
|
local unstash_which=$1
|
||||||
|
if [[ -z $unstash_which ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
local unstash_name=$(_mangle_var $unstash_which)
|
||||||
|
|
||||||
|
# This bit is a little tricky. Here are the rules:
|
||||||
|
# 1) unstash any alias, function, or variable which matches
|
||||||
|
# 2) if one or more matches, but not all, delete any that did not
|
||||||
|
# 3) if none match but nostash is found, delete all
|
||||||
|
# 4) if none match and nostash not found, do nothing
|
||||||
|
|
||||||
|
# Unstash any alias
|
||||||
|
if [[ -n "$(eval echo \$__varstash_alias__$unstash_name)" ]]; then
|
||||||
|
eval "alias $(eval echo \$__varstash_alias__$unstash_name)"
|
||||||
|
unset __varstash_alias__$unstash_name
|
||||||
|
local unstashed=1
|
||||||
|
local unstashed_alias=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Unstash any function
|
||||||
|
if [[ -n "$(eval echo \$__varstash_function__$unstash_name)" ]]; then
|
||||||
|
eval "function $(eval echo -e \"\$__varstash_function__$unstash_name\")"
|
||||||
|
unset __varstash_function__$unstash_name
|
||||||
|
local unstashed=1
|
||||||
|
local unstashed_function=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Unstash any variable
|
||||||
|
if [[ -n "$(declare -p __varstash_array__$unstash_name 2>/dev/null)" ]]; then
|
||||||
|
eval "$unstash_which=(\"\${__varstash_array__$unstash_name""[@]}\")"
|
||||||
|
unset __varstash_array__$unstash_name
|
||||||
|
local unstashed=1
|
||||||
|
local unstashed_variable=1
|
||||||
|
elif [[ -n "$(declare -p __varstash_export__$unstash_name 2>/dev/null)" ]]; then
|
||||||
|
eval "export $unstash_which=\"\$__varstash_export__$unstash_name\""
|
||||||
|
unset __varstash_export__$unstash_name
|
||||||
|
local unstashed=1
|
||||||
|
local unstashed_variable=1
|
||||||
|
elif [[ -n "$(declare -p __varstash_variable__$unstash_name 2>/dev/null)" ]]; then
|
||||||
|
# Unset variable first to reset export
|
||||||
|
unset -v $unstash_which
|
||||||
|
eval "$unstash_which=\"\$__varstash_variable__$unstash_name\""
|
||||||
|
unset __varstash_variable__$unstash_name
|
||||||
|
local unstashed=1
|
||||||
|
local unstashed_variable=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Unset any values which did not exist at time of stash
|
||||||
|
local nostash="$(eval echo \$__varstash_nostash__$unstash_name)"
|
||||||
|
unset __varstash_nostash__$unstash_name
|
||||||
|
if [[ ( -n "$nostash" && -z "$unstashed" ) || ( -n "$unstashed" && -z "$unstashed_alias" ) ]]; then
|
||||||
|
unalias $unstash_which 2>/dev/null
|
||||||
|
fi
|
||||||
|
if [[ ( -n "$nostash" && -z "$unstashed" ) || ( -n "$unstashed" && -z "$unstashed_function" ) ]]; then
|
||||||
|
unset -f $unstash_which 2>/dev/null
|
||||||
|
fi
|
||||||
|
if [[ ( -n "$nostash" && -z "$unstashed" ) || ( -n "$unstashed" && -z "$unstashed_variable" ) ]]; then
|
||||||
|
# Don't try to unset illegal variable names
|
||||||
|
if ! [[ $unstash_which =~ [^a-zA-Z0-9_] || $unstash_which =~ ^[0-9] ]]; then
|
||||||
|
unset -v $unstash_which
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function autounstash() {
|
||||||
|
# If there is anything in (mangled) variable AUTOSTASH, then unstash it
|
||||||
|
local autounstash_name=$(_mangle_var AUTOSTASH)
|
||||||
|
if (( $(alen $autounstash_name) > 0 )); then
|
||||||
|
local run_from_autounstash=1
|
||||||
|
while (( $(alen $autounstash_name) > 0 )); do
|
||||||
|
local autounstash_var=$(afirst $autounstash_name)
|
||||||
|
ashift $autounstash_name >/dev/null
|
||||||
|
unstash $autounstash_var
|
||||||
|
done
|
||||||
|
unset $autounstash_name
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function _mangle_var() {
|
||||||
|
local mangle_var_where="${varstash_dir:-$PWD}"
|
||||||
|
mangle_var_where=${mangle_var_where//[^A-Za-z0-9]/_}
|
||||||
|
local mangled_name=${1//[^A-Za-z0-9]/_}
|
||||||
|
echo "_tmp_${mangle_var_where}_${mangled_name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: filetype=sh autoindent expandtab shiftwidth=4 softtabstop=4
|
@ -1,4 +1,6 @@
|
|||||||
test -f "$TESTDIR/.zcompdump" && rm "$TESTDIR/.zcompdump"
|
test -f "$TESTDIR/.zcompdump" && rm "$TESTDIR/.zcompdump"
|
||||||
|
|
||||||
|
AUTOENV_DEBUG=0
|
||||||
|
|
||||||
source "$TESTDIR/../autoenv.plugin.zsh"
|
source "$TESTDIR/../autoenv.plugin.zsh"
|
||||||
export ENV_AUTHORIZATION_FILE="$PWD/.env_auth"
|
export AUTOENV_ENV_FILENAME="$PWD/.env_auth"
|
||||||
|
58
tests/_autoenv_stack.t
Normal file
58
tests/_autoenv_stack.t
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
Tests for internal stack handling.
|
||||||
|
|
||||||
|
$ source $TESTDIR/setup.sh
|
||||||
|
|
||||||
|
Non-existing entries are allowed and handled without error.
|
||||||
|
|
||||||
|
$ _autoenv_stack_entered_add non-existing
|
||||||
|
$ echo $_autoenv_stack_entered
|
||||||
|
non-existing
|
||||||
|
|
||||||
|
Add existing entries.
|
||||||
|
|
||||||
|
$ mkdir -p sub/sub2
|
||||||
|
$ touch -t 201401010101 sub/file
|
||||||
|
$ _autoenv_stack_entered_add sub
|
||||||
|
$ _autoenv_stack_entered_add sub/file
|
||||||
|
$ _autoenv_stack_entered_add sub/sub2
|
||||||
|
$ echo $_autoenv_stack_entered
|
||||||
|
non-existing sub sub/file sub/sub2
|
||||||
|
|
||||||
|
$ _autoenv_stack_entered_add non-existing
|
||||||
|
$ echo $_autoenv_stack_entered
|
||||||
|
sub sub/file sub/sub2 non-existing
|
||||||
|
|
||||||
|
$ echo ${(k)_autoenv_stack_entered}
|
||||||
|
sub sub/file sub/sub2 non-existing
|
||||||
|
|
||||||
|
$ echo $_autoenv_stack_entered_mtime
|
||||||
|
0 1388538060 0 0 (glob)
|
||||||
|
|
||||||
|
Touch the file and re-add it.
|
||||||
|
|
||||||
|
$ touch -t 201401012359 sub/file
|
||||||
|
$ _autoenv_stack_entered_add sub/file
|
||||||
|
|
||||||
|
The mtime should have been updated.
|
||||||
|
|
||||||
|
$ echo ${_autoenv_stack_entered_mtime[sub/file]}
|
||||||
|
1388620740
|
||||||
|
|
||||||
|
It should have moved to the end of the stack.
|
||||||
|
|
||||||
|
$ echo ${(k)_autoenv_stack_entered}
|
||||||
|
sub sub/sub2 non-existing sub/file
|
||||||
|
|
||||||
|
Test lookup of containing elements.
|
||||||
|
|
||||||
|
$ _autoenv_stack_entered_contains sub/file
|
||||||
|
$ _autoenv_stack_entered_contains non-existing
|
||||||
|
$ _autoenv_stack_entered_contains not-added
|
||||||
|
[1]
|
||||||
|
|
||||||
|
Test removing.
|
||||||
|
|
||||||
|
$ _autoenv_stack_entered_remove sub
|
||||||
|
$ echo ${_autoenv_stack_entered}
|
||||||
|
sub/sub2 non-existing sub/file
|
||||||
|
|
15
tests/_autoenv_utils.t
Normal file
15
tests/_autoenv_utils.t
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Tests for internal util methods.
|
||||||
|
|
||||||
|
$ source $TESTDIR/setup.sh
|
||||||
|
|
||||||
|
Non-existing entries are allowed and handled without error.
|
||||||
|
|
||||||
|
$ mkdir -p sub/sub2
|
||||||
|
$ touch file sub/file sub/sub2/file
|
||||||
|
|
||||||
|
Should not get the file from the current dir.
|
||||||
|
$ _autoenv_get_file_upwards . file
|
||||||
|
|
||||||
|
$ cd sub/sub2
|
||||||
|
$ _autoenv_get_file_upwards . file
|
||||||
|
*/_autoenv_utils.t/sub/file (glob)
|
@ -1,6 +1,4 @@
|
|||||||
Ensure we have our mocked out ENV_AUTHORIZATION_FILE
|
$ source $TESTDIR/setup.sh
|
||||||
|
|
||||||
$ [[ $ENV_AUTHORIZATION_FILE[0,4] == '/tmp' ]] || return 1
|
|
||||||
|
|
||||||
Lets set a simple .env action
|
Lets set a simple .env action
|
||||||
|
|
||||||
@ -8,17 +6,18 @@ Lets set a simple .env action
|
|||||||
|
|
||||||
Manually create auth file
|
Manually create auth file
|
||||||
|
|
||||||
$ echo "$PWD/.env:$(echo echo ENTERED | shasum)" > $ENV_AUTHORIZATION_FILE
|
$ test_autoenv_add_to_env $PWD/.env
|
||||||
$ cd .
|
$ cd .
|
||||||
ENTERED
|
ENTERED
|
||||||
|
|
||||||
Now try to make it accept it
|
Now try to make it accept it
|
||||||
|
|
||||||
$ unset _dotenv_stack_entered
|
$ unset _autoenv_stack_entered
|
||||||
$ rm $ENV_AUTHORIZATION_FILE
|
$ rm $AUTOENV_ENV_FILENAME
|
||||||
$ _dotenv_read_answer() { echo 'y' }
|
$ _autoenv_ask_for_yes() { echo "yes" }
|
||||||
$ cd .
|
$ cd .
|
||||||
Attempting to load unauthorized env file: /tmp/cramtests-??????/autoenv.t/.env (glob)
|
Attempting to load unauthorized env file!
|
||||||
|
-* /tmp/cramtests-*/autoenv.t/.env (glob)
|
||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
@ -26,26 +25,24 @@ Now try to make it accept it
|
|||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
Would you like to authorize it? [y/N]
|
Would you like to authorize it? (type 'yes') yes
|
||||||
ENTERED
|
ENTERED
|
||||||
|
|
||||||
|
|
||||||
|
The last "ENTERED" is because it executed the command.
|
||||||
|
|
||||||
|
Now lets see that it actually checks the shasum value.
|
||||||
|
|
||||||
|
$ unset _autoenv_stack_entered
|
||||||
The last "ENTERED" is because it executed the command
|
|
||||||
|
|
||||||
Now lets see that it actually checks the shasum value
|
|
||||||
|
|
||||||
$ unset _dotenv_stack_entered
|
|
||||||
$ cd .
|
$ cd .
|
||||||
ENTERED
|
ENTERED
|
||||||
|
|
||||||
$ unset _dotenv_stack_entered
|
$ unset _autoenv_stack_entered
|
||||||
$ rm $ENV_AUTHORIZATION_FILE
|
$ rm $AUTOENV_ENV_FILENAME
|
||||||
$ echo "$PWD/.env:$(echo mischief | shasum)" > $ENV_AUTHORIZATION_FILE
|
$ test_autoenv_add_to_env $PWD/.env mischief
|
||||||
$ cd .
|
$ cd .
|
||||||
Attempting to load unauthorized env file: /tmp/cramtests-??????/autoenv.t/.env (glob)
|
Attempting to load unauthorized env file!
|
||||||
|
-* /tmp/cramtests-*/autoenv.t/.env (glob)
|
||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
@ -53,20 +50,18 @@ Now lets see that it actually checks the shasum value
|
|||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
Would you like to authorize it? [y/N]
|
Would you like to authorize it? (type 'yes') yes
|
||||||
ENTERED
|
ENTERED
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Now, will it take no for an answer?
|
Now, will it take no for an answer?
|
||||||
|
|
||||||
$ unset _dotenv_stack_entered
|
$ unset _autoenv_stack_entered
|
||||||
$ rm $ENV_AUTHORIZATION_FILE
|
$ rm $AUTOENV_ENV_FILENAME
|
||||||
$ _dotenv_read_answer() { echo 'n' }
|
$ _autoenv_ask_for_yes() { echo "no"; return 1 }
|
||||||
$ cd .
|
$ cd .
|
||||||
Attempting to load unauthorized env file: /tmp/cramtests-??????/autoenv.t/.env (glob)
|
Attempting to load unauthorized env file!
|
||||||
|
-* /tmp/cramtests-*/autoenv.t/.env (glob)
|
||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
@ -74,16 +69,14 @@ Now, will it take no for an answer?
|
|||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
Would you like to authorize it? [y/N]
|
Would you like to authorize it? (type 'yes') no
|
||||||
|
|
||||||
|
|
||||||
|
Lets also try one more time to ensure it didn't add it.
|
||||||
|
|
||||||
|
|
||||||
Lets also try one more time to ensure it didnt add it
|
|
||||||
|
|
||||||
$ cd .
|
$ cd .
|
||||||
Attempting to load unauthorized env file: /tmp/cramtests-??????/autoenv.t/.env (glob)
|
Attempting to load unauthorized env file!
|
||||||
|
-* /tmp/cramtests-*/autoenv.t/.env (glob)
|
||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
@ -91,4 +84,4 @@ Lets also try one more time to ensure it didnt add it
|
|||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
Would you like to authorize it? [y/N]
|
Would you like to authorize it? (type 'yes') no
|
||||||
|
21
tests/cwd.t
21
tests/cwd.t
@ -1,29 +1,26 @@
|
|||||||
Test $PWD and $_dotenv_cwd.
|
Test $PWD, $_autoenv_from_dir and _autoenv_to_dir.
|
||||||
|
|
||||||
Ensure we have our mocked out ENV_AUTHORIZATION_FILE.
|
$ source $TESTDIR/setup.sh
|
||||||
|
|
||||||
$ [[ $ENV_AUTHORIZATION_FILE[0,4] == '/tmp' ]] || return 1
|
|
||||||
|
|
||||||
Setup env actions / output.
|
Setup env actions / output.
|
||||||
|
|
||||||
$ DOTENV_LOOK_UPWARDS=1
|
$ AUTOENV_LOOK_UPWARDS=1
|
||||||
$ mkdir -p sub/sub2
|
$ mkdir -p sub/sub2
|
||||||
$ cd sub
|
$ cd sub
|
||||||
$ echo 'echo ENTERED: cwd:${PWD:t} ${_dotenv_cwd:t}' >> .env
|
$ echo 'echo ENTERED: PWD:${PWD:t} from:${_autoenv_from_dir:t} to:${_autoenv_to_dir:t}' > .env
|
||||||
$ echo 'echo LEFT: cwd:${PWD:t} ${_dotenv_cwd:t}' >> .env.leave
|
$ echo 'echo LEFT: PWD:${PWD:t} from:${_autoenv_from_dir:t} to:${_autoenv_to_dir:t}' > .env.leave
|
||||||
|
|
||||||
Manually create auth files.
|
Manually create auth files.
|
||||||
|
|
||||||
$ echo "$PWD/$DOTENV_FILE_ENTER:$(echo $(<$DOTENV_FILE_ENTER) | shasum)" > $ENV_AUTHORIZATION_FILE
|
$ test_autoenv_auth_env_files
|
||||||
$ echo "$PWD/$DOTENV_FILE_LEAVE:$(echo $(<$DOTENV_FILE_LEAVE) | shasum)" >> $ENV_AUTHORIZATION_FILE
|
|
||||||
|
|
||||||
The actual tests.
|
The actual tests.
|
||||||
|
|
||||||
$ cd .
|
$ cd .
|
||||||
ENTERED: cwd:sub sub
|
ENTERED: PWD:sub from:sub to:sub
|
||||||
|
|
||||||
$ cd ..
|
$ cd ..
|
||||||
LEFT: cwd:sub cwd.t
|
LEFT: PWD:sub from:sub to:cwd.t
|
||||||
|
|
||||||
$ cd sub/sub2
|
$ cd sub/sub2
|
||||||
ENTERED: cwd:sub sub2
|
ENTERED: PWD:sub from:cwd.t to:sub2
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
Ensure we have our mocked out ENV_AUTHORIZATION_FILE
|
$ source $TESTDIR/setup.sh
|
||||||
|
|
||||||
$ [[ $ENV_AUTHORIZATION_FILE[0,4] == '/tmp' ]] || return 1
|
|
||||||
|
|
||||||
|
|
||||||
Lets set a simple .env action
|
Lets set a simple .env action
|
||||||
|
|
||||||
@ -12,9 +9,10 @@ Lets set a simple .env action
|
|||||||
|
|
||||||
Change to the directory.
|
Change to the directory.
|
||||||
|
|
||||||
$ _dotenv_read_answer() { echo 'y' }
|
$ _autoenv_ask_for_yes() { echo "yes"; return 0 }
|
||||||
$ cd .
|
$ cd .
|
||||||
Attempting to load unauthorized env file: /tmp/cramtests-??????/leave.t/sub/.env (glob)
|
Attempting to load unauthorized env file!
|
||||||
|
-* /tmp/cramtests-*/leave.t/sub/.env (glob)
|
||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
@ -22,15 +20,16 @@ Change to the directory.
|
|||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
Would you like to authorize it? [y/N]
|
Would you like to authorize it? (type 'yes') yes
|
||||||
ENTERED
|
ENTERED
|
||||||
|
|
||||||
|
|
||||||
Leave the directory and answer "no".
|
Leave the directory and answer "no".
|
||||||
|
|
||||||
$ _dotenv_read_answer() { echo 'n' }
|
$ _autoenv_ask_for_yes() { echo "no"; return 1 }
|
||||||
$ cd ..
|
$ cd ..
|
||||||
Attempting to load unauthorized env file: /tmp/cramtests-??????/leave.t/sub/.env.leave (glob)
|
Attempting to load unauthorized env file!
|
||||||
|
-* /tmp/cramtests-*/leave.t/sub/.env.leave (glob)
|
||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
@ -38,14 +37,15 @@ Leave the directory and answer "no".
|
|||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
Would you like to authorize it? [y/N]
|
Would you like to authorize it? (type 'yes') no
|
||||||
|
|
||||||
|
|
||||||
$ cd sub
|
$ cd sub
|
||||||
ENTERED
|
ENTERED
|
||||||
$ _dotenv_read_answer() { echo 'y' }
|
$ _autoenv_ask_for_yes() { echo "yes"; return 0 }
|
||||||
$ cd ..
|
$ cd ..
|
||||||
Attempting to load unauthorized env file: /tmp/cramtests-??????/leave.t/sub/.env.leave (glob)
|
Attempting to load unauthorized env file!
|
||||||
|
-* /tmp/cramtests-*/leave.t/sub/.env.leave (glob)
|
||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
@ -53,13 +53,13 @@ Leave the directory and answer "no".
|
|||||||
|
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
Would you like to authorize it? [y/N]
|
Would you like to authorize it? (type 'yes') yes
|
||||||
LEFT
|
LEFT
|
||||||
|
|
||||||
|
|
||||||
Now check with subdirs, looking upwards.
|
Now check with subdirs, looking upwards.
|
||||||
|
|
||||||
$ DOTENV_LOOK_UPWARDS=1
|
$ AUTOENV_LOOK_UPWARDS=1
|
||||||
$ mkdir sub/child
|
$ mkdir sub/child
|
||||||
$ cd sub/child
|
$ cd sub/child
|
||||||
ENTERED
|
ENTERED
|
||||||
@ -71,7 +71,7 @@ Now check with subdirs, looking upwards.
|
|||||||
|
|
||||||
Now check with subdirs, not looking at parent dirs.
|
Now check with subdirs, not looking at parent dirs.
|
||||||
|
|
||||||
$ DOTENV_LOOK_UPWARDS=0
|
$ AUTOENV_LOOK_UPWARDS=0
|
||||||
$ cd sub/child
|
$ cd sub/child
|
||||||
$ cd ..
|
$ cd ..
|
||||||
ENTERED
|
ENTERED
|
||||||
@ -80,10 +80,10 @@ Now check with subdirs, not looking at parent dirs.
|
|||||||
LEFT
|
LEFT
|
||||||
|
|
||||||
|
|
||||||
Test that .env is sourced only once with DOTENV_HANDLE_LEAVE=0.
|
Test that .env is sourced only once with AUTOENV_HANDLE_LEAVE=0.
|
||||||
|
|
||||||
$ unset _dotenv_stack_entered
|
$ unset _autoenv_stack_entered
|
||||||
$ DOTENV_HANDLE_LEAVE=0
|
$ AUTOENV_HANDLE_LEAVE=0
|
||||||
$ cd sub
|
$ cd sub
|
||||||
ENTERED
|
ENTERED
|
||||||
$ cd ..
|
$ cd ..
|
||||||
|
167
tests/recurse-upwards.t
Normal file
167
tests/recurse-upwards.t
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
Test recursing into parent .env files.
|
||||||
|
|
||||||
|
$ source $TESTDIR/setup.sh
|
||||||
|
|
||||||
|
Setup env actions / output.
|
||||||
|
|
||||||
|
$ AUTOENV_LOOK_UPWARDS=1
|
||||||
|
|
||||||
|
Create env files in root dir.
|
||||||
|
|
||||||
|
$ echo 'echo ENTERED_root: PWD:${PWD:t} from:${_autoenv_from_dir:t} to:${_autoenv_to_dir:t}' > .env
|
||||||
|
$ echo 'echo LEFT_root: PWD:${PWD:t} from:${_autoenv_from_dir:t} to:${_autoenv_to_dir:t}' > .env.leave
|
||||||
|
$ test_autoenv_auth_env_files
|
||||||
|
|
||||||
|
Create env files in sub dir.
|
||||||
|
|
||||||
|
$ mkdir -p sub/sub2
|
||||||
|
$ cd sub
|
||||||
|
ENTERED_root: PWD:recurse-upwards.t from:recurse-upwards.t to:sub
|
||||||
|
|
||||||
|
$ echo 'echo ENTERED_sub: PWD:${PWD:t} from:${_autoenv_from_dir:t} to:${_autoenv_to_dir:t}' > .env
|
||||||
|
$ echo 'echo LEFT_sub: PWD:${PWD:t} from:${_autoenv_from_dir:t} to:${_autoenv_to_dir:t}' > .env.leave
|
||||||
|
$ test_autoenv_auth_env_files
|
||||||
|
|
||||||
|
The actual tests.
|
||||||
|
|
||||||
|
$ cd .
|
||||||
|
ENTERED_sub: PWD:sub from:sub to:sub
|
||||||
|
|
||||||
|
$ cd ..
|
||||||
|
LEFT_sub: PWD:sub from:sub to:recurse-upwards.t
|
||||||
|
|
||||||
|
$ cd sub/sub2
|
||||||
|
ENTERED_sub: PWD:sub from:recurse-upwards.t to:sub2
|
||||||
|
|
||||||
|
$ cd ..
|
||||||
|
|
||||||
|
Changing the .env file should re-source it.
|
||||||
|
|
||||||
|
$ echo 'echo ENTER2' >> .env
|
||||||
|
|
||||||
|
Set timestamp of auth file into the past, so it gets seen as new below.
|
||||||
|
|
||||||
|
$ touch -t 201401010101 .env
|
||||||
|
|
||||||
|
$ test_autoenv_auth_env_files
|
||||||
|
$ cd .
|
||||||
|
ENTERED_sub: PWD:sub from:sub to:sub
|
||||||
|
ENTER2
|
||||||
|
|
||||||
|
Add sub/sub2/.env file, with a call to autoenv_source_parent.
|
||||||
|
|
||||||
|
$ echo "echo autoenv_source_parent_from_sub2:\nautoenv_source_parent\necho done_sub2\n" > sub2/.env
|
||||||
|
$ test_autoenv_add_to_env sub2/.env
|
||||||
|
$ cd sub2
|
||||||
|
autoenv_source_parent_from_sub2:
|
||||||
|
ENTERED_sub: PWD:sub from:sub to:sub2
|
||||||
|
ENTER2
|
||||||
|
done_sub2
|
||||||
|
|
||||||
|
Move sub/.env away, now the root .env file should get sourced.
|
||||||
|
|
||||||
|
$ mv ../.env ../.env.out
|
||||||
|
$ touch -t 201401010102 .env
|
||||||
|
$ cd .
|
||||||
|
autoenv_source_parent_from_sub2:
|
||||||
|
ENTERED_root: PWD:recurse-upwards.t from:sub2 to:sub2
|
||||||
|
done_sub2
|
||||||
|
$ mv ../.env.out ../.env
|
||||||
|
|
||||||
|
Prepend call to autoenv_source_parent to sub/.env file.
|
||||||
|
|
||||||
|
$ cd ..
|
||||||
|
$ sed -i -e "1s/^/echo autoenv_source_parent_from_sub:\nautoenv_source_parent\n/" .env
|
||||||
|
$ echo "echo done_sub" >> .env
|
||||||
|
$ touch -t 201401010103 .env
|
||||||
|
$ test_autoenv_auth_env_files
|
||||||
|
|
||||||
|
$ cd .
|
||||||
|
autoenv_source_parent_from_sub:
|
||||||
|
ENTERED_root: PWD:recurse-upwards.t from:sub to:sub
|
||||||
|
ENTERED_sub: PWD:sub from:sub to:sub
|
||||||
|
ENTER2
|
||||||
|
done_sub
|
||||||
|
|
||||||
|
|
||||||
|
Add sub/sub2/.env file.
|
||||||
|
|
||||||
|
$ echo -e "echo autoenv_source_parent_from_sub2:\nautoenv_source_parent\necho done_sub2\n" > sub2/.env
|
||||||
|
$ test_autoenv_add_to_env sub2/.env
|
||||||
|
$ cd sub2
|
||||||
|
autoenv_source_parent_from_sub2:
|
||||||
|
autoenv_source_parent_from_sub:
|
||||||
|
ENTERED_root: PWD:recurse-upwards.t from:sub to:sub
|
||||||
|
ENTERED_sub: PWD:sub from:sub to:sub
|
||||||
|
ENTER2
|
||||||
|
done_sub
|
||||||
|
done_sub2
|
||||||
|
|
||||||
|
Go to root.
|
||||||
|
This should not trigger the enter event, because it was handled via
|
||||||
|
autoenv_source_parent already.
|
||||||
|
|
||||||
|
$ cd ../..
|
||||||
|
LEFT_sub: PWD:sub from:sub2 to:recurse-upwards.t
|
||||||
|
|
||||||
|
|
||||||
|
Changing the root .env should trigger re-authentication via autoenv_source_parent.
|
||||||
|
|
||||||
|
First, let's answer "no".
|
||||||
|
|
||||||
|
$ echo "echo NEW" > .env
|
||||||
|
$ _autoenv_ask_for_yes() { echo "no"; return 1 }
|
||||||
|
$ cd sub
|
||||||
|
autoenv_source_parent_from_sub:
|
||||||
|
Attempting to load unauthorized env file!
|
||||||
|
-* /tmp/cramtests-*/recurse-upwards.t/.env (glob)
|
||||||
|
|
||||||
|
**********************************************
|
||||||
|
|
||||||
|
echo NEW
|
||||||
|
|
||||||
|
**********************************************
|
||||||
|
|
||||||
|
Would you like to authorize it? (type 'yes') no
|
||||||
|
ENTERED_sub: PWD:sub from:recurse-upwards.t to:sub
|
||||||
|
ENTER2
|
||||||
|
done_sub
|
||||||
|
|
||||||
|
Now with "yes".
|
||||||
|
This currently does not trigger re-execution of the .env file.
|
||||||
|
|
||||||
|
$ _autoenv_ask_for_yes() { echo "yes"; return 0 }
|
||||||
|
$ cd .
|
||||||
|
|
||||||
|
Touching the .env file will now source the parent env file.
|
||||||
|
|
||||||
|
$ touch -t 201401010104 .env
|
||||||
|
$ cd .
|
||||||
|
autoenv_source_parent_from_sub:
|
||||||
|
Attempting to load unauthorized env file!
|
||||||
|
-* /tmp/cramtests-*/recurse-upwards.t/.env (glob)
|
||||||
|
|
||||||
|
**********************************************
|
||||||
|
|
||||||
|
echo NEW
|
||||||
|
|
||||||
|
**********************************************
|
||||||
|
|
||||||
|
Would you like to authorize it? (type 'yes') yes
|
||||||
|
NEW
|
||||||
|
ENTERED_sub: PWD:sub from:sub to:sub
|
||||||
|
ENTER2
|
||||||
|
done_sub
|
||||||
|
|
||||||
|
|
||||||
|
$ cd ..
|
||||||
|
LEFT_sub: PWD:sub from:sub to:recurse-upwards.t
|
||||||
|
$ mkdir sub/sub2/sub3
|
||||||
|
$ cd sub/sub2/sub3
|
||||||
|
autoenv_source_parent_from_sub2:
|
||||||
|
autoenv_source_parent_from_sub:
|
||||||
|
NEW
|
||||||
|
ENTERED_sub: PWD:sub from:recurse-upwards.t to:sub
|
||||||
|
ENTER2
|
||||||
|
done_sub
|
||||||
|
done_sub2
|
18
tests/setup.sh
Normal file
18
tests/setup.sh
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Ensure we have our mocked out AUTOENV_ENV_FILENAME
|
||||||
|
# (via .zshenv).
|
||||||
|
|
||||||
|
[[ $AUTOENV_ENV_FILENAME[0,4] == '/tmp' ]] || return 1
|
||||||
|
|
||||||
|
# Reset any authentication.
|
||||||
|
echo -n > $AUTOENV_ENV_FILENAME
|
||||||
|
|
||||||
|
# Add file $1 (with optional hash $2) to authentication file.
|
||||||
|
test_autoenv_add_to_env() {
|
||||||
|
_autoenv_hash_pair $1 $2 >> $AUTOENV_ENV_FILENAME
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add enter and leave env files to authentication file.
|
||||||
|
test_autoenv_auth_env_files() {
|
||||||
|
test_autoenv_add_to_env $PWD/$AUTOENV_FILE_ENTER
|
||||||
|
test_autoenv_add_to_env $PWD/$AUTOENV_FILE_LEAVE
|
||||||
|
}
|
32
tests/varstash.t
Normal file
32
tests/varstash.t
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
Test varstash integration.
|
||||||
|
|
||||||
|
$ source $TESTDIR/setup.sh
|
||||||
|
|
||||||
|
Setup test environment.
|
||||||
|
|
||||||
|
$ mkdir sub
|
||||||
|
$ cd sub
|
||||||
|
$ echo 'echo ENTER; autostash FOO=baz' > $AUTOENV_FILE_ENTER
|
||||||
|
$ echo 'echo LEAVE; autounstash' > $AUTOENV_FILE_LEAVE
|
||||||
|
|
||||||
|
Manually create auth file
|
||||||
|
|
||||||
|
$ test_autoenv_auth_env_files
|
||||||
|
|
||||||
|
Set environment variable.
|
||||||
|
|
||||||
|
$ FOO=bar
|
||||||
|
|
||||||
|
Activating the env stashes it and applies a new value.
|
||||||
|
|
||||||
|
$ cd .
|
||||||
|
ENTER
|
||||||
|
$ echo $FOO
|
||||||
|
baz
|
||||||
|
|
||||||
|
Leaving the directory unstashes it.
|
||||||
|
|
||||||
|
$ cd ..
|
||||||
|
LEAVE
|
||||||
|
$ echo $FOO
|
||||||
|
bar
|
Loading…
Reference in New Issue
Block a user