Merge lp:~spiv/bzr/merge-minor-refactoring into lp:bzr
- merge-minor-refactoring
- Merge into bzr.dev
Proposed by
Andrew Bennetts
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~spiv/bzr/merge-minor-refactoring |
Merge into: | lp:bzr |
Diff against target: |
456 lines (+198/-167) 5 files modified
bzrlib/merge.py (+1/-2) bzrlib/tests/__init__.py (+1/-0) bzrlib/tests/per_merger.py (+191/-0) bzrlib/tests/test_merge.py (+1/-155) bzrlib/tests/test_merge_core.py (+4/-10) |
To merge this branch: | bzr merge lp:~spiv/bzr/merge-minor-refactoring |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Pool | Approve | ||
Review via email: mp+16326@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Andrew Bennetts (spiv) wrote : | # |
Revision history for this message
Martin Pool (mbp) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'bzrlib/merge.py' |
2 | --- bzrlib/merge.py 2009-12-10 17:16:19 +0000 |
3 | +++ bzrlib/merge.py 2009-12-18 08:25:25 +0000 |
4 | @@ -25,7 +25,6 @@ |
5 | osutils, |
6 | patiencediff, |
7 | progress, |
8 | - registry, |
9 | revision as _mod_revision, |
10 | textfile, |
11 | trace, |
12 | @@ -240,7 +239,7 @@ |
13 | if self.other_rev_id is None: |
14 | other_basis_tree = self.revision_tree(self.other_basis) |
15 | if other_basis_tree.has_changes(self.other_tree): |
16 | - raise WorkingTreeNotRevision(self.this_tree) |
17 | + raise errors.WorkingTreeNotRevision(self.this_tree) |
18 | other_rev_id = self.other_basis |
19 | self.other_tree = other_basis_tree |
20 | |
21 | |
22 | === modified file 'bzrlib/tests/__init__.py' |
23 | --- bzrlib/tests/__init__.py 2009-12-08 21:46:07 +0000 |
24 | +++ bzrlib/tests/__init__.py 2009-12-18 08:25:25 +0000 |
25 | @@ -3746,6 +3746,7 @@ |
26 | 'bzrlib.tests.per_inventory', |
27 | 'bzrlib.tests.per_interbranch', |
28 | 'bzrlib.tests.per_lock', |
29 | + 'bzrlib.tests.per_merger', |
30 | 'bzrlib.tests.per_transport', |
31 | 'bzrlib.tests.per_tree', |
32 | 'bzrlib.tests.per_pack_repository', |
33 | |
34 | === added file 'bzrlib/tests/per_merger.py' |
35 | --- bzrlib/tests/per_merger.py 1970-01-01 00:00:00 +0000 |
36 | +++ bzrlib/tests/per_merger.py 2009-12-18 08:25:25 +0000 |
37 | @@ -0,0 +1,191 @@ |
38 | +# Copyright (C) 2009 Canonical Ltd |
39 | +# |
40 | +# This program is free software; you can redistribute it and/or modify |
41 | +# it under the terms of the GNU General Public License as published by |
42 | +# the Free Software Foundation; either version 2 of the License, or |
43 | +# (at your option) any later version. |
44 | +# |
45 | +# This program is distributed in the hope that it will be useful, |
46 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
47 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
48 | +# GNU General Public License for more details. |
49 | +# |
50 | +# You should have received a copy of the GNU General Public License |
51 | +# along with this program; if not, write to the Free Software |
52 | +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
53 | + |
54 | +"""Implementation tests for bzrlib.merge.Merger.""" |
55 | + |
56 | +import os |
57 | + |
58 | +from bzrlib import ( |
59 | + errors, |
60 | + merge as _mod_merge, |
61 | + option, |
62 | + progress, |
63 | + ) |
64 | +from bzrlib.tests import ( |
65 | + multiply_tests, |
66 | + TestCaseWithTransport, |
67 | + ) |
68 | +from bzrlib.transform import TreeTransform |
69 | + |
70 | + |
71 | + |
72 | +def load_tests(standard_tests, module, loader): |
73 | + """Multiply tests for tranport implementations.""" |
74 | + result = loader.suiteClass() |
75 | + scenarios = [ |
76 | + (name, {'merge_type': merger}) |
77 | + for name, merger in option._merge_type_registry.items()] |
78 | + return multiply_tests(standard_tests, scenarios, result) |
79 | + |
80 | + |
81 | +class TestMergeImplementation(TestCaseWithTransport): |
82 | + |
83 | + def do_merge(self, target_tree, source_tree, **kwargs): |
84 | + merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(), |
85 | + target_tree, source_tree.last_revision(), |
86 | + other_branch=source_tree.branch) |
87 | + merger.merge_type=self.merge_type |
88 | + for name, value in kwargs.items(): |
89 | + setattr(merger, name, value) |
90 | + merger.do_merge() |
91 | + |
92 | + def test_merge_specific_file(self): |
93 | + this_tree = self.make_branch_and_tree('this') |
94 | + this_tree.lock_write() |
95 | + self.addCleanup(this_tree.unlock) |
96 | + self.build_tree_contents([ |
97 | + ('this/file1', 'a\nb\n'), |
98 | + ('this/file2', 'a\nb\n') |
99 | + ]) |
100 | + this_tree.add(['file1', 'file2']) |
101 | + this_tree.commit('Added files') |
102 | + other_tree = this_tree.bzrdir.sprout('other').open_workingtree() |
103 | + self.build_tree_contents([ |
104 | + ('other/file1', 'a\nb\nc\n'), |
105 | + ('other/file2', 'a\nb\nc\n') |
106 | + ]) |
107 | + other_tree.commit('modified both') |
108 | + self.build_tree_contents([ |
109 | + ('this/file1', 'd\na\nb\n'), |
110 | + ('this/file2', 'd\na\nb\n') |
111 | + ]) |
112 | + this_tree.commit('modified both') |
113 | + self.do_merge(this_tree, other_tree, interesting_files=['file1']) |
114 | + self.assertFileEqual('d\na\nb\nc\n', 'this/file1') |
115 | + self.assertFileEqual('d\na\nb\n', 'this/file2') |
116 | + |
117 | + def test_merge_move_and_change(self): |
118 | + this_tree = self.make_branch_and_tree('this') |
119 | + this_tree.lock_write() |
120 | + self.addCleanup(this_tree.unlock) |
121 | + self.build_tree_contents([ |
122 | + ('this/file1', 'line 1\nline 2\nline 3\nline 4\n'), |
123 | + ]) |
124 | + this_tree.add('file1',) |
125 | + this_tree.commit('Added file') |
126 | + other_tree = this_tree.bzrdir.sprout('other').open_workingtree() |
127 | + self.build_tree_contents([ |
128 | + ('other/file1', 'line 1\nline 2 to 2.1\nline 3\nline 4\n'), |
129 | + ]) |
130 | + other_tree.commit('Changed 2 to 2.1') |
131 | + self.build_tree_contents([ |
132 | + ('this/file1', 'line 1\nline 3\nline 2\nline 4\n'), |
133 | + ]) |
134 | + this_tree.commit('Swapped 2 & 3') |
135 | + self.do_merge(this_tree, other_tree) |
136 | + if self.merge_type is _mod_merge.LCAMerger: |
137 | + self.expectFailure( |
138 | + "lca merge doesn't conflict for move and change", |
139 | + self.assertFileEqual, |
140 | + 'line 1\n' |
141 | + '<<<<<<< TREE\n' |
142 | + 'line 3\n' |
143 | + 'line 2\n' |
144 | + '=======\n' |
145 | + 'line 2 to 2.1\n' |
146 | + 'line 3\n' |
147 | + '>>>>>>> MERGE-SOURCE\n' |
148 | + 'line 4\n', 'this/file1') |
149 | + else: |
150 | + self.assertFileEqual('line 1\n' |
151 | + '<<<<<<< TREE\n' |
152 | + 'line 3\n' |
153 | + 'line 2\n' |
154 | + '=======\n' |
155 | + 'line 2 to 2.1\n' |
156 | + 'line 3\n' |
157 | + '>>>>>>> MERGE-SOURCE\n' |
158 | + 'line 4\n', 'this/file1') |
159 | + |
160 | + def test_modify_conflicts_with_delete(self): |
161 | + # If one side deletes a line, and the other modifies that line, then |
162 | + # the modification should be considered a conflict |
163 | + builder = self.make_branch_builder('test') |
164 | + builder.start_series() |
165 | + builder.build_snapshot('BASE-id', None, |
166 | + [('add', ('', None, 'directory', None)), |
167 | + ('add', ('foo', 'foo-id', 'file', 'a\nb\nc\nd\ne\n')), |
168 | + ]) |
169 | + # Delete 'b\n' |
170 | + builder.build_snapshot('OTHER-id', ['BASE-id'], |
171 | + [('modify', ('foo-id', 'a\nc\nd\ne\n'))]) |
172 | + # Modify 'b\n', add 'X\n' |
173 | + builder.build_snapshot('THIS-id', ['BASE-id'], |
174 | + [('modify', ('foo-id', 'a\nb2\nc\nd\nX\ne\n'))]) |
175 | + builder.finish_series() |
176 | + branch = builder.get_branch() |
177 | + this_tree = branch.bzrdir.create_workingtree() |
178 | + this_tree.lock_write() |
179 | + self.addCleanup(this_tree.unlock) |
180 | + other_tree = this_tree.bzrdir.sprout('other', 'OTHER-id').open_workingtree() |
181 | + self.do_merge(this_tree, other_tree) |
182 | + if self.merge_type is _mod_merge.LCAMerger: |
183 | + self.expectFailure("lca merge doesn't track deleted lines", |
184 | + self.assertFileEqual, |
185 | + 'a\n' |
186 | + '<<<<<<< TREE\n' |
187 | + 'b2\n' |
188 | + '=======\n' |
189 | + '>>>>>>> MERGE-SOURCE\n' |
190 | + 'c\n' |
191 | + 'd\n' |
192 | + 'X\n' |
193 | + 'e\n', 'test/foo') |
194 | + else: |
195 | + self.assertFileEqual( |
196 | + 'a\n' |
197 | + '<<<<<<< TREE\n' |
198 | + 'b2\n' |
199 | + '=======\n' |
200 | + '>>>>>>> MERGE-SOURCE\n' |
201 | + 'c\n' |
202 | + 'd\n' |
203 | + 'X\n' |
204 | + 'e\n', 'test/foo') |
205 | + |
206 | + def get_limbodir_deletiondir(self, wt): |
207 | + transform = TreeTransform(wt) |
208 | + limbodir = transform._limbodir |
209 | + deletiondir = transform._deletiondir |
210 | + transform.finalize() |
211 | + return (limbodir, deletiondir) |
212 | + |
213 | + def test_merge_with_existing_limbo(self): |
214 | + wt = self.make_branch_and_tree('this') |
215 | + (limbodir, deletiondir) = self.get_limbodir_deletiondir(wt) |
216 | + os.mkdir(limbodir) |
217 | + self.assertRaises(errors.ExistingLimbo, self.do_merge, wt, wt) |
218 | + self.assertRaises(errors.LockError, wt.unlock) |
219 | + |
220 | + def test_merge_with_pending_deletion(self): |
221 | + wt = self.make_branch_and_tree('this') |
222 | + (limbodir, deletiondir) = self.get_limbodir_deletiondir(wt) |
223 | + os.mkdir(deletiondir) |
224 | + self.assertRaises(errors.ExistingPendingDeletion, self.do_merge, wt, wt) |
225 | + self.assertRaises(errors.LockError, wt.unlock) |
226 | + |
227 | + |
228 | + |
229 | |
230 | === modified file 'bzrlib/tests/test_merge.py' |
231 | --- bzrlib/tests/test_merge.py 2009-12-10 17:16:19 +0000 |
232 | +++ bzrlib/tests/test_merge.py 2009-12-18 08:25:25 +0000 |
233 | @@ -29,14 +29,12 @@ |
234 | transform, |
235 | versionedfile, |
236 | ) |
237 | -from bzrlib.branch import Branch |
238 | from bzrlib.conflicts import ConflictList, TextConflict |
239 | -from bzrlib.errors import UnrelatedBranches, NoCommits, BzrCommandError |
240 | +from bzrlib.errors import UnrelatedBranches, NoCommits |
241 | from bzrlib.merge import transform_tree, merge_inner, _PlanMerge |
242 | from bzrlib.osutils import pathjoin, file_kind |
243 | from bzrlib.tests import TestCaseWithTransport, TestCaseWithMemoryTransport |
244 | from bzrlib.workingtree import WorkingTree |
245 | -from bzrlib.transform import TreeTransform |
246 | |
247 | |
248 | class TestMerge(TestCaseWithTransport): |
249 | @@ -1144,158 +1142,6 @@ |
250 | ], list(plan)) |
251 | |
252 | |
253 | -class TestMergeImplementation(object): |
254 | - |
255 | - def do_merge(self, target_tree, source_tree, **kwargs): |
256 | - merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(), |
257 | - target_tree, source_tree.last_revision(), |
258 | - other_branch=source_tree.branch) |
259 | - merger.merge_type=self.merge_type |
260 | - for name, value in kwargs.items(): |
261 | - setattr(merger, name, value) |
262 | - merger.do_merge() |
263 | - |
264 | - def test_merge_specific_file(self): |
265 | - this_tree = self.make_branch_and_tree('this') |
266 | - this_tree.lock_write() |
267 | - self.addCleanup(this_tree.unlock) |
268 | - self.build_tree_contents([ |
269 | - ('this/file1', 'a\nb\n'), |
270 | - ('this/file2', 'a\nb\n') |
271 | - ]) |
272 | - this_tree.add(['file1', 'file2']) |
273 | - this_tree.commit('Added files') |
274 | - other_tree = this_tree.bzrdir.sprout('other').open_workingtree() |
275 | - self.build_tree_contents([ |
276 | - ('other/file1', 'a\nb\nc\n'), |
277 | - ('other/file2', 'a\nb\nc\n') |
278 | - ]) |
279 | - other_tree.commit('modified both') |
280 | - self.build_tree_contents([ |
281 | - ('this/file1', 'd\na\nb\n'), |
282 | - ('this/file2', 'd\na\nb\n') |
283 | - ]) |
284 | - this_tree.commit('modified both') |
285 | - self.do_merge(this_tree, other_tree, interesting_files=['file1']) |
286 | - self.assertFileEqual('d\na\nb\nc\n', 'this/file1') |
287 | - self.assertFileEqual('d\na\nb\n', 'this/file2') |
288 | - |
289 | - def test_merge_move_and_change(self): |
290 | - this_tree = self.make_branch_and_tree('this') |
291 | - this_tree.lock_write() |
292 | - self.addCleanup(this_tree.unlock) |
293 | - self.build_tree_contents([ |
294 | - ('this/file1', 'line 1\nline 2\nline 3\nline 4\n'), |
295 | - ]) |
296 | - this_tree.add('file1',) |
297 | - this_tree.commit('Added file') |
298 | - other_tree = this_tree.bzrdir.sprout('other').open_workingtree() |
299 | - self.build_tree_contents([ |
300 | - ('other/file1', 'line 1\nline 2 to 2.1\nline 3\nline 4\n'), |
301 | - ]) |
302 | - other_tree.commit('Changed 2 to 2.1') |
303 | - self.build_tree_contents([ |
304 | - ('this/file1', 'line 1\nline 3\nline 2\nline 4\n'), |
305 | - ]) |
306 | - this_tree.commit('Swapped 2 & 3') |
307 | - self.do_merge(this_tree, other_tree) |
308 | - self.assertFileEqual('line 1\n' |
309 | - '<<<<<<< TREE\n' |
310 | - 'line 3\n' |
311 | - 'line 2\n' |
312 | - '=======\n' |
313 | - 'line 2 to 2.1\n' |
314 | - 'line 3\n' |
315 | - '>>>>>>> MERGE-SOURCE\n' |
316 | - 'line 4\n', 'this/file1') |
317 | - |
318 | - def test_modify_conflicts_with_delete(self): |
319 | - # If one side deletes a line, and the other modifies that line, then |
320 | - # the modification should be considered a conflict |
321 | - builder = self.make_branch_builder('test') |
322 | - builder.start_series() |
323 | - builder.build_snapshot('BASE-id', None, |
324 | - [('add', ('', None, 'directory', None)), |
325 | - ('add', ('foo', 'foo-id', 'file', 'a\nb\nc\nd\ne\n')), |
326 | - ]) |
327 | - # Delete 'b\n' |
328 | - builder.build_snapshot('OTHER-id', ['BASE-id'], |
329 | - [('modify', ('foo-id', 'a\nc\nd\ne\n'))]) |
330 | - # Modify 'b\n', add 'X\n' |
331 | - builder.build_snapshot('THIS-id', ['BASE-id'], |
332 | - [('modify', ('foo-id', 'a\nb2\nc\nd\nX\ne\n'))]) |
333 | - builder.finish_series() |
334 | - branch = builder.get_branch() |
335 | - this_tree = branch.bzrdir.create_workingtree() |
336 | - this_tree.lock_write() |
337 | - self.addCleanup(this_tree.unlock) |
338 | - other_tree = this_tree.bzrdir.sprout('other', 'OTHER-id').open_workingtree() |
339 | - self.do_merge(this_tree, other_tree) |
340 | - if self.merge_type is _mod_merge.LCAMerger: |
341 | - self.expectFailure("lca merge doesn't track deleted lines", |
342 | - self.assertFileEqual, |
343 | - 'a\n' |
344 | - '<<<<<<< TREE\n' |
345 | - 'b2\n' |
346 | - '=======\n' |
347 | - '>>>>>>> MERGE-SOURCE\n' |
348 | - 'c\n' |
349 | - 'd\n' |
350 | - 'X\n' |
351 | - 'e\n', 'test/foo') |
352 | - else: |
353 | - self.assertFileEqual( |
354 | - 'a\n' |
355 | - '<<<<<<< TREE\n' |
356 | - 'b2\n' |
357 | - '=======\n' |
358 | - '>>>>>>> MERGE-SOURCE\n' |
359 | - 'c\n' |
360 | - 'd\n' |
361 | - 'X\n' |
362 | - 'e\n', 'test/foo') |
363 | - |
364 | - def get_limbodir_deletiondir(self, wt): |
365 | - transform = TreeTransform(wt) |
366 | - limbodir = transform._limbodir |
367 | - deletiondir = transform._deletiondir |
368 | - transform.finalize() |
369 | - return (limbodir, deletiondir) |
370 | - |
371 | - def test_merge_with_existing_limbo(self): |
372 | - wt = self.make_branch_and_tree('this') |
373 | - (limbodir, deletiondir) = self.get_limbodir_deletiondir(wt) |
374 | - os.mkdir(limbodir) |
375 | - self.assertRaises(errors.ExistingLimbo, self.do_merge, wt, wt) |
376 | - self.assertRaises(errors.LockError, wt.unlock) |
377 | - |
378 | - def test_merge_with_pending_deletion(self): |
379 | - wt = self.make_branch_and_tree('this') |
380 | - (limbodir, deletiondir) = self.get_limbodir_deletiondir(wt) |
381 | - os.mkdir(deletiondir) |
382 | - self.assertRaises(errors.ExistingPendingDeletion, self.do_merge, wt, wt) |
383 | - self.assertRaises(errors.LockError, wt.unlock) |
384 | - |
385 | - |
386 | -class TestMerge3Merge(TestCaseWithTransport, TestMergeImplementation): |
387 | - |
388 | - merge_type = _mod_merge.Merge3Merger |
389 | - |
390 | - |
391 | -class TestWeaveMerge(TestCaseWithTransport, TestMergeImplementation): |
392 | - |
393 | - merge_type = _mod_merge.WeaveMerger |
394 | - |
395 | - |
396 | -class TestLCAMerge(TestCaseWithTransport, TestMergeImplementation): |
397 | - |
398 | - merge_type = _mod_merge.LCAMerger |
399 | - |
400 | - def test_merge_move_and_change(self): |
401 | - self.expectFailure("lca merge doesn't conflict for move and change", |
402 | - super(TestLCAMerge, self).test_merge_move_and_change) |
403 | - |
404 | - |
405 | class LoggingMerger(object): |
406 | # These seem to be the required attributes |
407 | requires_base = False |
408 | |
409 | === modified file 'bzrlib/tests/test_merge_core.py' |
410 | --- bzrlib/tests/test_merge_core.py 2009-12-08 21:04:07 +0000 |
411 | +++ bzrlib/tests/test_merge_core.py 2009-12-18 08:25:25 +0000 |
412 | @@ -15,32 +15,26 @@ |
413 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
414 | |
415 | import os |
416 | -import stat |
417 | import sys |
418 | |
419 | import bzrlib |
420 | from bzrlib import ( |
421 | + errors, |
422 | generate_ids, |
423 | merge_directive, |
424 | osutils, |
425 | ) |
426 | from bzrlib.conflicts import ContentsConflict, TextConflict, PathConflict |
427 | -from bzrlib import errors |
428 | -from bzrlib.errors import (NotBranchError, NotVersionedError, |
429 | - WorkingTreeNotRevision, BzrCommandError, NoDiff3) |
430 | -from bzrlib import inventory |
431 | from bzrlib.merge import ( |
432 | Merge3Merger, |
433 | Diff3Merger, |
434 | WeaveMerger, |
435 | Merger, |
436 | ) |
437 | -from bzrlib.osutils import (file_kind, getcwd, pathjoin, rename, |
438 | - sha_file, |
439 | - ) |
440 | +from bzrlib.osutils import getcwd, pathjoin |
441 | from bzrlib import progress |
442 | from bzrlib.transform import TreeTransform |
443 | -from bzrlib.tests import TestCaseWithTransport, TestCase, TestSkipped |
444 | +from bzrlib.tests import TestCaseWithTransport, TestSkipped |
445 | from bzrlib.workingtree import WorkingTree |
446 | |
447 | |
448 | @@ -277,7 +271,7 @@ |
449 | " and therefore always fails on win32") |
450 | try: |
451 | self.do_contents_test(Diff3Merger) |
452 | - except NoDiff3: |
453 | + except errors.NoDiff3: |
454 | raise TestSkipped("diff3 not available") |
455 | |
456 | def test_contents_merge3(self): |
This has a few minor changes in preparation for <lp:~spiv/bzr/per-file-merge-hook-491711>:
* adds a per_merger test module for testing bzrlib.merge.Merger implementations, replacing the ad hoc subclassing in test_merge.
* removes some duplication in merge.py
* removes some unused imports