From: Tino Calancha <[email protected]>

Git option -C requires version >= 1.8.5.  Add a wrapper
function exec_git_command, to run the Git commands.  If
the system Git supports -C option, then use it; otherwise,
emulate that option inside the wrapper.

The options --matchdirs/--ignore-case, used by cmd_find,
require tree version >= v1.7.0.  For lower versions, print a message
to stderr and run tree without the unsupported options.

See: https://bugzilla.redhat.com/show_bug.cgi?id=1639806
* src/password-store.sh (exec_git_command): New function.
(cmd_find): Use --matchdirs/--ignore-case options if they are
available; otherwise, warn user and run tree without the
unsupported options.

* tests/t0500-find.sh: Update find test to cover tree versions < 1.7.0.

* tests/t0300-reencryption.sh: Tweak test to pass on git v1.8.3.
---
 src/password-store.sh       | 57 +++++++++++++++++++++++++++----------
 tests/t0300-reencryption.sh |  4 +--
 tests/t0500-find.sh         | 35 ++++++++++++++++-------
 3 files changed, 69 insertions(+), 27 deletions(-)

diff --git a/src/password-store.sh b/src/password-store.sh
index 1d119f2..a44282f 100755
--- a/src/password-store.sh
+++ b/src/password-store.sh
@@ -26,24 +26,40 @@ export GIT_CEILING_DIRECTORIES="$PREFIX/.."
 # BEGIN helper functions
 #
 
