commit 8e18b025e10d540468bcd3c06d2ca75169f6cb95
parent cefe552791b1e9ebb41f3836cd491490cdb04a0a
Author: Natasha Kerensikova <natgh@instinctive.eu>
Date: Sun, 3 Nov 2024 17:11:00 +0000
Copy and move commands are as covered as possible by integrated suites
Diffstat:
3 files changed, 184 insertions(+), 17 deletions(-)
diff --git a/README.md b/README.md
@@ -48,6 +48,9 @@ a confirming `y` on a standard input line.
- The commands `copy`, `edit`, `insert`, `list`, `move`, and `show`
accept multiple arguments to operate on many secrets at once.
+- The commands `copy` and `move` also operate on unencrypted files in the
+password store.
+
- The `edit` command does not warn a about using `/tmp` rather than
`/dev/shm`, because the warning does not seem actionable and quickly
becomes ignored noise.
@@ -65,8 +68,6 @@ how different it is; but now it installs `.age-recipients` and re-encrypts.
- The `insert` command makes the user try again when entering mismatching
passwords.
-- TODO
-
### New Features and Extensions
- The new `gitconfig` command configures an existing store repository to
@@ -75,8 +76,6 @@ decrypt before `diff`.
- The new `random` command leverages password generation without touching
the password store.
-- TODO
-
## Manual
TODO
diff --git a/spec/pashage_extra_spec.sh b/spec/pashage_extra_spec.sh
@@ -66,7 +66,8 @@ Describe 'Integrated Command Functions'
#| shared/.age-recipients | 2 ++
#| stale.age | 3 +++
#| subdir/file.age | 2 ++
- #| 9 files changed, 26 insertions(+)
+ #| y.txt | 3 +++
+ #| 10 files changed, 29 insertions(+)
}
setup_log_bin() { %text
@@ -81,7 +82,8 @@ Describe 'Integrated Command Functions'
#| shared/.age-recipients | 2 ++
#| stale.age | Bin 0 -> 55 bytes
#| subdir/file.age | Bin 0 -> 33 bytes
- #| 9 files changed, 7 insertions(+)
+ #| y.txt | 3 +++
+ #| 10 files changed, 10 insertions(+)
}
expected_log() { setup_log; } # Default log to override as needed
@@ -140,6 +142,10 @@ Describe 'Integrated Command Functions'
#|gpgRecipient:myOldSelf
#|gpg:very-old-password
#|gpg:Username: previous-life
+ %text >"${PREFIX}/y.txt"
+ #|# Title
+ #|Line of text
+ #|End of note
@git -C "${PREFIX}" add .
@git -C "${PREFIX}" commit -m 'Initial setup' >/dev/null
@@ -158,16 +164,18 @@ Describe 'Integrated Command Functions'
BeforeEach setup
AfterEach cleanup
- cat() { @cat "$@"; }
- dd() { @dd "$@"; }
- diff() { @diff "$@"; }
- dirname() { @dirname "$@"; }
- git() { @git "$@"; }
- mkdir() { @mkdir "$@"; }
- mktemp() { @mktemp "$@"; }
- mv() { @mv "$@"; }
- rm() { @rm "$@"; }
- tr() { @tr "$@"; }
+ basename() { @basename "$@"; }
+ cat() { @cat "$@"; }
+ cp() { @cp "$@"; }
+ dd() { @dd "$@"; }
+ diff() { @diff "$@"; }
+ dirname() { @dirname "$@"; }
+ git() { @git "$@"; }
+ mkdir() { @mkdir "$@"; }
+ mktemp() { @mktemp "$@"; }
+ mv() { @mv "$@"; }
+ rm() { @rm "$@"; }
+ tr() { @tr "$@"; }
platform_tmpdir() {
SECURE_TMPDIR="${SHELLSPEC_WORKDIR}/secure"
@@ -175,7 +183,104 @@ Describe 'Integrated Command Functions'
}
# Describe 'cmd_copy' is not needed (covered by 'cmd_copy_move')
-# Describe 'cmd_copy_move'
+
+ Describe 'cmd_copy_move'
+ DECISION=default
+ OVERWRITE=no
+
+ It 'processes several files and directories into a directory'
+ When call cmd_move extra stale subdir
+ The status should be success
+ The error should be blank
+ The output should be blank
+ expected_log() { %text
+ #|Move stale.age to subdir/stale.age
+ #|
+ #| stale.age => subdir/stale.age | 0
+ #| 1 file changed, 0 insertions(+), 0 deletions(-)
+ #|Move extra/ to subdir/extra/
+ #|
+ #| {extra => subdir/extra}/subdir/file.age | 0
+ #| 1 file changed, 0 insertions(+), 0 deletions(-)
+ setup_log
+ }
+ The result of function check_git_log should be successful
+ End
+
+ It 'processes unencrypted files'
+ When run cmd_move y.txt shared/yy
+ The status should be success
+ The error should be blank
+ The output should be blank
+ expected_log() { %text
+ #|Move y.txt to shared/yy
+ #|
+ #| y.txt => shared/yy | 0
+ #| 1 file changed, 0 insertions(+), 0 deletions(-)
+ setup_log
+ }
+ The result of function check_git_log should be successful
+ End
+
+ It 'does not overwrite a file without confirmation'
+ Data 'n'
+ When call cmd_copy subdir/file stale
+ The status should be success
+ The error should be blank
+ The output should equal 'stale.age already exists. Overwrite? [y/n]'
+ The result of function check_git_log should be successful
+ End
+
+ It 'overwrites a file after confirmation'
+ Data 'y'
+ When call cmd_copy subdir/file stale
+ The status should be success
+ The error should be blank
+ The output should equal 'stale.age already exists. Overwrite? [y/n]'
+ expected_log() { %text
+ #|Copy subdir/file.age to stale.age
+ #|
+ #| stale.age | 3 +--
+ #| 1 file changed, 1 insertion(+), 2 deletions(-)
+ setup_log
+ }
+ The result of function check_git_log should be successful
+ End
+
+ It 'display 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'
+ The result of function check_git_log should be successful
+ End
+
+ It 'display 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'
+ The result of function check_git_log should be successful
+ End
+
+ It 'displays both usages when in doubt'
+ PROGRAM=prg
+ COMMAND=bad
+ When run cmd_copy_move single
+ 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
+ }
+ The error should equal "$(expected_err)"
+ The result of function check_git_log should be successful
+ End
+ End
Describe 'cmd_delete'
DECISION=default
@@ -833,6 +938,14 @@ Describe 'Integrated Command Functions'
# to reach full coverage, by precisely identifying unreachable lines
# written for defensive programming against internal inconsistencies.
+ It 'includes invalid values of DECISION in do_copy_move_file'
+ DECISION='invalid'
+ When run do_copy_move_file subdir/file.age extra/file.age
+ The status should equal 1
+ The output should be blank
+ The error should equal 'Unexpected DECISION value "invalid"'
+ End
+
It 'includes invalid values of SHOW in do_show'
SHOW='invalid'
When run do_show
diff --git a/spec/pass_spec.sh b/spec/pass_spec.sh
@@ -2296,6 +2296,16 @@ Describe 'Pass-like command'
The contents of file "${GITLOG}" should equal "$(setup_log)"
End
+ It 'fails to move a directory into a file masquerading as a directory'
+ Skip if 'pass(age) needs bash' check_skip $2
+ When run script $1 mv subdir y.txt/
+ The status should equal 1
+ The error should include 'y.txt'
+ The error should include 'ot a directory'
+ The result of function git_log should be successful
+ The contents of file "${GITLOG}" should equal "$(setup_log)"
+ End
+
It 'rejects a source path containing ..'
Skip if 'pass(age) needs bash' check_skip $2
When run script $1 mv fluff/../stale subdir/
@@ -2323,6 +2333,24 @@ Describe 'Pass-like command'
The result of function git_log should be successful
The contents of file "${GITLOG}" should equal "$(setup_log)"
End
+
+ extra_setup() {
+ @mkdir "${PREFIX}/extra/stale.age" "${PREFIX}/extra/stale.gpg"
+ }
+ BeforeEach extra_setup
+
+ It 'fails to move a file where a directory already exists'
+ Skip if 'pass(age) needs bash' check_skip $2
+ When run script $1 mv -f stale extra/
+ The status should equal 1
+ if [ "$2" = pashage ]; then
+ The error should equal 'Error: extra/ already contains stale.age/'
+ else
+ The error should match pattern 'mv: *directory*'
+ fi
+ The result of function git_log should be successful
+ The contents of file "${GITLOG}" should equal "$(setup_log)"
+ End
End
Describe 'cp'
@@ -2729,6 +2757,15 @@ Describe 'Pass-like command'
The contents of file "${GITLOG}" should equal "$(setup_log)"
End
+ It 'fails to copy a directory into a file masquerading as a directory'
+ Skip if 'pass(age) needs bash' check_skip $2
+ When run script $1 cp subdir y.txt/
+ The status should equal 1
+ The error should include 'y.txt is not a directory'
+ The result of function git_log should be successful
+ The contents of file "${GITLOG}" should equal "$(setup_log)"
+ End
+
It 'rejects a source path containing ..'
Skip if 'pass(age) needs bash' check_skip $2
When run script $1 cp fluff/../stale subdir/
@@ -2752,6 +2789,24 @@ Describe 'Pass-like command'
The result of function git_log should be successful
The contents of file "${GITLOG}" should equal "$(setup_log)"
End
+
+ extra_setup() {
+ @mkdir "${PREFIX}/extra/stale.age" "${PREFIX}/extra/stale.gpg"
+ }
+ BeforeEach extra_setup
+
+ It 'fails to copy a file where a directory already exists'
+ Skip if 'pass(age) needs bash' check_skip $2
+ When run script $1 cp -f stale extra/
+ The status should equal 1
+ if [ "$2" = pashage ]; then
+ The error should equal 'Error: extra/ already contains stale.age/'
+ else
+ The error should match pattern 'cp: *directory*'
+ fi
+ The result of function git_log should be successful
+ The contents of file "${GITLOG}" should equal "$(setup_log)"
+ End
End
Describe 'git'