commit 2a562f1e1d852068ecd6501929e1b8f6d62f5c0f
parent 094404790dee16a61d257a8b26123e291d42e230
Author: Natasha Kerensikova <natgh@instinctive.eu>
Date: Sat, 1 Nov 2025 18:19:01 +0000
Raw list output is rewritten without subshell
This leads to a 2x speed improvement (from 55 to 25 ms for my store in my machine).
Diffstat:
2 files changed, 43 insertions(+), 63 deletions(-)
diff --git a/spec/action_spec.sh b/spec/action_spec.sh
@@ -1797,11 +1797,11 @@ Describe 'Action Functions'
It 'displays everything without a pattern'
result() {
%text
- #|Base/other/lower
- #|Base/root
- #|Base/subdir/subsub/old
+ #|other/lower
+ #|root
+ #|subdir/subsub/old
}
- When call do_list "${PREFIX}" 'Base/'
+ When call do_list ''
The status should be success
The output should equal "$(result)"
End
@@ -1809,22 +1809,22 @@ Describe 'Action Functions'
It 'displays only matching files'
result() {
%text
- #|Base/other/lower
- #|Base/subdir/subsub/old
+ #|other/lower
+ #|subdir/subsub/old
}
- When call do_list "${PREFIX}" 'Base/' -i L
+ When call do_list '' -i L
The status should be success
The output should equal "$(result)"
End
It 'does not display matching directories'
- When call do_list "${PREFIX}" 'Base/' t
+ When call do_list '' t
The status should be success
- The output should equal 'Base/root'
+ The output should equal 'root'
End
It 'might not display anything'
- When call do_list "${PREFIX}" 'Base/' z
+ When call do_list '' z
The status should be success
The output should equal ''
End
@@ -1872,7 +1872,7 @@ Describe 'Action Functions'
When call do_list_or_show ''
The status should be success
The output should be blank
- The error should equal "$ do_list ${PREFIX} "
+ The error should equal "$ do_list "
End
It 'lists the whole store as a tree'
@@ -1910,7 +1910,7 @@ Describe 'Action Functions'
When call do_list_or_show 'subdir'
The status should be success
The output should be blank
- The error should equal "$ do_list ${PREFIX}/subdir subdir/"
+ The error should equal "$ do_list subdir"
End
It 'lists a subdirectory as a tree'
diff --git a/src/pashage.sh b/src/pashage.sh
@@ -848,58 +848,38 @@ do_insert() {
}
# Display the entry list rooted at the given relative directory
-# $1: root directory
-# $2: path prefix
+# $1: path relative to prefix
# ...: (optional) grep arguments to filter
+# Note that this function is recrusive and cannot use variables to hold state.
do_list() {
- ( cd "$1" && shift && do_list_cwd "$@" )
-}
-
-# Display an entry list
-# $1: path prefix
-# ...: (optional) grep arguments to filter
-do_list_cwd() {
- LIST_PREFIX="$1"
- shift
-
- for ENTRY in *; do
- [ -e "${ENTRY}" ] || continue
- do_list_item "${ENTRY}" "${LIST_PREFIX}" "$@"
- done
- unset ENTRY
-
- unset LIST_PREFIX
-}
-
-# Display an entry in a list
-# $1: item name
-# $2: full item path
-# ...: (optional) grep arguments to filter
-do_list_item() {
- ITEM_NAME="$1"
- ITEM_PATH="$2"
- shift 2
-
- if [ -d "${ITEM_NAME}" ]; then
- do_list "${ITEM_NAME}" \
- "${ITEM_PATH}${ITEM_NAME}/" \
- "$@"
- elif [ "${ITEM_NAME%.age}.age" = "${ITEM_NAME}" ]; then
- if [ $# -eq 0 ] \
- || printf '%s\n' "${ITEM_NAME%.age}" | grep -q "$@"
- then
- printf '%s%s\n' "${ITEM_PATH}" "${ITEM_NAME%.age}"
- fi
- elif [ "${ITEM_NAME%.gpg}.gpg" = "${ITEM_NAME}" ]; then
- if [ $# -eq 0 ] \
- || printf '%s\n' "${ITEM_NAME%.age}" | grep -q "$@"
- then
- printf '%s%s\n' "${ITEM_PATH}" "${ITEM_NAME%.gpg}"
+ for FULL_ENTRY in "${PREFIX}/$1${1:+/}"*; do
+ ENTRY="${FULL_ENTRY#"${PREFIX}/"}"
+ ITEM_NAME="${ENTRY##*/}"
+ if [ -d "${FULL_ENTRY}" ]; then
+ shift
+ set -- "${ENTRY}" "$@"
+ do_list "$@"
+ elif [ "${ENTRY%.age}.age" = "${ENTRY}" ]; then
+ shift
+ set -- "-q" "$@"
+ if [ $# -le 1 ] \
+ || printf '%s\n' "${ITEM_NAME%.age}" | grep "$@"
+ then
+ printf '%s\n' "${ENTRY%.age}"
+ fi
+ elif [ "${ENTRY%.gpg}.gpg" = "${ENTRY}" ]; then
+ shift
+ set -- "-q" "$@"
+ if [ $# -le 1 ] \
+ || printf '%s\n' "${ITEM_NAME%.gpg}" | grep "$@"
+ then
+ printf '%s\n' "${ENTRY%.gpg}"
+ fi
fi
- fi
-
- unset ITEM_NAME
- unset ITEM_PATH
+ unset ENTRY
+ unset ITEM_NAME
+ done
+ unset FULL_ENTRY
}
# Display a single directory or entry
@@ -908,7 +888,7 @@ do_list_item() {
do_list_or_show() {
if [ -z "$1" ]; then
if [ "${LIST_VIEW-no}" = "yes" ]; then
- do_list "${PREFIX}" ""
+ do_list ''
else
do_tree "${PREFIX}" "Password Store"
fi
@@ -920,7 +900,7 @@ do_list_or_show() {
unset SECRET
elif [ -d "${PREFIX}/$1" ]; then
if [ "${LIST_VIEW-no}" = "yes" ]; then
- do_list "${PREFIX}/$1" "${1%/}/"
+ do_list "${1%/}"
else
do_tree "${PREFIX}/$1" "$1"
fi