From dfb56485055edafbb5ca901c0e65c47a13c62ff5 Mon Sep 17 00:00:00 2001 From: Rob Speed Date: Tue, 10 Jan 2017 06:07:39 -0500 Subject: [PATCH] Automatically upgrade v1 hashes (SHA-1) to v2 (`cksum`) (#55) A new parameter is added to `_autoenv_hash_pair` to specify the version, defaulting to the latest (2). It outputs a `cksum`-based hash for version 2 and `shasum`-based for version 1. Moves logic to check for an entry in `$AUTOENV_AUTH_FILE` into its own function (`_autoenv_authorized_pair`), as it may need to be called twice. Modifies `_autoenv_authorized_env_file` to check for v1 entries when v2 fails. Fixes #53. Alternative implementation to #54. --- autoenv.zsh | 52 ++++++++++++++++++++++++++++++++---------- tests/_autoenv_utils.t | 24 +++++++++---------- tests/setup.zsh | 4 ++-- tests/upgrade_hash.t | 43 ++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 26 deletions(-) create mode 100644 tests/upgrade_hash.t diff --git a/autoenv.zsh b/autoenv.zsh index ed570c0..e6cfc13 100644 --- a/autoenv.zsh +++ b/autoenv.zsh @@ -168,30 +168,58 @@ _autoenv_debug() { # }}} -# Generate hash pair for a given file ($1). -# A fixed hash value can be given as 2nd arg, but is used with tests only. +# Generate hash pair for a given file ($1) and version ($2). +# A fixed hash value can be given as 3rd arg, but is used with tests only. # The format is ":$file:$hash:$version". _autoenv_hash_pair() { local env_file=${1:A} - local env_cksum=${2:-} + local cksum_version=${2:-2} + local env_cksum=${3:-} if [[ -z $env_cksum ]]; then if ! [[ -e $env_file ]]; then echo "Missing file argument for _autoenv_hash_pair!" >&2 return 1 fi - # Get the output from `cksum` and join the first two words with a dot. - env_cksum=${(j:.:)${:-$(cksum "$env_file")}[1,2]} + if [ $cksum_version = 2 ]; then + # Get the output from `cksum` and join the first two words with a dot. + env_cksum=${(j:.:)${:-$(cksum "$env_file")}[1,2]} + elif [ $cksum_version = 1 ]; then + env_cksum=$(shasum $env_file | cut -d' ' -f1) + else + echo "Invalid version argument (${cksum_version}) for _autoenv_hash_pair!" >&2 + return 1 + fi fi - echo ":${env_file}:${env_cksum}:1" + echo ":${env_file}:${env_cksum}:${cksum_version}" } -_autoenv_authorized_env_file() { - local env_file=$1 - local pair="$(_autoenv_hash_pair $env_file)" + +# Checks for the existence of a hash signature in the auth file +_autoenv_authorized_pair() { + local pair=$1 test -f $AUTOENV_AUTH_FILE \ && \grep -qF $pair $AUTOENV_AUTH_FILE } + +_autoenv_authorized_env_file() { + local env_file=$1 + local pair + pair=$(_autoenv_hash_pair $env_file) + _autoenv_debug "v2 pair: ${pair}" + if ! _autoenv_authorized_pair $pair; then + # Fallback for v1 (SHA-1) pairs + pair=$(_autoenv_hash_pair $env_file 1) + _autoenv_debug "v1 pair: ${pair}" + if _autoenv_authorized_pair $pair; then + # Upgrade v1 entries to v2 + _autoenv_authorize $env_file + else + return 1 + fi + fi +} + _autoenv_authorize() { local env_file=${1:A} _autoenv_deauthorize $env_file @@ -200,12 +228,12 @@ _autoenv_authorize() { } # Deauthorize a given filename, by removing it from the auth file. -# This uses `test -s` to only handle non-empty files, and a subshell to -# allow for writing to the same file again. +# This uses `test -s` to only handle non-empty files. _autoenv_deauthorize() { local env_file=${1:A} if [[ -s $AUTOENV_AUTH_FILE ]]; then - echo "$(\grep -vF :${env_file}: $AUTOENV_AUTH_FILE)" >| $AUTOENV_AUTH_FILE + \grep -vF :${env_file}: $AUTOENV_AUTH_FILE >| $AUTOENV_AUTH_FILE.tmp + \mv $AUTOENV_AUTH_FILE.tmp $AUTOENV_AUTH_FILE fi } diff --git a/tests/_autoenv_utils.t b/tests/_autoenv_utils.t index bf46c83..f4f2e2c 100644 --- a/tests/_autoenv_utils.t +++ b/tests/_autoenv_utils.t @@ -35,41 +35,41 @@ Now adding some auth pair. $ echo first > first $ _autoenv_authorize first $ cat $AUTOENV_AUTH_FILE - :/tmp/cramtests-*/_autoenv_utils.t/first:2715464726.6:1 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/first:2715464726.6:2 (glob) And a second one. $ echo second > second $ _autoenv_authorize second $ cat $AUTOENV_AUTH_FILE - :/tmp/cramtests-*/_autoenv_utils.t/first:2715464726.6:1 (glob) - :/tmp/cramtests-*/_autoenv_utils.t/second:594940475.7:1 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/first:2715464726.6:2 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/second:594940475.7:2 (glob) And a third. $ echo third > third $ _autoenv_authorize third $ cat $AUTOENV_AUTH_FILE - :/tmp/cramtests-*/_autoenv_utils.t/first:2715464726.6:1 (glob) - :/tmp/cramtests-*/_autoenv_utils.t/second:594940475.7:1 (glob) - :/tmp/cramtests-*/_autoenv_utils.t/third:451243482.6:1 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/first:2715464726.6:2 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/second:594940475.7:2 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/third:451243482.6:2 (glob) Re-add the second one, with the same hash. $ _autoenv_authorize second $ cat $AUTOENV_AUTH_FILE - :/tmp/cramtests-*/_autoenv_utils.t/first:2715464726.6:1 (glob) - :/tmp/cramtests-*/_autoenv_utils.t/third:451243482.6:1 (glob) - :/tmp/cramtests-*/_autoenv_utils.t/second:594940475.7:1 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/first:2715464726.6:2 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/third:451243482.6:2 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/second:594940475.7:2 (glob) Re-add the first one, with a new hash. $ echo one more line >> first $ _autoenv_authorize first $ cat $AUTOENV_AUTH_FILE - :/tmp/cramtests-*/_autoenv_utils.t/third:451243482.6:1 (glob) - :/tmp/cramtests-*/_autoenv_utils.t/second:594940475.7:1 (glob) - :/tmp/cramtests-*/_autoenv_utils.t/first:3620404822.20:1 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/third:451243482.6:2 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/second:594940475.7:2 (glob) + :/tmp/cramtests-*/_autoenv_utils.t/first:3620404822.20:2 (glob) }}} diff --git a/tests/setup.zsh b/tests/setup.zsh index 78eb02e..9e789ec 100644 --- a/tests/setup.zsh +++ b/tests/setup.zsh @@ -28,9 +28,9 @@ if [[ -f $AUTOENV_AUTH_FILE ]]; then echo -n >| $AUTOENV_AUTH_FILE fi -# Add file $1 (with optional hash $2) to authentication file. +# Add file ($1), version ($2), and optional hash ($3) to authentication file. test_autoenv_add_to_env() { - _autoenv_hash_pair $1 ${2:-} >>| $AUTOENV_AUTH_FILE + _autoenv_hash_pair $1 1 ${2:-} >>| $AUTOENV_AUTH_FILE } # Add enter and leave env files to authentication file. diff --git a/tests/upgrade_hash.t b/tests/upgrade_hash.t new file mode 100644 index 0000000..03c9ae1 --- /dev/null +++ b/tests/upgrade_hash.t @@ -0,0 +1,43 @@ +Tests for upgrading hashes. + + $ source $TESTDIR/setup.zsh || return 1 + + $ mkdir -p sub + $ mkdir -p ${AUTOENV_AUTH_FILE:h} + +Create a single v1 hash entry. + + $ echo 'echo ENTERED' > sub/$AUTOENV_FILE_ENTER + $ echo 'echo LEAVE' > sub/$AUTOENV_FILE_LEAVE + + $ echo :$PWD/sub/$AUTOENV_FILE_ENTER:4c403f1870af2ab5472370a42b6b2b488cefe83c:1 > $AUTOENV_AUTH_FILE + $ cd sub + ENTERED + +Hashes should get upgraded automatically. +This also tests that there are no empty lines being added to the auth file when +de-authenticating the old hash. + + $ cat $AUTOENV_AUTH_FILE + :/tmp/cramtests-*/upgrade_hash.t/sub/.autoenv.zsh:3679467995.13:2 (glob) + +Re-create auth file with v1 hashes for both auth files. + + $ echo :$PWD/$AUTOENV_FILE_LEAVE:882cf0333ea3c35537c9459c08d8987f25087ea9:1 > $AUTOENV_AUTH_FILE + $ echo :$PWD/$AUTOENV_FILE_ENTER:4c403f1870af2ab5472370a42b6b2b488cefe83c:1 >> $AUTOENV_AUTH_FILE + +Only the leave file's hash should get updated. + + $ cd .. + LEAVE + $ cat $AUTOENV_AUTH_FILE + :/tmp/cramtests-*/upgrade_hash.t/sub/.autoenv.zsh:4c403f1870af2ab5472370a42b6b2b488cefe83c:1 (glob) + :/tmp/cramtests-*/upgrade_hash.t/sub/.autoenv_leave.zsh:803077150.11:2 (glob) + +The enter file's hash should get updated. + + $ cd sub + ENTERED + $ cat $AUTOENV_AUTH_FILE + :/tmp/cramtests-*/upgrade_hash.t/sub/.autoenv_leave.zsh:803077150.11:2 (glob) + :/tmp/cramtests-*/upgrade_hash.t/sub/.autoenv.zsh:3679467995.13:2 (glob) -- 2.44.0