patch: write .rej files without rewriting EOLs
Do not pass reject file content to patchfile.writelines() to:
- Avoid line endings transformations
- Avoid polluting overriding implementations with unrelated data. They should
override write_rej() to deal or ignore reject files properly.
Bug report, analysis and original patch and test by
Shun-ichi GOTO <shunichi.goto@gmail.com>
--- a/mercurial/patch.py Thu Dec 02 01:28:38 2010 -0200
+++ b/mercurial/patch.py Fri Dec 03 11:40:30 2010 +0900
@@ -485,6 +485,15 @@
for x, s in enumerate(self.lines):
self.hash.setdefault(s, []).append(x)
+ def makerejlines(self, fname):
+ base = os.path.basename(fname)
+ yield "--- %s\n+++ %s\n" % (base, base)
+ for x in self.rej:
+ for l in x.hunk:
+ yield l
+ if l[-1] != '\n':
+ yield "\n\ No newline at end of file\n"
+
def write_rej(self):
# our rejects are a little different from patch(1). This always
# creates rejects in the same form as the original patch. A file
@@ -499,16 +508,9 @@
_("%d out of %d hunks FAILED -- saving rejects to file %s\n") %
(len(self.rej), self.hunks, fname))
- def rejlines():
- base = os.path.basename(self.fname)
- yield "--- %s\n+++ %s\n" % (base, base)
- for x in self.rej:
- for l in x.hunk:
- yield l
- if l[-1] != '\n':
- yield "\n\ No newline at end of file\n"
-
- self.writelines(fname, rejlines())
+ fp = self.opener(fname, 'w')
+ fp.writelines(self.makerejlines(self.fname))
+ fp.close()
def apply(self, h):
if not h.complete():
--- a/tests/test-mq-eol.t Thu Dec 02 01:28:38 2010 -0200
+++ b/tests/test-mq-eol.t Fri Dec 03 11:40:30 2010 +0900
@@ -141,3 +141,67 @@
$ hg qpop
popping eol.diff
patch queue now empty
+ $ cd ..
+
+
+Test .rej file EOL are left unchanged
+
+ $ hg init testeol
+ $ cd testeol
+ $ python -c "file('a', 'wb').write('1\r\n2\r\n3\r\n4')"
+ $ hg ci -Am adda
+ adding a
+ $ python -c "file('a', 'wb').write('1\r\n2\r\n33\r\n4')"
+ $ hg qnew patch1
+ $ hg qpop
+ popping patch1
+ patch queue now empty
+ $ python -c "file('a', 'wb').write('1\r\n22\r\n33\r\n4')"
+ $ hg ci -m changea
+
+ $ hg --config 'patch.eol=LF' qpush
+ applying patch1
+ patching file a
+ Hunk #1 FAILED at 0
+ 1 out of 1 hunks FAILED -- saving rejects to file a.rej
+ patch failed, unable to continue (try -v)
+ patch failed, rejects left in working dir
+ errors during apply, please fix and refresh patch1
+ [2]
+ $ hg qpop
+ popping patch1
+ patch queue now empty
+ $ cat a.rej
+ --- a
+ +++ a
+ @@ -1,4 +1,4 @@
+ 1\r (esc)
+ 2\r (esc)
+ -3\r (esc)
+ +33\r (esc)
+ 4
+ \ No newline at end of file
+
+ $ hg --config 'patch.eol=auto' qpush
+ applying patch1
+ patching file a
+ Hunk #1 FAILED at 0
+ 1 out of 1 hunks FAILED -- saving rejects to file a.rej
+ patch failed, unable to continue (try -v)
+ patch failed, rejects left in working dir
+ errors during apply, please fix and refresh patch1
+ [2]
+ $ hg qpop
+ popping patch1
+ patch queue now empty
+ $ cat a.rej
+ --- a
+ +++ a
+ @@ -1,4 +1,4 @@
+ 1\r (esc)
+ 2\r (esc)
+ -3\r (esc)
+ +33\r (esc)
+ 4
+ \ No newline at end of file
+ $ cd ..