Code

Merge branch 'fg/autocrlf'
authorJunio C Hamano <gitster@pobox.com>
Mon, 21 Jun 2010 13:02:47 +0000 (06:02 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 21 Jun 2010 13:02:47 +0000 (06:02 -0700)
* fg/autocrlf:
  autocrlf: Make it work also for un-normalized repositories

convert.c
t/t0020-crlf.sh

index 824bd047a548800d51abd7ae9d6f3e2eef9b160c..64dce3ff5741bc0e15ddb2daefcc521bb4075f4d 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -120,6 +120,43 @@ static void check_safe_crlf(const char *path, int action,
        }
 }
 
+static int has_cr_in_index(const char *path)
+{
+       int pos, len;
+       unsigned long sz;
+       enum object_type type;
+       void *data;
+       int has_cr;
+       struct index_state *istate = &the_index;
+
+       len = strlen(path);
+       pos = index_name_pos(istate, path, len);
+       if (pos < 0) {
+               /*
+                * We might be in the middle of a merge, in which
+                * case we would read stage #2 (ours).
+                */
+               int i;
+               for (i = -pos - 1;
+                    (pos < 0 && i < istate->cache_nr &&
+                     !strcmp(istate->cache[i]->name, path));
+                    i++)
+                       if (ce_stage(istate->cache[i]) == 2)
+                               pos = i;
+       }
+       if (pos < 0)
+               return 0;
+       data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
+       if (!data || type != OBJ_BLOB) {
+               free(data);
+               return 0;
+       }
+
+       has_cr = memchr(data, '\r', sz) != NULL;
+       free(data);
+       return has_cr;
+}
+
 static int crlf_to_git(const char *path, const char *src, size_t len,
                        struct strbuf *buf, int action, enum safe_crlf checksafe)
 {
@@ -145,6 +182,13 @@ static int crlf_to_git(const char *path, const char *src, size_t len,
                 */
                if (is_binary(len, &stats))
                        return 0;
+
+               /*
+                * 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;
        }
 
        check_safe_crlf(path, action, &stats, checksafe);
@@ -203,6 +247,11 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len,
                return 0;
 
        if (action == CRLF_GUESS) {
+               /* If we have any CR or CRLF line endings, we do not touch it */
+               /* This is the new safer autocrlf-handling */
+               if (stats.cr > 0 || stats.crlf > 0)
+                       return 0;
+
                /* If we have any bare CR characters, we're not going to touch it */
                if (stats.cr != stats.crlf)
                        return 0;
index c3e7e322a8d62b988999b166d2abcf08930adbf7..234a94f3e6311c529b5bb476ee5a6a2ea705017f 100755 (executable)
@@ -453,5 +453,57 @@ test_expect_success 'invalid .gitattributes (must not crash)' '
        git diff
 
 '
+# Some more tests here to add new autocrlf functionality.
+# We want to have a known state here, so start a bit from scratch
+
+test_expect_success 'setting up for new autocrlf tests' '
+       git config core.autocrlf false &&
+       git config core.safecrlf false &&
+       rm -rf .????* * &&
+       for w in I am all LF; do echo $w; done >alllf &&
+       for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
+       for w in I am all CRLF; do echo $w; done | append_cr >allcrlf &&
+       git add -A . &&
+       git commit -m "alllf, allcrlf and mixed only" &&
+       git tag -a -m "message" autocrlf-checkpoint
+'
+
+test_expect_success 'report no change after setting autocrlf' '
+       git config core.autocrlf true &&
+       touch * &&
+       git diff --exit-code
+'
+
+test_expect_success 'files are clean after checkout' '
+       rm * &&
+       git checkout -f &&
+       git diff --exit-code
+'
+
+cr_to_Q_no_NL () {
+    tr '\015' Q | tr -d '\012'
+}
+
+test_expect_success 'LF only file gets CRLF with autocrlf' '
+       test "$(cr_to_Q_no_NL < alllf)" = "IQamQallQLFQ"
+'
+
+test_expect_success 'Mixed file is still mixed with autocrlf' '
+       test "$(cr_to_Q_no_NL < mixed)" = "OhhereisCRLFQintext"
+'
+
+test_expect_success 'CRLF only file has CRLF with autocrlf' '
+       test "$(cr_to_Q_no_NL < allcrlf)" = "IQamQallQCRLFQ"
+'
+
+test_expect_success 'New CRLF file gets LF in repo' '
+       tr -d "\015" < alllf | append_cr > alllf2 &&
+       git add alllf2 &&
+       git commit -m "alllf2 added" &&
+       git config core.autocrlf false &&
+       rm * &&
+       git checkout -f &&
+       test_cmp alllf alllf2
+'
 
 test_done