From: Anthony Sottile <hidden> Date: 2017-08-01 18:24:10
Here's my minimal reproduction -- it's slightly far-fetched in that it
involves *committing crlf* and
then using `autocrlf=true` (commit lf, check out crlf).
#!/bin/bashset-exrm-rffoogitinitfoocdfoo# Commit crlf into repositorygitconfig--localcore.autocrlffalsepython3-c'open("foo","wb").write(b"1\r\n2\r\n")'gitaddfoogitcommit-m"Initial commit with crlf"# Change whitespace mode to autocrlf, "commit lf, checkout crlf"gitconfig--localcore.autocrlftruepython3-c'open("foo","wb").write(b"1\r\n2\r\n\r\n\r\n\r\n")'# Generate a patch, check it out, restore itgitdiff--ignore-submodules--binary--no-color--no-ext-diff>patchpython3-c'print(open("patch","rb").read())'gitcheckout--.# I expect this to succeed, it failsgitapplypatch
I also tried with `git apply --ignore-whitespace`, but this causes the
line endings of the existing contents to be changed to *lf* (there may
be two bugs here?)
Thanks,
Anthony
Here's my minimal reproduction -- it's slightly far-fetched in that it
involves*committing crlf* and
then using `autocrlf=true` (commit lf, check out crlf).
#!/bin/bashset-exrm-rffoogitinitfoocdfoo# Commit crlf into repositorygitconfig--localcore.autocrlffalsepython3-c'open("foo","wb").write(b"1\r\n2\r\n")'gitaddfoogitcommit-m"Initial commit with crlf"# Change whitespace mode to autocrlf, "commit lf, checkout crlf"gitconfig--localcore.autocrlftruepython3-c'open("foo","wb").write(b"1\r\n2\r\n\r\n\r\n\r\n")'# Generate a patch, check it out, restore itgitdiff--ignore-submodules--binary--no-color--no-ext-diff>patchpython3-c'print(open("patch","rb").read())'gitcheckout--.# I expect this to succeed, it failsgitapplypatch
I also tried with `git apply --ignore-whitespace`, but this causes the
line endings of the existing contents to be changed to*lf* (there may
be two bugs here?)
Thanks,
Anthony
I can reproduce you test case here.
The line
git apply patch
would succeed, if you temporally (for the runtime of the apply command) set
core.autocrlf to false:
git -c core.autocrlf=false apply patch
So this seems to be a bug (in a corner case ?):
Typically repos which had been commited with CRLF should be normalized,
which means that the CRLF in the repo are replaced by LF.
So you test script is a corner case, for which Git has not been designed,
It seems as if "git apply" gets things wrong here.
Especially, as the '\r' is not a whitespace as a white space. but part
of the line ending.
So in my understanding the "--ignore-whitespace" option shouldn't affect
the line endings at all.
Fixes are possible, does anyone have a clue, why the '\r' is handled
like this in apply ?
And out of interest: is this a real life problem ?
From: Anthony Sottile <hidden> Date: 2017-08-01 20:59:16
Here's where I'm hitting the problem described:
https://github.com/pre-commit/pre-commit/issues/570
Note that `git -c core.autocrlf=false` apply patch fixes this
situation, but breaks others.
Here's a testcase where `git -c core.autocrlf=false apply patch`
causes a *different* patch failure:
#!/bin/bashset-exrm-rffoogitinitfoocdfoogitconfig--localcore.autocrlftrue# Commit lf into repositorypython3-c'open("foo","wb").write(b"1\r\n2\r\n")'gitaddfoopython3-c'open("foo","wb").write(b"3\n4\n")'# Generate a patch, check it out, restore itgitdiff--ignore-submodules--binary--no-color--no-ext-diff>patchpython3-c'print(open("patch","rb").read())'gitcheckout--.git-ccore.autocrlf=falseapplypatch
My current workaround is:
- try `git apply patch`
- try `git -c core.autocrlf=false apply patch`
which seems to work pretty well.
Anthony
On Tue, Aug 1, 2017 at 1:47 PM, Torsten Bögershausen [off-list ref] wrote:
On 08/01/2017 08:24 PM, Anthony Sottile wrote:
quoted
Here's my minimal reproduction -- it's slightly far-fetched in that it
involves*committing crlf* and
then using `autocrlf=true` (commit lf, check out crlf).
#!/bin/bashset-exrm-rffoogitinitfoocdfoo# Commit crlf into repositorygitconfig--localcore.autocrlffalsepython3-c'open("foo","wb").write(b"1\r\n2\r\n")'gitaddfoogitcommit-m"Initial commit with crlf"# Change whitespace mode to autocrlf, "commit lf, checkout crlf"gitconfig--localcore.autocrlftruepython3-c'open("foo","wb").write(b"1\r\n2\r\n\r\n\r\n\r\n")'# Generate a patch, check it out, restore itgitdiff--ignore-submodules--binary--no-color--no-ext-diff>patchpython3-c'print(open("patch","rb").read())'gitcheckout--.# I expect this to succeed, it failsgitapplypatch
I also tried with `git apply --ignore-whitespace`, but this causes the
line endings of the existing contents to be changed to*lf* (there may
be two bugs here?)
Thanks,
Anthony
I can reproduce you test case here.
The line
git apply patch
would succeed, if you temporally (for the runtime of the apply command) set
core.autocrlf to false:
git -c core.autocrlf=false apply patch
So this seems to be a bug (in a corner case ?):
Typically repos which had been commited with CRLF should be normalized,
which means that the CRLF in the repo are replaced by LF.
So you test script is a corner case, for which Git has not been designed,
It seems as if "git apply" gets things wrong here.
Especially, as the '\r' is not a whitespace as a white space. but part
of the line ending.
So in my understanding the "--ignore-whitespace" option shouldn't affect
the line endings at all.
Fixes are possible, does anyone have a clue, why the '\r' is handled
like this in apply ?
And out of interest: is this a real life problem ?
[]
I wasn't thinking of that - and thanks for the detailed report.
I seems as there are 3 things to be done:
- Make a workaround in your scripts/tools. It seems as if that is
already done.
- Fix Git.
My very first investigation shows that a patch like this could fix
the problem:
@@ -2278,6 +2278,8 @@ static int read_old_data(struct stat *st, const
char *path, struct strbuf *buf)
case S_IFREG:
if (strbuf_read_file(buf, path, st->st_size) !=
st->st_size)
return error(_("unable to open or read %s"), path);
+ if (would_convert_to_git(&the_index, path))
+ read_cache();
convert_to_git(&the_index, path, buf->buf, buf->len,
buf, 0);
return 0;
default:
----------------
I will probably do some more investigations if this is the core
problem, so it will take some days or weeks.
- Convince people to normalize their repos and convert all CRLF in the
repo into LF.
This may take even longer.
From: Torsten Bögershausen <redacted>
git apply does not find the source lines when files have CRLF in the index
and core.autocrlf is true:
These files should not get the CRLF converted to LF. Because cmd_apply()
does not load the index, this does not work, CRLF are converted into LF
and apply fails.
Fix this in the spirit of commit a08feb8ef0b6,
"correct blame for files commited with CRLF" by loading the index.
As an optimization, skip read_cache() when no conversion is specified
for this path.
Reported-by: Anthony Sottile <redacted>
Signed-off-by: Torsten Bögershausen <redacted>
---
apply.c | 2 ++
t/t0020-crlf.sh | 12 ++++++++++++
2 files changed, 14 insertions(+)
@@ -2278,6 +2278,8 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)caseS_IFREG:if(strbuf_read_file(buf,path,st->st_size)!=st->st_size)returnerror(_("unable to open or read %s"),path);+if(would_convert_to_git(&the_index,path))+read_cache();convert_to_git(&the_index,path,buf->buf,buf->len,buf,0);return0;default: