annotate mercurial/diffhelper.py @ 41987:c1d83d916e85

revert: option to choose what to keep, not what to discard I know the you (the reader) are probably tired of discussing how `hg revert -i -r .` should behave and so am I. And I know I'm one of the people who argued that showing the diff from the working copy to the parent was confusing. I think it is less confusing now that we show the diff from the parent to the working copy, but I still find it confusing. I think showing the diff of hunks to keep might make it easier to understand. So that's what this patch provides an option for. One argument doing it this way is that most people seem to find `hg split` natural. I suspect that is because it shows the forward diff (from parent commit to the commit) and asks you what to put in the first commit. I think the new "keep" mode for revert (this patch) matches that. In "keep" mode, all the changes are still selected by default. That means that `hg revert -i` followed by 'A' (keep all) (or 'c' in curses) will be different from `hg revert -a`. That's mostly because that was simplest. It can also be argued that it's safest. But it can also be argued that it should be consistent with `hg revert -a`. Note that in this mode, you can edit the hunks and it will do what you expect (e.g. add new lines to your file if you added a new lines when editing). The test case shows that that works. Differential Revision: https://phab.mercurial-scm.org/D6125
author Martin von Zweigbergk <martinvonz@google.com>
date Tue, 12 Mar 2019 14:17:41 -0700
parents e7aa113b14f7
children 57875cf423c9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
37803
72f6498c040b diffhelper: rename module to avoid conflicts with ancient C module (issue5846)
Yuya Nishihara <yuya@tcha.org>
parents: 37802
diff changeset
1 # diffhelper.py - helper routines for patch
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
2 #
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
4 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7702
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 8225
diff changeset
6 # GNU General Public License version 2 or any later version.
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
7
27336
80214358ac88 diffhelpers: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 12387
diff changeset
8 from __future__ import absolute_import
80214358ac88 diffhelpers: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 12387
diff changeset
9
37573
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
10 from .i18n import _
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
11
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
12 from . import (
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
13 error,
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37836
diff changeset
14 pycompat,
37573
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
15 )
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
16
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
17 def addlines(fp, hunk, lena, lenb, a, b):
37567
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
18 """Read lines from fp into the hunk
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
19
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
20 The hunk is parsed into two arrays, a and b. a gets the old state of
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
21 the text, b gets the new state. The control char from the hunk is saved
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
22 when inserting into a, but not b (for performance while deleting files.)
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
23 """
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
24 while True:
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
25 todoa = lena - len(a)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
26 todob = lenb - len(b)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
27 num = max(todoa, todob)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
28 if num == 0:
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
29 break
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37836
diff changeset
30 for i in pycompat.xrange(num):
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
31 s = fp.readline()
37573
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
32 if not s:
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
33 raise error.ParseError(_('incomplete hunk'))
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
34 if s == "\\ No newline at end of file\n":
37570
c4c8d0d1267f diffhelpers: naming and whitespace cleanup
Yuya Nishihara <yuya@tcha.org>
parents: 37567
diff changeset
35 fixnewline(hunk, a, b)
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
36 continue
37575
230eb9594150 diffhelpers: be more tolerant for stripped empty lines of CRLF ending
Yuya Nishihara <yuya@tcha.org>
parents: 37574
diff changeset
37 if s == '\n' or s == '\r\n':
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
38 # Some patches may be missing the control char
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
39 # on empty lines. Supply a leading space.
37575
230eb9594150 diffhelpers: be more tolerant for stripped empty lines of CRLF ending
Yuya Nishihara <yuya@tcha.org>
parents: 37574
diff changeset
40 s = ' ' + s
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
41 hunk.append(s)
37566
f53b55b162f4 py3: get rid of character access from pure.diffhelpers
Yuya Nishihara <yuya@tcha.org>
parents: 27336
diff changeset
42 if s.startswith('+'):
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
43 b.append(s[1:])
37566
f53b55b162f4 py3: get rid of character access from pure.diffhelpers
Yuya Nishihara <yuya@tcha.org>
parents: 27336
diff changeset
44 elif s.startswith('-'):
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
45 a.append(s)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
46 else:
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
47 b.append(s[1:])
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
48 a.append(s)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
49
37570
c4c8d0d1267f diffhelpers: naming and whitespace cleanup
Yuya Nishihara <yuya@tcha.org>
parents: 37567
diff changeset
50 def fixnewline(hunk, a, b):
37567
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
51 """Fix up the last lines of a and b when the patch has no newline at EOF"""
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
52 l = hunk[-1]
10551
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
53 # tolerate CRLF in last line
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
54 if l.endswith('\r\n'):
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
55 hline = l[:-2]
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
56 else:
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
57 hline = l[:-1]
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
58
37566
f53b55b162f4 py3: get rid of character access from pure.diffhelpers
Yuya Nishihara <yuya@tcha.org>
parents: 27336
diff changeset
59 if hline.startswith((' ', '+')):
10551
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
60 b[-1] = hline[1:]
37566
f53b55b162f4 py3: get rid of character access from pure.diffhelpers
Yuya Nishihara <yuya@tcha.org>
parents: 27336
diff changeset
61 if hline.startswith((' ', '-')):
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
62 a[-1] = hline
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
63 hunk[-1] = hline
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
64
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
65 def testhunk(a, b, bstart):
37567
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
66 """Compare the lines in a with the lines in b
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
67
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
68 a is assumed to have a control char at the start of each line, this char
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
69 is ignored in the compare.
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
70 """
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
71 alen = len(a)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
72 blen = len(b)
37802
090c89a8db32 diffhelpers: backport 9e40bc4c1bde from C implementation
Yuya Nishihara <yuya@tcha.org>
parents: 37575
diff changeset
73 if alen > blen - bstart or bstart < 0:
37574
a1bcc7ff0eac diffhelpers: make return value of testhunk() more Pythonic
Yuya Nishihara <yuya@tcha.org>
parents: 37573
diff changeset
74 return False
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37836
diff changeset
75 for i in pycompat.xrange(alen):
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
76 if a[i][1:] != b[i + bstart]:
37574
a1bcc7ff0eac diffhelpers: make return value of testhunk() more Pythonic
Yuya Nishihara <yuya@tcha.org>
parents: 37573
diff changeset
77 return False
a1bcc7ff0eac diffhelpers: make return value of testhunk() more Pythonic
Yuya Nishihara <yuya@tcha.org>
parents: 37573
diff changeset
78 return True