1#!/bin/sh
2
3test_description='CRLF conversion all combinations'
4
5. ./test-lib.sh
6
7compare_files () {
8	tr '\015\000' QN <"$1" >"$1".expect &&
9	tr '\015\000' QN <"$2" | tr -d 'Z' >"$2".actual &&
10	test_cmp "$1".expect "$2".actual &&
11	rm "$1".expect "$2".actual
12}
13
14compare_ws_file () {
15	pfx=$1
16	exp=$2.expect
17	act=$pfx.actual.$3
18	tr '\015\000abcdef0123456789' QN00000000000000000 <"$2" |
19		sed -e "s/0000*/$ZERO_OID/" >"$exp" &&
20	tr '\015\000abcdef0123456789' QN00000000000000000 <"$3" |
21		sed -e "s/0000*/$ZERO_OID/" >"$act" &&
22	test_cmp "$exp" "$act" &&
23	rm "$exp" "$act"
24}
25
26create_gitattributes () {
27	{
28		while test "$#" != 0
29		do
30			case "$1" in
31			auto)	 echo '*.txt text=auto' ;;
32			ident) echo '*.txt ident' ;;
33			text)	 echo '*.txt text' ;;
34			-text) echo '*.txt -text' ;;
35			crlf)  echo '*.txt eol=crlf' ;;
36			lf)    echo '*.txt eol=lf' ;;
37			"") ;;
38			*)
39				echo >&2 invalid attribute: "$1"
40				exit 1
41				;;
42			esac &&
43			shift
44		done
45	} >.gitattributes
46}
47
48# Create 2 sets of files:
49# The NNO files are "Not NOrmalized in the repo. We use CRLF_mix_LF and store
50#   it under different names for the different test cases, see ${pfx}
51#   Depending on .gitattributes they are normalized at the next commit (or not)
52# The MIX files have different contents in the repo.
53#   Depending on its contents, the "new safer autocrlf" may kick in.
54create_NNO_MIX_files () {
55	for crlf in false true input
56	do
57		for attr in "" auto text -text
58		do
59			for aeol in "" lf crlf
60			do
61				pfx=NNO_attr_${attr}_aeol_${aeol}_${crlf} &&
62				cp CRLF_mix_LF ${pfx}_LF.txt &&
63				cp CRLF_mix_LF ${pfx}_CRLF.txt &&
64				cp CRLF_mix_LF ${pfx}_CRLF_mix_LF.txt &&
65				cp CRLF_mix_LF ${pfx}_LF_mix_CR.txt &&
66				cp CRLF_mix_LF ${pfx}_CRLF_nul.txt &&
67				pfx=MIX_attr_${attr}_aeol_${aeol}_${crlf} &&
68				cp LF          ${pfx}_LF.txt &&
69				cp CRLF        ${pfx}_CRLF.txt &&
70				cp CRLF_mix_LF ${pfx}_CRLF_mix_LF.txt &&
71				cp LF_mix_CR   ${pfx}_LF_mix_CR.txt &&
72				cp CRLF_nul    ${pfx}_CRLF_nul.txt
73			done
74		done
75	done
76}
77
78check_warning () {
79	case "$1" in
80	LF_CRLF) echo "warning: LF will be replaced by CRLF" >"$2".expect ;;
81	CRLF_LF) echo "warning: CRLF will be replaced by LF" >"$2".expect ;;
82	'')	                                                 >"$2".expect ;;
83	*) echo >&2 "Illegal 1": "$1" ; return false ;;
84	esac
85	grep "will be replaced by" "$2" | sed -e "s/\(.*\) in [^ ]*$/\1/" | uniq  >"$2".actual
86	test_cmp "$2".expect "$2".actual
87}
88
89commit_check_warn () {
90	crlf=$1
91	attr=$2
92	lfname=$3
93	crlfname=$4
94	lfmixcrlf=$5
95	lfmixcr=$6
96	crlfnul=$7
97	pfx=crlf_${crlf}_attr_${attr}
98	create_gitattributes "$attr" &&
99	for f in LF CRLF LF_mix_CR CRLF_mix_LF LF_nul CRLF_nul
100	do
101		fname=${pfx}_$f.txt &&
102		cp $f $fname &&
103		git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err"
104	done &&
105	git commit -m "core.autocrlf $crlf" &&
106	check_warning "$lfname" ${pfx}_LF.err &&
107	check_warning "$crlfname" ${pfx}_CRLF.err &&
108	check_warning "$lfmixcrlf" ${pfx}_CRLF_mix_LF.err &&
109	check_warning "$lfmixcr" ${pfx}_LF_mix_CR.err &&
110	check_warning "$crlfnul" ${pfx}_CRLF_nul.err
111}
112
113commit_chk_wrnNNO () {
114	attr=$1 ; shift
115	aeol=$1 ; shift
116	crlf=$1 ; shift
117	lfwarn=$1 ; shift
118	crlfwarn=$1 ; shift
119	lfmixcrlf=$1 ; shift
120	lfmixcr=$1 ; shift
121	crlfnul=$1 ; shift
122	pfx=NNO_attr_${attr}_aeol_${aeol}_${crlf}
123	#Commit files on top of existing file
124	create_gitattributes "$attr" $aeol &&
125	for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
126	do
127		fname=${pfx}_$f.txt &&
128		cp $f $fname &&
129		printf Z >>"$fname" &&
130		git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err"
131	done
132
133	test_expect_success "commit NNO files crlf=$crlf attr=$attr LF" '
134		check_warning "$lfwarn" ${pfx}_LF.err
135	'
136	test_expect_success "commit NNO files attr=$attr aeol=$aeol crlf=$crlf CRLF" '
137		check_warning "$crlfwarn" ${pfx}_CRLF.err
138	'
139
140	test_expect_success "commit NNO files attr=$attr aeol=$aeol crlf=$crlf CRLF_mix_LF" '
141		check_warning "$lfmixcrlf" ${pfx}_CRLF_mix_LF.err
142	'
143
144	test_expect_success "commit NNO files attr=$attr aeol=$aeol crlf=$crlf LF_mix_cr" '
145		check_warning "$lfmixcr" ${pfx}_LF_mix_CR.err
146	'
147
148	test_expect_success "commit NNO files attr=$attr aeol=$aeol crlf=$crlf CRLF_nul" '
149		check_warning "$crlfnul" ${pfx}_CRLF_nul.err
150	'
151}
152
153# Commit a file with mixed line endings on top of different files
154# in the index. Check for warnings
155commit_MIX_chkwrn () {
156	attr=$1 ; shift
157	aeol=$1 ; shift
158	crlf=$1 ; shift
159	lfwarn=$1 ; shift
160	crlfwarn=$1 ; shift
161	lfmixcrlf=$1 ; shift
162	lfmixcr=$1 ; shift
163	crlfnul=$1 ; shift
164	pfx=MIX_attr_${attr}_aeol_${aeol}_${crlf}
165	#Commit file with CLRF_mix_LF on top of existing file
166	create_gitattributes "$attr" $aeol &&
167	for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
168	do
169		fname=${pfx}_$f.txt &&
170		cp CRLF_mix_LF $fname &&
171		printf Z >>"$fname" &&
172		git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err"
173	done
174
175	test_expect_success "commit file with mixed EOL onto LF crlf=$crlf attr=$attr" '
176		check_warning "$lfwarn" ${pfx}_LF.err
177	'
178	test_expect_success "commit file with mixed EOL onto CLRF attr=$attr aeol=$aeol crlf=$crlf" '
179		check_warning "$crlfwarn" ${pfx}_CRLF.err
180	'
181
182	test_expect_success "commit file with mixed EOL onto CRLF_mix_LF attr=$attr aeol=$aeol crlf=$crlf" '
183		check_warning "$lfmixcrlf" ${pfx}_CRLF_mix_LF.err
184	'
185
186	test_expect_success "commit file with mixed EOL onto LF_mix_cr attr=$attr aeol=$aeol crlf=$crlf " '
187		check_warning "$lfmixcr" ${pfx}_LF_mix_CR.err
188	'
189
190	test_expect_success "commit file with mixed EOL onto CRLF_nul attr=$attr aeol=$aeol crlf=$crlf" '
191		check_warning "$crlfnul" ${pfx}_CRLF_nul.err
192	'
193}
194
195
196stats_ascii () {
197	case "$1" in
198	LF)
199		echo lf
200		;;
201	CRLF)
202		echo crlf
203		;;
204	CRLF_mix_LF)
205		echo mixed
206		;;
207	LF_mix_CR|CRLF_nul|LF_nul|CRLF_mix_CR)
208		echo "-text"
209		;;
210	*)
211		echo error_invalid $1
212		;;
213	esac
214
215}
216
217
218# construct the attr/ returned by git ls-files --eol
219# Take none (=empty), one or two args
220# convert.c: eol=XX overrides text=auto
221attr_ascii () {
222	case $1,$2 in
223	-text,*)   echo "-text" ;;
224	text,)     echo "text" ;;
225	text,lf)   echo "text eol=lf" ;;
226	text,crlf) echo "text eol=crlf" ;;
227	auto,)     echo "text=auto" ;;
228	auto,lf)   echo "text=auto eol=lf" ;;
229	auto,crlf) echo "text=auto eol=crlf" ;;
230	lf,)       echo "text eol=lf" ;;
231	crlf,)     echo "text eol=crlf" ;;
232	,) echo "" ;;
233	*) echo invalid_attr "$1,$2" ;;
234	esac
235}
236
237check_files_in_repo () {
238	crlf=$1
239	attr=$2
240	lfname=$3
241	crlfname=$4
242	lfmixcrlf=$5
243	lfmixcr=$6
244	crlfnul=$7
245	pfx=crlf_${crlf}_attr_${attr}_ &&
246	compare_files $lfname ${pfx}LF.txt &&
247	compare_files $crlfname ${pfx}CRLF.txt &&
248	compare_files $lfmixcrlf ${pfx}CRLF_mix_LF.txt &&
249	compare_files $lfmixcr ${pfx}LF_mix_CR.txt &&
250	compare_files $crlfnul ${pfx}CRLF_nul.txt
251}
252
253check_in_repo_NNO () {
254	attr=$1 ; shift
255	aeol=$1 ; shift
256	crlf=$1 ; shift
257	lfname=$1 ; shift
258	crlfname=$1 ; shift
259	lfmixcrlf=$1 ; shift
260	lfmixcr=$1 ; shift
261	crlfnul=$1 ; shift
262	pfx=NNO_attr_${attr}_aeol_${aeol}_${crlf}
263	test_expect_success "compare_files $lfname ${pfx}_LF.txt" '
264		compare_files $lfname ${pfx}_LF.txt
265	'
266	test_expect_success "compare_files $crlfname ${pfx}_CRLF.txt" '
267		compare_files $crlfname ${pfx}_CRLF.txt
268	'
269	test_expect_success "compare_files $lfmixcrlf ${pfx}_CRLF_mix_LF.txt" '
270		compare_files $lfmixcrlf ${pfx}_CRLF_mix_LF.txt
271	'
272	test_expect_success "compare_files $lfmixcr ${pfx}_LF_mix_CR.txt" '
273		compare_files $lfmixcr ${pfx}_LF_mix_CR.txt
274	'
275	test_expect_success "compare_files $crlfnul ${pfx}_CRLF_nul.txt" '
276		compare_files $crlfnul ${pfx}_CRLF_nul.txt
277	'
278}
279
280checkout_files () {
281	attr=$1 ; shift
282	ident=$1; shift
283	aeol=$1 ; shift
284	crlf=$1 ; shift
285	ceol=$1 ; shift
286	lfname=$1 ; shift
287	crlfname=$1 ; shift
288	lfmixcrlf=$1 ; shift
289	lfmixcr=$1 ; shift
290	crlfnul=$1 ; shift
291	create_gitattributes "$attr" $ident $aeol &&
292	git config core.autocrlf $crlf &&
293	pfx=eol_${ceol}_crlf_${crlf}_attr_${attr}_ &&
294	for f in LF CRLF LF_mix_CR CRLF_mix_LF LF_nul
295	do
296		rm crlf_false_attr__$f.txt &&
297		if test -z "$ceol"; then
298			git checkout -- crlf_false_attr__$f.txt
299		else
300			git -c core.eol=$ceol checkout -- crlf_false_attr__$f.txt
301		fi
302	done
303
304	test_expect_success "ls-files --eol attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol" '
305		test_when_finished "rm expect actual" &&
306		sort <<-EOF >expect &&
307		i/crlf w/$(stats_ascii $crlfname) attr/$(attr_ascii $attr $aeol) crlf_false_attr__CRLF.txt
308		i/mixed w/$(stats_ascii $lfmixcrlf) attr/$(attr_ascii $attr $aeol) crlf_false_attr__CRLF_mix_LF.txt
309		i/lf w/$(stats_ascii $lfname) attr/$(attr_ascii $attr $aeol) crlf_false_attr__LF.txt
310		i/-text w/$(stats_ascii $lfmixcr) attr/$(attr_ascii $attr $aeol) crlf_false_attr__LF_mix_CR.txt
311		i/-text w/$(stats_ascii $crlfnul) attr/$(attr_ascii $attr $aeol) crlf_false_attr__CRLF_nul.txt
312		i/-text w/$(stats_ascii $crlfnul) attr/$(attr_ascii $attr $aeol) crlf_false_attr__LF_nul.txt
313		EOF
314		git ls-files --eol crlf_false_attr__* |
315		sed -e "s/	/ /g" -e "s/  */ /g" |
316		sort >actual &&
317		test_cmp expect actual
318	'
319	test_expect_success "checkout attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol file=LF" "
320		compare_ws_file $pfx $lfname    crlf_false_attr__LF.txt
321	"
322	test_expect_success "checkout attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol file=CRLF" "
323		compare_ws_file $pfx $crlfname  crlf_false_attr__CRLF.txt
324	"
325	test_expect_success "checkout attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol file=CRLF_mix_LF" "
326		compare_ws_file $pfx $lfmixcrlf crlf_false_attr__CRLF_mix_LF.txt
327	"
328	test_expect_success "checkout attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol file=LF_mix_CR" "
329		compare_ws_file $pfx $lfmixcr   crlf_false_attr__LF_mix_CR.txt
330	"
331	test_expect_success "checkout attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol file=LF_nul" "
332		compare_ws_file $pfx $crlfnul   crlf_false_attr__LF_nul.txt
333	"
334}
335
336# Test control characters
337# NUL SOH CR EOF==^Z
338test_expect_success 'ls-files --eol -o Text/Binary' '
339	test_when_finished "rm expect actual TeBi_*" &&
340	STRT=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA &&
341	STR=$STRT$STRT$STRT$STRT &&
342	printf "${STR}BBB\001" >TeBi_127_S &&
343	printf "${STR}BBBB\001">TeBi_128_S &&
344	printf "${STR}BBB\032" >TeBi_127_E &&
345	printf "\032${STR}BBB" >TeBi_E_127 &&
346	printf "${STR}BBBB\000">TeBi_128_N &&
347	printf "${STR}BBB\012">TeBi_128_L &&
348	printf "${STR}BBB\015">TeBi_127_C &&
349	printf "${STR}BB\015\012" >TeBi_126_CL &&
350	printf "${STR}BB\015\012\015" >TeBi_126_CLC &&
351	sort <<-\EOF >expect &&
352	i/ w/-text TeBi_127_S
353	i/ w/none TeBi_128_S
354	i/ w/none TeBi_127_E
355	i/ w/-text TeBi_E_127
356	i/ w/-text TeBi_128_N
357	i/ w/lf TeBi_128_L
358	i/ w/-text TeBi_127_C
359	i/ w/crlf TeBi_126_CL
360	i/ w/-text TeBi_126_CLC
361	EOF
362	git ls-files --eol -o |
363	sed -n -e "/TeBi_/{s!attr/[	]*!!g
364	s!	! !g
365	s!  *! !g
366	p
367	}" | sort >actual &&
368	test_cmp expect actual
369'
370
371test_expect_success 'setup main' '
372	echo >.gitattributes &&
373	git checkout -b main &&
374	git add .gitattributes &&
375	git commit -m "add .gitattributes" . &&
376	printf "\$Id: 0000000000000000000000000000000000000000 \$\nLINEONE\nLINETWO\nLINETHREE"     >LF &&
377	printf "\$Id: 0000000000000000000000000000000000000000 \$\r\nLINEONE\r\nLINETWO\r\nLINETHREE" >CRLF &&
378	printf "\$Id: 0000000000000000000000000000000000000000 \$\nLINEONE\r\nLINETWO\nLINETHREE"   >CRLF_mix_LF &&
379	printf "\$Id: 0000000000000000000000000000000000000000 \$\nLINEONE\nLINETWO\rLINETHREE"     >LF_mix_CR &&
380	printf "\$Id: 0000000000000000000000000000000000000000 \$\r\nLINEONE\r\nLINETWO\rLINETHREE"   >CRLF_mix_CR &&
381	printf "\$Id: 0000000000000000000000000000000000000000 \$\r\nLINEONEQ\r\nLINETWO\r\nLINETHREE" | q_to_nul >CRLF_nul &&
382	printf "\$Id: 0000000000000000000000000000000000000000 \$\nLINEONEQ\nLINETWO\nLINETHREE" | q_to_nul >LF_nul &&
383	create_NNO_MIX_files &&
384	git -c core.autocrlf=false add NNO_*.txt MIX_*.txt &&
385	git commit -m "mixed line endings" &&
386	test_tick
387'
388
389# Disable extra chain-linting for the next set of tests. There are many
390# auto-generated ones that are not worth checking over and over.
391GIT_TEST_CHAIN_LINT_HARDER_DEFAULT=0
392
393warn_LF_CRLF="LF will be replaced by CRLF"
394warn_CRLF_LF="CRLF will be replaced by LF"
395
396# WILC stands for "Warn if (this OS) converts LF into CRLF".
397# WICL: Warn if CRLF becomes LF
398# WAMIX: Mixed line endings: either CRLF->LF or LF->CRLF
399if test_have_prereq NATIVE_CRLF
400then
401	WILC=LF_CRLF
402	WICL=
403	WAMIX=LF_CRLF
404else
405	WILC=
406	WICL=CRLF_LF
407	WAMIX=CRLF_LF
408fi
409
410#                         attr   LF        CRLF      CRLFmixLF LFmixCR   CRLFNUL
411test_expect_success 'commit files empty attr' '
412	commit_check_warn false ""     ""        ""        ""        ""        "" &&
413	commit_check_warn true  ""     "LF_CRLF" ""        "LF_CRLF" ""        "" &&
414	commit_check_warn input ""     ""        "CRLF_LF" "CRLF_LF" ""        ""
415'
416
417test_expect_success 'commit files attr=auto' '
418	commit_check_warn false "auto" "$WILC"   "$WICL"   "$WAMIX"  ""        "" &&
419	commit_check_warn true  "auto" "LF_CRLF" ""        "LF_CRLF" ""        "" &&
420	commit_check_warn input "auto" ""        "CRLF_LF" "CRLF_LF" ""        ""
421'
422
423test_expect_success 'commit files attr=text' '
424	commit_check_warn false "text" "$WILC"   "$WICL"   "$WAMIX"  "$WILC"   "$WICL"   &&
425	commit_check_warn true  "text" "LF_CRLF" ""        "LF_CRLF" "LF_CRLF" ""        &&
426	commit_check_warn input "text" ""        "CRLF_LF" "CRLF_LF" ""        "CRLF_LF"
427'
428
429test_expect_success 'commit files attr=-text' '
430	commit_check_warn false "-text" ""       ""        ""        ""        "" &&
431	commit_check_warn true  "-text" ""       ""        ""        ""        "" &&
432	commit_check_warn input "-text" ""       ""        ""        ""        ""
433'
434
435test_expect_success 'commit files attr=lf' '
436	commit_check_warn false "lf"    ""       "CRLF_LF" "CRLF_LF"  ""       "CRLF_LF" &&
437	commit_check_warn true  "lf"    ""       "CRLF_LF" "CRLF_LF"  ""       "CRLF_LF" &&
438	commit_check_warn input "lf"    ""       "CRLF_LF" "CRLF_LF"  ""       "CRLF_LF"
439'
440
441test_expect_success 'commit files attr=crlf' '
442	commit_check_warn false "crlf" "LF_CRLF" ""        "LF_CRLF" "LF_CRLF" "" &&
443	commit_check_warn true  "crlf" "LF_CRLF" ""        "LF_CRLF" "LF_CRLF" "" &&
444	commit_check_warn input "crlf" "LF_CRLF" ""        "LF_CRLF" "LF_CRLF" ""
445'
446
447# Commit "CRLFmixLF" on top of these files already in the repo:
448#                                         mixed     mixed     mixed       mixed       mixed
449#                                         onto      onto      onto        onto        onto
450#                 attr                    LF        CRLF      CRLFmixLF   LF_mix_CR   CRLFNUL
451commit_MIX_chkwrn ""      ""      false   ""        ""        ""          ""          ""
452commit_MIX_chkwrn ""      ""      true    "LF_CRLF" ""        ""          "LF_CRLF"   "LF_CRLF"
453commit_MIX_chkwrn ""      ""      input   "CRLF_LF" ""        ""          "CRLF_LF"   "CRLF_LF"
454
455commit_MIX_chkwrn "auto"  ""      false   "$WAMIX"  ""        ""          "$WAMIX"    "$WAMIX"
456commit_MIX_chkwrn "auto"  ""      true    "LF_CRLF" ""        ""          "LF_CRLF"   "LF_CRLF"
457commit_MIX_chkwrn "auto"  ""      input   "CRLF_LF" ""        ""          "CRLF_LF"   "CRLF_LF"
458
459#                 attr                    LF        CRLF      CRLFmixLF   LF_mix_CR   CRLFNUL
460commit_chk_wrnNNO ""      ""      false   ""        ""        ""          ""          ""
461commit_chk_wrnNNO ""      ""      true    LF_CRLF   ""        ""          ""          ""
462commit_chk_wrnNNO ""      ""      input   ""        ""        ""          ""          ""
463
464commit_chk_wrnNNO "auto"  ""      false   "$WILC"   ""        ""          ""          ""
465commit_chk_wrnNNO "auto"  ""      true    LF_CRLF   ""        ""          ""          ""
466commit_chk_wrnNNO "auto"  ""      input   ""        ""        ""          ""          ""
467for crlf in true false input
468do
469	commit_chk_wrnNNO -text ""      $crlf   ""        ""        ""          ""          ""
470	commit_chk_wrnNNO -text lf      $crlf   ""        ""        ""          ""          ""
471	commit_chk_wrnNNO -text crlf    $crlf   ""        ""        ""          ""          ""
472	commit_chk_wrnNNO ""    lf      $crlf   ""       CRLF_LF    CRLF_LF      ""         CRLF_LF
473	commit_chk_wrnNNO ""    crlf    $crlf   LF_CRLF   ""        LF_CRLF     LF_CRLF     ""
474	commit_chk_wrnNNO auto  lf    	$crlf   ""        ""        ""          ""          ""
475	commit_chk_wrnNNO auto  crlf  	$crlf   LF_CRLF   ""        ""          ""          ""
476	commit_chk_wrnNNO text  lf    	$crlf   ""       CRLF_LF    CRLF_LF     ""          CRLF_LF
477	commit_chk_wrnNNO text  crlf  	$crlf   LF_CRLF   ""        LF_CRLF     LF_CRLF     ""
478done
479
480commit_chk_wrnNNO "text"  ""      false   "$WILC"   "$WICL"   "$WAMIX"    "$WILC"     "$WICL"
481commit_chk_wrnNNO "text"  ""      true    LF_CRLF   ""        LF_CRLF     LF_CRLF     ""
482commit_chk_wrnNNO "text"  ""      input   ""        CRLF_LF   CRLF_LF     ""          CRLF_LF
483
484test_expect_success 'commit NNO and cleanup' '
485	git commit -m "commit files on top of NNO" &&
486	rm -f *.txt &&
487	git -c core.autocrlf=false reset --hard
488'
489
490test_expect_success 'commit empty gitattribues' '
491	check_files_in_repo false ""      LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul &&
492	check_files_in_repo true  ""      LF LF   LF          LF_mix_CR CRLF_nul &&
493	check_files_in_repo input ""      LF LF   LF          LF_mix_CR CRLF_nul
494'
495
496test_expect_success 'commit text=auto' '
497	check_files_in_repo false "auto"  LF LF   LF          LF_mix_CR CRLF_nul &&
498	check_files_in_repo true  "auto"  LF LF   LF          LF_mix_CR CRLF_nul &&
499	check_files_in_repo input "auto"  LF LF   LF          LF_mix_CR CRLF_nul
500'
501
502test_expect_success 'commit text' '
503	check_files_in_repo false "text"  LF LF   LF          LF_mix_CR LF_nul &&
504	check_files_in_repo true  "text"  LF LF   LF          LF_mix_CR LF_nul &&
505	check_files_in_repo input "text"  LF LF   LF          LF_mix_CR LF_nul
506'
507
508test_expect_success 'commit -text' '
509	check_files_in_repo false "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul &&
510	check_files_in_repo true  "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul &&
511	check_files_in_repo input "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
512'
513
514for crlf in true false input
515do
516	#                 attr  aeol           LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLFNUL
517	check_in_repo_NNO ""    ""     $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
518	check_in_repo_NNO -text ""     $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
519	check_in_repo_NNO -text lf     $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
520	check_in_repo_NNO -text crlf   $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
521	check_in_repo_NNO auto  ""     $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
522	check_in_repo_NNO auto  lf     $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
523	check_in_repo_NNO auto  crlf   $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
524	check_in_repo_NNO text  ""     $crlf   LF  LF    LF           LF_mix_CR  LF_nul
525	check_in_repo_NNO text  lf     $crlf   LF  LF    LF           LF_mix_CR  LF_nul
526	check_in_repo_NNO text  crlf   $crlf   LF  LF    LF           LF_mix_CR  LF_nul
527done
528################################################################################
529# Check how files in the repo are changed when they are checked out
530# How to read the table below:
531# - checkout_files will check multiple files with a combination of settings
532#   and attributes (core.autocrlf=input is forbidden with core.eol=crlf)
533#
534# - parameter $1 	: text in .gitattributs  "" (empty) | auto | text | -text
535# - parameter $2 	: ident                  "" | i (i == ident)
536# - parameter $3 	: eol in .gitattributs   "" (empty) | lf | crlf
537# - parameter $4 	: core.autocrlf          false | true | input
538# - parameter $5 	: core.eol               "" | lf | crlf | "native"
539# - parameter $6 	: reference for a file with only LF in the repo
540# - parameter $7 	: reference for a file with only CRLF in the repo
541# - parameter $8 	: reference for a file with mixed LF and CRLF in the repo
542# - parameter $9 	: reference for a file with LF and CR in the repo
543# - parameter $10 : reference for a file with CRLF and a NUL (should be handled as binary when auto)
544
545if test_have_prereq NATIVE_CRLF
546then
547MIX_CRLF_LF=CRLF
548MIX_LF_CR=CRLF_mix_CR
549NL=CRLF
550LFNUL=CRLF_nul
551else
552MIX_CRLF_LF=CRLF_mix_LF
553MIX_LF_CR=LF_mix_CR
554NL=LF
555LFNUL=LF_nul
556fi
557export CRLF_MIX_LF_CR MIX NL
558
559# Same handling with and without ident
560for id in "" ident
561do
562	for ceol in lf crlf native
563	do
564		for crlf in true false input
565		do
566			# -text overrides core.autocrlf and core.eol
567			# text and eol=crlf or eol=lf override core.autocrlf and core.eol
568			checkout_files -text "$id" ""     "$crlf" "$ceol"  LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
569			checkout_files -text "$id" "lf"   "$crlf" "$ceol"  LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
570			checkout_files -text "$id" "crlf" "$crlf" "$ceol"  LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
571			# text
572			checkout_files text  "$id" "lf"   "$crlf" "$ceol"  LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
573			checkout_files text  "$id" "crlf" "$crlf" "$ceol"  CRLF  CRLF  CRLF         CRLF_mix_CR  CRLF_nul
574			# currently the same as text, eol=XXX
575			checkout_files auto  "$id" "lf"   "$crlf" "$ceol"  LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
576			checkout_files auto  "$id" "crlf" "$crlf" "$ceol"  CRLF  CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
577		done
578
579		# core.autocrlf false, different core.eol
580		checkout_files   ""    "$id" ""     false   "$ceol"  LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
581		# core.autocrlf true
582		checkout_files   ""    "$id" ""     true    "$ceol"  CRLF  CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
583		# text: core.autocrlf = true overrides core.eol
584		checkout_files   auto  "$id" ""     true    "$ceol"  CRLF  CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
585		checkout_files   text  "$id" ""     true    "$ceol"  CRLF  CRLF  CRLF         CRLF_mix_CR  CRLF_nul
586		# text: core.autocrlf = input overrides core.eol
587		checkout_files   text  "$id" ""     input   "$ceol"  LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
588		checkout_files   auto  "$id" ""     input   "$ceol"  LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
589		# text=auto + eol=XXX
590	done
591	# text: core.autocrlf=false uses core.eol
592	checkout_files     text  "$id" ""     false   crlf     CRLF  CRLF  CRLF         CRLF_mix_CR  CRLF_nul
593	checkout_files     text  "$id" ""     false   lf       LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
594	# text: core.autocrlf=false and core.eol unset(or native) uses native eol
595	checkout_files     text  "$id" ""     false   ""       $NL   CRLF  $MIX_CRLF_LF $MIX_LF_CR   $LFNUL
596	checkout_files     text  "$id" ""     false   native   $NL   CRLF  $MIX_CRLF_LF $MIX_LF_CR   $LFNUL
597	# auto: core.autocrlf=false and core.eol unset(or native) uses native eol
598	checkout_files     auto  "$id" ""     false   ""       $NL   CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
599	checkout_files     auto  "$id" ""     false   native   $NL   CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
600done
601
602# The rest of the tests are unique; do the usual linting.
603unset GIT_TEST_CHAIN_LINT_HARDER_DEFAULT
604
605# Should be the last test case: remove some files from the worktree
606test_expect_success 'ls-files --eol -d -z' '
607	rm crlf_false_attr__CRLF.txt crlf_false_attr__CRLF_mix_LF.txt crlf_false_attr__LF.txt .gitattributes &&
608	cat >expect <<-\EOF &&
609	i/crlf w/ crlf_false_attr__CRLF.txt
610	i/lf w/ .gitattributes
611	i/lf w/ crlf_false_attr__LF.txt
612	i/mixed w/ crlf_false_attr__CRLF_mix_LF.txt
613	EOF
614	git ls-files --eol -d |
615	sed -e "s!attr/[^	]*!!g" -e "s/	/ /g" -e "s/  */ /g" |
616	sort >actual &&
617	test_cmp expect actual
618'
619
620test_done
621