re: non-interactive usage, resurrecting this patch (with tests) from 2019.

I run it locally (as I am constantly `pass show | grep ...`-ing) and have had 
no issues with it since developing it.

--Robert


Begin forwarded message:

On Saturday, July 20, 2019, 2:50 AM, Robert Ames <[email protected]> wrote:
> When working with nested password directories / structures, it's a pain to 
> pick out a particular password key/identifier for copy/paste.  This patch 
> (and test) is the beginning of teaching pass about interactive v. 
> non-interactive usage so that `pass ls` will print fully qualified 
> identifiers when in non-interactive mode.
> 
> The gist of it is captured below, and similar behavior can be seen in the 
> `lastpass-cli` tool (not that lastpass is a great example of what to do in 
> general, but it's very handy to have access to the fully qualified password 
> identifiers).
> 
> https://github.com/lastpass/lastpass-cli/blob/master/cmd-ls.c#L287-L288
> 
> $ ./src/password-store.sh ls
> Password Store
> ├── xxxxxxxx
> │   └── xxxxx.xxx
> └── xxxxx
>     ├── xxxxxxxxxxxxx.xxx
>     ├── xxxxxxx.xxx
>     ├── xxxxxxx.xxx
>     ├── xxxxxxxxx.xxx
>     ├── xxxxxxxxxxxxxxxxxxx.xxx
>     ├── xxxxxxxx.xxx
>     ├── xx.xx-xxxxxxxx
>     ├── xx.xxxxx.xxx
>     │   └── xxx-xxx
>     ├── xxxxxxx.xxx
>     ├── xxxxxxxx
>     │   ├── xxxxxx-xxxxx
>     │   ├── xxxxx-xxxxx-xxxxxxxx
>     │   └── xxxxx-xxxxx-xxxxxxx
>     └── xxxxxx.xxx
> 
> $ ./src/password-store.sh ls | cat
> xxxxxxxx/xxxxx.xxx
> xxxxx/xxxxxxx.xxx
> xxxxx/xx.xxxxx.xxx/xxx-xxx
> xxxxx/xxxxxxx.xxx
> xxxxx/xxxxxxx.xxx
> xxxxx/xxxxxxxx.xxx
> xxxxx/xx.xx-xxxxxxxx
> xxxxx/xxxxxxxxxxxxx.xxx
> xxxxx/xxxxxxxxx.xxx
> xxxxx/xxxxxxxx/xxxxx-xxxxx-xxxxxxxx
> xxxxx/xxxxxxxx/xxxxxx-xxxxx
> xxxxx/xxxxxxxx/xxxxx-xxxxx-xxxxxxx
> xxxxx/xxxxxx.xxx
> xxxxx/xxxxxxxxxxxxxxxxxxx.xxx
> 
> $ ./src/password-store.sh ls | while read id ; do echo "--==[[ $id ]]==--" ; 
> echo ./src/password-store.sh show $id ; done
> --==[[ xxxxxxxx/xxxxx.xxx ]]==--
> ./src/password-store.sh show xxxxxxxx/xxxxx.xxx
> --==[[ xxxxx/xxxxxxx.xxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxxx.xxx
> --==[[ xxxxx/xx.xxxxx.xxx/xxx-xxx ]]==--
> ./src/password-store.sh show xxxxx/xx.xxxxx.xxx/xxx-xxx
> --==[[ xxxxx/xxxxxxx.xxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxxx.xxx
> --==[[ xxxxx/xxxxxxx.xxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxxx.xxx
> --==[[ xxxxx/xxxxxxxx.xxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxxxx.xxx
> --==[[ xxxxx/xx.xx-xxxxxxxx ]]==--
> ./src/password-store.sh show xxxxx/xx.xx-xxxxxxxx
> --==[[ xxxxx/xxxxxxxxxxxxx.xxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxxxxxxxxx.xxx
> --==[[ xxxxx/xxxxxxxxx.xxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxxxxx.xxx
> --==[[ xxxxx/xxxxxxxx/xxxxx-xxxxx-xxxxxxxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxxxx/xxxxx-xxxxx-xxxxxxxx
> --==[[ xxxxx/xxxxxxxx/xxxxxx-xxxxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxxxx/xxxxxx-xxxxx
> --==[[ xxxxx/xxxxxxxx/xxxxx-xxxxx-xxxxxxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxxxx/xxxxx-xxxxx-xxxxxxx
> --==[[ xxxxx/xxxxxx.xxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxx.xxx
> --==[[ xxxxx/xxxxxxxxxxxxxxxxxxx.xxx ]]==--
> ./src/password-store.sh show xxxxx/xxxxxxxxxxxxxxxxxxx.xxx
> 
> 
> 
> 
>> 

From 8e70219ffb7730f524d4eaeaf23409f8ecdd67f3 Mon Sep 17 00:00:00 2001
From: Robert Ames <[email protected]>
Date: Fri, 19 Jul 2019 23:49:21 -0700
Subject: [PATCH] Print full paths in pipeline / non-interactive usage

When using nested directories for password management, the use of "tree"
during password listing makes it difficult to copy/paste password
identifiers.

Attempt basic detection of "TTY" (interactive) as a pre-requisite for
displaying a tree.  For non-interactive uses prefer a simple find
statement which emits full password identifiers ready to by copy/pasted
or proper filtering by any element of the path.

This more closely matches the behaviour of other CLI password tools, for
example `lastpass-cli`[1], and "print_tree" / "isatty"

[1]: https://github.com/lastpass/lastpass-cli/blob/2a70884ed7ef48a8d621687acb96202cc354245b/cmd-ls.c#L287-L288
---
 src/password-store.sh     | 11 +++++++++--
 tests/t0020-show-tests.sh |  8 ++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/password-store.sh b/src/password-store.sh
index 1d119f2..66fe4f1 100755
--- a/src/password-store.sh
+++ b/src/password-store.sh
@@ -5,6 +5,7 @@
 
 umask "${PASSWORD_STORE_UMASK:-077}"
 set -o pipefail
+[[ -t 1 ]] && YES_TTY=1
 
 GPG_OPTS=( $PASSWORD_STORE_GPG_OPTS "--quiet" "--yes" "--compress-algo=none" "--no-encrypt-to" )
 GPG="gpg"
@@ -395,11 +396,17 @@ cmd_show() {
 		fi
 	elif [[ -d $PREFIX/$path ]]; then
 		if [[ -z $path ]]; then
-			echo "Password Store"
+			if [[ $YES_TTY -eq 1 ]] ; then
+				echo "Password Store"
+			fi
 		else
 			echo "${path%\/}"
 		fi
-		tree -C -l --noreport "$PREFIX/$path" | tail -n +2 | sed -E 's/\.gpg(\x1B\[[0-9]+m)?( ->|$)/\1\2/g' # remove .gpg at end of line, but keep colors
+		if [[ -z $YES_TTY ]] ; then
+			find "$PREFIX/$path" -type f -iname \*.gpg | sed -e 's/\.gpg$//g' -e "s,^$PREFIX,,g" -e 's/^\///g' # when non-interactive (pipeline) print full-path-per-entry (for easy copy/paste or filtering)
+		else
+			tree -C -l --noreport "$PREFIX/$path" | tail -n +2 | sed -E 's/\.gpg(\x1B\[[0-9]+m)?( ->|$)/\1\2/g' # remove .gpg at end of line, but keep colors
+		fi
 	elif [[ -z $path ]]; then
 		die "Error: password store is empty. Try \"pass init\"."
 	else
diff --git a/tests/t0020-show-tests.sh b/tests/t0020-show-tests.sh
index a4b782f..c3671b2 100755
--- a/tests/t0020-show-tests.sh
+++ b/tests/t0020-show-tests.sh
@@ -19,4 +19,12 @@ test_expect_success 'Test "show" of nonexistant password' '
 	test_must_fail "$PASS" show cred2
 '
 
+test_expect_success 'Test "show" command with simple tree' '
+	"$PASS" insert -e tree/of/creds1 <<<"blah" &&
+	"$PASS" insert -e tree/of/creds2 <<<"blah" &&
+	[[ $("$PASS" show | grep "tree.of" | wc -l | sed "s/ *//g") == "2" ]] &&
+	"$PASS" rm tree/of/creds1 &&
+	"$PASS" rm tree/of/creds2
+'
+
 test_done
-- 
2.17.1

Reply via email to