Files
git-mirror/t/t3902-quoted.sh
Patrick Steinhardt 0c8424c259 t: work around multibyte bug in quoted heredocs with Dash v0.5.13
When executing our test suite with Dash v0.5.13.2 one can observe
several test failures that all have the same symptoms: we have a quoted
heredoc that contains multibyte characters, but the final data does not
match what we actually wanted to write. One such example is in t0300,
where we see the diffs like the following:

  --- expect-stdout	2026-04-01 07:25:45.249919440 +0000
  +++ stdout	2026-04-01 07:25:45.254919509 +0000
  @@ -1,5 +1,5 @@
   protocol=https
   host=example.com
  -path=perú.git
  +path=perú.git
   username=foo
   password=bar

While seemingly the same, the data that we've written via the heredoc
contains some invisible bytes. The expected hex representation of the
string is:

  7065 72c3 ba2e 6769 74                 per...git

But what we actually get instead is this string:

  7065 7285 02c3 ba02 852e 6769 74       per.......git

What's important to note here is that the multibyte character exists in
both versions. But in the broken version we see that the bytes are
wrapped in a sequence of "85 02" and "02 85". This is the CTLMBCHAR byte
sequence of Dash, which it uses internally to quote multibyte sequences.

As it turns out, this bug was introduced in c5bf970 (expand: Add
multi-byte support to pmatch, 2024-06-02), which adds multibyte support
to more contexts of Dash. One of these contexts seems to be in heredocs,
and Dash _does_ correctly unquote these multibyte sequences when using
an unquoted heredoc. But the bug seems to be that this unquoting does
not happen in quoted heredocs, and the bug still exists on the latest
"master" branch.

For now, work around the bug by using unquoted heredocs instead.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-02 11:39:42 -07:00

155 lines
2.9 KiB
Bash
Executable File

#!/bin/sh
#
# Copyright (c) 2006 Junio C Hamano
#
test_description='quoted output'
. ./test-lib.sh
FN='濱野'
GN='純'
HT=' '
DQ='"'
test_have_prereq MINGW ||
echo foo 2>/dev/null > "Name and an${HT}HT"
if ! test -f "Name and an${HT}HT"
then
# FAT/NTFS does not allow tabs in filenames
skip_all='Your filesystem does not allow tabs in filenames'
test_done
fi
for_each_name () {
for name in \
Name "Name and a${LF}LF" "Name and an${HT}HT" "Name${DQ}" \
"$FN$HT$GN" "$FN$LF$GN" "$FN $GN" "$FN$GN" "$FN$DQ$GN" \
"With SP in it" "$FN/file"
do
eval "$1"
done
}
test_expect_success 'setup' '
mkdir "$FN" &&
for_each_name "echo initial >\"\$name\"" &&
git add . &&
git commit -q -m Initial &&
for_each_name "echo second >\"\$name\"" &&
git commit -a -m Second &&
for_each_name "echo modified >\"\$name\""
'
test_expect_success 'setup expected files' '
cat >expect.quoted <<\EOF &&
Name
"Name and a\nLF"
"Name and an\tHT"
"Name\""
With SP in it
"\346\277\261\351\207\216\t\347\264\224"
"\346\277\261\351\207\216\n\347\264\224"
"\346\277\261\351\207\216 \347\264\224"
"\346\277\261\351\207\216\"\347\264\224"
"\346\277\261\351\207\216/file"
"\346\277\261\351\207\216\347\264\224"
EOF
# NOTE: do not quote this heredoc, Dash 0.5.13 has a bug with heredocs
# that contain multibyte chars.
cat >expect.raw <<EOF
Name
"Name and a\\nLF"
"Name and an\\tHT"
"Name\\""
With SP in it
"濱野\\t純"
"濱野\\n純"
濱野 純
"濱野\\"純"
濱野/file
濱野純
EOF
'
test_expect_success 'check fully quoted output from ls-files' '
git ls-files >current && test_cmp expect.quoted current
'
test_expect_success 'check fully quoted output from diff-files' '
git diff --name-only >current &&
test_cmp expect.quoted current
'
test_expect_success 'check fully quoted output from diff-index' '
git diff --name-only HEAD >current &&
test_cmp expect.quoted current
'
test_expect_success 'check fully quoted output from diff-tree' '
git diff --name-only HEAD^ HEAD >current &&
test_cmp expect.quoted current
'
test_expect_success 'check fully quoted output from ls-tree' '
git ls-tree --name-only -r HEAD >current &&
test_cmp expect.quoted current
'
test_expect_success 'setting core.quotepath' '
git config --bool core.quotepath false
'
test_expect_success 'check fully quoted output from ls-files' '
git ls-files >current && test_cmp expect.raw current
'
test_expect_success 'check fully quoted output from diff-files' '
git diff --name-only >current &&
test_cmp expect.raw current
'
test_expect_success 'check fully quoted output from diff-index' '
git diff --name-only HEAD >current &&
test_cmp expect.raw current
'
test_expect_success 'check fully quoted output from diff-tree' '
git diff --name-only HEAD^ HEAD >current &&
test_cmp expect.raw current
'
test_expect_success 'check fully quoted output from ls-tree' '
git ls-tree --name-only -r HEAD >current &&
test_cmp expect.raw current
'
test_done