Skip to content

Commit 6523728

Browse files
tboegigitster
authored andcommitted
convert: unify the "auto" handling of CRLF
Before this change, $ echo "* text=auto" >.gitattributes $ echo "* eol=crlf" >>.gitattributes would have the same effect as $ echo "* text" >.gitattributes $ git config core.eol crlf Since the 'eol' attribute had higher priority than 'text=auto', this may corrupt binary files and is not what most users expect to happen. Make the 'eol' attribute to obey 'text=auto' and now $ echo "* text=auto" >.gitattributes $ echo "* eol=crlf" >>.gitattributes behaves the same as $ echo "* text=auto" >.gitattributes $ git config core.eol crlf In other words, $ echo "* text=auto eol=crlf" >.gitattributes has the same effect as $ git config core.autocrlf true and $ echo "* text=auto eol=lf" >.gitattributes has the same effect as $ git config core.autocrlf input Signed-off-by: Torsten Bögershausen <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent caa47ad commit 6523728

File tree

7 files changed

+69
-59
lines changed

7 files changed

+69
-59
lines changed

Documentation/config.txt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -389,13 +389,11 @@ file with mixed line endings would be reported by the `core.safecrlf`
389389
mechanism.
390390

391391
core.autocrlf::
392-
Setting this variable to "true" is almost the same as setting
393-
the `text` attribute to "auto" on all files except that text
394-
files are not guaranteed to be normalized: files that contain
395-
`CRLF` in the repository will not be touched. Use this
396-
setting if you want to have `CRLF` line endings in your
397-
working directory even though the repository does not have
398-
normalized line endings. This variable can be set to 'input',
392+
Setting this variable to "true" is the same as setting
393+
the `text` attribute to "auto" on all files and core.eol to "crlf".
394+
Set to true if you want to have `CRLF` line endings in your
395+
working directory and the repository has LF line endings.
396+
This variable can be set to 'input',
399397
in which case no output conversion is performed.
400398

401399
core.symlinks::

Documentation/gitattributes.txt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ text file is normalized, its line endings are converted to LF in the
115115
repository. To control what line ending style is used in the working
116116
directory, use the `eol` attribute for a single file and the
117117
`core.eol` configuration variable for all text files.
118+
Note that `core.autocrlf` overrides `core.eol`
118119

119120
Set::
120121

@@ -130,8 +131,9 @@ Unset::
130131
Set to string value "auto"::
131132

132133
When `text` is set to "auto", the path is marked for automatic
133-
end-of-line normalization. If Git decides that the content is
134-
text, its line endings are normalized to LF on checkin.
134+
end-of-line conversion. If Git decides that the content is
135+
text, its line endings are converted to LF on checkin.
136+
When the file has been commited with CRLF, no conversion is done.
135137

136138
Unspecified::
137139

@@ -146,7 +148,7 @@ unspecified.
146148
^^^^^
147149

148150
This attribute sets a specific line-ending style to be used in the
149-
working directory. It enables end-of-line normalization without any
151+
working directory. It enables end-of-line conversion without any
150152
content checks, effectively setting the `text` attribute.
151153

152154
Set to string value "crlf"::
@@ -186,9 +188,10 @@ the working directory, and prevent .jpg files from being normalized
186188
regardless of their content.
187189

188190
------------------------
191+
* text=auto
189192
*.txt text
190-
*.vcproj eol=crlf
191-
*.sh eol=lf
193+
*.vcproj text eol=crlf
194+
*.sh text eol=lf
192195
*.jpg -text
193196
------------------------
194197

@@ -198,7 +201,7 @@ normalization in Git.
198201

199202
If you simply want to have CRLF line endings in your working directory
200203
regardless of the repository you are working with, you can set the
201-
config variable "core.autocrlf" without changing any attributes.
204+
config variable "core.autocrlf" without using any attributes.
202205

203206
------------------------
204207
[core]

