Mercurial > hg
comparison tests/test-absorb-filefixupstate.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | dcda50856843 |
children | 89a2afe31e82 |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
2 | 2 |
3 import itertools | 3 import itertools |
4 from mercurial import pycompat | 4 from mercurial import pycompat |
5 from hgext import absorb | 5 from hgext import absorb |
6 | 6 |
7 | |
7 class simplefctx(object): | 8 class simplefctx(object): |
8 def __init__(self, content): | 9 def __init__(self, content): |
9 self.content = content | 10 self.content = content |
10 | 11 |
11 def data(self): | 12 def data(self): |
12 return self.content | 13 return self.content |
14 | |
13 | 15 |
14 def insertreturns(x): | 16 def insertreturns(x): |
15 # insert "\n"s after each single char | 17 # insert "\n"s after each single char |
16 if isinstance(x, bytes): | 18 if isinstance(x, bytes): |
17 return b''.join(ch + b'\n' for ch in pycompat.bytestr(x)) | 19 return b''.join(ch + b'\n' for ch in pycompat.bytestr(x)) |
18 else: | 20 else: |
19 return pycompat.maplist(insertreturns, x) | 21 return pycompat.maplist(insertreturns, x) |
20 | 22 |
23 | |
21 def removereturns(x): | 24 def removereturns(x): |
22 # the revert of "insertreturns" | 25 # the revert of "insertreturns" |
23 if isinstance(x, bytes): | 26 if isinstance(x, bytes): |
24 return x.replace(b'\n', b'') | 27 return x.replace(b'\n', b'') |
25 else: | 28 else: |
26 return pycompat.maplist(removereturns, x) | 29 return pycompat.maplist(removereturns, x) |
27 | 30 |
31 | |
28 def assertlistequal(lhs, rhs, decorator=lambda x: x): | 32 def assertlistequal(lhs, rhs, decorator=lambda x: x): |
29 if lhs != rhs: | 33 if lhs != rhs: |
30 raise RuntimeError('mismatch:\n actual: %r\n expected: %r' | 34 raise RuntimeError( |
31 % tuple(map(decorator, [lhs, rhs]))) | 35 'mismatch:\n actual: %r\n expected: %r' |
36 % tuple(map(decorator, [lhs, rhs])) | |
37 ) | |
38 | |
32 | 39 |
33 def testfilefixup(oldcontents, workingcopy, expectedcontents, fixups=None): | 40 def testfilefixup(oldcontents, workingcopy, expectedcontents, fixups=None): |
34 """([str], str, [str], [(rev, a1, a2, b1, b2)]?) -> None | 41 """([str], str, [str], [(rev, a1, a2, b1, b2)]?) -> None |
35 | 42 |
36 workingcopy is a string, of which every character denotes a single line. | 43 workingcopy is a string, of which every character denotes a single line. |
41 if fixups is not None, it's the expected fixups list and will be checked. | 48 if fixups is not None, it's the expected fixups list and will be checked. |
42 """ | 49 """ |
43 expectedcontents = insertreturns(expectedcontents) | 50 expectedcontents = insertreturns(expectedcontents) |
44 oldcontents = insertreturns(oldcontents) | 51 oldcontents = insertreturns(oldcontents) |
45 workingcopy = insertreturns(workingcopy) | 52 workingcopy = insertreturns(workingcopy) |
46 state = absorb.filefixupstate(pycompat.maplist(simplefctx, oldcontents), | 53 state = absorb.filefixupstate( |
47 'path') | 54 pycompat.maplist(simplefctx, oldcontents), 'path' |
55 ) | |
48 state.diffwith(simplefctx(workingcopy)) | 56 state.diffwith(simplefctx(workingcopy)) |
49 if fixups is not None: | 57 if fixups is not None: |
50 assertlistequal(state.fixups, fixups) | 58 assertlistequal(state.fixups, fixups) |
51 state.apply() | 59 state.apply() |
52 assertlistequal(state.finalcontents, expectedcontents, removereturns) | 60 assertlistequal(state.finalcontents, expectedcontents, removereturns) |
53 | 61 |
62 | |
54 def buildcontents(linesrevs): | 63 def buildcontents(linesrevs): |
55 # linesrevs: [(linecontent : str, revs : [int])] | 64 # linesrevs: [(linecontent : str, revs : [int])] |
56 revs = set(itertools.chain(*[revs for line, revs in linesrevs])) | 65 revs = set(itertools.chain(*[revs for line, revs in linesrevs])) |
57 return [b''] + [ | 66 return [b''] + [ |
58 b''.join([l for l, rs in linesrevs if r in rs]) | 67 b''.join([l for l, rs in linesrevs if r in rs]) for r in sorted(revs) |
59 for r in sorted(revs) | |
60 ] | 68 ] |
69 | |
61 | 70 |
62 # input case 0: one single commit | 71 # input case 0: one single commit |
63 case0 = [b'', b'11'] | 72 case0 = [b'', b'11'] |
64 | 73 |
65 # replace a single chunk | 74 # replace a single chunk |
67 testfilefixup(case0, b'2', [b'', b'2']) | 76 testfilefixup(case0, b'2', [b'', b'2']) |
68 testfilefixup(case0, b'22', [b'', b'22']) | 77 testfilefixup(case0, b'22', [b'', b'22']) |
69 testfilefixup(case0, b'222', [b'', b'222']) | 78 testfilefixup(case0, b'222', [b'', b'222']) |
70 | 79 |
71 # input case 1: 3 lines, each commit adds one line | 80 # input case 1: 3 lines, each commit adds one line |
72 case1 = buildcontents([ | 81 case1 = buildcontents([(b'1', [1, 2, 3]), (b'2', [2, 3]), (b'3', [3]),]) |
73 (b'1', [1, 2, 3]), | |
74 (b'2', [ 2, 3]), | |
75 (b'3', [ 3]), | |
76 ]) | |
77 | 82 |
78 # 1:1 line mapping | 83 # 1:1 line mapping |
79 testfilefixup(case1, b'123', case1) | 84 testfilefixup(case1, b'123', case1) |
80 testfilefixup(case1, b'12c', [b'', b'1', b'12', b'12c']) | 85 testfilefixup(case1, b'12c', [b'', b'1', b'12', b'12c']) |
81 testfilefixup(case1, b'1b3', [b'', b'1', b'1b', b'1b3']) | 86 testfilefixup(case1, b'1b3', [b'', b'1', b'1b', b'1b3']) |
88 # non 1:1 edits | 93 # non 1:1 edits |
89 testfilefixup(case1, b'abcd', case1) | 94 testfilefixup(case1, b'abcd', case1) |
90 testfilefixup(case1, b'ab', case1) | 95 testfilefixup(case1, b'ab', case1) |
91 | 96 |
92 # deletion | 97 # deletion |
93 testfilefixup(case1, b'', [b'', b'', b'', b'']) | 98 testfilefixup(case1, b'', [b'', b'', b'', b'']) |
94 testfilefixup(case1, b'1', [b'', b'1', b'1', b'1']) | 99 testfilefixup(case1, b'1', [b'', b'1', b'1', b'1']) |
95 testfilefixup(case1, b'2', [b'', b'', b'2', b'2']) | 100 testfilefixup(case1, b'2', [b'', b'', b'2', b'2']) |
96 testfilefixup(case1, b'3', [b'', b'', b'', b'3']) | 101 testfilefixup(case1, b'3', [b'', b'', b'', b'3']) |
97 testfilefixup(case1, b'13', [b'', b'1', b'1', b'13']) | 102 testfilefixup(case1, b'13', [b'', b'1', b'1', b'13']) |
98 | 103 |
99 # replaces | 104 # replaces |
100 testfilefixup(case1, b'1bb3', [b'', b'1', b'1bb', b'1bb3']) | 105 testfilefixup(case1, b'1bb3', [b'', b'1', b'1bb', b'1bb3']) |
101 | 106 |
114 # (confusing) insertions | 119 # (confusing) insertions |
115 testfilefixup(case1, b'1a23', case1) | 120 testfilefixup(case1, b'1a23', case1) |
116 testfilefixup(case1, b'12b3', case1) | 121 testfilefixup(case1, b'12b3', case1) |
117 | 122 |
118 # input case 2: delete in the middle | 123 # input case 2: delete in the middle |
119 case2 = buildcontents([ | 124 case2 = buildcontents([(b'11', [1, 2]), (b'22', [1]), (b'33', [1, 2]),]) |
120 (b'11', [1, 2]), | |
121 (b'22', [1 ]), | |
122 (b'33', [1, 2]), | |
123 ]) | |
124 | 125 |
125 # deletion (optimize code should make it 2 chunks) | 126 # deletion (optimize code should make it 2 chunks) |
126 testfilefixup(case2, b'', [b'', b'22', b''], | 127 testfilefixup( |
127 fixups=[(4, 0, 2, 0, 0), (4, 2, 4, 0, 0)]) | 128 case2, b'', [b'', b'22', b''], fixups=[(4, 0, 2, 0, 0), (4, 2, 4, 0, 0)] |
129 ) | |
128 | 130 |
129 # 1:1 line mapping | 131 # 1:1 line mapping |
130 testfilefixup(case2, b'aaaa', [b'', b'aa22aa', b'aaaa']) | 132 testfilefixup(case2, b'aaaa', [b'', b'aa22aa', b'aaaa']) |
131 | 133 |
132 # non 1:1 edits | 134 # non 1:1 edits |
133 # note: unlike case0, the chunk is not "continuous" and no edit allowed | 135 # note: unlike case0, the chunk is not "continuous" and no edit allowed |
134 testfilefixup(case2, b'aaa', case2) | 136 testfilefixup(case2, b'aaa', case2) |
135 | 137 |
136 # input case 3: rev 3 reverts rev 2 | 138 # input case 3: rev 3 reverts rev 2 |
137 case3 = buildcontents([ | 139 case3 = buildcontents([(b'1', [1, 2, 3]), (b'2', [2]), (b'3', [1, 2, 3]),]) |
138 (b'1', [1, 2, 3]), | |
139 (b'2', [ 2 ]), | |
140 (b'3', [1, 2, 3]), | |
141 ]) | |
142 | 140 |
143 # 1:1 line mapping | 141 # 1:1 line mapping |
144 testfilefixup(case3, b'13', case3) | 142 testfilefixup(case3, b'13', case3) |
145 testfilefixup(case3, b'1b', [b'', b'1b', b'12b', b'1b']) | 143 testfilefixup(case3, b'1b', [b'', b'1b', b'12b', b'1b']) |
146 testfilefixup(case3, b'a3', [b'', b'a3', b'a23', b'a3']) | 144 testfilefixup(case3, b'a3', [b'', b'a3', b'a23', b'a3']) |
155 | 153 |
156 # insertion | 154 # insertion |
157 testfilefixup(case3, b'a13c', [b'', b'a13c', b'a123c', b'a13c']) | 155 testfilefixup(case3, b'a13c', [b'', b'a13c', b'a123c', b'a13c']) |
158 | 156 |
159 # input case 4: a slightly complex case | 157 # input case 4: a slightly complex case |
160 case4 = buildcontents([ | 158 case4 = buildcontents( |
161 (b'1', [1, 2, 3]), | 159 [ |
162 (b'2', [ 2, 3]), | 160 (b'1', [1, 2, 3]), |
163 (b'3', [1, 2, ]), | 161 (b'2', [2, 3]), |
164 (b'4', [1, 3]), | 162 (b'3', [1, 2,]), |
165 (b'5', [ 3]), | 163 (b'4', [1, 3]), |
166 (b'6', [ 2, 3]), | 164 (b'5', [3]), |
167 (b'7', [ 2 ]), | 165 (b'6', [2, 3]), |
168 (b'8', [ 2, 3]), | 166 (b'7', [2]), |
169 (b'9', [ 3]), | 167 (b'8', [2, 3]), |
170 ]) | 168 (b'9', [3]), |
169 ] | |
170 ) | |
171 | 171 |
172 testfilefixup(case4, b'1245689', case4) | 172 testfilefixup(case4, b'1245689', case4) |
173 testfilefixup(case4, b'1a2456bbb', case4) | 173 testfilefixup(case4, b'1a2456bbb', case4) |
174 testfilefixup(case4, b'1abc5689', case4) | 174 testfilefixup(case4, b'1abc5689', case4) |
175 testfilefixup(case4, b'1ab5689', [b'', b'134', b'1a3678', b'1ab5689']) | 175 testfilefixup(case4, b'1ab5689', [b'', b'134', b'1a3678', b'1ab5689']) |
176 testfilefixup(case4, b'aa2bcd8ee', [b'', b'aa34', b'aa23d78', b'aa2bcd8ee']) | 176 testfilefixup(case4, b'aa2bcd8ee', [b'', b'aa34', b'aa23d78', b'aa2bcd8ee']) |
177 testfilefixup(case4, b'aa2bcdd8ee',[b'', b'aa34', b'aa23678', b'aa24568ee']) | 177 testfilefixup(case4, b'aa2bcdd8ee', [b'', b'aa34', b'aa23678', b'aa24568ee']) |
178 testfilefixup(case4, b'aaaaaa', case4) | 178 testfilefixup(case4, b'aaaaaa', case4) |
179 testfilefixup(case4, b'aa258b', [b'', b'aa34', b'aa2378', b'aa258b']) | 179 testfilefixup(case4, b'aa258b', [b'', b'aa34', b'aa2378', b'aa258b']) |
180 testfilefixup(case4, b'25bb', [b'', b'34', b'23678', b'25689']) | 180 testfilefixup(case4, b'25bb', [b'', b'34', b'23678', b'25689']) |
181 testfilefixup(case4, b'27', [b'', b'34', b'23678', b'245689']) | 181 testfilefixup(case4, b'27', [b'', b'34', b'23678', b'245689']) |
182 testfilefixup(case4, b'28', [b'', b'34', b'2378', b'28']) | 182 testfilefixup(case4, b'28', [b'', b'34', b'2378', b'28']) |
183 testfilefixup(case4, b'', [b'', b'34', b'37', b'']) | 183 testfilefixup(case4, b'', [b'', b'34', b'37', b'']) |
184 | 184 |
185 # input case 5: replace a small chunk which is near a deleted line | 185 # input case 5: replace a small chunk which is near a deleted line |
186 case5 = buildcontents([ | 186 case5 = buildcontents([(b'12', [1, 2]), (b'3', [1]), (b'4', [1, 2]),]) |
187 (b'12', [1, 2]), | |
188 (b'3', [1]), | |
189 (b'4', [1, 2]), | |
190 ]) | |
191 | 187 |
192 testfilefixup(case5, b'1cd4', [b'', b'1cd34', b'1cd4']) | 188 testfilefixup(case5, b'1cd4', [b'', b'1cd34', b'1cd4']) |
193 | 189 |
194 # input case 6: base "changeset" is immutable | 190 # input case 6: base "changeset" is immutable |
195 case6 = [b'1357', b'0125678'] | 191 case6 = [b'1357', b'0125678'] |