diff options
-rw-r--r-- | Documentation/config.txt | 12 | ||||
-rw-r--r-- | Documentation/gitattributes.txt | 15 | ||||
-rw-r--r-- | cache.h | 1 | ||||
-rw-r--r-- | convert.c | 42 | ||||
-rw-r--r-- | convert.h | 3 | ||||
-rw-r--r-- | merge-recursive.c | 17 | ||||
-rw-r--r-- | read-cache.c | 5 | ||||
-rwxr-xr-x | t/t0025-crlf-auto.sh | 4 | ||||
-rwxr-xr-x | t/t0027-auto-crlf.sh | 29 | ||||
-rwxr-xr-x | t/t6038-merge-text-auto.sh | 74 |
10 files changed, 112 insertions, 90 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt index e455faeb2..8b1aee4b3 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -412,13 +412,11 @@ file with mixed line endings would be reported by the `core.safecrlf` mechanism. core.autocrlf:: - Setting this variable to "true" is almost the same as setting - the `text` attribute to "auto" on all files except that text - files are not guaranteed to be normalized: files that contain - `CRLF` in the repository will not be touched. Use this - setting if you want to have `CRLF` line endings in your - working directory even though the repository does not have - normalized line endings. This variable can be set to 'input', + Setting this variable to "true" is the same as setting + the `text` attribute to "auto" on all files and core.eol to "crlf". + Set to true if you want to have `CRLF` line endings in your + working directory and the repository has LF line endings. + This variable can be set to 'input', in which case no output conversion is performed. core.symlinks:: diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 8882a3e91..b40068bdf 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -115,6 +115,7 @@ text file is normalized, its line endings are converted to LF in the repository. To control what line ending style is used in the working directory, use the `eol` attribute for a single file and the `core.eol` configuration variable for all text files. +Note that `core.autocrlf` overrides `core.eol` Set:: @@ -130,8 +131,9 @@ Unset:: Set to string value "auto":: When `text` is set to "auto", the path is marked for automatic - end-of-line normalization. If Git decides that the content is - text, its line endings are normalized to LF on checkin. + end-of-line conversion. If Git decides that the content is + text, its line endings are converted to LF on checkin. + When the file has been commited with CRLF, no conversion is done. Unspecified:: @@ -146,7 +148,7 @@ unspecified. ^^^^^ This attribute sets a specific line-ending style to be used in the -working directory. It enables end-of-line normalization without any +working directory. It enables end-of-line conversion without any content checks, effectively setting the `text` attribute. Set to string value "crlf":: @@ -186,9 +188,10 @@ the working directory, and prevent .jpg files from being normalized regardless of their content. ------------------------ +* text=auto *.txt text -*.vcproj eol=crlf -*.sh eol=lf +*.vcproj text eol=crlf +*.sh text eol=lf *.jpg -text ------------------------ @@ -198,7 +201,7 @@ normalization in Git. If you simply want to have CRLF line endings in your working directory regardless of the repository you are working with, you can set the -config variable "core.autocrlf" without changing any attributes. +config variable "core.autocrlf" without using any attributes. ------------------------ [core] @@ -632,6 +632,7 @@ extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st); #define REFRESH_IGNORE_SUBMODULES 0x0010 /* ignore submodules */ #define REFRESH_IN_PORCELAIN 0x0020 /* user friendly output, not "needs update" */ extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg); +extern struct cache_entry *refresh_cache_entry(struct cache_entry *, unsigned int); extern void update_index_if_able(struct index_state *, struct lock_file *); @@ -176,7 +176,9 @@ static enum eol output_eol(enum crlf_action crlf_action) return EOL_LF; case CRLF_UNDEFINED: case CRLF_AUTO_CRLF: + return EOL_CRLF; case CRLF_AUTO_INPUT: + return EOL_LF; case CRLF_TEXT: case CRLF_AUTO: /* fall through */ @@ -254,17 +256,15 @@ static int crlf_to_git(const char *path, const char *src, size_t len, if (crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) { if (convert_is_binary(len, &stats)) return 0; - - if (crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) { - /* - * If the file in the index has any CR in it, do not convert. - * This is the new safer autocrlf handling. - */ - if (has_cr_in_index(path)) - return 0; - } + /* + * If the file in the index has any CR in it, do not convert. + * This is the new safer autocrlf handling. + */ + if (checksafe == SAFE_CRLF_RENORMALIZE) + checksafe = SAFE_CRLF_FALSE; + else if (has_cr_in_index(path)) + return 0; } - check_safe_crlf(path, crlf_action, &stats, checksafe); /* 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, return 0; if (crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) { - if (crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) { - /* If we have any CR or CRLF line endings, we do not touch it */ - /* This is the new safer autocrlf-handling */ - if (stats.lonecr || stats.crlf ) - return 0; - } + /* If we have any CR or CRLF line endings, we do not touch it */ + /* This is the new safer autocrlf-handling */ + if (stats.lonecr || stats.crlf ) + return 0; if (convert_is_binary(len, &stats)) return 0; @@ -786,7 +784,11 @@ static void convert_attrs(struct conv_attrs *ca, const char *path) ca->drv = git_path_check_convert(ccheck + 2); if (ca->crlf_action != CRLF_BINARY) { enum eol eol_attr = git_path_check_eol(ccheck + 3); - if (eol_attr == EOL_LF) + if (ca->crlf_action == CRLF_AUTO && eol_attr == EOL_LF) + ca->crlf_action = CRLF_AUTO_INPUT; + else if (ca->crlf_action == CRLF_AUTO && eol_attr == EOL_CRLF) + ca->crlf_action = CRLF_AUTO_CRLF; + else if (eol_attr == EOL_LF) ca->crlf_action = CRLF_TEXT_INPUT; else if (eol_attr == EOL_CRLF) ca->crlf_action = CRLF_TEXT_CRLF; @@ -845,9 +847,9 @@ const char *get_convert_attr_ascii(const char *path) case CRLF_AUTO: return "text=auto"; case CRLF_AUTO_CRLF: - return "text=auto eol=crlf"; /* This is not supported yet */ + return "text=auto eol=crlf"; case CRLF_AUTO_INPUT: - return "text=auto eol=lf"; /* This is not supported yet */ + return "text=auto eol=lf"; } return ""; } @@ -949,7 +951,7 @@ int renormalize_buffer(const char *path, const char *src, size_t len, struct str src = dst->buf; len = dst->len; } - return ret | convert_to_git(path, src, len, dst, SAFE_CRLF_FALSE); + return ret | convert_to_git(path, src, len, dst, SAFE_CRLF_RENORMALIZE); } /***************************************************************** @@ -7,7 +7,8 @@ enum safe_crlf { SAFE_CRLF_FALSE = 0, SAFE_CRLF_FAIL = 1, - SAFE_CRLF_WARN = 2 + SAFE_CRLF_WARN = 2, + SAFE_CRLF_RENORMALIZE = 3 }; extern enum safe_crlf safe_crlf; diff --git a/merge-recursive.c b/merge-recursive.c index 48fe7e738..a4a1195f6 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -202,12 +202,21 @@ static int add_cacheinfo(unsigned int mode, const struct object_id *oid, const char *path, int stage, int refresh, int options) { struct cache_entry *ce; - ce = make_cache_entry(mode, oid ? oid->hash : null_sha1, path, stage, - (refresh ? (CE_MATCH_REFRESH | - CE_MATCH_IGNORE_MISSING) : 0 )); + int ret; + + ce = make_cache_entry(mode, oid ? oid->hash : null_sha1, path, stage, 0); if (!ce) return error(_("addinfo_cache failed for path '%s'"), path); - return add_cache_entry(ce, options); + + ret = add_cache_entry(ce, options); + if (refresh) { + struct cache_entry *nce; + + nce = refresh_cache_entry(ce, CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING); + if (nce != ce) + ret = add_cache_entry(nce, options); + } + return ret; } static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree) diff --git a/read-cache.c b/read-cache.c index db2776605..491e52d12 100644 --- a/read-cache.c +++ b/read-cache.c @@ -19,9 +19,6 @@ #include "split-index.h" #include "utf8.h" -static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, - unsigned int options); - /* Mask for the name length in ce_flags in the on-disk index */ #define CE_NAMEMASK (0x0fff) @@ -1257,7 +1254,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, return has_errors; } -static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, +struct cache_entry *refresh_cache_entry(struct cache_entry *ce, unsigned int options) { return refresh_cache_ent(&the_index, ce, options, NULL, NULL); diff --git a/t/t0025-crlf-auto.sh b/t/t0025-crlf-auto.sh index c164b4662..d0bee08b2 100755 --- a/t/t0025-crlf-auto.sh +++ b/t/t0025-crlf-auto.sh @@ -114,7 +114,7 @@ test_expect_success 'autocrlf=true does not normalize CRLF files' ' test -z "$LFonlydiff" -a -z "$CRLFonlydiff" -a -z "$LFwithNULdiff" ' -test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' ' +test_expect_success 'text=auto, autocrlf=true does not normalize CRLF files' ' rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL && git config core.autocrlf true && @@ -126,7 +126,7 @@ test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' ' LFonlydiff=$(git diff LFonly) && CRLFonlydiff=$(git diff CRLFonly) && LFwithNULdiff=$(git diff LFwithNUL) && - test -z "$LFonlydiff" -a -n "$CRLFonlydiff" -a -z "$LFwithNULdiff" + test -z "$LFonlydiff" -a -z "$CRLFonlydiff" -a -z "$LFwithNULdiff" ' test_expect_success 'text=auto, autocrlf=true does not normalize binary files' ' diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh index 93725895a..2860d2d08 100755 --- a/t/t0027-auto-crlf.sh +++ b/t/t0027-auto-crlf.sh @@ -175,8 +175,8 @@ attr_ascii () { text,lf) echo "text eol=lf" ;; text,crlf) echo "text eol=crlf" ;; auto,) echo "text=auto" ;; - auto,lf) echo "text eol=lf" ;; - auto,crlf) echo "text eol=crlf" ;; + auto,lf) echo "text=auto eol=lf" ;; + auto,crlf) echo "text=auto eol=crlf" ;; lf,) echo "text eol=lf" ;; crlf,) echo "text eol=crlf" ;; ,) echo "" ;; @@ -397,10 +397,9 @@ commit_chk_wrnNNO "" "" false "" "" "" "" commit_chk_wrnNNO "" "" true LF_CRLF "" "" "" "" commit_chk_wrnNNO "" "" input "" "" "" "" "" -commit_chk_wrnNNO "auto" "" false "$WILC" "$WICL" "$WAMIX" "" "" -commit_chk_wrnNNO "auto" "" true LF_CRLF "" LF_CRLF "" "" -commit_chk_wrnNNO "auto" "" input "" CRLF_LF CRLF_LF "" "" - +commit_chk_wrnNNO "auto" "" false "$WILC" "" "" "" "" +commit_chk_wrnNNO "auto" "" true LF_CRLF "" "" "" "" +commit_chk_wrnNNO "auto" "" input "" "" "" "" "" for crlf in true false input do commit_chk_wrnNNO -text "" $crlf "" "" "" "" "" @@ -408,8 +407,8 @@ do commit_chk_wrnNNO -text crlf $crlf "" "" "" "" "" commit_chk_wrnNNO "" lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF commit_chk_wrnNNO "" crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF "" - commit_chk_wrnNNO auto lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF - commit_chk_wrnNNO auto crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF "" + commit_chk_wrnNNO auto lf $crlf "" "" "" "" "" + commit_chk_wrnNNO auto crlf $crlf LF_CRLF "" "" "" "" commit_chk_wrnNNO text lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF commit_chk_wrnNNO text crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF "" done @@ -454,9 +453,9 @@ do check_in_repo_NNO -text "" $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul check_in_repo_NNO -text lf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul check_in_repo_NNO -text crlf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul - check_in_repo_NNO auto "" $crlf LF LF LF LF_mix_CR CRLF_nul - check_in_repo_NNO auto lf $crlf LF LF LF LF_mix_CR LF_nul - check_in_repo_NNO auto crlf $crlf LF LF LF LF_mix_CR LF_nul + check_in_repo_NNO auto "" $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul + check_in_repo_NNO auto lf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul + check_in_repo_NNO auto crlf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul check_in_repo_NNO text "" $crlf LF LF LF LF_mix_CR LF_nul check_in_repo_NNO text lf $crlf LF LF LF LF_mix_CR LF_nul check_in_repo_NNO text crlf $crlf LF LF LF LF_mix_CR LF_nul @@ -509,7 +508,7 @@ do checkout_files text "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul # currently the same as text, eol=XXX checkout_files auto "$id" "lf" "$crlf" "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul - checkout_files auto "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul + checkout_files auto "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul done # core.autocrlf false, different core.eol @@ -517,7 +516,7 @@ do # core.autocrlf true checkout_files "" "$id" "" true "$ceol" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul # text: core.autocrlf = true overrides core.eol - checkout_files auto "$id" "" true "$ceol" CRLF CRLF CRLF LF_mix_CR LF_nul + checkout_files auto "$id" "" true "$ceol" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul checkout_files text "$id" "" true "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul # text: core.autocrlf = input overrides core.eol checkout_files text "$id" "" input "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul @@ -531,8 +530,8 @@ do checkout_files text "$id" "" false "" $NL CRLF $MIX_CRLF_LF $MIX_LF_CR $LFNUL checkout_files text "$id" "" false native $NL CRLF $MIX_CRLF_LF $MIX_LF_CR $LFNUL # auto: core.autocrlf=false and core.eol unset(or native) uses native eol - checkout_files auto "$id" "" false "" $NL CRLF $MIX_CRLF_LF LF_mix_CR LF_nul - checkout_files auto "$id" "" false native $NL CRLF $MIX_CRLF_LF LF_mix_CR LF_nul + checkout_files auto "$id" "" false "" $NL CRLF CRLF_mix_LF LF_mix_CR LF_nul + checkout_files auto "$id" "" false native $NL CRLF CRLF_mix_LF LF_mix_CR LF_nul done # Should be the last test case: remove some files from the worktree diff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh index 85c10b094..5e8d5fa50 100755 --- a/t/t6038-merge-text-auto.sh +++ b/t/t6038-merge-text-auto.sh @@ -16,6 +16,13 @@ test_description='CRLF merge conflict across text=auto change test_have_prereq SED_STRIPS_CR && SED_OPTIONS=-b +compare_files () { + tr '\015\000' QN <"$1" >"$1".expect && + tr '\015\000' QN <"$2" >"$2".actual && + test_cmp "$1".expect "$2".actual && + rm "$1".expect "$2".actual +} + test_expect_success setup ' git config core.autocrlf false && @@ -30,7 +37,7 @@ test_expect_success setup ' git branch side && echo "* text=auto" >.gitattributes && - touch file && + echo first line >file && git add .gitattributes file && test_tick && git commit -m "normalize file" && @@ -81,38 +88,49 @@ test_expect_success 'Merge after setting text=auto' ' rm -f .gitattributes && git reset --hard a && git merge b && - test_cmp expected file + compare_files expected file ' -test_expect_success 'Merge addition of text=auto' ' +test_expect_success 'Merge addition of text=auto eol=LF' ' + git config core.eol lf && cat <<-\EOF >expected && first line same line EOF - if test_have_prereq NATIVE_CRLF; then - append_cr <expected >expected.temp && - mv expected.temp expected - fi && git config merge.renormalize true && git rm -fr . && rm -f .gitattributes && git reset --hard b && git merge a && - test_cmp expected file + compare_files expected file +' + +test_expect_success 'Merge addition of text=auto eol=CRLF' ' + git config core.eol crlf && + cat <<-\EOF >expected && + first line + same line + EOF + + append_cr <expected >expected.temp && + mv expected.temp expected && + git config merge.renormalize true && + git rm -fr . && + rm -f .gitattributes && + git reset --hard b && + echo >&2 "After git reset --hard b" && + git ls-files -s --eol >&2 && + git merge a && + compare_files expected file ' test_expect_success 'Detect CRLF/LF conflict after setting text=auto' ' + git config core.eol native && echo "<<<<<<<" >expected && - if test_have_prereq NATIVE_CRLF; then - echo first line | append_cr >>expected && - echo same line | append_cr >>expected && - echo ======= | append_cr >>expected - else - echo first line >>expected && - echo same line >>expected && - echo ======= >>expected - fi && + echo first line >>expected && + echo same line >>expected && + echo ======= >>expected && echo first line | append_cr >>expected && echo same line | append_cr >>expected && echo ">>>>>>>" >>expected && @@ -121,29 +139,23 @@ test_expect_success 'Detect CRLF/LF conflict after setting text=auto' ' git reset --hard a && test_must_fail git merge b && fuzz_conflict file >file.fuzzy && - test_cmp expected file.fuzzy + compare_files expected file.fuzzy ' test_expect_success 'Detect LF/CRLF conflict from addition of text=auto' ' echo "<<<<<<<" >expected && echo first line | append_cr >>expected && echo same line | append_cr >>expected && - if test_have_prereq NATIVE_CRLF; then - echo ======= | append_cr >>expected && - echo first line | append_cr >>expected && - echo same line | append_cr >>expected - else - echo ======= >>expected && - echo first line >>expected && - echo same line >>expected - fi && + echo ======= >>expected && + echo first line >>expected && + echo same line >>expected && echo ">>>>>>>" >>expected && git config merge.renormalize false && rm -f .gitattributes && git reset --hard b && test_must_fail git merge a && fuzz_conflict file >file.fuzzy && - test_cmp expected file.fuzzy + compare_files expected file.fuzzy ' test_expect_failure 'checkout -m after setting text=auto' ' @@ -158,7 +170,7 @@ test_expect_failure 'checkout -m after setting text=auto' ' git reset --hard initial && git checkout a -- . && git checkout -m b && - test_cmp expected file + compare_files expected file ' test_expect_failure 'checkout -m addition of text=auto' ' @@ -173,7 +185,7 @@ test_expect_failure 'checkout -m addition of text=auto' ' git reset --hard initial && git checkout b -- . && git checkout -m a && - test_cmp expected file + compare_files expected file ' test_expect_failure 'cherry-pick patch from after text=auto was added' ' @@ -187,7 +199,7 @@ test_expect_failure 'cherry-pick patch from after text=auto was added' ' git reset --hard b && test_must_fail git cherry-pick a >err 2>&1 && grep "[Nn]othing added" err && - test_cmp expected file + compare_files expected file ' test_expect_success 'Test delete/normalize conflict' ' |