[PATCH] Improve extensions support
HacKan
hackan at gmail.com
Thu Mar 23 04:27:06 CET 2017
- Change command selection switch based on parameters by a more flexible
design using eval.
- Read user extensions first when executing a command, so even internal
commmands can be overridden.
- Add helper `override_function()` to enable extensions to override, but
use, internal functions. Overriden functions are renamed to
`pass_{function name}`.
---
src/password-store.sh | 118 ++++++++++++++++++++++++++++++++++----------------
1 file changed, 80 insertions(+), 38 deletions(-)
diff --git a/src/password-store.sh b/src/password-store.sh
index 2a9cad6..893ca66 100755
--- a/src/password-store.sh
+++ b/src/password-store.sh
@@ -142,6 +142,42 @@ check_sneaky_paths() {
done
}
+SYSTEM_EXTENSION_DIR=""
+check_extension_and_load() {
+ check_sneaky_paths "$1"
+ local user_extension system_extension extension
+ [[ -n $SYSTEM_EXTENSION_DIR ]] && system_extension="$SYSTEM_EXTENSION_DIR/$1.bash"
+ [[ $PASSWORD_STORE_ENABLE_EXTENSIONS == true ]] && user_extension="$EXTENSIONS/$1.bash"
+ if [[ -n $user_extension && -f $user_extension && -x $user_extension ]]; then
+ verify_file "$user_extension"
+ extension="$user_extension"
+ elif [[ -n $system_extension && -f $system_extension && -x $system_extension ]]; then
+ extension="$system_extension"
+ else
+ return 1
+ fi
+ shift
+ # shellcheck source=/dev/null
+ source "$extension" "$@"
+ return 0
+}
+
+override_function() {
+ # Recieves a function name, and it renames it to pass_<function name>
+ # based on http://mivok.net/2009/09/20/bashfunctionoverrist.html
+ local func="$1"
+
+ if type "$func" > /dev/null 2>&1; then
+ local contents newname
+ contents=$(declare -f $func)
+ newname="pass_${func}${contents#$func}"
+ eval "$newname"
+ return $?
+ fi
+
+ return 1
+}
+
in_array() {
local seeking="$1"; shift
local in=1
@@ -338,6 +374,8 @@ cmd_usage() {
echo "More information may be found in the ${PROGRAM}(1) man page."
}
+cmd_help() { cmd_usage "$@"; }
+cmd_h() { cmd_usage "$@"; }
cmd_init() {
local opts id_path=""
@@ -500,6 +538,7 @@ cmd_insert() {
fi
git_add_file "$passfile" "Add given password for $path to store."
}
+cmd_add() { cmd_insert "$@"; }
cmd_edit() {
[[ $# -ne 1 ]] && die "Usage: $PROGRAM $COMMAND pass-name"
@@ -612,6 +651,8 @@ cmd_delete() {
fi
rmdir -p "${passfile%/*}" 2>/dev/null
}
+cmd_remove() { cmd_delete "$@"; }
+cmd_rm() { cmd_delete "$@"; }
cmd_copy_move() {
local opts move=1 force=0
@@ -667,6 +708,10 @@ cmd_copy_move() {
git_add_file "$new_path" "Copy ${1} to ${2}."
fi
}
+cmd_rename() { cmd_copy_move "move" "$@"; }
+cmd_mv() { cmd_copy_move "move" "$@"; }
+cmd_cp() { cmd_copy_move "copy" "$@"; }
+cmd_copy() { cmd_copy_move "copy" "$@"; }
cmd_git() {
set_git "$PREFIX/"
@@ -688,30 +733,26 @@ cmd_git() {
fi
}
-cmd_extension_or_show() {
- if ! cmd_extension "$@"; then
- COMMAND="show"
- cmd_show "$@"
- fi
-}
+cmd_internal() {
+ local cmd counter=0
+ cmd="$COMMAND"
-SYSTEM_EXTENSION_DIR=""
-cmd_extension() {
- check_sneaky_paths "$1"
- local user_extension system_extension extension
- [[ -n $SYSTEM_EXTENSION_DIR ]] && system_extension="$SYSTEM_EXTENSION_DIR/$1.bash"
- [[ $PASSWORD_STORE_ENABLE_EXTENSIONS == true ]] && user_extension="$EXTENSIONS/$1.bash"
- if [[ -n $user_extension && -f $user_extension && -x $user_extension ]]; then
- verify_file "$user_extension"
- extension="$user_extension"
- elif [[ -n $system_extension && -f $system_extension && -x $system_extension ]]; then
- extension="$system_extension"
- else
- return 1
+ # Remove dashes (up to 2)
+ while [[ "${cmd:0:1}" == "-" && $counter -lt 2 ]]; do
+ cmd="${cmd:1}"
+ let counter+=1
+ done
+
+ # Check if a function exists
+ if type "cmd_${cmd}" > /dev/null 2>&1; then
+ shift
+ eval '"cmd_${cmd}" "$@"'
+ # Internal commands don't handle well return values, but they either
+ # die (exit 1) or succeed, so fix return value to 0
+ return 0
fi
- shift
- source "$extension" "$@"
- return 0
+
+ return 1
}
#
@@ -721,20 +762,21 @@ cmd_extension() {
PROGRAM="${0##*/}"
COMMAND="$1"
-case "$1" in
- init) shift; cmd_init "$@" ;;
- help|--help) shift; cmd_usage "$@" ;;
- version|--version) shift; cmd_version "$@" ;;
- show|ls|list) shift; cmd_show "$@" ;;
- find|search) shift; cmd_find "$@" ;;
- grep) shift; cmd_grep "$@" ;;
- insert|add) shift; cmd_insert "$@" ;;
- edit) shift; cmd_edit "$@" ;;
- generate) shift; cmd_generate "$@" ;;
- delete|rm|remove) shift; cmd_delete "$@" ;;
- rename|mv) shift; cmd_copy_move "move" "$@" ;;
- copy|cp) shift; cmd_copy_move "copy" "$@" ;;
- git) shift; cmd_git "$@" ;;
- *) cmd_extension_or_show "$@" ;;
-esac
+# Check if command is an extension
+check_extension_and_load "$@" && exit 0
+
+# Check if command is internal command
+#
+# Internal commands must begin with cmd_ and named like cmd_command
+# Multiname functions such as delete=remove=rm can be done like
+# cmd_remove() { cmd_delete "$@"; }
+# cmd_rm() { cmd_delete "$@"; }
+# Others like help=--help=-h are handled by cmd_internal() as long as a
+# function without the dashes but same name exists.
+cmd_internal "$@" && exit 0
+
+# Assume its an implicit show command
+COMMAND="show"
+check_extension_and_load show "$@" || cmd_show "$@"
+
exit 0
--
2.11.0
More information about the Password-Store
mailing list