convert.c

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,9 @@ static enum eol output_eol(enum crlf_action crlf_action)
176176
return EOL_LF;
177177
case CRLF_UNDEFINED:
178178
case CRLF_AUTO_CRLF:
179+
return EOL_CRLF;
179180
case CRLF_AUTO_INPUT:
181+
return EOL_LF;
180182
case CRLF_TEXT:
181183
case CRLF_AUTO:
182184
/* fall through */
@@ -254,17 +256,15 @@ static int crlf_to_git(const char *path, const char *src, size_t len,
254256
if (crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
255257
if (convert_is_binary(len, &stats))
256258
return 0;
257-
258-
if (crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
259-
/*
260-
* If the file in the index has any CR in it, do not convert.
261-
* This is the new safer autocrlf handling.
262-
*/
263-
if (has_cr_in_index(path))
264-
return 0;
265-
}
259+
/*
260+
* If the file in the index has any CR in it, do not convert.
261+
* This is the new safer autocrlf handling.
262+
*/
263+
if (checksafe == SAFE_CRLF_RENORMALIZE)
264+
checksafe = SAFE_CRLF_FALSE;
265+
else if (has_cr_in_index(path))
266+
return 0;
266267
}
267-
268268
check_safe_crlf(path, crlf_action, &stats, checksafe);
269269

270270
/* Optimization: No CRLF? Nothing to convert, regardless. */
@@ -320,12 +320,10 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len,
320320
return 0;
321321

322322
if (crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
323-
if (crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
324-
/* If we have any CR or CRLF line endings, we do not touch it */
325-
/* This is the new safer autocrlf-handling */
326-
if (stats.lonecr || stats.crlf )
327-
return 0;
328-
}
323+
/* If we have any CR or CRLF line endings, we do not touch it */
324+
/* This is the new safer autocrlf-handling */
325+
if (stats.lonecr || stats.crlf )
326+
return 0;
329327

330328
if (convert_is_binary(len, &stats))
331329
return 0;
@@ -786,7 +784,11 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
786784
ca->drv = git_path_check_convert(ccheck + 2);
787785
if (ca->crlf_action != CRLF_BINARY) {
788786
enum eol eol_attr = git_path_check_eol(ccheck + 3);
789-
if (eol_attr == EOL_LF)
787+
if (ca->crlf_action == CRLF_AUTO && eol_attr == EOL_LF)
788+
ca->crlf_action = CRLF_AUTO_INPUT;
789+
else if (ca->crlf_action == CRLF_AUTO && eol_attr == EOL_CRLF)
790+
ca->crlf_action = CRLF_AUTO_CRLF;
791+
else if (eol_attr == EOL_LF)
790792
ca->crlf_action = CRLF_TEXT_INPUT;
791793
else if (eol_attr == EOL_CRLF)
792794
ca->crlf_action = CRLF_TEXT_CRLF;
@@ -845,9 +847,9 @@ const char *get_convert_attr_ascii(const char *path)
845847
case CRLF_AUTO:
846848
return "text=auto";
847849
case CRLF_AUTO_CRLF:
848-
return "text=auto eol=crlf"; /* This is not supported yet */
850+
return "text=auto eol=crlf";
849851
case CRLF_AUTO_INPUT:
850-
return "text=auto eol=lf"; /* This is not supported yet */
852+
return "text=auto eol=lf";
851853
}
852854
return "";
853855
}
@@ -949,7 +951,7 @@ int renormalize_buffer(const char *path, const char *src, size_t len, struct str
949951
src = dst->buf;
950952
len = dst->len;
951953
}
952-
return ret | convert_to_git(path, src, len, dst, SAFE_CRLF_FALSE);
954+
return ret | convert_to_git(path, src, len, dst, SAFE_CRLF_RENORMALIZE);
953955
}
954956

