diff --git a/tests/test_crypt.bats b/tests/test_crypt.bats index d4b4ede..cf5875e 100755 --- a/tests/test_crypt.bats +++ b/tests/test_crypt.bats @@ -135,6 +135,40 @@ SECRET_CONTENT_ENC="U2FsdGVkX1/6ilR0PmJpAyCF7iG3+k4aBwbgVd48WaQXznsg42nXbQrlWsf/ rm "$FILENAME" } +@test "crypt: challenging file name with special characters is included in --list" { + FILENAME='"Difficult file name""")))(((][][].secret' + SECRET_CONTENT_ENC="U2FsdGVkX18wtFI6Ydnw7t7uUCKUMK3KeqExy6bC9mGNx1BjpXLbaOH3mxOtoPjn" + + # It's too hard to use `encrypt_named_file` function here due to difficult + # filename quoting, so do similar steps manually + echo "$SECRET_CONTENT" > "$FILENAME" + echo "*.secret filter=crypt diff=crypt merge=crypt" >> .gitattributes + git add .gitattributes "${FILENAME}" + run git commit -m "Encrypt file \"$FILENAME\"" + + # Working copy is decrypted + run cat "$FILENAME" + [ "$status" -eq 0 ] + [ "${lines[0]}" = "$SECRET_CONTENT" ] + + # Git internal copy is encrypted + run git show HEAD:"\"Difficult file name\"\"\")))(((][][].secret" --no-textconv + [ "$status" -eq 0 ] + [ "${lines[0]}" = "$SECRET_CONTENT_ENC" ] + + # git ls-crypt lists encrypted file + run git ls-crypt + [ "$status" -eq 0 ] + [[ "${output}" = *"$FILENAME" ]] + + # transcrypt --list lists encrypted file" + run ../transcrypt --list + [ "$status" -eq 0 ] + [[ "${output}" = *"$FILENAME" ]] + + rm "$FILENAME" +} + @test "crypt: handle very small file" { FILENAME="small file.txt" SECRET_CONTENT="sh" diff --git a/transcrypt b/transcrypt index 8280058..3fdfe7f 100755 --- a/transcrypt +++ b/transcrypt @@ -177,19 +177,23 @@ _list_encrypted_files() { # backslash and control characters (eval) which are part of the output # regardless of core.quotePath=false as per # https://git-scm.com/docs/git-config#Documentation/git-config.txt-corequotePath - git -c core.quotePath=false ls-files -z | tr '\0' '\n' | - git -c core.quotePath=false check-attr filter --stdin 2>/dev/null | + git -c core.quotePath=false ls-files -z | + git -c core.quotePath=false check-attr filter -z --stdin 2>/dev/null | + # Split null-delimited list of filename + filter entries to be one line + # per file with space delimiters in that line by replacing every third + # null character with newline and the rest with a space + awk -v RS='\x00' 'NR % 3 == 0 {printf "%s\n", $0} NR % 3 != 0 {printf "%s ", $0}' | { # Only output names of encrypted files matching the context, either # strictly (if $1 = "true") or loosely (if $1 is false or unset) if [[ "$strict_context" == "true" ]]; then - grep ": filter: crypt${CONTEXT_CRYPT_SUFFIX:-}$" || true + grep " filter crypt${CONTEXT_CRYPT_SUFFIX:-}$" || true else - grep ": filter: crypt${CONTEXT_CRYPT_SUFFIX:-}.*$" || true + grep " filter crypt${CONTEXT_CRYPT_SUFFIX:-}.*$" || true fi } | - sed "s|: filter: crypt${CONTEXT_CRYPT_SUFFIX:-}.*||" | - while read -r file; do eval "echo $file"; done + sed "s| filter crypt${CONTEXT_CRYPT_SUFFIX:-}.*||" | + while read -r filename; do eval 'echo $filename'; done } # Detect OpenSSL major version 3 or later which requires a compatibility