Skip to content
  • Torsten Bögershausen's avatar
    apply: file commited with CRLF should roundtrip diff and apply · c24f3aba
    Torsten Bögershausen authored and Junio C Hamano's avatar Junio C Hamano committed
    
    
    When a file had been commited with CRLF but now .gitattributes say
    "* text=auto" (or core.autocrlf is true), the following does not
    roundtrip, `git apply` fails:
    
        printf "Added line\r\n" >>file &&
        git diff >patch &&
        git checkout -- . &&
        git apply patch
    
    Before applying the patch, the file from working tree is converted
    into the index format (clean filter, CRLF conversion, ...).  Here,
    when commited with CRLF, the line endings should not be converted.
    
    Note that `git apply --index` or `git apply --cache` doesn't call
    convert_to_git() because the source material is already in index
    format.
    
    Analyze the patch if there is a) any context line with CRLF, or b)
    if any line with CRLF is to be removed.  In this case the patch file
    `patch` has mixed line endings, for a) it looks like this:
    
        diff --git a/one b/one
        index 533790e..c30dea8 100644
        --- a/one
        +++ b/one
        @@ -1 +1,2 @@
         a\r
        +b\r
    
    And for b) it looks like this:
    
        diff --git a/one b/one
        index 533790e..485540d 100644
        --- a/one
        +++ b/one
        @@ -1 +1 @@
        -a\r
        +b\r
    
    If `git apply` detects that the patch itself has CRLF, (look at the
    line " a\r" or "-a\r" above), the new flag crlf_in_old is set in
    "struct patch" and two things will happen:
    
        - read_old_data() will not convert CRLF into LF by calling
          convert_to_git(..., SAFE_CRLF_KEEP_CRLF);
        - The WS_CR_AT_EOL bit is set in the "white space rule",
          CRLF are no longer treated as white space.
    
    While at there, make it clear that read_old_data() in apply.c knows
    what it wants convert_to_git() to do with respect to CRLF.  In fact,
    this codepath is about applying a patch to a file in the filesystem,
    which may not exist in the index, or may exist but may not match
    what is recorded in the index, or in the extreme case, we may not
    even be in a Git repository.  If convert_to_git() peeked at the
    index while doing its work, it *would* be a bug.
    
    Pass NULL instead of &the_index to convert_to_git() to make sure we
    catch future bugs to clarify this.
    
    Update the test in t4124: split one test case into 3:
    
        - Detect the " a\r" line in the patch
        - Detect the "-a\r" line in the patch
        - Use LF in repo and CLRF in the worktree.
    
    Reported-by: default avatarAnthony Sottile <asottile@umich.edu>
    Signed-off-by: default avatarTorsten Bögershausen <tboegi@web.de>
    Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
    c24f3aba