+# If the system Git doesn't support the -C option, then emulate
+# it with pushd/popd.
+exec_git_command() {
+    if git --help | grep -q '\[-C <path>\]'; then
+        git -C "$INNER_GIT_DIR" "$@"
+        return $?
+    fi
+    # Emulate Git -C option.
+    pushd "$INNER_GIT_DIR" > /dev/null
+    git "$@"
+    local result=$?
+    popd > /dev/null
+    return $result
+}
+
+
 set_git() {
        INNER_GIT_DIR="${1%/*}"
        while [[ ! -d $INNER_GIT_DIR && ${INNER_GIT_DIR%/*}/ == "${PREFIX%/}/"* 
]]; do
                INNER_GIT_DIR="${INNER_GIT_DIR%/*}"
        done
-       [[ $(git -C "$INNER_GIT_DIR" rev-parse --is-inside-work-tree 
2>/dev/null) == true ]] || INNER_GIT_DIR=""
+       [[ $(exec_git_command rev-parse --is-inside-work-tree 2>/dev/null) == 
true ]] || INNER_GIT_DIR=""
 }
 git_add_file() {
        [[ -n $INNER_GIT_DIR ]] || return
-       git -C "$INNER_GIT_DIR" add "$1" || return
-       [[ -n $(git -C "$INNER_GIT_DIR" status --porcelain "$1") ]] || return
+       exec_git_command add "$1" || return
+       [[ -n $(exec_git_command status --porcelain "$1") ]] || return
        git_commit "$2"
 }
 git_commit() {
        local sign=""
        [[ -n $INNER_GIT_DIR ]] || return
-       [[ $(git -C "$INNER_GIT_DIR" config --bool --get pass.signcommits) == 
"true" ]] && sign="-S"
-       git -C "$INNER_GIT_DIR" commit $sign -m "$1"
+       [[ $(exec_git_command config --bool --get pass.signcommits) == "true" 
]] && sign="-S"
+       exec_git_command commit $sign -m "$1"
 }
 yesno() {
        [[ -t 0 ]] || return 0
@@ -336,7 +352,7 @@ cmd_init() {
                [[ ! -f "$gpg_id" ]] && die "Error: $gpg_id does not exist and 
so cannot be removed."
                rm -v -f "$gpg_id" || exit 1
                if [[ -n $INNER_GIT_DIR ]]; then
-                       git -C "$INNER_GIT_DIR" rm -qr "$gpg_id"
+                       exec_git_command rm -qr "$gpg_id"
                        git_commit "Deinitialize ${gpg_id}${id_path:+ 
($id_path)}."
                fi
                rmdir -p "${gpg_id%/*}" 2>/dev/null
@@ -411,7 +427,18 @@ cmd_find() {
        [[ $# -eq 0 ]] && die "Usage: $PROGRAM $COMMAND pass-names..."
        IFS="," eval 'echo "Search Terms: $*"'
        local terms="*$(printf '%s*|*' "$@")"
-       tree -C -l --noreport -P "${terms%|*}" --prune --matchdirs 
--ignore-case "$PREFIX" | tail -n +2 | sed -E 's/\.gpg(\x1B\[[0-9]+m)?( 
->|$)/\1\2/g'
+    local tree_version=$(tree --version | sed 's/tree 
\([^[:space:]]\+\).*/\1/g')
+    # Use --matchdirs and --ignore-case options only when available.
+    if tree --help |& grep -q -e --matchdirs; then
+           tree -C -l --noreport -P "${terms%|*}" --prune --matchdirs 
--ignore-case "$PREFIX" | tail -n +2 | sed -E 's/\.gpg(\x1B\[[0-9]+m)?( 
->|$)/\1\2/g'
+    else
+        cat >&2 <<-_EOF
+        Your tree version ($tree_version) doesn't support 
--ignore-case/--matchdirs options.
+        Upgrade tree to version >= 1.7.0 if you wish to use them.
+
+_EOF
+        tree -C -l --noreport -P "${terms%|*}" --prune "$PREFIX" | tail -n +2 
| sed -E 's/\.gpg(\x1B\[[0-9]+m)?( ->|$)/\1\2/g'
+    fi
 }
 
 cmd_grep() {
@@ -584,7 +611,7 @@ cmd_delete() {
        rm $recursive -f -v "$passfile"
        set_git "$passfile"
        if [[ -n $INNER_GIT_DIR && ! -e $passfile ]]; then
-               git -C "$INNER_GIT_DIR" rm -qr "$passfile"
+               exec_git_command rm -qr "$passfile"
                set_git "$passfile"
                git_commit "Remove $path from store."
        fi
@@ -628,15 +655,15 @@ cmd_copy_move() {
 
                set_git "$new_path"
                if [[ -n $INNER_GIT_DIR && ! -e $old_path ]]; then
-                       git -C "$INNER_GIT_DIR" rm -qr "$old_path" 2>/dev/null
+                       exec_git_command rm -qr "$old_path" 2>/dev/null
                        set_git "$new_path"
                        git_add_file "$new_path" "Rename ${1} to ${2}."
                fi
                set_git "$old_path"
                if [[ -n $INNER_GIT_DIR && ! -e $old_path ]]; then
-                       git -C "$INNER_GIT_DIR" rm -qr "$old_path" 2>/dev/null
+                       exec_git_command rm -qr "$old_path" 2>/dev/null
                        set_git "$old_path"
-                       [[ -n $(git -C "$INNER_GIT_DIR" status --porcelain 
"$old_path") ]] && git_commit "Remove ${1}."
+                       [[ -n $(exec_git_command status --porcelain 
"$old_path") ]] && git_commit "Remove ${1}."
                fi
                rmdir -p "$old_dir" 2>/dev/null
        else
@@ -650,17 +677,17 @@ cmd_git() {
        set_git "$PREFIX/"
        if [[ $1 == "init" ]]; then
                INNER_GIT_DIR="$PREFIX"
-               git -C "$INNER_GIT_DIR" "$@" || exit 1
+               exec_git_command "$@" || exit 1
                git_add_file "$PREFIX" "Add current contents of password store."
 
                echo '*.gpg diff=gpg' > "$PREFIX/.gitattributes"
                git_add_file .gitattributes "Configure git repository for gpg 
file diff."
-               git -C "$INNER_GIT_DIR" config --local diff.gpg.binary true
-               git -C "$INNER_GIT_DIR" config --local diff.gpg.textconv "$GPG 
-d ${GPG_OPTS[*]}"
+               exec_git_command config --local diff.gpg.binary true
+               exec_git_command config --local diff.gpg.textconv "$GPG -d 
${GPG_OPTS[*]}"
        elif [[ -n $INNER_GIT_DIR ]]; then
                tmpdir nowarn #Defines $SECURE_TMPDIR. We don't warn, because 
at most, this only copies encrypted files.
                export TMPDIR="$SECURE_TMPDIR"
-               git -C "$INNER_GIT_DIR" "$@"
+               exec_git_command "$@"
        else
                die "Error: the password store is not a git repository. Try 
\"$PROGRAM git init\"."
        fi
diff --git a/tests/t0300-reencryption.sh b/tests/t0300-reencryption.sh
index 3c88987..4729f58 100755
--- a/tests/t0300-reencryption.sh
+++ b/tests/t0300-reencryption.sh
@@ -90,8 +90,8 @@ test_expect_success 'Reencryption subfolder multiple keys, 
move, deinit' '
 test_expect_success 'Reencryption skips links' '
        ln -s "$PASSWORD_STORE_DIR/folder/cred1.gpg" 
"$PASSWORD_STORE_DIR/folder/linked_cred.gpg" &&
        [[ -L $PASSWORD_STORE_DIR/folder/linked_cred.gpg ]] &&
-       git add "$PASSWORD_STORE_DIR/folder/linked_cred.gpg" &&
-       git commit "$PASSWORD_STORE_DIR/folder/linked_cred.gpg" -m "Added 
linked cred" &&
+       git add "folder/linked_cred.gpg" &&
+       git commit -m "Added linked cred" &&
        "$PASS" init -p folder $KEY3 &&
        [[ -L $PASSWORD_STORE_DIR/folder/linked_cred.gpg ]]
 '
diff --git a/tests/t0500-find.sh b/tests/t0500-find.sh
index 3cf6815..9727b35 100755
--- a/tests/t0500-find.sh
+++ b/tests/t0500-find.sh
@@ -4,15 +4,30 @@ test_description='Find check'
 cd "$(dirname "$0")"
 . ./setup.sh
 
-test_expect_success 'Make sure find resolves correct files' '
-       "$PASS" init $KEY1 &&
-       "$PASS" generate Something/neat 19 &&
-       "$PASS" generate Anotherthing/okay 38 &&
-       "$PASS" generate Fish 12 &&
-       "$PASS" generate Fishthings 122 &&
-       "$PASS" generate Fishies/stuff 21 &&
-       "$PASS" generate Fishies/otherstuff 1234 &&
-       [[ $("$PASS" find fish | sed "s/^[ \`|-]*//g;s/$(printf 
\\x1b)\\[[0-9;]*[a-zA-Z]//g" | tr "\\n" -) == "Search Terms: 
fish-Fish-Fishies-otherstuff-stuff-Fishthings-" ]]
-'
+if tree --help 2>&1 | grep -q -e --ignore-case -e --matchdirs; then
+       test_expect_success 'Make sure find resolves correct files' '
+               "$PASS" init $KEY1 &&
+               "$PASS" generate Something/neat 19 &&
+               "$PASS" generate Anotherthing/okay 38 &&
+               "$PASS" generate Fish 12 &&
+               "$PASS" generate Fishthings 122 &&
+               "$PASS" generate Fishies/stuff 21 &&
+               "$PASS" generate Fishies/otherstuff 1234 &&
+               [[ $("$PASS" find fish | sed "s/^[ \`|-]*//g;s/$(printf 
\\x1b)\\[[0-9;]*[a-zA-Z]//g" | tr "\\n" -) == "Search Terms: 
fish-Fish-Fishies-otherstuff-stuff-Fishthings-" ]]
+       '
+else
+       # Redirect stderr to /dev/null to drop the warning message.
+       test_expect_success 'Make sure find resolves correct files' '
+               "$PASS" init $KEY1 &&
+               "$PASS" generate Something/neat 19 &&
+               "$PASS" generate Anotherthing/okay 38 &&
+               "$PASS" generate Fish 12 &&
+               "$PASS" generate myfish 12 &&
+               "$PASS" generate Fishthings 122 &&
+               "$PASS" generate Fishies/stuff 21 &&
+               "$PASS" generate Fishies/otherstuff 1234 &&
+               [[ $("$PASS" find fish 2>/dev/null | sed "s/^[ 
\`|-]*//g;s/$(printf \\x1b)\\[[0-9;]*[a-zA-Z]//g" | tr "\\n" -) == "Search 
Terms: fish-myfish-" ]]
+       '
+fi
 
 test_done
-- 
2.20.1

_______________________________________________
Password-Store mailing list
[email protected]
https://lists.zx2c4.com/mailman/listinfo/password-store

Reply via email to