commit cefe552791b1e9ebb41f3836cd491490cdb04a0a
parent f562e3cda4f5407ef8fa8f969cad7cc1a92f3f89
Author: Natasha Kerensikova <natgh@instinctive.eu>
Date: Sun, 3 Nov 2024 17:07:27 +0000
Re-encryption in copy and move commands is redesigned
Diffstat:
3 files changed, 89 insertions(+), 74 deletions(-)
diff --git a/spec/action_spec.sh b/spec/action_spec.sh
@@ -41,7 +41,7 @@ Describe 'Action Functions'
}
basename() { @basename "$@"; }
- diff() { @diff "$@"; }
+ cat() { @cat "$@"; }
dirname() { @dirname "$@"; }
mkdir() { mocklog mkdir "$@"; }
@@ -202,7 +202,13 @@ Describe 'Action Functions'
result() {
%text:expand
#|$ scm_begin
- #|$ scm_mv sub/ subdir/sub/
+ #|$ mkdir -p -- ${PREFIX}/subdir/sub
+ #|$ scm_mv sub/.age-recipients subdir/sub/.age-recipients
+ #|$ mkdir -p -- ${PREFIX}/subdir/sub/bare
+ #|$ scm_mv sub/bare/deep.age subdir/sub/bare/deep.age
+ #|$ mkdir -p -- ${PREFIX}/subdir/sub/bare/sub
+ #|$ scm_mv sub/bare/sub/deepest.age subdir/sub/bare/sub/deepest.age
+ #|$ scm_mv sub/secret.age subdir/sub/secret.age
#|$ scm_commit Move sub/ to subdir/sub/
}
When call do_copy_move sub subdir/
@@ -211,7 +217,46 @@ Describe 'Action Functions'
The error should equal "$(result)"
End
- It 'recursively re-enecrypts a directory'
+ It 'recursively moves files to a directory with the same identity'
+ result() {
+ %text:expand
+ #|$ scm_begin
+ #|$ mkdir -p -- ${PREFIX}/subdir/new-bare
+ #|$ scm_mv sub/bare/deep.age subdir/new-bare/deep.age
+ #|$ mkdir -p -- ${PREFIX}/subdir/new-bare/sub
+ #|$ scm_mv sub/bare/sub/deepest.age subdir/new-bare/sub/deepest.age
+ #|$ scm_commit Move sub/bare/ to subdir/new-bare/
+ }
+ When call do_copy_move sub/bare subdir/new-bare
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'recursively re-encrypts a directory'
+ result() {
+ %text:expand
+ #|$ scm_begin
+ #|$ mkdir -p -- ${PREFIX}/new-bare
+ #|$ do_decrypt ${PREFIX}/sub/bare/deep.age
+ #|$ do_encrypt new-bare/deep.age
+ #|$ scm_rm sub/bare/deep.age
+ #|$ scm_add new-bare/deep.age
+ #|$ mkdir -p -- ${PREFIX}/new-bare/sub
+ #|$ do_decrypt ${PREFIX}/sub/bare/sub/deepest.age
+ #|$ do_encrypt new-bare/sub/deepest.age
+ #|$ scm_rm sub/bare/sub/deepest.age
+ #|$ scm_add new-bare/sub/deepest.age
+ #|$ scm_commit Move sub/bare/ to new-bare/
+ }
+ When call do_copy_move sub/bare new-bare
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'recursively re-encrypts a directory with the same identity when forced'
+ DECISION=force
result() {
%text:expand
#|$ scm_begin
@@ -297,14 +342,6 @@ Describe 'Action Functions'
The status should equal 1
End
- It 'checks internal consistency of DECISION'
- DECISION=garbage
- When run do_copy_move root subdir
- The output should be blank
- The error should equal 'Unexpected DECISION value "garbage"'
- The status should equal 1
- End
-
# Unreachable branches in do_copy_move_file, defensively implemented
It 'defensively avois re-encrypting'
DECISION=keep
diff --git a/spec/internal_spec.sh b/spec/internal_spec.sh
@@ -158,6 +158,7 @@ Describe 'Internal Helper Functions'
echo "Toplevel recipient" >"${PREFIX}/.age-recipients"
echo "Subdir recipient" >"${PREFIX}/subdir/.age-recipients"
}
+ cat() { @cat "$@"; }
cleanup() { @rm -rf "${PREFIX}"; }
BeforeEach 'setup'
@@ -168,6 +169,7 @@ Describe 'Internal Helper Functions'
The status should be success
The variable LOCAL_RECIPIENT_FILE should equal \
"${PREFIX}/.age-recipients"
+ The variable LOCAL_RECIPIENTS should equal 'Toplevel recipient'
End
It 'returns root from unmarked subdirectory'
@@ -175,6 +177,7 @@ Describe 'Internal Helper Functions'
The status should be success
The variable LOCAL_RECIPIENT_FILE should equal \
"${PREFIX}/.age-recipients"
+ The variable LOCAL_RECIPIENTS should equal 'Toplevel recipient'
End
It 'returns subdirectory from itself'
@@ -182,6 +185,7 @@ Describe 'Internal Helper Functions'
The status should be success
The variable LOCAL_RECIPIENT_FILE should equal \
"${PREFIX}/subdir/.age-recipients"
+ The variable LOCAL_RECIPIENTS should equal 'Subdir recipient'
End
It 'returns subdirectory from sub-subdirectory'
@@ -189,6 +193,7 @@ Describe 'Internal Helper Functions'
The status should be success
The variable LOCAL_RECIPIENT_FILE should equal \
"${PREFIX}/subdir/.age-recipients"
+ The variable LOCAL_RECIPIENTS should equal 'Subdir recipient'
End
setup() {
@@ -201,12 +206,14 @@ Describe 'Internal Helper Functions'
When call set_LOCAL_RECIPIENT_FILE foo
The status should be success
The variable LOCAL_RECIPIENT_FILE should equal ''
+ The variable LOCAL_RECIPIENTS should equal ''
End
It 'returns nothing from unmarked subdirectory below empty root'
When call set_LOCAL_RECIPIENT_FILE special/foo
The status should be success
The variable LOCAL_RECIPIENT_FILE should equal ''
+ The variable LOCAL_RECIPIENTS should equal ''
End
It 'returns subdirectory from itself even under empty root'
@@ -214,6 +221,7 @@ Describe 'Internal Helper Functions'
The status should be success
The variable LOCAL_RECIPIENT_FILE should equal \
"${PREFIX}/subdir/.age-recipients"
+ The variable LOCAL_RECIPIENTS should equal 'Subdir recipient'
End
It 'returns subdirectory from sub-subdirectory even under empty root'
@@ -221,6 +229,7 @@ Describe 'Internal Helper Functions'
The status should be success
The variable LOCAL_RECIPIENT_FILE should equal \
"${PREFIX}/subdir/.age-recipients"
+ The variable LOCAL_RECIPIENTS should equal 'Subdir recipient'
End
End
diff --git a/src/pashage.sh b/src/pashage.sh
@@ -89,10 +89,12 @@ set_LOCAL_RECIPIENT_FILE() {
if ! [ -f "${PREFIX}${LOCAL_RECIPIENT_FILE}/.age-recipients" ]; then
LOCAL_RECIPIENT_FILE=
+ LOCAL_RECIPIENTS=
return 0
fi
LOCAL_RECIPIENT_FILE="${PREFIX}${LOCAL_RECIPIENT_FILE}/.age-recipients"
+ LOCAL_RECIPIENTS="$(cat "${LOCAL_RECIPIENT_FILE}")"
}
# Count how many characters are in the first argument
@@ -273,51 +275,10 @@ do_copy_move() {
LOCAL_ACTION=do_copy_move_file
fi
- case "${DECISION}" in
- force|interactive)
- ANSWER=y
- ;;
- keep)
- ANSWER=n
- ;;
- default)
- if [ "${SRC}" = "${SRC%/}/" ]; then
- # Handled in do_copy_move_dir
- ANSWER=y
- else
- set_LOCAL_RECIPIENT_FILE "${SRC}"
- SRC_FILE="${LOCAL_RECIPIENT_FILE}"
- set_LOCAL_RECIPIENT_FILE "${DEST}"
- DST_FILE="${LOCAL_RECIPIENT_FILE}"
-
- if [ "${SRC_FILE}" = "${DST_FILE}" ]; then
- ANSWER=n
- elif [ -n "${SRC_FILE}" ] \
- && [ -n "${DST_FILE}" ] \
- && diff "${SRC_FILE}" "${DST_FILE}" >/dev/null 2>&1
- then
- ANSWER=n
- else
- ANSWER=y
- fi
-
- unset DST_FILE
- unset SRC_FILE
- fi
- ;;
- *)
- die "Unexpected DECISION value \"${DECISION}\""
- ;;
- esac
-
scm_begin
SCM_COMMIT_MSG="${ACTION} ${SRC} to ${DEST}"
- if [ "${ANSWER}" = y ]; then
- "${LOCAL_ACTION}" "${SRC}" "${DEST}"
- else
- "${SCM_ACTION}" "${SRC}" "${DEST}"
- fi
+ "${LOCAL_ACTION}" "${SRC}" "${DEST}"
scm_commit "${SCM_COMMIT_MSG}"
@@ -337,29 +298,22 @@ do_copy_move_dir() {
[ "$2" = "${2%/}/" ] || [ -z "$2" ] || die 'Internal error'
[ -d "${PREFIX}/$1" ] || die 'Internal error'
- if [ -e "${PREFIX}/$1.age-recipients" ] \
- && { [ "${DECISION}" = keep ] || [ "${DECISION}" = default ]; }
- then
- # Recipiends are transported too, no need to reencrypt
- "${SCM_ACTION}" "$1" "$2"
- else
- [ -d "${PREFIX}/$2" ] || mkdir -p -- "${PREFIX}/${2%/}"
+ [ -d "${PREFIX}/$2" ] || mkdir -p -- "${PREFIX}/${2%/}"
- for ARG in "${PREFIX}/$1".* "${PREFIX}/$1"*; do
- SRC="${ARG#"${PREFIX}/"}"
- DEST="$2$(basename "${ARG}")"
+ for ARG in "${PREFIX}/$1".* "${PREFIX}/$1"*; do
+ SRC="${ARG#"${PREFIX}/"}"
+ DEST="$2$(basename "${ARG}")"
- if [ -f "${ARG}" ]; then
- do_copy_move_file "${SRC}" "${DEST}"
- elif [ -d "${ARG}" ] && [ "${ARG}" = "${ARG%/.*}" ]
- then
- do_copy_move_dir "${SRC}/" "${DEST}/"
- fi
- done
+ if [ -f "${ARG}" ]; then
+ do_copy_move_file "${SRC}" "${DEST}"
+ elif [ -d "${ARG}" ] && [ "${ARG}" = "${ARG%/.*}" ]
+ then
+ do_copy_move_dir "${SRC}/" "${DEST}/"
+ fi
+ done
- unset ARG
- rmdir -p -- "${PREFIX}/$1" 2>/dev/null || true
- fi
+ unset ARG
+ rmdir -p -- "${PREFIX}/$1" 2>/dev/null || true
}
# Copy or move a secret file (depending on ${ACTION})
@@ -388,7 +342,22 @@ do_copy_move_file() {
interactive)
yesno "Reencrypt ${1%.age} into ${2%.age}?"
;;
- default|force)
+ default)
+ set_LOCAL_RECIPIENT_FILE "$1"
+ SRC_RCPT="${LOCAL_RECIPIENTS}"
+ set_LOCAL_RECIPIENT_FILE "$2"
+ DST_RCPT="${LOCAL_RECIPIENTS}"
+
+ if [ "${SRC_RCPT}" = "${DST_RCPT}" ]; then
+ ANSWER=n
+ else
+ ANSWER=y
+ fi
+
+ unset DST_RCPT
+ unset SRC_RCPT
+ ;;
+ force)
ANSWER=y
;;
*)