pass_spec.sh (111578B)
1 # pashage - age-backed POSIX password manager 2 # Copyright (C) 2024 Natasha Kerensikova 3 # 4 # This program is free software; you can redistribute it and/or 5 # modify it under the terms of the GNU General Public License 6 # as published by the Free Software Foundation; either version 2 7 # of the License, or (at your option) any later version. 8 # 9 # This program is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with this program; if not, write to the Free Software 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 18 # This test file should pass with pashage, pass (the original password-store), 19 # or passage (the pass fork by Filippo Valsorda). 20 21 # The test suite also checks the internal of the store, thanks to mocked 22 # cryptography. This should ensure that pashage is indeed a drop-in replacement 23 # for passage, and that both of them can update interchangeably the same 24 # password store repository. 25 26 # The other password-store scripts can be added to the parameters list 27 # to run the cases against it. 28 # bash seems to escape the sandbox by resetting PATH on the slightest 29 # provocation, while the tests rely heavily on the mocked cryptography 30 # to check the store behavior. 31 # So it only works when using shellspec with bash and calling the `pass` 32 # or `password-store.sh` script directly 33 # (e.g. on FreeBSD `/usr/local/libexec/password-store/pass` 34 # instead of `/usr/local/bin/pass`). 35 36 Parameters # script/path scriptname encryption 37 # /usr/bin/pass pass gpg 38 # /git/passage/src/password-store.sh passage age 39 ./src/run.sh pashage age 40 End 41 42 Describe 'Pass-like command' 43 check_skip() { 44 [ -z "${1%%pass*}" ] && ! [ "${SHELLSPEC_SHELL_TYPE}" = bash ] 45 } 46 47 GITLOG="${SHELLSPEC_WORKDIR}/git-log.txt" 48 PREFIX="${SHELLSPEC_WORKDIR}/store" 49 50 export PASSWORD_STORE_DIR="${PREFIX}" 51 export PASSAGE_DIR="${PREFIX}" 52 export PASSAGE_IDENTITIES_FILE="${SHELLSPEC_WORKDIR}/age-identities" 53 54 git_log() { 55 @git -C "${PREFIX}" status --porcelain >&2 56 @git -C "${PREFIX}" log --format='%s' --stat >|"${GITLOG}" 57 } 58 59 setup_log() { %text 60 #|Initial setup 61 #| 62 #| -g.age | 2 ++ 63 #| -g.gpg | 2 ++ 64 #| .gpg-id | 1 + 65 #| extra.age | 2 ++ 66 #| extra.gpg | 2 ++ 67 #| extra/subdir/file.age | 2 ++ 68 #| extra/subdir/file.gpg | 2 ++ 69 #| fluff/.age-recipients | 2 ++ 70 #| fluff/.gpg-id | 2 ++ 71 #| fluff/one.age | 3 +++ 72 #| fluff/one.gpg | 3 +++ 73 #| fluff/three.age | 5 +++++ 74 #| fluff/three.gpg | 5 +++++ 75 #| fluff/two.age | 4 ++++ 76 #| fluff/two.gpg | 4 ++++ 77 #| shared/.age-recipients | 2 ++ 78 #| shared/.gpg-id | 2 ++ 79 #| stale.age | 3 +++ 80 #| stale.gpg | 3 +++ 81 #| subdir/file.age | 2 ++ 82 #| subdir/file.gpg | 2 ++ 83 #| y.txt | 3 +++ 84 #| 22 files changed, 58 insertions(+) 85 } 86 87 setup_id() { 88 @mkdir -p "${PREFIX}/$1" 89 @cat >"${PREFIX}/$1/.age-recipients" 90 @cp -i "${PREFIX}/$1/.age-recipients" "${PREFIX}/$1/.gpg-id" 91 } 92 93 setup_secret() { 94 [ "$1" = "${1%/*}" ] || @mkdir -p "${PREFIX}/${1%/*}" 95 @sed 's/^/age/' >"${PREFIX}/$1.age" 96 @sed 's/^age/gpg/' "${PREFIX}/$1.age" >"${PREFIX}/$1.gpg" 97 } 98 99 setup() { 100 @git init -q -b main "${PREFIX}" 101 @git -C "${PREFIX}" config --local user.name 'Test User' 102 @git -C "${PREFIX}" config --local user.email 'test@example.com' 103 %putsn 'myself' >"${PASSAGE_IDENTITIES_FILE}" 104 %putsn 'myself' >"${PREFIX}/.gpg-id" 105 %text | setup_secret 'subdir/file' 106 #|Recipient:myself 107 #|:p4ssw0rd 108 %text | setup_secret 'extra' 109 #|Recipient:myself 110 #|:ambiguous 111 %text | setup_secret 'extra/subdir/file' 112 #|Recipient:myself 113 #|:Pa55worD 114 %text | setup_id 'shared' 115 #|myself 116 #|friend 117 %text | setup_id 'fluff' 118 #|master 119 #|myself 120 %text | setup_secret 'fluff/one' 121 #|Recipient:master 122 #|Recipient:myself 123 #|:1-password 124 %text | setup_secret 'fluff/two' 125 #|Recipient:master 126 #|Recipient:myself 127 #|:2-password 128 #|:URL: https://example.com/login 129 %text | setup_secret 'fluff/three' 130 #|Recipient:master 131 #|Recipient:myself 132 #|:3-password 133 #|:Username: 3Jane 134 #|:URL: https://example.com/login 135 %text | setup_secret 'stale' 136 #|Recipient:master 137 #|Recipient:myself 138 #|:0-password 139 %text | setup_secret '-g' 140 #|Recipient:myself 141 #|:-- 142 %text >"${PREFIX}/y.txt" 143 #|Unencrypted line 1 144 #|Unencrypted line 2 145 #|Unencrypted line 3 146 @git -C "${PREFIX}" add . 147 @git -C "${PREFIX}" commit -m 'Initial setup' >/dev/null 148 149 # Check setup_log consistency 150 git_log 151 setup_log | @diff -u - "${GITLOG}" 152 } 153 154 cleanup() { 155 @rm -rf "${PREFIX}" 156 @rm -f "${PASSAGE_IDENTITIES_FILE}" 157 } 158 159 BeforeEach setup 160 AfterEach cleanup 161 162 Mock age 163 mock-age "$@" 164 End 165 166 Mock base64 167 . "${SHELLSPEC_SUPPORT_BIN}" 168 invoke base64 "$@" 169 End 170 171 Mock basename 172 @basename "$@" 173 End 174 175 Mock cat 176 @cat "$@" 177 End 178 179 Mock cp 180 @cp "$@" 181 End 182 183 Mock cut 184 . "${SHELLSPEC_SUPPORT_BIN}" 185 invoke cut "$@" 186 End 187 188 Mock dd 189 @dd "$@" 190 End 191 192 Mock diff 193 @diff "$@" 194 End 195 196 Mock dirname 197 @dirname "$@" 198 End 199 200 Mock ed 201 . "${SHELLSPEC_SUPPORT_BIN}" 202 if [ "${1-}" = '-c' ]; then 203 shift 204 invoke touch "$@" 205 fi 206 invoke ed "$@" 207 End 208 209 Mock feh 210 printf '$ feh %s\n' "$*" >&2 211 @cat >&2 212 End 213 214 Mock find 215 . "${SHELLSPEC_SUPPORT_BIN}" 216 invoke find "$@" 217 End 218 219 Mock git 220 @git "$@" 221 End 222 223 Mock gpg 224 mock-gpg "$@" 225 End 226 227 Mock grep 228 @grep "$@" 229 End 230 231 Mock head 232 @head "$@" 233 End 234 235 Mock mkdir 236 @mkdir "$@" 237 End 238 239 Mock mv 240 @mv "$@" 241 End 242 243 Mock openssl 244 . "${SHELLSPEC_SUPPORT_BIN}" 245 invoke openssl "$@" 246 End 247 248 Mock qrencode 249 . "${SHELLSPEC_SUPPORT_BIN}" 250 invoke od -v -t x1 | sed 's/ */ /g;s/ *$//' 251 End 252 253 Mock mktemp 254 . "${SHELLSPEC_SUPPORT_BIN}" 255 invoke mktemp "$@" 256 End 257 258 Mock rm 259 @rm "$@" 260 End 261 262 Mock rmdir 263 . "${SHELLSPEC_SUPPORT_BIN}" 264 invoke rmdir "$@" 265 End 266 267 Mock sed 268 @sed "$@" 269 End 270 271 Mock sleep 272 : 273 End 274 275 Mock sort 276 . "${SHELLSPEC_SUPPORT_BIN}" 277 invoke sort "$@" 278 End 279 280 Mock tail 281 @tail "$@" 282 End 283 284 Mock tr 285 @tr "$@" 286 End 287 288 Mock tree 289 . "${SHELLSPEC_SUPPORT_BIN}" 290 invoke tree "$@" 291 End 292 293 Mock uname 294 @uname "$@" 295 End 296 297 Mock which 298 false 299 End 300 301 Mock xclip 302 . "${SHELLSPEC_SUPPORT_BIN}" 303 if [ "$1" = '-o' ]; then 304 printf 'previous contents\n' 305 else 306 printf '$ xclip %s\n' "$*" >&2 307 invoke od -v -t x1 | sed 's/ */ /g;s/ *$//' >&2 308 fi 309 End 310 311 Describe 'init' 312 It 're-encrypts the whole store using a new recipient id' 313 Skip if 'pass(age) needs bash' check_skip $2 314 Skip if 'passage has no init' [ "$2" = passage ] 315 When run script $1 init 'new-id' 316 The status should be success 317 The output should include 'Password store' 318 expected_log() { 319 if [ "$2" = pashage ]; then 320 %text 321 #|Set age recipients at store root 322 #| 323 #| -g.age | 2 +- 324 #| .age-recipients | 1 + 325 #| extra.age | 2 +- 326 #| extra/subdir/file.age | 2 +- 327 #| stale.age | 3 +-- 328 #| subdir/file.age | 2 +- 329 #| 6 files changed, 6 insertions(+), 6 deletions(-) 330 else 331 %text:expand 332 #|Reencrypt password store using new GPG id new-id. 333 #| 334 #| -g.$1 | 2 +- 335 #| extra.$1 | 2 +- 336 #| extra/subdir/file.$1 | 2 +- 337 #| stale.$1 | 3 +-- 338 #| subdir/file.$1 | 2 +- 339 #| 5 files changed, 5 insertions(+), 6 deletions(-) 340 #|Set GPG id to new-id. 341 #| 342 #| .gpg-id | 2 +- 343 #| 1 file changed, 1 insertion(+), 1 deletion(-) 344 fi 345 setup_log 346 } 347 The result of function git_log should be successful 348 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 349 End 350 351 It 're-encrypts a subdirectory using a new recipient id' 352 Skip if 'pass(age) needs bash' check_skip $2 353 Skip if 'passage has no init' [ "$2" = passage ] 354 When run script $1 init -p subdir 'new-id' 355 The status should be success 356 The output should start with 'Password store' 357 The output should include 'subdir' 358 expected_log() { 359 if [ "$2" = pashage ]; then 360 %text 361 #|Set age recipients at subdir 362 #| 363 #| subdir/.age-recipients | 1 + 364 #| subdir/file.age | 2 +- 365 #| 2 files changed, 2 insertions(+), 1 deletion(-) 366 else 367 %text:expand 368 #|Reencrypt password store using new GPG id new-id (subdir). 369 #| 370 #| subdir/file.$1 | 2 +- 371 #| 1 file changed, 1 insertion(+), 1 deletion(-) 372 #|Set GPG id to new-id (subdir). 373 #| 374 #| subdir/.gpg-id | 1 + 375 #| 1 file changed, 1 insertion(+) 376 fi 377 setup_log 378 } 379 The result of function git_log should be successful 380 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 381 End 382 383 It 're-encrypts a subdirectory after replacing recipient ids' 384 Skip if 'pass(age) needs bash' check_skip $2 385 Skip if 'passage has no init' [ "$2" = passage ] 386 When run script $1 init --path=fluff 'new-id' 'new-master' 387 The status should be success 388 The output should start with 'Password store' 389 The output should include 'fluff' 390 expected_log() { 391 if [ "$2" = pashage ]; then 392 %text 393 #|Set age recipients at fluff 394 #| 395 #| fluff/.age-recipients | 4 ++-- 396 #| fluff/one.age | 4 ++-- 397 #| fluff/three.age | 4 ++-- 398 #| fluff/two.age | 4 ++-- 399 #| 4 files changed, 8 insertions(+), 8 deletions(-) 400 else 401 %text:expand 402 #|Reencrypt password store using new GPG id new-id, new-master (fluff). 403 #| 404 #| fluff/one.$1 | 4 ++-- 405 #| fluff/three.$1 | 4 ++-- 406 #| fluff/two.$1 | 4 ++-- 407 #| 3 files changed, 6 insertions(+), 6 deletions(-) 408 #|Set GPG id to new-id, new-master (fluff). 409 #| 410 #| fluff/.gpg-id | 4 ++-- 411 #| 1 file changed, 2 insertions(+), 2 deletions(-) 412 fi 413 setup_log 414 } 415 The result of function git_log should be successful 416 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 417 End 418 419 It 're-encrypts a subdirectory after removing dedicated recipient ids' 420 Skip if 'pass(age) needs bash' check_skip $2 421 Skip if 'passage has no init' [ "$2" = passage ] 422 When run script $1 init -pfluff '' 423 The status should be successful 424 expected_log() { 425 if [ "$2" = pashage ]; then 426 %text 427 #|Deinitialize fluff 428 #| 429 #| fluff/.age-recipients | 2 -- 430 #| fluff/one.age | 1 - 431 #| fluff/three.age | 1 - 432 #| fluff/two.age | 1 - 433 #| 4 files changed, 5 deletions(-) 434 else 435 %text:expand 436 #|Reencrypt password store using new GPG id (fluff). 437 #| 438 #| fluff/one.$1 | 1 - 439 #| fluff/three.$1 | 1 - 440 #| fluff/two.$1 | 1 - 441 #| 3 files changed, 3 deletions(-) 442 #|Deinitialize ${PREFIX}/fluff/.gpg-id (fluff). 443 #| 444 #| fluff/.gpg-id | 2 -- 445 #| 1 file changed, 2 deletions(-) 446 fi 447 setup_log 448 } 449 The result of function git_log should be successful 450 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 451 End 452 453 It 'creates a new subdirectory with recipient ids' 454 Skip if 'pass(age) needs bash' check_skip $2 455 Skip if 'passage has no init' [ "$2" = passage ] 456 When run script $1 init -p newdir new-id new-master 457 The status should be successful 458 The output should include 'newdir' 459 The directory "${PREFIX}/newdir" should be exist 460 expected_log() { 461 if [ "$2" = pashage ]; then 462 %text 463 #|Set age recipients at newdir 464 #| 465 #| newdir/.age-recipients | 2 ++ 466 #| 1 file changed, 2 insertions(+) 467 else 468 %text:expand 469 #|Set GPG id to new-id, new-master (newdir). 470 #| 471 #| newdir/.gpg-id | 2 ++ 472 #| 1 file changed, 2 insertions(+) 473 fi 474 setup_log 475 } 476 The result of function git_log should be successful 477 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 478 End 479 480 It 'does not create a new subdirectory without recipient id' 481 Skip if 'pass(age) needs bash' check_skip $2 482 Skip if 'passage has no init' [ "$2" = passage ] 483 When run script $1 init -p newdir '' 484 The status should be successful 485 The output should be blank 486 The error should include "newdir" 487 The directory "${PREFIX}/newdir" should not be exist 488 The result of function git_log should be successful 489 The contents of file "${GITLOG}" should equal "$(setup_log)" 490 End 491 492 It 'displays usage when called without argument' 493 Skip if 'pass(age) needs bash' check_skip $2 494 Skip if 'passage has no init' [ "$2" = passage ] 495 When run script $1 init 496 The status should equal 1 497 The output should be blank 498 The error should include 'Usage:' 499 The error should include ' init ' 500 The result of function git_log should be successful 501 The contents of file "${GITLOG}" should equal "$(setup_log)" 502 End 503 504 It 'displays usage when called with incomplete flag' 505 Skip if 'pass(age) needs bash' check_skip $2 506 Skip if 'passage has no init' [ "$2" = passage ] 507 When run script $1 init -p 508 The status should equal 1 509 The output should be blank 510 The error should include 'Usage:' 511 The error should include ' init ' 512 The result of function git_log should be successful 513 The contents of file "${GITLOG}" should equal "$(setup_log)" 514 End 515 516 It 'displays usage when called with unknown flag' 517 Skip if 'pass(age) needs bash' check_skip $2 518 Skip if 'passage has no init' [ "$2" = passage ] 519 When run script $1 init -x new-id-1 new-id-2 520 The status should equal 1 521 The output should be blank 522 The error should include 'Usage:' 523 The error should include ' init ' 524 The result of function git_log should be successful 525 The contents of file "${GITLOG}" should equal "$(setup_log)" 526 End 527 528 It 'rejects a path containing ..' 529 Skip if 'pass(age) needs bash' check_skip $2 530 Skip if 'passage has no init' [ "$2" = passage ] 531 When run script $1 init --path fluff/../newdir new-id 532 The status should equal 1 533 The output should be blank 534 The error should include 'sneaky' 535 The directory "${PREFIX}/newdir" should not be exist 536 The result of function git_log should be successful 537 The contents of file "${GITLOG}" should equal "$(setup_log)" 538 End 539 End 540 541 Describe 'ls' 542 It 'lists a directory' 543 Skip if 'pass(age) needs bash' check_skip $2 544 When run script $1 ls subdir 545 The status should be success 546 The line 1 of output should include 'subdir' 547 The line 2 of output should include 'file' 548 End 549 550 It 'lists a directory implicitly' 551 Skip if 'pass(age) needs bash' check_skip $2 552 When run script $1 subdir 553 The status should be success 554 The line 1 of output should include 'subdir' 555 The line 2 of output should include 'file' 556 End 557 558 It 'lists a directory when called as `show`' 559 Skip if 'pass(age) needs bash' check_skip $2 560 When run script $1 show subdir 561 The status should be success 562 The line 1 of output should include 'subdir' 563 The line 2 of output should include 'file' 564 End 565 566 It 'lists the whole store without argument' 567 Skip if 'pass(age) needs bash' check_skip $2 568 When run script $1 569 The status should be success 570 if [ $2 = passage ]; then 571 The line 1 of output should equal 'Passage' 572 else 573 The line 1 of output should equal 'Password Store' 574 fi 575 The line 2 of output should include '-g' 576 The line 3 of output should include '-g' 577 The line 4 of output should include 'extra' 578 The line 5 of output should include 'subdir' 579 The line 6 of output should include 'file' 580 The line 7 of output should include 'file' 581 The line 8 of output should include 'extra' 582 The line 9 of output should include 'extra' 583 The line 10 of output should include 'fluff' 584 The line 11 of output should include 'one' 585 The line 12 of output should include 'one' 586 The line 13 of output should include 'three' 587 The line 14 of output should include 'three' 588 The line 15 of output should include 'two' 589 The line 16 of output should include 'two' 590 The line 17 of output should include 'shared' 591 The line 18 of output should include 'stale' 592 The line 19 of output should include 'stale' 593 The line 20 of output should include 'subdir' 594 The line 21 of output should include 'file' 595 The line 22 of output should include 'file' 596 if [ $2 = pashage ]; then 597 The lines of output should equal 22 598 else 599 The line 23 of output should include 'y.txt' 600 fi 601 End 602 603 It 'does not list a file masquerading as a directory' 604 Skip if 'pass(age) needs bash' check_skip $2 605 When run script $1 subdir/file/ 606 The status should equal 1 607 The error should equal 'Error: subdir/file/ is not in the password store.' 608 End 609 610 It 'lists a directory having an ambiguous name with `/` suffix' 611 Skip if 'pass(age) needs bash' check_skip $2 612 When run script $1 extra/ 613 The status should be success 614 The line 1 of output should include 'extra' 615 The line 2 of output should include 'subdir' 616 The line 3 of output should include 'file' 617 The line 4 of output should include 'file' 618 End 619 620 It 'fails to list a non-existent directory' 621 Skip if 'pass(age) needs bash' check_skip $2 622 When run script $1 non-existent/ 623 The status should equal 1 624 The output should be blank 625 The error should equal \ 626 'Error: non-existent/ is not in the password store.' 627 End 628 629 It 'fails to list a file masquerading as a directory' 630 Skip if 'pass(age) needs bash' check_skip $2 631 When run script $1 stale/ 632 The status should equal 1 633 The output should be blank 634 The error should equal 'Error: stale/ is not in the password store.' 635 End 636 637 It 'rejects a path containing ..' 638 Skip if 'pass(age) needs bash' check_skip $2 639 When run script $1 subdir/../fluff/ 640 The status should equal 1 641 The output should be blank 642 The error should include 'sneaky' 643 The result of function git_log should be successful 644 The contents of file "${GITLOG}" should equal "$(setup_log)" 645 End 646 End 647 648 Describe 'find' 649 It 'lists entries matching a substring' 650 Skip if 'pass(age) needs bash' check_skip $2 651 When run script $1 find o 652 The status should be success 653 The lines of output should equal 6 654 The line 1 of output should match pattern 'Search *: o' 655 The line 2 of output should include 'fluff' 656 The line 3 of output should include 'one' 657 The line 4 of output should include 'one' 658 The line 5 of output should include 'two' 659 The line 6 of output should include 'two' 660 End 661 662 It 'reports success even without match' 663 Skip if 'pass(age) needs bash' check_skip $2 664 When run script $1 find z 665 The status should be success 666 The lines of output should equal 1 667 The line 1 of output should match pattern 'Search *: z' 668 The error should be blank 669 End 670 671 It 'displays usage when called without argument' 672 Skip if 'pass(age) needs bash' check_skip $2 673 When run script $1 find 674 The status should equal 1 675 The output should be blank 676 The error should include 'Usage:' 677 The error should include ' find ' 678 The result of function git_log should be successful 679 The contents of file "${GITLOG}" should equal "$(setup_log)" 680 End 681 End 682 683 Describe 'show' 684 It 'decrypts a password file' 685 Skip if 'pass(age) needs bash' check_skip $2 686 When run script $1 show subdir/file 687 The status should be success 688 The output should equal 'p4ssw0rd' 689 End 690 691 It 'decrypts a password file implicitly' 692 Skip if 'pass(age) needs bash' check_skip $2 693 When run script $1 subdir/file 694 The status should be success 695 The output should equal 'p4ssw0rd' 696 End 697 698 It 'fails to decrypt a flag' 699 Skip if 'pass(age) needs bash' check_skip $2 700 When run script $1 -g 701 The status should equal 1 702 The output should be blank 703 The error should include 'Usage:' 704 End 705 706 It 'decrypts a password file named like a flag' 707 Skip if 'pass(age) needs bash' check_skip $2 708 When run script $1 -- -g 709 The status should be success 710 The output should equal '--' 711 End 712 713 It 'decrypts a password file even when called as `list`' 714 Skip if 'pass(age) needs bash' check_skip $2 715 When run script $1 ls subdir/file 716 The status should be success 717 The output should equal 'p4ssw0rd' 718 End 719 720 It 'decrypts a file having an ambiguous name without suffix' 721 Skip if 'pass(age) needs bash' check_skip $2 722 When run script $1 extra 723 The status should be success 724 The output should equal 'ambiguous' 725 End 726 727 It 'displays the password as a QR-code' 728 export DISPLAY=mock 729 Skip if 'pass(age) needs bash' check_skip $2 730 When run script $1 -q fluff/one 731 The status should be success 732 expected_err() { %text:expand 733 #|$ feh -x --title ${1}: fluff/one -g +200+200 - 734 #|0000000 31 2d 70 61 73 73 77 6f 72 64 735 #|0000012 736 } 737 if [ $2 = pashage ]; then 738 The error should equal "$(expected_err 'pashage')" 739 else 740 The error should equal "$(expected_err 'pass')" 741 fi 742 End 743 744 It 'displays the given long-option line as a QR-code' 745 export DISPLAY=mock 746 Skip if 'pass(age) needs bash' check_skip $2 747 When run script $1 --qrcode=2 fluff/three 748 The status should be success 749 expected_err() { %text:expand 750 #|$ feh -x --title ${1}: fluff/three -g +200+200 - 751 #|0000000 55 73 65 72 6e 61 6d 65 3a 20 33 4a 61 6e 65 752 #|0000017 753 } 754 if [ $2 = pashage ]; then 755 The error should equal "$(expected_err 'pashage')" 756 else 757 The error should equal "$(expected_err 'pass')" 758 fi 759 End 760 761 It 'displays the given short-option line as a QR-code' 762 export DISPLAY=mock 763 Skip if 'pass(age) needs bash' check_skip $2 764 When run script $1 -q2 fluff/three 765 The status should be success 766 expected_err() { %text:expand 767 #|$ feh -x --title ${1}: fluff/three -g +200+200 - 768 #|0000000 55 73 65 72 6e 61 6d 65 3a 20 33 4a 61 6e 65 769 #|0000017 770 } 771 if [ $2 = pashage ]; then 772 The error should equal "$(expected_err 'pashage')" 773 else 774 The error should equal "$(expected_err 'pass')" 775 fi 776 End 777 778 It 'pastes into the clipboard' 779 export DISPLAY=mock 780 Skip if 'pass(age) needs bash' check_skip $2 781 When run script $1 show -c fluff/three 782 The status should be success 783 The output should start with \ 784 'Copied fluff/three to clipboard. Will clear in 45 seconds.' 785 expected_err() { %text 786 #|$ xclip -selection clipboard 787 #|0000000 33 2d 70 61 73 73 77 6f 72 64 788 #|0000012 789 } 790 The error should start with "$(expected_err)" 791 End 792 793 It 'pastes a selected long-option line into the clipboard' 794 export DISPLAY=mock 795 Skip if 'pass(age) needs bash' check_skip $2 796 When run script $1 show --clip=2 fluff/three 797 The status should be success 798 The output should start with \ 799 'Copied fluff/three to clipboard. Will clear in 45 seconds.' 800 expected_err() { %text 801 #|$ xclip -selection clipboard 802 #|0000000 55 73 65 72 6e 61 6d 65 3a 20 33 4a 61 6e 65 803 #|0000017 804 } 805 The error should start with "$(expected_err)" 806 End 807 808 It 'pastes a selected short-option line into the clipboard' 809 export DISPLAY=mock 810 Skip if 'pass(age) needs bash' check_skip $2 811 When run script $1 show -c2 fluff/three 812 The status should be success 813 The output should start with \ 814 'Copied fluff/three to clipboard. Will clear in 45 seconds.' 815 expected_err() { %text 816 #|$ xclip -selection clipboard 817 #|0000000 55 73 65 72 6e 61 6d 65 3a 20 33 4a 61 6e 65 818 #|0000017 819 } 820 The error should start with "$(expected_err)" 821 End 822 823 It 'fails to show a non-existent file' 824 Skip if 'pass(age) needs bash' check_skip $2 825 When run script $1 non-existent 826 The status should equal 1 827 The output should be blank 828 The error should equal \ 829 'Error: non-existent is not in the password store.' 830 End 831 832 It 'does not show an unencrypted file in the store' 833 Skip if 'pass(age) needs bash' check_skip $2 834 When run script $1 show y.txt 835 The status should equal 1 836 The output should be blank 837 The error should equal 'Error: y.txt is not in the password store.' 838 End 839 840 It 'displays usage when called with incompatible arguments' 841 Skip if 'pass(age) needs bash' check_skip $2 842 When run script $1 show -c -q subdir/file 843 The status should equal 1 844 The output should be blank 845 The error should include 'Usage:' 846 The error should include 'show' 847 The result of function git_log should be successful 848 The contents of file "${GITLOG}" should equal "$(setup_log)" 849 End 850 851 It 'rejects a path containing ..' 852 Skip if 'pass(age) needs bash' check_skip $2 853 When run script $1 subdir/../fluff/one 854 The status should equal 1 855 The output should be blank 856 The error should include 'sneaky' 857 The result of function git_log should be successful 858 The contents of file "${GITLOG}" should equal "$(setup_log)" 859 End 860 End 861 862 Describe 'grep' 863 It 'shows decrypted lines matching a regex' 864 Skip if 'pass(age) needs bash' check_skip $2 865 When run script $1 grep -i Com 866 The status should be success 867 The lines of output should equal 4 868 The line 1 of output should include 'fluff' 869 The output should include 'three' 870 The line 2 of output should include 'https://example.' 871 The line 3 of output should include 'fluff' 872 The output should include 'two' 873 The line 4 of output should include 'https://example.' 874 End 875 876 It 'is successful even without match' 877 Skip if 'pass(age) needs bash' check_skip $2 878 When run script $1 grep nothing.matches 879 The status should be success 880 The output should be blank 881 End 882 883 It 'does not look into unencrypted files in the store' 884 Skip if 'pass(age) needs bash' check_skip $2 885 When run script $1 grep Unencrypted 886 The status should be success 887 The output should be blank 888 End 889 890 It 'displays usage when called without argument' 891 Skip if 'pass(age) needs bash' check_skip $2 892 When run script $1 grep 893 The status should equal 1 894 The output should be blank 895 The error should include 'Usage:' 896 The error should include ' grep ' 897 The result of function git_log should be successful 898 The contents of file "${GITLOG}" should equal "$(setup_log)" 899 End 900 End 901 902 Describe 'insert' 903 It 'inserts a new multi-line entry' 904 Skip if 'pass(age) needs bash' check_skip $2 905 Data 906 #|password 907 #|Username: tester 908 #|URL: https://example.com/login 909 End 910 When run script $1 insert -m rootpass 911 The status should be success 912 The output should include 'rootpass' 913 The contents of file "${PREFIX}/rootpass.$3" \ 914 should include "$3:Username: tester" 915 expected_log() { %text:expand 916 #|Add given password for rootpass to store. 917 #| 918 #| rootpass.$1 | 4 ++++ 919 #| 1 file changed, 4 insertions(+) 920 setup_log 921 } 922 The result of function git_log should be successful 923 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 924 End 925 926 It 'inserts a new single-line entry' 927 Skip if 'pass(age) needs bash' check_skip $2 928 Mock stty 929 true 930 End 931 Data 932 #|pass-word 933 #|pass-word 934 End 935 When run script $1 insert newdir/newpass 936 The status should be success 937 The output should include 'newdir/newpass' 938 The contents of file "${PREFIX}/newdir/newpass.$3" \ 939 should include "$3:pass-word" 940 expected_log() { %text:expand 941 #|Add given password for newdir/newpass to store. 942 #| 943 #| newdir/newpass.$1 | 2 ++ 944 #| 1 file changed, 2 insertions(+) 945 setup_log 946 } 947 The result of function git_log should be successful 948 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 949 End 950 951 It 'fails to insert an unescaped flag' 952 Skip if 'pass(age) needs bash' check_skip $2 953 When run script $1 insert -h 954 The status should equal 1 955 The output should be blank 956 The error should include 'Usage:' 957 The result of function git_log should be successful 958 The contents of file "${GITLOG}" should equal "$(setup_log)" 959 End 960 961 It 'inserts a new single-line entry named like a flag' 962 Skip if 'pass(age) needs bash' check_skip $2 963 Data 964 #|pass-word 965 #|pass-word 966 End 967 When run script $1 insert -- -h 968 The status should be success 969 The output should include '-h' 970 The contents of file "${PREFIX}/-h.$3" \ 971 should include "$3:pass-word" 972 expected_log() { %text:expand 973 #|Add given password for -h to store. 974 #| 975 #| -h.$1 | 2 ++ 976 #| 1 file changed, 2 insertions(+) 977 setup_log 978 } 979 The result of function git_log should be successful 980 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 981 End 982 983 It 'inserts a new single-line entry with echo' 984 Skip if 'pass(age) needs bash' check_skip $2 985 Data "pass-word" 986 When run script $1 insert -e newdir/newpass 987 The status should be success 988 The output should include 'newdir/newpass' 989 The output should not include 'Retype' 990 The contents of file "${PREFIX}/newdir/newpass.$3" \ 991 should include "$3:pass-word" 992 expected_log() { %text:expand 993 #|Add given password for newdir/newpass to store. 994 #| 995 #| newdir/newpass.$1 | 2 ++ 996 #| 1 file changed, 2 insertions(+) 997 setup_log 998 } 999 The result of function git_log should be successful 1000 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1001 End 1002 1003 It 'inserts an entry with local recipient list' 1004 Skip if 'pass(age) needs bash' check_skip $2 1005 Data "passWord" 1006 When run script $1 insert -e shared/newpass 1007 The status should be success 1008 The output should include 'shared/newpass' 1009 The contents of file "${PREFIX}/shared/newpass.$3" \ 1010 should include 'friend' 1011 The contents of file "${PREFIX}/shared/newpass.$3" \ 1012 should include 'myself' 1013 The contents of file "${PREFIX}/shared/newpass.$3" \ 1014 should include "$3:passWord" 1015 expected_log() { %text:expand 1016 #|Add given password for shared/newpass to store. 1017 #| 1018 #| shared/newpass.$1 | 3 +++ 1019 #| 1 file changed, 3 insertions(+) 1020 setup_log 1021 } 1022 The result of function git_log should be successful 1023 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1024 End 1025 1026 It 'inserts forcefully over an existing single-line entry with echo' 1027 Skip if 'pass(age) needs bash' check_skip $2 1028 Data "pass-word" 1029 When run script $1 insert -e -f subdir/file 1030 The status should be success 1031 The output should include 'subdir/file' 1032 The output should not include 'Retype' 1033 The contents of file "${PREFIX}/subdir/file.$3" \ 1034 should include "$3:pass-word" 1035 expected_log() { %text:expand 1036 #|Add given password for subdir/file to store. 1037 #| 1038 #| subdir/file.$1 | 2 +- 1039 #| 1 file changed, 1 insertion(+), 1 deletion(-) 1040 setup_log 1041 } 1042 The result of function git_log should be successful 1043 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1044 End 1045 1046 It 'inserts an entry into a new directory' 1047 Skip if 'pass(age) needs bash' check_skip $2 1048 Data "drowssap" 1049 When run script $1 insert -e new-dir/newpass 1050 The status should be success 1051 The output should include 'new-dir/newpass' 1052 The contents of file "${PREFIX}/new-dir/newpass.$3" \ 1053 should include 'myself' 1054 The contents of file "${PREFIX}/new-dir/newpass.$3" \ 1055 should include "$3:drowssap" 1056 expected_log() { %text:expand 1057 #|Add given password for new-dir/newpass to store. 1058 #| 1059 #| new-dir/newpass.$1 | 2 ++ 1060 #| 1 file changed, 2 insertions(+) 1061 setup_log 1062 } 1063 The result of function git_log should be successful 1064 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1065 End 1066 1067 It 'inserts an entry encrypted using an explicit recipient file' 1068 Skip if 'pass(age) needs bash' check_skip $2 1069 Skip if 'this is an age recipient test' [ -n "${3#age}" ] 1070 export PASSAGE_RECIPIENTS_FILE="${PREFIX}/fluff/.age-recipients" 1071 export PASSAGE_RECIPIENTS='shadowed' 1072 Data 'pass' 1073 When run script $1 insert -e shared/new-file 1074 The status should be success 1075 The output should include 'shared/new-file' 1076 expected_file() { %text:expand 1077 #|$1Recipient:master 1078 #|$1Recipient:myself 1079 #|$1:pass 1080 } 1081 The contents of file "${PREFIX}/shared/new-file.$3" should \ 1082 equal "$(expected_file $3)" 1083 expected_log() { %text:expand 1084 #|Add given password for shared/new-file to store. 1085 #| 1086 #| shared/new-file.$1 | 3 +++ 1087 #| 1 file changed, 3 insertions(+) 1088 setup_log 1089 } 1090 The result of function git_log should be successful 1091 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1092 End 1093 1094 It 'inserts an entry encrypted using explicit recipients' 1095 Skip if 'pass(age) needs bash' check_skip $2 1096 Skip if 'this is an age recipient test' [ -n "${3#age}" ] 1097 export PASSAGE_RECIPIENTS='force-1 force-2' 1098 Data 'pass' 1099 When run script $1 insert -e shared/new-file 1100 The status should be success 1101 The output should include 'shared/new-file' 1102 expected_file() { %text:expand 1103 #|$1Recipient:force-1 1104 #|$1Recipient:force-2 1105 #|$1:pass 1106 } 1107 The contents of file "${PREFIX}/shared/new-file.$3" should \ 1108 equal "$(expected_file $3)" 1109 expected_log() { %text:expand 1110 #|Add given password for shared/new-file to store. 1111 #| 1112 #| shared/new-file.$1 | 3 +++ 1113 #| 1 file changed, 3 insertions(+) 1114 setup_log 1115 } 1116 The result of function git_log should be successful 1117 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1118 End 1119 1120 It 'displays usage when called without argument' 1121 Skip if 'pass(age) needs bash' check_skip $2 1122 When run script $1 insert 1123 The status should equal 1 1124 The output should be blank 1125 The error should include 'Usage:' 1126 The error should include ' insert ' 1127 The result of function git_log should be successful 1128 The contents of file "${GITLOG}" should equal "$(setup_log)" 1129 End 1130 1131 It 'displays usage when called with incompatible arguments' 1132 Skip if 'pass(age) needs bash' check_skip $2 1133 When run script $1 insert -em new-secret 1134 The status should equal 1 1135 The output should be blank 1136 The error should include 'Usage:' 1137 The error should include ' insert ' 1138 The result of function git_log should be successful 1139 The contents of file "${GITLOG}" should equal "$(setup_log)" 1140 End 1141 1142 It 'rejects a path containing ..' 1143 Skip if 'pass(age) needs bash' check_skip $2 1144 When run script $1 insert -e fluff/../new-secret 1145 The status should equal 1 1146 The output should be blank 1147 The error should include 'sneaky' 1148 The file "${PREFIX}/new-secret.age" should not be exist 1149 The file "${PREFIX}/new-secret.gpg" should not be exist 1150 The result of function git_log should be successful 1151 The contents of file "${GITLOG}" should equal "$(setup_log)" 1152 End 1153 End 1154 1155 Describe 'edit' 1156 EDITOR=ed 1157 TERM=dumb 1158 1159 It 'creates a file using EDITOR' 1160 EDITOR='ed -c' 1161 Skip if 'pass(age) needs bash' check_skip $2 1162 Data 1163 #|a 1164 #|New password 1165 #|New annotation 1166 #|. 1167 #|wq 1168 End 1169 When run script $1 edit subdir/new 1170 The status should be success 1171 The file "${PREFIX}/subdir/new.$3" should be exist 1172 expected_file() { %text:expand 1173 #|$1Recipient:myself 1174 #|$1:New password 1175 #|$1:New annotation 1176 } 1177 The contents of file "${PREFIX}/subdir/new.$3" should \ 1178 equal "$(expected_file "$3")" 1179 expected_log() { %text:expand 1180 #|Add password for subdir/new using ed -c. 1181 #| 1182 #| subdir/new.$1 | 3 +++ 1183 #| 1 file changed, 3 insertions(+) 1184 setup_log 1185 } 1186 The result of function git_log should be successful 1187 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1188 End 1189 1190 It 'creates a file in a new directory' 1191 EDITOR='ed -c' 1192 Skip if 'pass(age) needs bash' check_skip $2 1193 Data 1194 #|a 1195 #|p4ssword! 1196 #|. 1197 #|wq 1198 End 1199 When run script $1 edit new-subdir/new 1200 The status should be success 1201 The directory "${PREFIX}/new-subdir" should be exist 1202 The file "${PREFIX}/new-subdir/new.$3" should be exist 1203 expected_file() { %text:expand 1204 #|$1Recipient:myself 1205 #|$1:p4ssword! 1206 } 1207 The contents of file "${PREFIX}/new-subdir/new.$3" should \ 1208 equal "$(expected_file "$3")" 1209 expected_log() { %text:expand 1210 #|Add password for new-subdir/new using ed -c. 1211 #| 1212 #| new-subdir/new.$1 | 2 ++ 1213 #| 1 file changed, 2 insertions(+) 1214 setup_log 1215 } 1216 The result of function git_log should be successful 1217 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1218 End 1219 1220 It 'creates a file named like a flag' 1221 EDITOR='ed -c' 1222 Skip if 'pass(age) needs bash' check_skip $2 1223 Data 1224 #|a 1225 #|New password 1226 #|. 1227 #|wq 1228 End 1229 When run script $1 edit -h 1230 The status should be success 1231 The file "${PREFIX}/-h.$3" should be exist 1232 expected_file() { %text:expand 1233 #|$1Recipient:myself 1234 #|$1:New password 1235 } 1236 The contents of file "${PREFIX}/-h.$3" should \ 1237 equal "$(expected_file "$3")" 1238 expected_log() { %text:expand 1239 #|Add password for -h using ed -c. 1240 #| 1241 #| -h.$1 | 2 ++ 1242 #| 1 file changed, 2 insertions(+) 1243 setup_log 1244 } 1245 The result of function git_log should be successful 1246 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1247 End 1248 1249 It 'creates a file named like a directory' 1250 EDITOR='ed -c' 1251 Skip if 'pass(age) needs bash' check_skip $2 1252 Data 1253 #|a 1254 #|New ambiguous password 1255 #|. 1256 #|wq 1257 End 1258 When run script $1 edit fluff 1259 The status should be success 1260 The file "${PREFIX}/fluff.$3" should be exist 1261 expected_file() { %text:expand 1262 #|$1Recipient:myself 1263 #|$1:New ambiguous password 1264 } 1265 The contents of file "${PREFIX}/fluff.$3" should \ 1266 equal "$(expected_file "$3")" 1267 expected_log() { %text:expand 1268 #|Add password for fluff using ed -c. 1269 #| 1270 #| fluff.$1 | 2 ++ 1271 #| 1 file changed, 2 insertions(+) 1272 setup_log 1273 } 1274 The result of function git_log should be successful 1275 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1276 End 1277 1278 It 'creates a secret file named like an unencrypted file' 1279 EDITOR='ed -c' 1280 Skip if 'pass(age) needs bash' check_skip $2 1281 Data 1282 #|a 1283 #|New password in a new file 1284 #|. 1285 #|wq 1286 End 1287 When run script $1 edit y.txt 1288 The status should be success 1289 The file "${PREFIX}/y.txt.$3" should be exist 1290 expected_file() { %text:expand 1291 #|$1Recipient:myself 1292 #|$1:New password in a new file 1293 } 1294 The contents of file "${PREFIX}/y.txt.$3" should \ 1295 equal "$(expected_file "$3")" 1296 expected_log() { %text:expand 1297 #|Add password for y.txt using ed -c. 1298 #| 1299 #| y.txt.$1 | 2 ++ 1300 #| 1 file changed, 2 insertions(+) 1301 setup_log 1302 } 1303 The result of function git_log should be successful 1304 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1305 End 1306 1307 It 'updates a file using EDITOR' 1308 Skip if 'pass(age) needs bash' check_skip $2 1309 Data 1310 #|2i 1311 #|New line 1312 #|. 1313 #|wq 1314 End 1315 When run script $1 edit fluff/two 1316 The status should be success 1317 expected_file() { %text:expand 1318 #|$1Recipient:master 1319 #|$1Recipient:myself 1320 #|$1:2-password 1321 #|$1:New line 1322 #|$1:URL: https://example.com/login 1323 } 1324 The contents of file "${PREFIX}/fluff/two.$3" should \ 1325 equal "$(expected_file "$3")" 1326 expected_log() { %text:expand 1327 #|Edit password for fluff/two using ed. 1328 #| 1329 #| fluff/two.$1 | 1 + 1330 #| 1 file changed, 1 insertion(+) 1331 setup_log 1332 } 1333 The result of function git_log should be successful 1334 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1335 End 1336 1337 It 'updates a file having an ambiguous name without suffix' 1338 Skip if 'pass(age) needs bash' check_skip $2 1339 Data 1340 #|1i 1341 #|New line 1342 #|. 1343 #|wq 1344 End 1345 When run script $1 edit extra 1346 The status should be success 1347 expected_file() { %text:expand 1348 #|$1Recipient:myself 1349 #|$1:New line 1350 #|$1:ambiguous 1351 } 1352 The contents of file "${PREFIX}/extra.$3" should \ 1353 equal "$(expected_file "$3")" 1354 expected_log() { %text:expand 1355 #|Edit password for extra using ed. 1356 #| 1357 #| extra.$1 | 1 + 1358 #| 1 file changed, 1 insertion(+) 1359 setup_log 1360 } 1361 The result of function git_log should be successful 1362 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1363 End 1364 1365 It 'reencrypts an updated file using EDITOR' 1366 Skip if 'pass(age) needs bash' check_skip $2 1367 Data 1368 #|a 1369 #|New option 1370 #|. 1371 #|wq 1372 End 1373 When run script $1 edit stale 1374 The status should be success 1375 expected_file() { %text:expand 1376 #|$1Recipient:myself 1377 #|$1:0-password 1378 #|$1:New option 1379 } 1380 The contents of file "${PREFIX}/stale.$3" should \ 1381 equal "$(expected_file "$3")" 1382 expected_log() { %text:expand 1383 #|Edit password for stale using ed. 1384 #| 1385 #| stale.$1 | 2 +- 1386 #| 1 file changed, 1 insertion(+), 1 deletion(-) 1387 setup_log 1388 } 1389 The result of function git_log should be successful 1390 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1391 End 1392 1393 It 'does not reencrypt an unchanged file using EDITOR' 1394 Skip if 'pass(age) needs bash' check_skip $2 1395 Data 'q' 1396 When run script $1 edit stale 1397 The status should equal \ 1398 "$(if [ $2 = pashage ]; then echo 0; else echo 1; fi)" 1399 expected_file() { %text:expand 1400 #|$1Recipient:master 1401 #|$1Recipient:myself 1402 #|$1:0-password 1403 } 1404 The contents of file "${PREFIX}/stale.$3" should \ 1405 equal "$(expected_file "$3")" 1406 The result of function git_log should be successful 1407 The contents of file "${GITLOG}" should equal "$(setup_log)" 1408 End 1409 1410 It 'allows cancelling file creation' 1411 Skip if 'pass(age) needs bash' check_skip $2 1412 Data 'q' 1413 When run script $1 edit subdir/new 1414 The status should be successful 1415 The file "${PREFIX}/subdir/new.age" should not be exist 1416 The file "${PREFIX}/subdir/new.gpg" should not be exist 1417 The result of function git_log should be successful 1418 The contents of file "${GITLOG}" should equal "$(setup_log)" 1419 End 1420 1421 It 'displays usage when called without argument' 1422 Skip if 'pass(age) needs bash' check_skip $2 1423 When run script $1 edit 1424 The status should equal 1 1425 The output should be blank 1426 The error should include 'Usage:' 1427 The error should include ' edit ' 1428 The result of function git_log should be successful 1429 The contents of file "${GITLOG}" should equal "$(setup_log)" 1430 End 1431 1432 It 'rejects a path containing ..' 1433 Skip if 'pass(age) needs bash' check_skip $2 1434 EDITOR=true 1435 When run script $1 edit subdir/../stale 1436 The status should equal 1 1437 The output should be blank 1438 The error should include 'sneaky' 1439 The result of function git_log should be successful 1440 The contents of file "${GITLOG}" should equal "$(setup_log)" 1441 End 1442 End 1443 1444 Describe 'generate' 1445 It 'generates a new file' 1446 Skip if 'pass(age) needs bash' check_skip $2 1447 When run script $1 generate newdir/newfile 1448 The status should be success 1449 The output should include 'The generated password for' 1450 The file "${PREFIX}/newdir/newfile.$3" should be exist 1451 The lines of contents of file "${PREFIX}/newdir/newfile.$3" should \ 1452 equal 2 1453 The line 1 of contents of file "${PREFIX}/newdir/newfile.$3" should \ 1454 equal "$3Recipient:myself" 1455 The output should \ 1456 include "$(@sed -n "2s/$3://p" "${PREFIX}/newdir/newfile.$3")" 1457 expected_log() { %text:expand 1458 #|Add generated password for newdir/newfile. 1459 #| 1460 #| newdir/newfile.$1 | 2 ++ 1461 #| 1 file changed, 2 insertions(+) 1462 setup_log 1463 } 1464 The result of function git_log should be successful 1465 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1466 End 1467 1468 It 'fails to generates a new file named like a flag without escape' 1469 Skip if 'pass(age) needs bash' check_skip $2 1470 When run script $1 generate -h 1471 The status should equal 1 1472 The output should be blank 1473 The error should include 'Usage:' 1474 The result of function git_log should be successful 1475 The contents of file "${GITLOG}" should equal "$(setup_log)" 1476 End 1477 1478 It 'generates a new file named like a flag' 1479 Skip if 'pass(age) needs bash' check_skip $2 1480 When run script $1 generate -- -h 1481 The status should be success 1482 The output should include 'The generated password for' 1483 The file "${PREFIX}/-h.$3" should be exist 1484 The lines of contents of file "${PREFIX}/-h.$3" should equal 2 1485 The line 1 of contents of file "${PREFIX}/-h.$3" should \ 1486 equal "$3Recipient:myself" 1487 The output should \ 1488 include "$(@sed -n "2s/$3://p" "${PREFIX}/-h.$3")" 1489 expected_log() { %text:expand 1490 #|Add generated password for -h. 1491 #| 1492 #| -h.$1 | 2 ++ 1493 #| 1 file changed, 2 insertions(+) 1494 setup_log 1495 } 1496 The result of function git_log should be successful 1497 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1498 End 1499 1500 It 'generates a new file named like a directory' 1501 Skip if 'pass(age) needs bash' check_skip $2 1502 When run script $1 generate fluff 1503 The status should be success 1504 The output should include 'The generated password for' 1505 The file "${PREFIX}/fluff.$3" should be exist 1506 The lines of contents of file "${PREFIX}/fluff.$3" should equal 2 1507 The line 1 of contents of file "${PREFIX}/fluff.$3" should \ 1508 equal "$3Recipient:myself" 1509 The output should \ 1510 include "$(@sed -n "2s/$3://p" "${PREFIX}/fluff.$3")" 1511 expected_log() { %text:expand 1512 #|Add generated password for fluff. 1513 #| 1514 #| fluff.$1 | 2 ++ 1515 #| 1 file changed, 2 insertions(+) 1516 setup_log 1517 } 1518 The result of function git_log should be successful 1519 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1520 End 1521 1522 It 'generates a new file in a new directory' 1523 Skip if 'pass(age) needs bash' check_skip $2 1524 When run script $1 generate brand-new-dir/file 1525 The status should be success 1526 The output should include 'The generated password for' 1527 The file "${PREFIX}/brand-new-dir/file.$3" should be exist 1528 The lines of contents of file "${PREFIX}/brand-new-dir/file.$3" should \ 1529 equal 2 1530 The line 1 of contents of file "${PREFIX}/brand-new-dir/file.$3" should \ 1531 equal "$3Recipient:myself" 1532 The output should \ 1533 include "$(@sed -n "2s/$3://p" "${PREFIX}/brand-new-dir/file.$3")" 1534 expected_log() { %text:expand 1535 #|Add generated password for brand-new-dir/file. 1536 #| 1537 #| brand-new-dir/file.$1 | 2 ++ 1538 #| 1 file changed, 2 insertions(+) 1539 setup_log 1540 } 1541 The result of function git_log should be successful 1542 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1543 End 1544 1545 It 'generates a new file without symbols' 1546 Skip if 'pass(age) needs bash' check_skip $2 1547 When run script $1 generate -n newfile 4 1548 The status should be success 1549 The output should include 'The generated password for' 1550 The file "${PREFIX}/newfile.$3" should be exist 1551 The lines of contents of file "${PREFIX}/newfile.$3" should \ 1552 equal 2 1553 The line 1 of contents of file "${PREFIX}/newfile.$3" should \ 1554 equal "$3Recipient:myself" 1555 The line 2 of contents of file "${PREFIX}/newfile.$3" should \ 1556 match pattern "$3:[0-9a-zA-z][0-9a-zA-z][0-9a-zA-z][0-9a-zA-z]" 1557 The output should \ 1558 include "$(@sed -n "2s/$3://p" "${PREFIX}/newfile.$3")" 1559 expected_log() { %text:expand 1560 #|Add generated password for newfile. 1561 #| 1562 #| newfile.$1 | 2 ++ 1563 #| 1 file changed, 2 insertions(+) 1564 setup_log 1565 } 1566 The result of function git_log should be successful 1567 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1568 End 1569 1570 It 'replaces an existing file when forced' 1571 Skip if 'pass(age) needs bash' check_skip $2 1572 When run script $1 generate -f fluff/three 20 1573 The status should be success 1574 The output should include 'The generated password for' 1575 The lines of contents of file "${PREFIX}/fluff/three.$3" should equal 3 1576 The output should \ 1577 include "$(@sed -n "3s/$3://p" "${PREFIX}/fluff/three.$3")" 1578 expected_log() { %text:expand 1579 #|Add generated password for fluff/three. 1580 #| 1581 #| fluff/three.$1 | 4 +--- 1582 #| 1 file changed, 1 insertion(+), 3 deletions(-) 1583 setup_log 1584 } 1585 The result of function git_log should be successful 1586 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1587 End 1588 1589 It 'replaces the first line of an existing file' 1590 Skip if 'pass(age) needs bash' check_skip $2 1591 When run script $1 generate -ni fluff/three 4 1592 The status should be success 1593 The output should include 'The generated password for' 1594 The lines of contents of file "${PREFIX}/fluff/three.$3" should equal 5 1595 The line 3 of contents of file "${PREFIX}/fluff/three.$3" should \ 1596 match pattern "$3:[0-9a-zA-z][0-9a-zA-z][0-9a-zA-z][0-9a-zA-z]" 1597 The output should \ 1598 include "$(@sed -n "3s/$3://p" "${PREFIX}/fluff/three.$3")" 1599 expected_log() { %text:expand 1600 #|Replace generated password for fluff/three. 1601 #| 1602 #| fluff/three.$1 | 2 +- 1603 #| 1 file changed, 1 insertion(+), 1 deletion(-) 1604 setup_log 1605 } 1606 The result of function git_log should be successful 1607 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1608 End 1609 1610 It 'replaces the line of an existing one-line file' 1611 Skip if 'pass(age) needs bash' check_skip $2 1612 When run script $1 generate -ni fluff/one 4 1613 The status should be success 1614 The output should include 'The generated password for' 1615 The lines of contents of file "${PREFIX}/fluff/one.$3" should equal 3 1616 The line 3 of contents of file "${PREFIX}/fluff/one.$3" should \ 1617 match pattern "$3:[0-9a-zA-z][0-9a-zA-z][0-9a-zA-z][0-9a-zA-z]" 1618 The output should \ 1619 include "$(@sed -n "3s/$3://p" "${PREFIX}/fluff/one.$3")" 1620 expected_log() { %text:expand 1621 #|Replace generated password for fluff/one. 1622 #| 1623 #| fluff/one.$1 | 2 +- 1624 #| 1 file changed, 1 insertion(+), 1 deletion(-) 1625 setup_log 1626 } 1627 The result of function git_log should be successful 1628 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1629 End 1630 1631 It 'pastes the generated password into the clipboard' 1632 export DISPLAY=mock 1633 Skip if 'pass(age) needs bash' check_skip $2 1634 When run script $1 generate -nc subdir/new 1635 The status should be success 1636 The output should not include 'The generated password for' 1637 The output should not \ 1638 include "$(@sed -n "2s/$3://p" "${PREFIX}/subdir/new.$3")" 1639 The output should include \ 1640 'Copied subdir/new to clipboard. Will clear in 45 seconds.' 1641 The error should start with '$ xclip -selection clipboard' 1642 expected_log() { %text:expand 1643 #|Add generated password for subdir/new. 1644 #| 1645 #| subdir/new.$1 | 2 ++ 1646 #| 1 file changed, 2 insertions(+) 1647 setup_log 1648 } 1649 The result of function git_log should be successful 1650 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1651 End 1652 1653 It 'displays the generated password as a QR-code' 1654 export DISPLAY=mock 1655 Skip if 'pass(age) needs bash' check_skip $2 1656 When run script $1 generate -qn new 1657 The status should be success 1658 The output should not include 'The generated password for' 1659 The output should not include "$(@sed -n "2s/$3://p" "${PREFIX}/new.$3")" 1660 The error should start with '$ feh -x --title pas' 1661 expected_log() { %text:expand 1662 #|Add generated password for new. 1663 #| 1664 #| new.$1 | 2 ++ 1665 #| 1 file changed, 2 insertions(+) 1666 setup_log 1667 } 1668 The result of function git_log should be successful 1669 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1670 End 1671 1672 It 'reports a generation error' 1673 Skip if 'pass(age) needs bash' check_skip $2 1674 Mock tr 1675 if [ "$1" = '-dc' ]; then 1676 %putsn '0123456789' 1677 else 1678 @tr "$@" 1679 fi 1680 End 1681 expected_err() { 1682 if [ "$1" = pashage ]; then 1683 %putsn 'Error while generating password: 10/12 bytes read' 1684 else 1685 %putsn 'Could not generate password from /dev/urandom.' 1686 fi 1687 } 1688 When run script $1 generate -f new-secret 12 1689 The status should equal 1 1690 The output should be blank 1691 The error should equal "$(expected_err $2)" 1692 The result of function git_log should be successful 1693 The contents of file "${GITLOG}" should equal "$(setup_log)" 1694 End 1695 1696 It 'displays usage when called without argument' 1697 Skip if 'pass(age) needs bash' check_skip $2 1698 When run script $1 generate 1699 The status should equal 1 1700 The output should be blank 1701 The error should include 'Usage:' 1702 The error should include ' generate ' 1703 The result of function git_log should be successful 1704 The contents of file "${GITLOG}" should equal "$(setup_log)" 1705 End 1706 1707 It 'displays usage when called with incompatible display options' 1708 Skip if 'pass(age) needs bash' check_skip $2 1709 When run script $1 generate --clip --qrcode new-secret 1710 The status should equal 1 1711 The output should be blank 1712 The error should include 'Usage:' 1713 The error should include ' generate ' 1714 The result of function git_log should be successful 1715 The contents of file "${GITLOG}" should equal "$(setup_log)" 1716 End 1717 1718 It 'displays usage when called with reversed incompatible display options' 1719 Skip if 'pass(age) needs bash' check_skip $2 1720 When run script $1 generate --qrcode --clip new-secret 1721 The status should equal 1 1722 The output should be blank 1723 The error should include 'Usage:' 1724 The error should include ' generate ' 1725 The result of function git_log should be successful 1726 The contents of file "${GITLOG}" should equal "$(setup_log)" 1727 End 1728 1729 It 'displays usage when called with incompatible overwriting options' 1730 Skip if 'pass(age) needs bash' check_skip $2 1731 When run script $1 generate --force --in-place new-secret 1732 The status should equal 1 1733 The output should be blank 1734 The error should include 'Usage:' 1735 The error should include ' generate ' 1736 The result of function git_log should be successful 1737 The contents of file "${GITLOG}" should equal "$(setup_log)" 1738 End 1739 1740 It 'displays usage when called with reversed incompatible overwriting opt' 1741 Skip if 'pass(age) needs bash' check_skip $2 1742 When run script $1 generate --in-place --force new-secret 1743 The status should equal 1 1744 The output should be blank 1745 The error should include 'Usage:' 1746 The error should include ' generate ' 1747 The result of function git_log should be successful 1748 The contents of file "${GITLOG}" should equal "$(setup_log)" 1749 End 1750 1751 It 'rejects a path containing ..' 1752 Skip if 'pass(age) needs bash' check_skip $2 1753 When run script $1 generate subdir/../new-secret 1754 The status should equal 1 1755 The output should be blank 1756 The error should include 'sneaky' 1757 The file "${PREFIX}/new-secret.age" should not be exist 1758 The file "${PREFIX}/new-secret.gpg" should not be exist 1759 The result of function git_log should be successful 1760 The contents of file "${GITLOG}" should equal "$(setup_log)" 1761 End 1762 End 1763 1764 Describe 'rm' 1765 It 'removes a file without confirmation when forced' 1766 Skip if 'pass(age) needs bash' check_skip $2 1767 When run script $1 rm -f subdir/file 1768 The status should be success 1769 The output should include 'subdir/file' 1770 The error should be blank 1771 The file "${PREFIX}/subdir/file.$3" should not be exist 1772 expected_log() { %text:expand 1773 #|Remove subdir/file from store. 1774 #| 1775 #| subdir/file.$1 | 2 -- 1776 #| 1 file changed, 2 deletions(-) 1777 setup_log 1778 } 1779 The result of function git_log should be successful 1780 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1781 End 1782 1783 It 'fails to remove a file named like a flag without escape' 1784 Skip if 'pass(age) needs bash' check_skip $2 1785 When run script $1 rm -f -g 1786 The status should equal 1 1787 The output should be blank 1788 The error should include 'Usage:' 1789 The result of function git_log should be successful 1790 The contents of file "${GITLOG}" should equal "$(setup_log)" 1791 End 1792 1793 It 'removes a file named like a flag' 1794 Skip if 'pass(age) needs bash' check_skip $2 1795 When run script $1 rm -f -- -g 1796 The status should be success 1797 The output should include '-g' 1798 The error should be blank 1799 The file "${PREFIX}/-g.$3" should not be exist 1800 expected_log() { %text:expand 1801 #|Remove -g from store. 1802 #| 1803 #| -g.$1 | 2 -- 1804 #| 1 file changed, 2 deletions(-) 1805 setup_log 1806 } 1807 The result of function git_log should be successful 1808 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1809 End 1810 1811 It 'removes a file having an ambiguous name without suffix' 1812 Skip if 'pass(age) needs bash' check_skip $2 1813 When run script $1 rm -f extra 1814 The status should be success 1815 The output should include 'extra' 1816 The error should be blank 1817 The file "${PREFIX}/extra.$3" should not be exist 1818 The directory "${PREFIX}/extra" should be exist 1819 expected_log() { %text:expand 1820 #|Remove extra from store. 1821 #| 1822 #| extra.$1 | 2 -- 1823 #| 1 file changed, 2 deletions(-) 1824 setup_log 1825 } 1826 The result of function git_log should be successful 1827 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1828 End 1829 1830 It 'fails to remove a non-existent file' 1831 Skip if 'pass(age) needs bash' check_skip $2 1832 When run script $1 rm -f non-existent-file 1833 The status should equal 1 1834 The error should include 'non-existent-file' 1835 The result of function git_log should be successful 1836 The contents of file "${GITLOG}" should equal "$(setup_log)" 1837 End 1838 1839 It 'does not remove a directory without `-r` even when forced' 1840 Skip if 'pass(age) needs bash' check_skip $2 1841 When run script $1 rm -f fluff 1842 The status should equal \ 1843 "$(if [ $2 = pashage ]; then echo 1; else echo 0; fi)" 1844 The error should include 'fluff/' 1845 The error should include 's a directory' 1846 The directory "${PREFIX}/fluff" should be exist 1847 The file "${PREFIX}/fluff/one.$3" should be exist 1848 The result of function git_log should be successful 1849 The contents of file "${GITLOG}" should equal "$(setup_log)" 1850 End 1851 1852 It 'removes a directory when forced and recursive' 1853 Skip if 'pass(age) needs bash' check_skip $2 1854 When run script $1 rm -rf fluff 1855 The status should be success 1856 The directory "${PREFIX}/fluff" should not be exist 1857 expected_log() { 1858 if [ $1 = pashage ]; then 1859 %putsn 'Remove fluff/ from store.' 1860 else 1861 %putsn 'Remove fluff from store.' 1862 fi 1863 %text:expand 1864 #| 1865 #| fluff/.age-recipients | 2 -- 1866 #| fluff/.gpg-id | 2 -- 1867 #| fluff/one.age | 3 --- 1868 #| fluff/one.gpg | 3 --- 1869 #| fluff/three.age | 5 ----- 1870 #| fluff/three.gpg | 5 ----- 1871 #| fluff/two.age | 4 ---- 1872 #| fluff/two.gpg | 4 ---- 1873 #| 8 files changed, 28 deletions(-) 1874 setup_log 1875 } 1876 The result of function git_log should be successful 1877 The contents of file "${GITLOG}" should equal "$(expected_log $2)" 1878 End 1879 1880 It 'removes a directory having an ambiguous name with `/` suffix' 1881 Skip if 'pass(age) needs bash' check_skip $2 1882 When run script $1 rm -rf extra/ 1883 The status should be success 1884 The output should include 'extra' 1885 The error should be blank 1886 The file "${PREFIX}/extra.age" should be exist 1887 The file "${PREFIX}/extra.gpg" should be exist 1888 The directory "${PREFIX}/extra" should not be exist 1889 expected_log() { %text:expand 1890 #|Remove extra/ from store. 1891 #| 1892 #| extra/subdir/file.age | 2 -- 1893 #| extra/subdir/file.gpg | 2 -- 1894 #| 2 files changed, 4 deletions(-) 1895 setup_log 1896 } 1897 The result of function git_log should be successful 1898 The contents of file "${GITLOG}" should equal "$(expected_log $3)" 1899 End 1900 1901 It 'does not remove anything with `/` suffix but no recursive flag' 1902 Skip if 'pass(age) needs bash' check_skip $2 1903 When run script $1 rm -f extra/ 1904 The status should equal \ 1905 "$(if [ $2 = pashage ]; then echo 1; else echo 0; fi)" 1906 The error should include 'extra/' 1907 The error should include 's a directory' 1908 The directory "${PREFIX}/extra" should be exist 1909 The file "${PREFIX}/extra.age" should be exist 1910 The file "${PREFIX}/extra.gpg" should be exist 1911 The result of function git_log should be successful 1912 The contents of file "${GITLOG}" should equal "$(setup_log)" 1913 End 1914 1915 It 'fails to remove a non-existent directory' 1916 Skip if 'pass(age) needs bash' check_skip $2 1917 When run script $1 rm -rf stale/ 1918 The status should equal 1 1919 The error should include 'stale/' 1920 The result of function git_log should be successful 1921 The contents of file "${GITLOG}" should equal "$(setup_log)" 1922 End 1923 1924 It 'does not remove an unencrypted file in the store' 1925 Skip if 'pass(age) needs bash' check_skip $2 1926 When run script $1 rm -f y.txt 1927 The status should equal 1 1928 The output should be blank 1929 The error should include 'y.txt' 1930 The file "${PREFIX}/y.txt" should be exist 1931 The result of function git_log should be successful 1932 The contents of file "${GITLOG}" should equal "$(setup_log)" 1933 End 1934 1935 It 'does not remove an unencrypted file with `/` suffix' 1936 Skip if 'pass(age) needs bash' check_skip $2 1937 When run script $1 rm -rf y.txt/ 1938 The status should equal 1 1939 The output should be blank 1940 The error should include 'y.txt' 1941 The file "${PREFIX}/y.txt" should be exist 1942 The result of function git_log should be successful 1943 The contents of file "${GITLOG}" should equal "$(setup_log)" 1944 End 1945 1946 It 'displays usage when called without argument' 1947 Skip if 'pass(age) needs bash' check_skip $2 1948 When run script $1 delete 1949 The status should equal 1 1950 The output should be blank 1951 The error should include 'Usage:' 1952 The error should include ' delete ' 1953 The result of function git_log should be successful 1954 The contents of file "${GITLOG}" should equal "$(setup_log)" 1955 End 1956 1957 It 'rejects a path containing ..' 1958 Skip if 'pass(age) needs bash' check_skip $2 1959 When run script $1 delete subdir/../fluff/one 1960 The status should equal 1 1961 The output should be blank 1962 The error should include 'sneaky' 1963 The file "${PREFIX}/fluff/one.age" should be exist 1964 The file "${PREFIX}/fluff/one.gpg" should be exist 1965 The result of function git_log should be successful 1966 The contents of file "${GITLOG}" should equal "$(setup_log)" 1967 End 1968 End 1969 1970 Describe 'mv' 1971 It 'renames a file without reencrypting' 1972 Skip if 'pass(age) needs bash' check_skip $2 1973 When run script $1 mv subdir/file subdir/renamed 1974 The status should be success 1975 The error should be blank 1976 The file "${PREFIX}/subdir/file.$3" should not be exist 1977 file_contents() { %text:expand 1978 #|${1}Recipient:myself 1979 #|${1}:p4ssw0rd 1980 } 1981 The contents of file "${PREFIX}/subdir/renamed.$3" \ 1982 should equal "$(file_contents "$3")" 1983 expected_log() { 1984 if [ "$2" = pashage ]; then 1985 %putsn 'Move subdir/file.age to subdir/renamed.age' 1986 else 1987 %putsn 'Rename subdir/file to subdir/renamed.' 1988 fi 1989 %text:expand 1990 #| 1991 #| subdir/{file.$1 => renamed.$1} | 0 1992 #| 1 file changed, 0 insertions(+), 0 deletions(-) 1993 setup_log 1994 } 1995 The result of function git_log should be successful 1996 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 1997 End 1998 1999 It 'fails to rename a file named like a flag without escape' 2000 Skip if 'pass(age) needs bash' check_skip $2 2001 When run script $1 mv -g safe-name 2002 The status should equal 1 2003 The output should be blank 2004 The error should include 'Usage:' 2005 The result of function git_log should be successful 2006 The contents of file "${GITLOG}" should equal "$(setup_log)" 2007 End 2008 2009 It 'renames a file named like a flag' 2010 Skip if 'pass(age) needs bash' check_skip $2 2011 When run script $1 mv -- -g -h 2012 The status should be success 2013 The error should be blank 2014 The file "${PREFIX}/-g.$3" should not be exist 2015 file_contents() { %text:expand 2016 #|${1}Recipient:myself 2017 #|${1}:-- 2018 } 2019 The contents of file "${PREFIX}/-h.$3" \ 2020 should equal "$(file_contents "$3")" 2021 expected_log() { 2022 if [ "$2" = pashage ]; then 2023 %putsn 'Move -g.age to -h.age' 2024 else 2025 %putsn 'Rename -g to -h.' 2026 fi 2027 %text:expand 2028 #| 2029 #| -g.$1 => -h.$1 | 0 2030 #| 1 file changed, 0 insertions(+), 0 deletions(-) 2031 setup_log 2032 } 2033 The result of function git_log should be successful 2034 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2035 End 2036 2037 It 'reencrypts a moved file' 2038 Skip if 'pass(age) needs bash' check_skip $2 2039 When run script $1 mv subdir/file shared/renamed 2040 The status should be success 2041 The error should be blank 2042 The file "${PREFIX}/subdir/file.$3" should not be exist 2043 file_contents() { %text:expand 2044 #|${1}Recipient:myself 2045 #|${1}Recipient:friend 2046 #|${1}:p4ssw0rd 2047 } 2048 The contents of file "${PREFIX}/shared/renamed.$3" \ 2049 should equal "$(file_contents "$3")" 2050 expected_log() { 2051 if [ "$2" = pashage ]; then 2052 %putsn 'Move subdir/file.age to shared/renamed.age' 2053 else 2054 %putsn 'Rename subdir/file to shared/renamed.' 2055 fi 2056 %text:expand 2057 #| 2058 #| subdir/file.$1 => shared/renamed.$1 | 1 + 2059 #| 1 file changed, 1 insertion(+) 2060 setup_log 2061 } 2062 The result of function git_log should be successful 2063 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2064 End 2065 2066 It 'moves an unencrypted file without reencrypting it' 2067 Skip if 'pass(age) needs bash' check_skip $2 2068 When run script $1 mv y.txt shared 2069 The status should be success 2070 The error should be blank 2071 The file "${PREFIX}/y.txt" should not be exist 2072 file_contents() { %text 2073 #|Unencrypted line 1 2074 #|Unencrypted line 2 2075 #|Unencrypted line 3 2076 } 2077 The contents of file "${PREFIX}/shared/y.txt" \ 2078 should equal "$(file_contents)" 2079 expected_log() { 2080 if [ "$2" = pashage ]; then 2081 %putsn 'Move y.txt to shared/y.txt' 2082 else 2083 %putsn 'Rename y.txt to shared.' 2084 fi 2085 %text 2086 #| 2087 #| y.txt => shared/y.txt | 0 2088 #| 1 file changed, 0 insertions(+), 0 deletions(-) 2089 setup_log 2090 } 2091 The result of function git_log should be successful 2092 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2093 End 2094 2095 It 'reencrypts relevant files in a moved directory' 2096 Skip if 'pass(age) needs bash' check_skip $2 2097 When run script $1 mv subdir shared/ 2098 The status should be success 2099 The error should be blank 2100 The file "${PREFIX}/subdir/file.$3" should not be exist 2101 file_contents() { %text:expand 2102 #|${1}Recipient:myself 2103 #|${1}Recipient:friend 2104 #|${1}:p4ssw0rd 2105 } 2106 The contents of file "${PREFIX}/shared/subdir/file.$3" \ 2107 should equal "$(file_contents "$3")" 2108 expected_log() { 2109 if [ "$2" = pashage ]; then 2110 %putsn 'Move subdir/ to shared/subdir/' 2111 else 2112 %putsn 'Rename subdir to shared/.' 2113 fi 2114 if [ "$1" = age ]; then 2115 %text:expand 2116 #| 2117 #| {subdir => shared/subdir}/file.age | 1 + 2118 #| {subdir => shared/subdir}/file.gpg | 0 2119 #| 2 files changed, 1 insertion(+) 2120 else 2121 %text:expand 2122 #| 2123 #| {subdir => shared/subdir}/file.age | 0 2124 #| {subdir => shared/subdir}/file.gpg | 1 + 2125 #| 2 files changed, 1 insertion(+) 2126 fi 2127 setup_log 2128 } 2129 The result of function git_log should be successful 2130 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2131 End 2132 2133 It 'moves a file into a new directory' 2134 Skip if 'pass(age) needs bash' check_skip $2 2135 When run script $1 mv subdir/file new-subdir/ 2136 The status should be success 2137 The error should be blank 2138 The file "${PREFIX}/subdir/file.$3" should not be exist 2139 file_contents() { %text:expand 2140 #|${1}Recipient:myself 2141 #|${1}:p4ssw0rd 2142 } 2143 The contents of file "${PREFIX}/new-subdir/file.$3" \ 2144 should equal "$(file_contents "$3")" 2145 expected_log() { 2146 if [ "$2" = pashage ]; then 2147 %putsn 'Move subdir/file.age to new-subdir/file.age' 2148 else 2149 %putsn 'Rename subdir/file to new-subdir/.' 2150 fi 2151 %text:expand 2152 #| 2153 #| {subdir => new-subdir}/file.$1 | 0 2154 #| 1 file changed, 0 insertions(+), 0 deletions(-) 2155 setup_log 2156 } 2157 The result of function git_log should be successful 2158 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2159 End 2160 2161 It 'fails to rename a non-existent file' 2162 Skip if 'pass(age) needs bash' check_skip $2 2163 When run script $1 mv non-existent-file new-name 2164 The status should equal 1 2165 The error should \ 2166 equal 'Error: non-existent-file is not in the password store.' 2167 The result of function git_log should be successful 2168 The contents of file "${GITLOG}" should equal "$(setup_log)" 2169 End 2170 2171 It 'renames a directory with recipients' 2172 Skip if 'pass(age) needs bash' check_skip $2 2173 When run script $1 mv fluff filler 2174 The status should be success 2175 The error should be blank 2176 The directory "${PREFIX}/fluff" should not be exist 2177 The directory "${PREFIX}/filler" should be exist 2178 expected_log() { 2179 if [ "$2" = pashage ]; then 2180 %putsn 'Move fluff/ to filler/' 2181 else 2182 %putsn 'Rename fluff to filler.' 2183 fi 2184 %text:expand 2185 #| 2186 #| {fluff => filler}/.age-recipients | 0 2187 #| {fluff => filler}/.gpg-id | 0 2188 #| {fluff => filler}/one.age | 0 2189 #| {fluff => filler}/one.gpg | 0 2190 #| {fluff => filler}/three.age | 0 2191 #| {fluff => filler}/three.gpg | 0 2192 #| {fluff => filler}/two.age | 0 2193 #| {fluff => filler}/two.gpg | 0 2194 #| 8 files changed, 0 insertions(+), 0 deletions(-) 2195 setup_log 2196 } 2197 The result of function git_log should be successful 2198 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2199 End 2200 2201 It 'renames a directory without recipients' 2202 Skip if 'pass(age) needs bash' check_skip $2 2203 When run script $1 mv subdir newdir 2204 The status should be success 2205 The error should be blank 2206 The directory "${PREFIX}/subdir" should not be exist 2207 file_contents() { %text:expand 2208 #|${1}Recipient:myself 2209 #|${1}:p4ssw0rd 2210 } 2211 The contents of file "${PREFIX}/newdir/file.$3" \ 2212 should equal "$(file_contents "$3")" 2213 expected_log() { 2214 if [ "$2" = pashage ]; then 2215 %putsn 'Move subdir/ to newdir/' 2216 else 2217 %putsn 'Rename subdir to newdir.' 2218 fi 2219 %text:expand 2220 #| 2221 #| {subdir => newdir}/file.age | 0 2222 #| {subdir => newdir}/file.gpg | 0 2223 #| 2 files changed, 0 insertions(+), 0 deletions(-) 2224 setup_log 2225 } 2226 The result of function git_log should be successful 2227 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2228 End 2229 2230 It 'overwrites an existing file when forced' 2231 Skip if 'pass(age) needs bash' check_skip $2 2232 When run script $1 mv -f fluff/two fluff/one 2233 The status should be success 2234 The file "${PREFIX}/fluff/two.$3" should not be exist 2235 file_contents() { %text:expand 2236 #|${1}Recipient:master 2237 #|${1}Recipient:myself 2238 #|${1}:2-password 2239 #|${1}:URL: https://example.com/login 2240 } 2241 The contents of file "${PREFIX}/fluff/one.$3" \ 2242 should equal "$(file_contents "$3")" 2243 expected_log() { 2244 if [ "$2" = pashage ]; then 2245 %putsn 'Move fluff/two.age to fluff/one.age' 2246 else 2247 %putsn 'Rename fluff/two to fluff/one.' 2248 fi 2249 %text:expand 2250 #| 2251 #| fluff/one.$1 | 3 ++- 2252 #| fluff/two.$1 | 4 ---- 2253 #| 2 files changed, 2 insertions(+), 5 deletions(-) 2254 setup_log 2255 } 2256 The result of function git_log should be successful 2257 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2258 End 2259 2260 It 'renames a file having an ambiguous name without suffix' 2261 Skip if 'pass(age) needs bash' check_skip $2 2262 When run script $1 mv extra new 2263 The status should be success 2264 The file "${PREFIX}/extra.$3" should not be exist 2265 file_contents() { %text:expand 2266 #|${1}Recipient:myself 2267 #|${1}:ambiguous 2268 } 2269 The contents of file "${PREFIX}/new.$3" \ 2270 should equal "$(file_contents "$3")" 2271 expected_log() { 2272 if [ "$2" = pashage ]; then 2273 %putsn 'Move extra.age to new.age' 2274 else 2275 %putsn 'Rename extra to new.' 2276 fi 2277 %text:expand 2278 #| 2279 #| extra.$1 => new.$1 | 0 2280 #| 1 file changed, 0 insertions(+), 0 deletions(-) 2281 setup_log 2282 } 2283 The result of function git_log should be successful 2284 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2285 End 2286 2287 It 'renames a directory having an ambiguous name with `/` suffix' 2288 Skip if 'pass(age) needs bash' check_skip $2 2289 When run script $1 mv extra/ new 2290 The status should be success 2291 The directory "${PREFIX}/extra" should not be exist 2292 The file "${PREFIX}/new/subdir/file.age" should be exist 2293 The file "${PREFIX}/new/subdir/file.gpg" should be exist 2294 expected_log() { 2295 if [ "$2" = pashage ]; then 2296 %putsn 'Move extra/ to new/' 2297 else 2298 %putsn 'Rename extra/ to new.' 2299 fi 2300 %text:expand 2301 #| 2302 #| {extra => new}/subdir/file.age | 0 2303 #| {extra => new}/subdir/file.gpg | 0 2304 #| 2 files changed, 0 insertions(+), 0 deletions(-) 2305 setup_log 2306 } 2307 The result of function git_log should be successful 2308 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2309 End 2310 2311 It 'moves a file to a directory having an ambiguous name without suffix' 2312 Skip if 'pass(age) needs bash' check_skip $2 2313 When run script $1 mv subdir/file extra 2314 The status should be success 2315 The file "${PREFIX}/subdir/file.$3" should not be exist 2316 file_contents() { %text:expand 2317 #|${1}Recipient:myself 2318 #|${1}:p4ssw0rd 2319 } 2320 The contents of file "${PREFIX}/extra/file.$3" \ 2321 should equal "$(file_contents "$3")" 2322 expected_log() { 2323 if [ "$2" = pashage ]; then 2324 %putsn "Move subdir/file.$1 to extra/file.$1" 2325 else 2326 %putsn 'Rename subdir/file to extra.' 2327 fi 2328 %text:expand 2329 #| 2330 #| {subdir => extra}/file.$1 | 0 2331 #| 1 file changed, 0 insertions(+), 0 deletions(-) 2332 setup_log 2333 } 2334 The result of function git_log should be successful 2335 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2336 End 2337 2338 It 'does not merge directories recursively' 2339 Skip if 'pass(age) needs bash' check_skip $2 2340 When run script $1 mv -f subdir/ extra/ 2341 The status should equal 1 2342 The error should include 'subdir' 2343 The error should include 'extra/' 2344 The directory "${PREFIX}/subdir" should be exist 2345 The file "${PREFIX}/subdir/file.$3" should be exist 2346 The result of function git_log should be successful 2347 The contents of file "${GITLOG}" should equal "$(setup_log)" 2348 End 2349 2350 It 'displays usage when called without argument' 2351 Skip if 'pass(age) needs bash' check_skip $2 2352 When run script $1 mv 2353 The status should equal 1 2354 The output should be blank 2355 The error should include 'Usage:' 2356 The result of function git_log should be successful 2357 The contents of file "${GITLOG}" should equal "$(setup_log)" 2358 End 2359 2360 It 'fails to rename a non-existent directory' 2361 Skip if 'pass(age) considers "stale/" as the file "stale"' \ 2362 [ ! $2 = pashage ] 2363 When run script $1 mv stale/ new-name 2364 The status should equal 1 2365 The error should equal 'Error: stale/ is not in the password store.' 2366 The directory "${PREFIX}/new-name" should not be exist 2367 The file "${PREFIX}/new-name.age" should not be exist 2368 The file "${PREFIX}/new-name.gpg" should not be exist 2369 The result of function git_log should be successful 2370 The contents of file "${GITLOG}" should equal "$(setup_log)" 2371 End 2372 2373 It 'fails to move a directory into a file masquerading as a directory' 2374 Skip if 'pass(age) needs bash' check_skip $2 2375 When run script $1 mv subdir y.txt/ 2376 The status should equal 1 2377 The error should include 'y.txt' 2378 The error should include 'ot a directory' 2379 The result of function git_log should be successful 2380 The contents of file "${GITLOG}" should equal "$(setup_log)" 2381 End 2382 2383 It 'rejects a source path containing ..' 2384 Skip if 'pass(age) needs bash' check_skip $2 2385 When run script $1 mv fluff/../stale subdir/ 2386 The status should equal 1 2387 The output should be blank 2388 The error should include 'sneaky' 2389 The file "${PREFIX}/stale.age" should be exist 2390 The file "${PREFIX}/stale.gpg" should be exist 2391 The file "${PREFIX}/subdir/stale.age" should not be exist 2392 The file "${PREFIX}/subdir/stale.gpg" should not be exist 2393 The result of function git_log should be successful 2394 The contents of file "${GITLOG}" should equal "$(setup_log)" 2395 End 2396 2397 It 'rejects a destination path containing ..' 2398 Skip if 'pass(age) needs bash' check_skip $2 2399 When run script $1 mv subdir/file extra/subdir/.. 2400 The status should equal 1 2401 The output should be blank 2402 The error should include 'sneaky' 2403 The file "${PREFIX}/subdir/file.age" should be exist 2404 The file "${PREFIX}/subdir/file.gpg" should be exist 2405 The file "${PREFIX}/extra/file.age" should not be exist 2406 The file "${PREFIX}/extra/file.gpg" should not be exist 2407 The result of function git_log should be successful 2408 The contents of file "${GITLOG}" should equal "$(setup_log)" 2409 End 2410 2411 extra_setup() { 2412 @mkdir "${PREFIX}/extra/stale.age" "${PREFIX}/extra/stale.gpg" 2413 } 2414 BeforeEach extra_setup 2415 2416 It 'fails to move a file where a directory already exists' 2417 Skip if 'pass(age) needs bash' check_skip $2 2418 When run script $1 mv -f stale extra/ 2419 The status should equal 1 2420 if [ "$2" = pashage ]; then 2421 The error should equal 'Error: extra/ already contains stale.age/' 2422 else 2423 The error should match pattern 'mv: *directory*' 2424 fi 2425 The result of function git_log should be successful 2426 The contents of file "${GITLOG}" should equal "$(setup_log)" 2427 End 2428 End 2429 2430 Describe 'cp' 2431 It 'copies a file without reencrypting' 2432 Skip if 'pass(age) needs bash' check_skip $2 2433 When run script $1 cp subdir/file subdir/copy 2434 The status should be success 2435 The error should be blank 2436 file_contents() { %text:expand 2437 #|${1}Recipient:myself 2438 #|${1}:p4ssw0rd 2439 } 2440 The contents of file "${PREFIX}/subdir/copy.$3" \ 2441 should equal "$(file_contents "$3")" 2442 expected_log() { 2443 if [ "$2" = pashage ]; then 2444 %putsn 'Copy subdir/file.age to subdir/copy.age' 2445 else 2446 %putsn 'Copy subdir/file to subdir/copy.' 2447 fi 2448 %text:expand 2449 #| 2450 #| subdir/copy.$1 | 2 ++ 2451 #| 1 file changed, 2 insertions(+) 2452 setup_log 2453 } 2454 The result of function git_log should be successful 2455 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2456 End 2457 2458 It 'fails to copy a file named like a flag without escape' 2459 Skip if 'pass(age) needs bash' check_skip $2 2460 When run script $1 cp -g safe-name 2461 The status should equal 1 2462 The output should be blank 2463 The error should not be blank 2464 The error should include 'Usage:' 2465 The contents of file "${GITLOG}" should equal "$(setup_log)" 2466 End 2467 2468 It 'copies a file named like a flag' 2469 Skip if 'pass(age) needs bash' check_skip $2 2470 When run script $1 cp -- -g -h 2471 The status should be success 2472 The error should be blank 2473 file_contents() { %text:expand 2474 #|${1}Recipient:myself 2475 #|${1}:-- 2476 } 2477 The contents of file "${PREFIX}/-h.$3" \ 2478 should equal "$(file_contents "$3")" 2479 expected_log() { 2480 if [ "$2" = pashage ]; then 2481 %putsn 'Copy -g.age to -h.age' 2482 else 2483 %putsn 'Copy -g to -h.' 2484 fi 2485 %text:expand 2486 #| 2487 #| -h.$1 | 2 ++ 2488 #| 1 file changed, 2 insertions(+) 2489 setup_log 2490 } 2491 The result of function git_log should be successful 2492 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2493 End 2494 2495 It 'reencrypts a copied file' 2496 Skip if 'pass(age) needs bash' check_skip $2 2497 When run script $1 cp subdir/file shared/copy 2498 The status should be success 2499 The error should be blank 2500 file_contents() { %text:expand 2501 #|${1}Recipient:myself 2502 #|${1}Recipient:friend 2503 #|${1}:p4ssw0rd 2504 } 2505 The contents of file "${PREFIX}/shared/copy.$3" \ 2506 should equal "$(file_contents "$3")" 2507 expected_log() { 2508 if [ "$2" = pashage ]; then 2509 %putsn 'Copy subdir/file.age to shared/copy.age' 2510 else 2511 %putsn 'Copy subdir/file to shared/copy.' 2512 fi 2513 %text:expand 2514 #| 2515 #| shared/copy.$1 | 3 +++ 2516 #| 1 file changed, 3 insertions(+) 2517 setup_log 2518 } 2519 The result of function git_log should be successful 2520 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2521 End 2522 2523 It 'copies an unencrypted file without reencrypting it' 2524 Skip if 'pass(age) needs bash' check_skip $2 2525 When run script $1 cp y.txt shared 2526 The status should be success 2527 The error should be blank 2528 file_contents() { %text 2529 #|Unencrypted line 1 2530 #|Unencrypted line 2 2531 #|Unencrypted line 3 2532 } 2533 The contents of file "${PREFIX}/shared/y.txt" \ 2534 should equal "$(file_contents)" 2535 expected_log() { 2536 if [ "$2" = pashage ]; then 2537 %putsn 'Copy y.txt to shared/y.txt' 2538 else 2539 %putsn 'Copy y.txt to shared.' 2540 fi 2541 %text 2542 #| 2543 #| shared/y.txt | 3 +++ 2544 #| 1 file changed, 3 insertions(+) 2545 setup_log 2546 } 2547 The result of function git_log should be successful 2548 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2549 End 2550 2551 It 'reencrypts relevant files in a copied directory' 2552 Skip if 'pass(age) needs bash' check_skip $2 2553 When run script $1 cp subdir shared/ 2554 The status should be success 2555 The error should be blank 2556 file_contents() { %text:expand 2557 #|${1}Recipient:myself 2558 #|${1}Recipient:friend 2559 #|${1}:p4ssw0rd 2560 } 2561 The contents of file "${PREFIX}/shared/subdir/file.$3" \ 2562 should equal "$(file_contents "$3")" 2563 expected_log() { 2564 if [ "$2" = pashage ]; then 2565 %putsn 'Copy subdir/ to shared/subdir/' 2566 else 2567 %putsn 'Copy subdir to shared/.' 2568 fi 2569 if [ "$1" = age ]; then 2570 %text:expand 2571 #| 2572 #| shared/subdir/file.age | 3 +++ 2573 #| shared/subdir/file.gpg | 2 ++ 2574 #| 2 files changed, 5 insertions(+) 2575 else 2576 %text:expand 2577 #| 2578 #| shared/subdir/file.age | 2 ++ 2579 #| shared/subdir/file.gpg | 3 +++ 2580 #| 2 files changed, 5 insertions(+) 2581 fi 2582 setup_log 2583 } 2584 The result of function git_log should be successful 2585 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2586 End 2587 2588 It 'copies a file into a new directory' 2589 Skip if 'pass(age) needs bash' check_skip $2 2590 When run script $1 cp subdir/file new-subdir/ 2591 The status should be success 2592 The error should be blank 2593 file_contents() { %text:expand 2594 #|${1}Recipient:myself 2595 #|${1}:p4ssw0rd 2596 } 2597 The contents of file "${PREFIX}/new-subdir/file.$3" \ 2598 should equal "$(file_contents "$3")" 2599 expected_log() { 2600 if [ "$2" = pashage ]; then 2601 %putsn 'Copy subdir/file.age to new-subdir/file.age' 2602 else 2603 %putsn 'Copy subdir/file to new-subdir/.' 2604 fi 2605 %text:expand 2606 #| 2607 #| new-subdir/file.$1 | 2 ++ 2608 #| 1 file changed, 2 insertions(+) 2609 setup_log 2610 } 2611 The result of function git_log should be successful 2612 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2613 End 2614 2615 It 'fails to copy a non-existent file' 2616 Skip if 'pass(age) needs bash' check_skip $2 2617 When run script $1 cp non-existent-file new-name 2618 The status should equal 1 2619 The error should \ 2620 equal 'Error: non-existent-file is not in the password store.' 2621 The result of function git_log should be successful 2622 The contents of file "${GITLOG}" should equal "$(setup_log)" 2623 End 2624 2625 It 'copies a directory with recipients' 2626 Skip if 'pass(age) needs bash' check_skip $2 2627 When run script $1 cp fluff filler 2628 The status should be success 2629 The error should be blank 2630 The directory "${PREFIX}/filler" should be exist 2631 expected_log() { 2632 if [ "$2" = pashage ]; then 2633 %putsn 'Copy fluff/ to filler/' 2634 else 2635 %putsn 'Copy fluff to filler.' 2636 fi 2637 %text:expand 2638 #| 2639 #| filler/.age-recipients | 2 ++ 2640 #| filler/.gpg-id | 2 ++ 2641 #| filler/one.age | 3 +++ 2642 #| filler/one.gpg | 3 +++ 2643 #| filler/three.age | 5 +++++ 2644 #| filler/three.gpg | 5 +++++ 2645 #| filler/two.age | 4 ++++ 2646 #| filler/two.gpg | 4 ++++ 2647 #| 8 files changed, 28 insertions(+) 2648 setup_log 2649 } 2650 The result of function git_log should be successful 2651 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2652 End 2653 2654 It 'copies a directory without recipients' 2655 Skip if 'pass(age) needs bash' check_skip $2 2656 When run script $1 cp subdir newdir 2657 The status should be success 2658 The error should be blank 2659 file_contents() { %text:expand 2660 #|${1}Recipient:myself 2661 #|${1}:p4ssw0rd 2662 } 2663 The contents of file "${PREFIX}/newdir/file.$3" \ 2664 should equal "$(file_contents "$3")" 2665 expected_log() { 2666 if [ "$2" = pashage ]; then 2667 %putsn 'Copy subdir/ to newdir/' 2668 else 2669 %putsn 'Copy subdir to newdir.' 2670 fi 2671 %text:expand 2672 #| 2673 #| newdir/file.age | 2 ++ 2674 #| newdir/file.gpg | 2 ++ 2675 #| 2 files changed, 4 insertions(+) 2676 setup_log 2677 } 2678 The result of function git_log should be successful 2679 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2680 End 2681 2682 It 'overwrites an existing file when forced' 2683 Skip if 'pass(age) needs bash' check_skip $2 2684 When run script $1 cp -f fluff/two fluff/one 2685 The status should be success 2686 file_contents() { %text:expand 2687 #|${1}Recipient:master 2688 #|${1}Recipient:myself 2689 #|${1}:2-password 2690 #|${1}:URL: https://example.com/login 2691 } 2692 The contents of file "${PREFIX}/fluff/one.$3" \ 2693 should equal "$(file_contents "$3")" 2694 expected_log() { 2695 if [ "$2" = pashage ]; then 2696 %putsn 'Copy fluff/two.age to fluff/one.age' 2697 else 2698 %putsn 'Copy fluff/two to fluff/one.' 2699 fi 2700 %text:expand 2701 #| 2702 #| fluff/one.$1 | 3 ++- 2703 #| 1 file changed, 2 insertions(+), 1 deletion(-) 2704 setup_log 2705 } 2706 The result of function git_log should be successful 2707 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2708 End 2709 2710 It 'overwrites collisions when copying recursively and forcefully' 2711 Skip if 'pass(age) needs bash' check_skip $2 2712 When run script $1 cp -f subdir/ extra/ 2713 The status should be success 2714 expected_log() { 2715 if [ "$2" = pashage ]; then 2716 %putsn 'Copy subdir/ to extra/subdir/' 2717 else 2718 %putsn 'Copy subdir/ to extra/.' 2719 fi 2720 %text:expand 2721 #| 2722 #| extra/subdir/file.age | 2 +- 2723 #| extra/subdir/file.gpg | 2 +- 2724 #| 2 files changed, 2 insertions(+), 2 deletions(-) 2725 setup_log 2726 } 2727 The result of function git_log should be successful 2728 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2729 End 2730 2731 It 'copies a file having an ambiguous name without suffix' 2732 Skip if 'pass(age) needs bash' check_skip $2 2733 When run script $1 cp extra new 2734 The status should be success 2735 file_contents() { %text:expand 2736 #|${1}Recipient:myself 2737 #|${1}:ambiguous 2738 } 2739 The contents of file "${PREFIX}/new.$3" \ 2740 should equal "$(file_contents "$3")" 2741 expected_log() { 2742 if [ "$2" = pashage ]; then 2743 %putsn 'Copy extra.age to new.age' 2744 else 2745 %putsn 'Copy extra to new.' 2746 fi 2747 %text:expand 2748 #| 2749 #| new.$1 | 2 ++ 2750 #| 1 file changed, 2 insertions(+) 2751 setup_log 2752 } 2753 The result of function git_log should be successful 2754 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2755 End 2756 2757 It 'copies a directory having an ambiguous name with `/` suffix' 2758 Skip if 'pass(age) needs bash' check_skip $2 2759 When run script $1 cp extra/ new 2760 The status should be success 2761 file_contents() { %text:expand 2762 #|${1}Recipient:myself 2763 #|${1}:Pa55worD 2764 } 2765 The contents of file "${PREFIX}/new/subdir/file.$3" \ 2766 should equal "$(file_contents $3)" 2767 expected_log() { 2768 if [ "$2" = pashage ]; then 2769 %putsn 'Copy extra/ to new/' 2770 else 2771 %putsn 'Copy extra/ to new.' 2772 fi 2773 %text:expand 2774 #| 2775 #| new/subdir/file.age | 2 ++ 2776 #| new/subdir/file.gpg | 2 ++ 2777 #| 2 files changed, 4 insertions(+) 2778 setup_log 2779 } 2780 The result of function git_log should be successful 2781 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2782 End 2783 2784 It 'copies a file to a directory having an ambiguous name without suffix' 2785 Skip if 'pass(age) needs bash' check_skip $2 2786 When run script $1 cp subdir/file extra 2787 The status should be success 2788 file_contents() { %text:expand 2789 #|${1}Recipient:myself 2790 #|${1}:p4ssw0rd 2791 } 2792 The contents of file "${PREFIX}/extra/file.$3" \ 2793 should equal "$(file_contents "$3")" 2794 expected_log() { 2795 if [ "$2" = pashage ]; then 2796 %putsn "Copy subdir/file.$1 to extra/file.$1" 2797 else 2798 %putsn 'Copy subdir/file to extra.' 2799 fi 2800 %text:expand 2801 #| 2802 #| extra/file.$1 | 2 ++ 2803 #| 1 file changed, 2 insertions(+) 2804 setup_log 2805 } 2806 The result of function git_log should be successful 2807 The contents of file "${GITLOG}" should equal "$(expected_log $3 $2)" 2808 End 2809 2810 It 'displays usage when called without argument' 2811 Skip if 'pass(age) needs bash' check_skip $2 2812 When run script $1 copy 2813 The status should equal 1 2814 The output should be blank 2815 The error should include 'Usage:' 2816 The error should include ' copy ' 2817 The result of function git_log should be successful 2818 The contents of file "${GITLOG}" should equal "$(setup_log)" 2819 End 2820 2821 It 'fails to copy a non-existent directory' 2822 Skip if 'pass(age) considers "stale/" as the file "stale"' \ 2823 [ ! $2 = pashage ] 2824 When run script $1 cp stale/ new-name 2825 The status should equal 1 2826 The error should equal 'Error: stale/ is not in the password store.' 2827 The directory "${PREFIX}/new-name" should not be exist 2828 The file "${PREFIX}/new-name.age" should not be exist 2829 The file "${PREFIX}/new-name.gpg" should not be exist 2830 The result of function git_log should be successful 2831 The contents of file "${GITLOG}" should equal "$(setup_log)" 2832 End 2833 2834 It 'fails to copy a directory into a file masquerading as a directory' 2835 Skip if 'pass(age) needs bash' check_skip $2 2836 When run script $1 cp subdir y.txt/ 2837 The status should equal 1 2838 The error should include 'y.txt is not a directory' 2839 The result of function git_log should be successful 2840 The contents of file "${GITLOG}" should equal "$(setup_log)" 2841 End 2842 2843 It 'rejects a source path containing ..' 2844 Skip if 'pass(age) needs bash' check_skip $2 2845 When run script $1 cp fluff/../stale subdir/ 2846 The status should equal 1 2847 The output should be blank 2848 The error should include 'sneaky' 2849 The file "${PREFIX}/subdir/stale.age" should not be exist 2850 The file "${PREFIX}/subdir/stale.gpg" should not be exist 2851 The result of function git_log should be successful 2852 The contents of file "${GITLOG}" should equal "$(setup_log)" 2853 End 2854 2855 It 'rejects a destination path containing ..' 2856 Skip if 'pass(age) needs bash' check_skip $2 2857 When run script $1 cp subdir/file extra/subdir/.. 2858 The status should equal 1 2859 The output should be blank 2860 The error should include 'sneaky' 2861 The file "${PREFIX}/extra/file.age" should not be exist 2862 The file "${PREFIX}/extra/file.gpg" should not be exist 2863 The result of function git_log should be successful 2864 The contents of file "${GITLOG}" should equal "$(setup_log)" 2865 End 2866 2867 extra_setup() { 2868 @mkdir "${PREFIX}/extra/stale.age" "${PREFIX}/extra/stale.gpg" 2869 } 2870 BeforeEach extra_setup 2871 2872 It 'fails to copy a file where a directory already exists' 2873 Skip if 'pass(age) needs bash' check_skip $2 2874 When run script $1 cp -f stale extra/ 2875 The status should equal 1 2876 if [ "$2" = pashage ]; then 2877 The error should equal 'Error: extra/ already contains stale.age/' 2878 else 2879 The error should match pattern 'cp: *directory*' 2880 fi 2881 The result of function git_log should be successful 2882 The contents of file "${GITLOG}" should equal "$(setup_log)" 2883 End 2884 End 2885 2886 Describe 'git' 2887 It 'transmits arguments to git' 2888 Skip if 'pass(age) needs bash' check_skip $2 2889 When run script $1 git log --format='%s' --stat 2890 The status should be success 2891 The output should equal "$(setup_log)" 2892 End 2893 2894 It 'displays git usage when called without argument' 2895 Skip if 'pass(age) needs bash' check_skip $2 2896 When run script $1 git 2897 The status should equal \ 2898 "$(if [ $2 = pashage ]; then echo 1; else echo 0; fi)" 2899 The output should include 'usage: git' 2900 The error should be blank 2901 The result of function git_log should be successful 2902 The contents of file "${GITLOG}" should equal "$(setup_log)" 2903 End 2904 2905 remove_git() { rm -rf "${PREFIX}/.git"; } 2906 BeforeEach remove_git 2907 2908 It 'fails without a git repository' 2909 Skip if 'pass(age) needs bash' check_skip $2 2910 When run script $1 git log 2911 The status should equal 1 2912 The output should be blank 2913 The error should match pattern \ 2914 'Error: the password store is not a git repository. Try "* git init".' 2915 End 2916 2917 It 're-initializes the git repository' 2918 Skip if 'pass(age) needs bash' check_skip $2 2919 When run script $1 git init -b trunk 2920 The status should be successful 2921 The output should start with \ 2922 "Initialized empty Git repository in ${PREFIX}/.git" 2923 The error should be blank 2924 The directory "${PREFIX}/.git" should be exist 2925 The file "${PREFIX}/.gitattributes" should be exist 2926 End 2927 End 2928 2929 Describe 'help' 2930 It 'displays a help text with supported commands' 2931 Skip if 'pass(age) needs bash' check_skip $2 2932 When run script $1 help 2933 The status should be success 2934 if ! [ $2 = passage ]; then 2935 The output should include ' init ' 2936 fi 2937 The output should include ' find ' 2938 The output should include ' [show] ' 2939 The output should include ' grep ' 2940 The output should include ' insert ' 2941 The output should include ' edit ' 2942 The output should include ' generate ' 2943 The output should include ' git ' 2944 The output should include ' help' 2945 The output should include ' version' 2946 End 2947 End 2948 2949 Describe 'version' 2950 It 'displays a version box' 2951 Skip if 'pass(age) needs bash' check_skip $2 2952 When run script $1 version 2953 The status should be success 2954 The output should include "$2:" 2955 The output should match pattern "*v[0-9].[0-9].[0-9]*" 2956 The output should include 'password manager' 2957 The output should start with '=============' 2958 The output should end with '=============' 2959 End 2960 End 2961 2962 Describe 'working outside of a repository:' 2963 REF_PREFIX="${SHELLSPEC_WORKDIR}/ref" 2964 CHANGE_FILE="${SHELLSPEC_WORKDIR}/changes.diff" 2965 make_gitless() { 2966 @rm -rf "${PREFIX}/.git" 2967 @cp -r "${PREFIX}" "${REF_PREFIX}" 2968 } 2969 clean_gitless() { 2970 @rm -rf "${REF_PREFIX}" "${CHANGE_FILE}" 2971 } 2972 BeforeEach make_gitless 2973 AfterEach clean_gitless 2974 2975 check_changes() { 2976 (cd "${SHELLSPEC_WORKDIR}" && @diff -r ref store ||true)>"${CHANGE_FILE}" 2977 } 2978 2979 Example 'init' 2980 Skip if 'pass(age) needs bash' check_skip $2 2981 Skip if 'passage has no init' [ "$2" = passage ] 2982 When run script $1 init 'new-id' 2983 The error should be blank 2984 The status should be success 2985 The output should include 'Password store' 2986 changes() { 2987 %text:expand 2988 #|diff -r ref/-g.$1 store/-g.$1 2989 #|1c1 2990 #|< $1Recipient:myself 2991 #|--- 2992 #|> $1Recipient:new-id 2993 if [ "$1" = age ]; then 2994 %putsn 'Only in store: .age-recipients' 2995 else 2996 %text 2997 #|diff -r ref/.gpg-id store/.gpg-id 2998 #|1c1 2999 #|< myself 3000 #|--- 3001 #|> new-id 3002 fi 3003 %text:expand 3004 #|diff -r ref/extra/subdir/file.$1 store/extra/subdir/file.$1 3005 #|1c1 3006 #|< $1Recipient:myself 3007 #|--- 3008 #|> $1Recipient:new-id 3009 #|diff -r ref/extra.$1 store/extra.$1 3010 #|1c1 3011 #|< $1Recipient:myself 3012 #|--- 3013 #|> $1Recipient:new-id 3014 #|diff -r ref/stale.$1 store/stale.$1 3015 #|1,2c1 3016 #|< $1Recipient:master 3017 #|< $1Recipient:myself 3018 #|--- 3019 #|> $1Recipient:new-id 3020 #|diff -r ref/subdir/file.$1 store/subdir/file.$1 3021 #|1c1 3022 #|< $1Recipient:myself 3023 #|--- 3024 #|> $1Recipient:new-id 3025 } 3026 The directory "${PREFIX}/.git" should not be exist 3027 The result of function check_changes should be successful 3028 The contents of file "${CHANGE_FILE}" should equal "$(changes $3)" 3029 End 3030 3031 Example 'ls' 3032 Skip if 'pass(age) needs bash' check_skip $2 3033 When run script $1 ls subdir 3034 The status should be success 3035 The error should be blank 3036 The line 1 of output should include 'subdir' 3037 The line 2 of output should include 'file' 3038 The directory "${PREFIX}/.git" should not be exist 3039 The result of function check_changes should be successful 3040 The contents of file "${CHANGE_FILE}" should equal '' 3041 End 3042 3043 Example 'find' 3044 Skip if 'pass(age) needs bash' check_skip $2 3045 When run script $1 find o 3046 The status should be success 3047 The lines of output should equal 6 3048 The line 1 of output should match pattern 'Search *: o' 3049 The line 2 of output should include 'fluff' 3050 The line 3 of output should include 'one' 3051 The line 4 of output should include 'one' 3052 The line 5 of output should include 'two' 3053 The line 6 of output should include 'two' 3054 The directory "${PREFIX}/.git" should not be exist 3055 The result of function check_changes should be successful 3056 The contents of file "${CHANGE_FILE}" should equal '' 3057 End 3058 3059 Example 'show' 3060 Skip if 'pass(age) needs bash' check_skip $2 3061 When run script $1 show subdir/file 3062 The status should be success 3063 The output should equal 'p4ssw0rd' 3064 The error should be blank 3065 The directory "${PREFIX}/.git" should not be exist 3066 The result of function check_changes should be successful 3067 The contents of file "${CHANGE_FILE}" should equal '' 3068 End 3069 3070 Example 'grep' 3071 Skip if 'pass(age) needs bash' check_skip $2 3072 When run script $1 grep -i Com 3073 The status should be success 3074 The lines of output should equal 4 3075 The line 1 of output should include 'fluff' 3076 The output should include 'three' 3077 The line 2 of output should include 'https://example.' 3078 The line 3 of output should include 'fluff' 3079 The output should include 'two' 3080 The line 4 of output should include 'https://example.' 3081 The directory "${PREFIX}/.git" should not be exist 3082 The result of function check_changes should be successful 3083 The contents of file "${CHANGE_FILE}" should equal '' 3084 End 3085 3086 Example 'insert' 3087 Skip if 'pass(age) needs bash' check_skip $2 3088 Data 3089 #|password 3090 #|Username: tester 3091 #|URL: https://example.com/login 3092 End 3093 When run script $1 insert -m rootpass 3094 The status should be success 3095 The output should include 'rootpass' 3096 The error should be blank 3097 expected_file() { %text:expand 3098 #|$1Recipient:myself 3099 #|$1:password 3100 #|$1:Username: tester 3101 #|$1:URL: https://example.com/login 3102 } 3103 The contents of file "${PREFIX}/rootpass.$3" should \ 3104 equal "$(expected_file $3)" 3105 The directory "${PREFIX}/.git" should not be exist 3106 The result of function check_changes should be successful 3107 The contents of file "${CHANGE_FILE}" should \ 3108 equal "Only in store: rootpass.$3" 3109 End 3110 3111 Example 'edit' 3112 EDITOR=ed 3113 TERM=dumb 3114 Skip if 'pass(age) needs bash' check_skip $2 3115 Data 3116 #|2i 3117 #|New line 3118 #|. 3119 #|wq 3120 End 3121 When run script $1 edit fluff/two 3122 The status should be success 3123 The error should be blank 3124 changes() { %text:expand 3125 #|diff -r ref/fluff/two.$1 store/fluff/two.$1 3126 #|3a4 3127 #|> $1:New line 3128 } 3129 The directory "${PREFIX}/.git" should not be exist 3130 The result of function check_changes should be successful 3131 The contents of file "${CHANGE_FILE}" should equal "$(changes $3)" 3132 End 3133 3134 Example 'generate' 3135 Skip if 'pass(age) needs bash' check_skip $2 3136 When run script $1 generate newfile 3137 The status should be success 3138 The output should include 'The generated password for' 3139 The file "${PREFIX}/newfile.$3" should be exist 3140 The lines of contents of file "${PREFIX}/newfile.$3" should equal 2 3141 The line 1 of contents of file "${PREFIX}/newfile.$3" should \ 3142 equal "$3Recipient:myself" 3143 The output should include "$(@sed -n "2s/$3://p" "${PREFIX}/newfile.$3")" 3144 The directory "${PREFIX}/.git" should not be exist 3145 The result of function check_changes should be successful 3146 The contents of file "${CHANGE_FILE}" should \ 3147 equal "Only in store: newfile.$3" 3148 End 3149 3150 Example 'rm' 3151 Skip if 'pass(age) needs bash' check_skip $2 3152 When run script $1 rm -f subdir/file 3153 The status should be success 3154 The output should include 'subdir/file' 3155 The error should be blank 3156 The file "${PREFIX}/subdir/file.$3" should not be exist 3157 The directory "${PREFIX}/.git" should not be exist 3158 The result of function check_changes should be successful 3159 The contents of file "${CHANGE_FILE}" should \ 3160 equal "Only in ref/subdir: file.$3" 3161 End 3162 3163 Example 'mv' 3164 Skip if 'pass(age) needs bash' check_skip $2 3165 When run script $1 mv subdir/file subdir/renamed 3166 The status should be success 3167 The error should be blank 3168 The file "${PREFIX}/subdir/file.$3" should not be exist 3169 file_contents() { %text:expand 3170 #|${1}Recipient:myself 3171 #|${1}:p4ssw0rd 3172 } 3173 The contents of file "${PREFIX}/subdir/renamed.$3" \ 3174 should equal "$(file_contents "$3")" 3175 changes() { %text:expand 3176 #|Only in ref/subdir: file.$1 3177 #|Only in store/subdir: renamed.$1 3178 } 3179 The directory "${PREFIX}/.git" should not be exist 3180 The result of function check_changes should be successful 3181 The contents of file "${CHANGE_FILE}" should equal "$(changes $3)" 3182 End 3183 3184 Example 'cp' 3185 Skip if 'pass(age) needs bash' check_skip $2 3186 When run script $1 cp subdir/file copy 3187 The status should be success 3188 The error should be blank 3189 file_contents() { %text:expand 3190 #|${1}Recipient:myself 3191 #|${1}:p4ssw0rd 3192 } 3193 The contents of file "${PREFIX}/copy.$3" \ 3194 should equal "$(file_contents "$3")" 3195 The directory "${PREFIX}/.git" should not be exist 3196 The result of function check_changes should be successful 3197 The contents of file "${CHANGE_FILE}" should \ 3198 equal "Only in store: copy.$3" 3199 End 3200 3201 Example 'help' 3202 Skip if 'pass(age) needs bash' check_skip $2 3203 When run script $1 help 3204 The status should be success 3205 if ! [ $2 = passage ]; then 3206 The output should include ' init ' 3207 fi 3208 The output should include ' find ' 3209 The output should include ' [show] ' 3210 The output should include ' grep ' 3211 The output should include ' insert ' 3212 The output should include ' edit ' 3213 The output should include ' generate ' 3214 The output should include ' git ' 3215 The output should include ' help' 3216 The output should include ' version' 3217 The directory "${PREFIX}/.git" should not be exist 3218 The result of function check_changes should be successful 3219 The contents of file "${CHANGE_FILE}" should equal '' 3220 End 3221 3222 Example 'version' 3223 Skip if 'pass(age) needs bash' check_skip $2 3224 When run script $1 version 3225 The status should be success 3226 The output should include "$2:" 3227 The output should match pattern "*v[0-9].[0-9].[0-9]*" 3228 The output should include 'password manager' 3229 The output should start with '=============' 3230 The output should end with '=============' 3231 The directory "${PREFIX}/.git" should not be exist 3232 The result of function check_changes should be successful 3233 The contents of file "${CHANGE_FILE}" should equal '' 3234 End 3235 End 3236 End