commit b9ac582d07c6c85dca72b83693338b4b6313391d
parent 8e18b025e10d540468bcd3c06d2ca75169f6cb95
Author: Natasha Kerensikova <natgh@instinctive.eu>
Date: Mon, 4 Nov 2024 23:41:00 +0000
Re-encryption decision in copy and move commands is controlled by flags
Diffstat:
4 files changed, 426 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
@@ -70,6 +70,9 @@ passwords.
### New Features and Extensions
+- The commands `copy` and `move` have new flags to control re-encryption
+(always, never, ask for each file).
+
- The new `gitconfig` command configures an existing store repository to
decrypt before `diff`.
diff --git a/spec/pashage_extra_spec.sh b/spec/pashage_extra_spec.sh
@@ -247,23 +247,142 @@ Describe 'Integrated Command Functions'
The result of function check_git_log should be successful
End
- It 'display copy usage with `c*` commands'
+ It 'does not re-encrypt by default when recipients do not change'
+ When call cmd_move stale renamed
+ The status should be success
+ The error should be blank
+ The output should be blank
+ expected_log() { %text
+ #|Move stale.age to renamed.age
+ #|
+ #| stale.age => renamed.age | 0
+ #| 1 file changed, 0 insertions(+), 0 deletions(-)
+ setup_log
+ }
+ The result of function check_git_log should be successful
+ End
+
+ It 're-encrypts by default when recipients change'
+ When call cmd_move stale shared
+ The status should be success
+ The error should be blank
+ The output should be blank
+ expected_file() { %text
+ #|ageRecipient:myself
+ #|ageRecipient:friend
+ #|age:0-password
+ }
+ The contents of file "${PREFIX}/shared/stale.age" should \
+ equal "$(expected_file)"
+ expected_log() { %text
+ #|Move stale.age to shared/stale.age
+ #|
+ #| stale.age => shared/stale.age | 2 +-
+ #| 1 file changed, 1 insertion(+), 1 deletion(-)
+ setup_log
+ }
+ The result of function check_git_log should be successful
+ End
+
+ It 'always re-encrypts when forced'
+ When call cmd_move --reencrypt stale renamed
+ The status should be success
+ The error should be blank
+ The output should be blank
+ expected_log() { %text
+ #|Move stale.age to renamed.age
+ #|
+ #| stale.age => renamed.age | 1 -
+ #| 1 file changed, 1 deletion(-)
+ setup_log
+ }
+ The result of function check_git_log should be successful
+ End
+
+ It 'never re-encrypts when forced'
+ When call cmd_move --keep stale shared
+ The status should be success
+ The error should be blank
+ The output should be blank
+ expected_log() { %text
+ #|Move stale.age to shared/stale.age
+ #|
+ #| stale.age => shared/stale.age | 0
+ #| 1 file changed, 0 insertions(+), 0 deletions(-)
+ setup_log
+ }
+ The result of function check_git_log should be successful
+ End
+
+ It 'interactively re-encrypts when asked'
+ Data
+ #|n
+ #|y
+ End
+ When call cmd_move --interactive stale extra/subdir/file shared
+ The status should be success
+ The error should be blank
+ The output should equal 'Reencrypt stale into shared/stale? [y/n]Reencrypt extra/subdir/file into shared/file? [y/n]'
+ expected_file() { %text
+ #|ageRecipient:myself
+ #|ageRecipient:friend
+ #|age:Pa55worD
+ }
+ The contents of file "${PREFIX}/shared/file.age" should \
+ equal "$(expected_file)"
+ expected_log() { %text
+ #|Move extra/subdir/file.age to shared/file.age
+ #|
+ #| {extra/subdir => shared}/file.age | 1 +
+ #| 1 file changed, 1 insertion(+)
+ #|Move stale.age to shared/stale.age
+ #|
+ #| stale.age => shared/stale.age | 0
+ #| 1 file changed, 0 insertions(+), 0 deletions(-)
+ setup_log
+ }
+ The result of function check_git_log should be successful
+ End
+
+ It 'displays usage when called with incompatible reencryption arguments'
+ PROGRAM=prg
+ COMMAND=copy
+ When run cmd_copy_move -eik stale shared/
+ The status should equal 1
+ The output should be blank
+ expected_err() { %text
+ #|Usage: prg copy [--reencrypt,-e | --interactive,-i | --keep,-k ]
+ #| [--force,-f] old-path new-path
+ }
+ The error should equal "$(expected_err)"
+ The result of function check_git_log should be successful
+ End
+
+ It 'displays copy usage with `c*` commands'
PROGRAM=prg
COMMAND=curious
When run cmd_copy_move single
The status should equal 1
The output should be blank
- The error should equal 'Usage: prg copy [--force,-f] old-path new-path'
+ expected_err() { %text
+ #|Usage: prg copy [--reencrypt,-e | --interactive,-i | --keep,-k ]
+ #| [--force,-f] old-path new-path
+ }
+ The error should equal "$(expected_err)"
The result of function check_git_log should be successful
End
- It 'display move usage with `m*` commands'
+ It 'displays move usage with `m*` commands'
PROGRAM=prg
COMMAND=memory
When run cmd_copy_move single
The status should equal 1
The output should be blank
- The error should equal 'Usage: prg move [--force,-f] old-path new-path'
+ expected_err() { %text
+ #|Usage: prg move [--reencrypt,-e | --interactive,-i | --keep,-k ]
+ #| [--force,-f] old-path new-path
+ }
+ The error should equal "$(expected_err)"
The result of function check_git_log should be successful
End
@@ -274,8 +393,10 @@ Describe 'Integrated Command Functions'
The status should equal 1
The output should be blank
expected_err() { %text
- #|Usage: prg copy [--force,-f] old-path new-path
- #| prg move [--force,-f] old-path new-path
+ #|Usage: prg copy [--reencrypt,-e | --interactive,-i | --keep,-k ]
+ #| [--force,-f] old-path new-path
+ #| prg move [--reencrypt,-e | --interactive,-i | --keep,-k ]
+ #| [--force,-f] old-path new-path
}
The error should equal "$(expected_err)"
The result of function check_git_log should be successful
diff --git a/spec/usage_spec.sh b/spec/usage_spec.sh
@@ -208,6 +208,108 @@ Describe 'Command-Line Parsing'
The error should equal "$(result)"
End
+ It 'always reencrypts with a long option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Copy
+ #|DECISION=force
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_cp
+ }
+ When call cmd_copy --reencrypt src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'always reencrypts with a short option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Copy
+ #|DECISION=force
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_cp
+ }
+ When call cmd_copy -e src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'interactively reencrypts with a long option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Copy
+ #|DECISION=interactive
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_cp
+ }
+ When call cmd_copy --interactive src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'interactively reencrypts with a short option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Copy
+ #|DECISION=interactive
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_cp
+ }
+ When call cmd_copy -i src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'never reencrypts with a long option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Copy
+ #|DECISION=keep
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_cp
+ }
+ When call cmd_copy --keep src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'never reencrypts with a short option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Copy
+ #|DECISION=keep
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_cp
+ }
+ When call cmd_copy -k src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
It 'copies a file named like a flag'
result() {
%text
@@ -225,11 +327,40 @@ Describe 'Command-Line Parsing'
The error should equal "$(result)"
End
+ usage_text() { %text
+ #|Usage: prg copy [--reencrypt,-e | --interactive,-i | --keep,-k ]
+ #| [--force,-f] old-path new-path
+ }
+
It 'reports a bad option'
cat() { @cat; }
When run cmd_copy -s arg
The output should be blank
- The error should equal 'Usage: prg copy [--force,-f] old-path new-path'
+ The error should equal "$(usage_text)"
+ The status should equal 1
+ End
+
+ It 'reports incompatible re-encryption options (-e and -i)'
+ cat() { @cat; }
+ When run cmd_copy -ei src dest
+ The output should be blank
+ The error should equal "$(usage_text)"
+ The status should equal 1
+ End
+
+ It 'reports incompatible re-encryption options (-i and -k)'
+ cat() { @cat; }
+ When run cmd_copy -ik src dest
+ The output should be blank
+ The error should equal "$(usage_text)"
+ The status should equal 1
+ End
+
+ It 'reports incompatible re-encryption options (-k and -e)'
+ cat() { @cat; }
+ When run cmd_copy -ke src dest
+ The output should be blank
+ The error should equal "$(usage_text)"
The status should equal 1
End
@@ -237,7 +368,7 @@ Describe 'Command-Line Parsing'
cat() { @cat; }
When run cmd_copy src
The output should be blank
- The error should equal 'Usage: prg copy [--force,-f] old-path new-path'
+ The error should equal "$(usage_text)"
The status should equal 1
End
End
@@ -248,8 +379,10 @@ Describe 'Command-Line Parsing'
It 'reports both commands when confused'
cat() { @cat; }
result() { %text
- #|Usage: prg copy [--force,-f] old-path new-path
- #| prg move [--force,-f] old-path new-path
+ #|Usage: prg copy [--reencrypt,-e | --interactive,-i | --keep,-k ]
+ #| [--force,-f] old-path new-path
+ #| prg move [--reencrypt,-e | --interactive,-i | --keep,-k ]
+ #| [--force,-f] old-path new-path
}
When run cmd_copy src
The output should be blank
@@ -1619,6 +1752,108 @@ Describe 'Command-Line Parsing'
The error should equal "$(result)"
End
+ It 'always reencrypts with a long option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Move
+ #|DECISION=force
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_mv
+ }
+ When call cmd_move --reencrypt src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'always reencrypts with a short option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Move
+ #|DECISION=force
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_mv
+ }
+ When call cmd_move -e src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'interactively reencrypts with a long option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Move
+ #|DECISION=interactive
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_mv
+ }
+ When call cmd_move --interactive src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'interactively reencrypts with a short option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Move
+ #|DECISION=interactive
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_mv
+ }
+ When call cmd_move -i src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'never reencrypts with a long option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Move
+ #|DECISION=keep
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_mv
+ }
+ When call cmd_move --keep src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
+ It 'never reencrypts with a short option'
+ result() {
+ %text
+ #|$ check_sneaky_path src
+ #|$ check_sneaky_path dest
+ #|$ do_copy_move src dest
+ #|ACTION=Move
+ #|DECISION=keep
+ #|OVERWRITE=no
+ #|SCM_ACTION=scm_mv
+ }
+ When call cmd_move -k src dest
+ The status should be success
+ The output should be blank
+ The error should equal "$(result)"
+ End
+
It 'moves a file named like a flag'
result() {
%text
@@ -1636,11 +1871,40 @@ Describe 'Command-Line Parsing'
The error should equal "$(result)"
End
+ usage_text() { %text
+ #|Usage: prg move [--reencrypt,-e | --interactive,-i | --keep,-k ]
+ #| [--force,-f] old-path new-path
+ }
+
It 'reports a bad option'
cat() { @cat; }
When run cmd_move -s arg
The output should be blank
- The error should equal 'Usage: prg move [--force,-f] old-path new-path'
+ The error should equal "$(usage_text)"
+ The status should equal 1
+ End
+
+ It 'reports incompatible re-encryption options (-e and -i)'
+ cat() { @cat; }
+ When run cmd_move -ei src dest
+ The output should be blank
+ The error should equal "$(usage_text)"
+ The status should equal 1
+ End
+
+ It 'reports incompatible re-encryption options (-i and -k)'
+ cat() { @cat; }
+ When run cmd_move -ik src dest
+ The output should be blank
+ The error should equal "$(usage_text)"
+ The status should equal 1
+ End
+
+ It 'reports incompatible re-encryption options (-k and -e)'
+ cat() { @cat; }
+ When run cmd_move -ke src dest
+ The output should be blank
+ The error should equal "$(usage_text)"
The status should equal 1
End
@@ -1648,7 +1912,7 @@ Describe 'Command-Line Parsing'
cat() { @cat; }
When run cmd_move src
The output should be blank
- The error should equal 'Usage: prg move [--force,-f] old-path new-path'
+ The error should equal "$(usage_text)"
The status should equal 1
End
End
diff --git a/src/pashage.sh b/src/pashage.sh
@@ -1005,6 +1005,26 @@ cmd_copy_move() {
-f|--force)
OVERWRITE=yes
shift ;;
+ -e|--reencrypt)
+ [ "${DECISION}" = default ] || PARSE_ERROR=yes
+ DECISION=force
+ shift ;;
+ -i|--interactive)
+ [ "${DECISION}" = default ] || PARSE_ERROR=yes
+ DECISION=interactive
+ shift ;;
+ -k|--keep)
+ [ "${DECISION}" = default ] || PARSE_ERROR=yes
+ DECISION=keep
+ shift ;;
+ -[efik]?*)
+ REST="${1#??}"
+ FIRST="${1%"${REST}"}"
+ shift
+ set -- "${FIRST}" "-${REST}" "$@"
+ unset FIRST
+ unset REST
+ ;;
--)
shift
break ;;
@@ -1505,11 +1525,12 @@ EOF
;;
copy)
cat <<EOF
-${F}${PROGRAM} copy [--force,-f] old-path new-path
+${F}${PROGRAM} copy [--reencrypt,-e | --interactive,-i | --keep,-k ]
+${I}${BLANKPG} [--force,-f] old-path new-path
EOF
[ "${VERBOSE}" = yes ] && cat <<EOF
${I} Copies old-path to new-path, optionally forcefully,
-${I} selectively reencrypting.
+${I} reencrypting if needed or forced.
EOF
;;
delete)
@@ -1606,11 +1627,12 @@ EOF
;;
move)
cat <<EOF
-${F}${PROGRAM} move [--force,-f] old-path new-path
+${F}${PROGRAM} move [--reencrypt,-e | --interactive,-i | --keep,-k ]
+${I}${BLANKPG} [--force,-f] old-path new-path
EOF
[ "${VERBOSE}" = yes ] && cat <<EOF
${I} Renames or moves old-path to new-path, optionally forcefully,
-${I} selectively reencrypting.
+${I} reencrypting if needed or forced.
EOF
;;
random)