955957
/*****************************************************************

convert.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
enum safe_crlf {
88
SAFE_CRLF_FALSE = 0,
99
SAFE_CRLF_FAIL = 1,
10-
SAFE_CRLF_WARN = 2
10+
SAFE_CRLF_WARN = 2,
11+
SAFE_CRLF_RENORMALIZE = 3
1112
};
1213

1314
extern enum safe_crlf safe_crlf;

t/t0025-crlf-auto.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ test_expect_success 'autocrlf=true does not normalize CRLF files' '
114114
test -z "$LFonlydiff" -a -z "$CRLFonlydiff" -a -z "$LFwithNULdiff"
115115
'
116116

117-
test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' '
117+
test_expect_success 'text=auto, autocrlf=true does not normalize CRLF files' '
118118
119119
rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
120120
git config core.autocrlf true &&
@@ -126,7 +126,7 @@ test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' '
126126
LFonlydiff=$(git diff LFonly) &&
127127
CRLFonlydiff=$(git diff CRLFonly) &&
128128
LFwithNULdiff=$(git diff LFwithNUL) &&
129-
test -z "$LFonlydiff" -a -n "$CRLFonlydiff" -a -z "$LFwithNULdiff"
129+
test -z "$LFonlydiff" -a -z "$CRLFonlydiff" -a -z "$LFwithNULdiff"
130130
'
131131

132132
test_expect_success 'text=auto, autocrlf=true does not normalize binary files' '

t/t0027-auto-crlf.sh

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ attr_ascii () {
175175
text,lf) echo "text eol=lf" ;;
176176
text,crlf) echo "text eol=crlf" ;;
177177
auto,) echo "text=auto" ;;
178-
auto,lf) echo "text eol=lf" ;;
179-
auto,crlf) echo "text eol=crlf" ;;
178+
auto,lf) echo "text=auto eol=lf" ;;
179+
auto,crlf) echo "text=auto eol=crlf" ;;
180180
lf,) echo "text eol=lf" ;;
181181
crlf,) echo "text eol=crlf" ;;
182182
,) echo "" ;;
@@ -397,19 +397,18 @@ commit_chk_wrnNNO "" "" false "" "" "" ""
397397
commit_chk_wrnNNO "" "" true LF_CRLF "" "" "" ""
398398
commit_chk_wrnNNO "" "" input "" "" "" "" ""
399399

400-
commit_chk_wrnNNO "auto" "" false "$WILC" "$WICL" "$WAMIX" "" ""
401-
commit_chk_wrnNNO "auto" "" true LF_CRLF "" LF_CRLF "" ""
402-
commit_chk_wrnNNO "auto" "" input "" CRLF_LF CRLF_LF "" ""
403-
400+
commit_chk_wrnNNO "auto" "" false "$WILC" "" "" "" ""
401+
commit_chk_wrnNNO "auto" "" true LF_CRLF "" "" "" ""
402+
commit_chk_wrnNNO "auto" "" input "" "" "" "" ""
404403
for crlf in true false input
405404
do
406405
commit_chk_wrnNNO -text "" $crlf "" "" "" "" ""
407406
commit_chk_wrnNNO -text lf $crlf "" "" "" "" ""
408407
commit_chk_wrnNNO -text crlf $crlf "" "" "" "" ""
409408
commit_chk_wrnNNO "" lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF
410409
commit_chk_wrnNNO "" crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF ""
411-
commit_chk_wrnNNO auto lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF
412-
commit_chk_wrnNNO auto crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF ""
410+
commit_chk_wrnNNO auto lf $crlf "" "" "" "" ""
411+
commit_chk_wrnNNO auto crlf $crlf LF_CRLF "" "" "" ""
413412
commit_chk_wrnNNO text lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF
414413
commit_chk_wrnNNO text crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF ""
415414
done
@@ -454,9 +453,9 @@ do
454453
check_in_repo_NNO -text "" $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
455454
check_in_repo_NNO -text lf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
456455
check_in_repo_NNO -text crlf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
457-
check_in_repo_NNO auto "" $crlf LF LF LF LF_mix_CR CRLF_nul
458-
check_in_repo_NNO auto lf $crlf LF LF LF LF_mix_CR LF_nul
459-
check_in_repo_NNO auto crlf $crlf LF LF LF LF_mix_CR LF_nul
456+
check_in_repo_NNO auto "" $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
457+
check_in_repo_NNO auto lf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
458+
check_in_repo_NNO auto crlf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
460459
check_in_repo_NNO text "" $crlf LF LF LF LF_mix_CR LF_nul
461460
check_in_repo_NNO text lf $crlf LF LF LF LF_mix_CR LF_nul
462461
check_in_repo_NNO text crlf $crlf LF LF LF LF_mix_CR LF_nul
@@ -509,15 +508,15 @@ do
509508
checkout_files text "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
510509
# currently the same as text, eol=XXX
511510
checkout_files auto "$id" "lf" "$crlf" "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
512-
checkout_files auto "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
511+
checkout_files auto "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul
513512
done
514513

515514
# core.autocrlf false, different core.eol
516515
checkout_files "" "$id" "" false "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
517516
# core.autocrlf true
518517
checkout_files "" "$id" "" true "$ceol" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul
519518
# text: core.autocrlf = true overrides core.eol
520-
checkout_files auto "$id" "" true "$ceol" CRLF CRLF CRLF LF_mix_CR LF_nul
519+
checkout_files auto "$id" "" true "$ceol" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul
521520
checkout_files text "$id" "" true "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
522521
# text: core.autocrlf = input overrides core.eol
523522
checkout_files text "$id" "" input "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
@@ -531,8 +530,8 @@ do
531530
checkout_files text "$id" "" false "" $NL CRLF $MIX_CRLF_LF $MIX_LF_CR $LFNUL
532531
checkout_files text "$id" "" false native $NL CRLF $MIX_CRLF_LF $MIX_LF_CR $LFNUL
533532
# auto: core.autocrlf=false and core.eol unset(or native) uses native eol
534-
checkout_files auto "$id" "" false "" $NL CRLF $MIX_CRLF_LF LF_mix_CR LF_nul
535-
checkout_files auto "$id" "" false native $NL CRLF $MIX_CRLF_LF LF_mix_CR LF_nul
533+
checkout_files auto "$id" "" false "" $NL CRLF CRLF_mix_LF LF_mix_CR LF_nul
534+
checkout_files auto "$id" "" false native $NL CRLF CRLF_mix_LF LF_mix_CR LF_nul
536535
done
537536

538537
# Should be the last test case: remove some files from the worktree

t/t6038-merge-text-auto.sh

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ test_description='CRLF merge conflict across text=auto change
1616

1717
test_have_prereq SED_STRIPS_CR && SED_OPTIONS=-b
1818

19+
compare_files () {
20+
tr '\015\000' QN <"$1" >"$1".expect &&
21+
tr '\015\000' QN <"$2" >"$2".actual &&
22+
test_cmp "$1".expect "$2".actual &&
23+
rm "$1".expect "$2".actual
24+
}
25+
1926
test_expect_success setup '
2027
git config core.autocrlf false &&
2128
@@ -30,7 +37,7 @@ test_expect_success setup '
3037
git branch side &&
3138
3239
echo "* text=auto" >.gitattributes &&
33-
touch file &&
40+
echo first line >file &&
3441
git add .gitattributes file &&
3542
test_tick &&
3643
git commit -m "normalize file" &&
@@ -81,7 +88,7 @@ test_expect_success 'Merge after setting text=auto' '
8188
rm -f .gitattributes &&
8289
git reset --hard a &&
8390
git merge b &&
84-
test_cmp expected file
91+
compare_files expected file
8592
'
8693

8794
test_expect_success 'Merge addition of text=auto' '
@@ -99,7 +106,7 @@ test_expect_success 'Merge addition of text=auto' '
99106
rm -f .gitattributes &&
100107
git reset --hard b &&
101108
git merge a &&
102-
test_cmp expected file
109+
compare_files expected file
103110
'
104111

105112
test_expect_success 'Detect CRLF/LF conflict after setting text=auto' '
@@ -121,7 +128,7 @@ test_expect_success 'Detect CRLF/LF conflict after setting text=auto' '
121128
git reset --hard a &&
122129
test_must_fail git merge b &&
123130
fuzz_conflict file >file.fuzzy &&
124-
test_cmp expected file.fuzzy
131+
compare_files expected file.fuzzy
125132
'
126133

127134
test_expect_success 'Detect LF/CRLF conflict from addition of text=auto' '
@@ -143,7 +150,7 @@ test_expect_success 'Detect LF/CRLF conflict from addition of text=auto' '
143150
git reset --hard b &&
144151
test_must_fail git merge a &&
145152
fuzz_conflict file >file.fuzzy &&
146-
test_cmp expected file.fuzzy
153+
compare_files expected file.fuzzy
147154
'
148155

149156
test_expect_failure 'checkout -m after setting text=auto' '
@@ -158,7 +165,7 @@ test_expect_failure 'checkout -m after setting text=auto' '
158165
git reset --hard initial &&
159166
git checkout a -- . &&
160167
git checkout -m b &&
161-
test_cmp expected file
168+
compare_files expected file
162169
'
163170

164171
test_expect_failure 'checkout -m addition of text=auto' '
@@ -173,7 +180,7 @@ test_expect_failure 'checkout -m addition of text=auto' '
173180
git reset --hard initial &&
174181
git checkout b -- . &&
175182
git checkout -m a &&
176-
test_cmp expected file
183+
compare_files expected file
177184
'
178185

179186
test_expect_failure 'cherry-pick patch from after text=auto was added' '
@@ -187,7 +194,7 @@ test_expect_failure 'cherry-pick patch from after text=auto was added' '
187194
git reset --hard b &&
188195
test_must_fail git cherry-pick a >err 2>&1 &&
189196
grep "[Nn]othing added" err &&
190-
test_cmp expected file
197+
compare_files expected file
191198
'
192199

193200
test_expect_success 'Test delete/normalize conflict' '

0 commit comments

Comments
 (0)