Skip to content

Commit 4d715ac

Browse files
j6tgitster
authored andcommitted
Windows: a test_cmp that is agnostic to random LF <> CRLF conversions
In a number of tests, output that was produced by a shell script is compared to expected output using test_cmp. Unfortunately, the MSYS bash-- when invoked via git, such as in hooks--converts LF to CRLF on output (as produced by echo and printf), which leads to many false positives. Implements a diff tool that undoes the converted CRLF. To avoid that sub-processes are spawned (which is very slow on Windows), the tool is implemented as a shell function. Diff is invoked as usual only when a difference is detected by the shell code. Signed-off-by: Johannes Sixt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ce1a047 commit 4d715ac

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

t/test-lib-functions.sh

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,3 +710,69 @@ test_ln_s_add () {
710710
git update-index --add --cacheinfo 120000 $ln_s_obj "$2"
711711
fi
712712
}
713+
714+
# The following mingw_* functions obey POSIX shell syntax, but are actually
715+
# bash scripts, and are meant to be used only with bash on Windows.
716+
717+
# A test_cmp function that treats LF and CRLF equal and avoids to fork
718+
# diff when possible.
719+
mingw_test_cmp () {
720+
# Read text into shell variables and compare them. If the results
721+
# are different, use regular diff to report the difference.
722+
local test_cmp_a= test_cmp_b=
723+
724+
# When text came from stdin (one argument is '-') we must feed it
725+
# to diff.
726+
local stdin_for_diff=
727+
728+
# Since it is difficult to detect the difference between an
729+
# empty input file and a failure to read the files, we go straight
730+
# to diff if one of the inputs is empty.
731+
if test -s "$1" && test -s "$2"
732+
then
733+
# regular case: both files non-empty
734+
mingw_read_file_strip_cr_ test_cmp_a <"$1"
735+
mingw_read_file_strip_cr_ test_cmp_b <"$2"
736+
elif test -s "$1" && test "$2" = -
737+
then
738+
# read 2nd file from stdin
739+
mingw_read_file_strip_cr_ test_cmp_a <"$1"
740+
mingw_read_file_strip_cr_ test_cmp_b
741+
stdin_for_diff='<<<"$test_cmp_b"'
742+
elif test "$1" = - && test -s "$2"
743+
then
744+
# read 1st file from stdin
745+
mingw_read_file_strip_cr_ test_cmp_a
746+
mingw_read_file_strip_cr_ test_cmp_b <"$2"
747+
stdin_for_diff='<<<"$test_cmp_a"'
748+
fi
749+
test -n "$test_cmp_a" &&
750+
test -n "$test_cmp_b" &&
751+
test "$test_cmp_a" = "$test_cmp_b" ||
752+
eval "diff -u \"\$@\" $stdin_for_diff"
753+
}
754+
755+
# $1 is the name of the shell variable to fill in
756+
mingw_read_file_strip_cr_ () {
757+
# Read line-wise using LF as the line separator
758+
# and use IFS to strip CR.
759+
local line
760+
while :
761+
do
762+
if IFS=$'\r' read -r -d $'\n' line
763+
then
764+
# good
765+
line=$line$'\n'
766+
else
767+
# we get here at EOF, but also if the last line
768+
# was not terminated by LF; in the latter case,
769+
# some text was read
770+
if test -z "$line"
771+
then
772+
# EOF, really
773+
break
774+
fi
775+
fi
776+
eval "$1=\$$1\$line"
777+
done
778+
}

t/test-lib.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ case $(uname -s) in
817817
test_set_prereq NOT_CYGWIN
818818
test_set_prereq SED_STRIPS_CR
819819
test_set_prereq GREP_STRIPS_CR
820+
GIT_TEST_CMP=mingw_test_cmp
820821
;;
821822
*CYGWIN*)
822823
test_set_prereq POSIXPERM

0 commit comments

Comments
 (0)