Merge lp:~vila/bzr/426344-check-pending-merges into lp:bzr
- 426344-check-pending-merges
- Merge into bzr.dev
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | John A Meinel | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~vila/bzr/426344-check-pending-merges | ||||
Merge into: | lp:bzr | ||||
Diff against target: | None lines | ||||
To merge this branch: | bzr merge lp:~vila/bzr/426344-check-pending-merges | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
John A Meinel | Approve | ||
Review via email: mp+11378@code.launchpad.net |
Commit message
Description of the change
Vincent Ladeuil (vila) wrote : | # |
John A Meinel (jameinel) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Vincent Ladeuil wrote:
> Vincent Ladeuil has proposed merging lp:~vila/bzr/426344-check-pending-merges into lp:bzr.
>
> Requested reviews:
> bzr-core (bzr-core)
>
> This fixes the last two places where we were checking uncommitted changes
> while not taking pending merges into account: merge and remove-tree.
>
review: approve
merge: approve
However, this is looking more and more like we should have a simple:
working_
Which takes no target, and grabs its own basis_tree, and looks at its
own pending merge list. Which I asked for in the beginning, though, so
perhaps I'm biased.
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://
iEYEARECAAYFAkq
3JUAoJKgX7MQd/
=LDTT
-----END PGP SIGNATURE-----
Preview Diff
1 | === modified file 'NEWS' | |||
2 | --- NEWS 2009-09-04 00:49:55 +0000 | |||
3 | +++ NEWS 2009-09-08 16:46:40 +0000 | |||
4 | @@ -30,6 +30,10 @@ | |||
5 | 30 | longer report incorrect errors about ``Missing inventory ('TREE_ROOT', ...)`` | 30 | longer report incorrect errors about ``Missing inventory ('TREE_ROOT', ...)`` |
6 | 31 | (Robert Collins, #416732) | 31 | (Robert Collins, #416732) |
7 | 32 | 32 | ||
8 | 33 | * ``bzr merge`` and ``bzr remove-tree`` now requires --force if pending | ||
9 | 34 | merges are present in the working tree. | ||
10 | 35 | (Vincent Ladeuil, #426344) | ||
11 | 36 | |||
12 | 33 | * Don't restrict the command name used to run the test suite. | 37 | * Don't restrict the command name used to run the test suite. |
13 | 34 | (Vincent Ladeuil, #419950) | 38 | (Vincent Ladeuil, #419950) |
14 | 35 | 39 | ||
15 | 36 | 40 | ||
16 | === modified file 'bzrlib/builtins.py' | |||
17 | --- bzrlib/builtins.py 2009-08-28 05:00:33 +0000 | |||
18 | +++ bzrlib/builtins.py 2009-09-08 16:45:11 +0000 | |||
19 | @@ -461,8 +461,8 @@ | |||
20 | 461 | raise errors.BzrCommandError("You cannot remove the working tree" | 461 | raise errors.BzrCommandError("You cannot remove the working tree" |
21 | 462 | " of a remote path") | 462 | " of a remote path") |
22 | 463 | if not force: | 463 | if not force: |
25 | 464 | # XXX: What about pending merges ? -- vila 20090629 | 464 | if (working.has_changes(working.basis_tree()) |
26 | 465 | if working.has_changes(working.basis_tree()): | 465 | or len(working.get_parent_ids()) > 1): |
27 | 466 | raise errors.UncommittedChanges(working) | 466 | raise errors.UncommittedChanges(working) |
28 | 467 | 467 | ||
29 | 468 | working_path = working.bzrdir.root_transport.base | 468 | working_path = working.bzrdir.root_transport.base |
30 | @@ -3653,13 +3653,14 @@ | |||
31 | 3653 | verified = 'inapplicable' | 3653 | verified = 'inapplicable' |
32 | 3654 | tree = WorkingTree.open_containing(directory)[0] | 3654 | tree = WorkingTree.open_containing(directory)[0] |
33 | 3655 | 3655 | ||
34 | 3656 | # die as quickly as possible if there are uncommitted changes | ||
35 | 3657 | try: | 3656 | try: |
36 | 3658 | basis_tree = tree.revision_tree(tree.last_revision()) | 3657 | basis_tree = tree.revision_tree(tree.last_revision()) |
37 | 3659 | except errors.NoSuchRevision: | 3658 | except errors.NoSuchRevision: |
38 | 3660 | basis_tree = tree.basis_tree() | 3659 | basis_tree = tree.basis_tree() |
39 | 3660 | |||
40 | 3661 | # die as quickly as possible if there are uncommitted changes | ||
41 | 3661 | if not force: | 3662 | if not force: |
43 | 3662 | if tree.has_changes(basis_tree): | 3663 | if tree.has_changes(basis_tree) or len(tree.get_parent_ids()) > 1: |
44 | 3663 | raise errors.UncommittedChanges(tree) | 3664 | raise errors.UncommittedChanges(tree) |
45 | 3664 | 3665 | ||
46 | 3665 | view_info = _get_view_info_for_change_reporter(tree) | 3666 | view_info = _get_view_info_for_change_reporter(tree) |
47 | 3666 | 3667 | ||
48 | === modified file 'bzrlib/tests/blackbox/test_merge.py' | |||
49 | --- bzrlib/tests/blackbox/test_merge.py 2009-08-06 06:58:09 +0000 | |||
50 | +++ bzrlib/tests/blackbox/test_merge.py 2009-09-08 16:42:51 +0000 | |||
51 | @@ -21,23 +21,26 @@ | |||
52 | 21 | 21 | ||
53 | 22 | import os | 22 | import os |
54 | 23 | 23 | ||
66 | 24 | from bzrlib import merge_directive | 24 | from bzrlib import ( |
67 | 25 | from bzrlib.branch import Branch | 25 | branch, |
68 | 26 | from bzrlib.bzrdir import BzrDir | 26 | bzrdir, |
69 | 27 | from bzrlib.conflicts import ConflictList, ContentsConflict | 27 | conflicts, |
70 | 28 | from bzrlib.osutils import abspath, file_kind, pathjoin | 28 | errors, |
71 | 29 | from bzrlib.tests.blackbox import ExternalBase | 29 | merge_directive, |
72 | 30 | import bzrlib.urlutils as urlutils | 30 | osutils, |
73 | 31 | from bzrlib.workingtree import WorkingTree | 31 | tests, |
74 | 32 | 32 | urlutils, | |
75 | 33 | 33 | workingtree, | |
76 | 34 | class TestMerge(ExternalBase): | 34 | ) |
77 | 35 | |||
78 | 36 | |||
79 | 37 | class TestMerge(tests.TestCaseWithTransport): | ||
80 | 35 | 38 | ||
81 | 36 | def example_branch(self, path='.'): | 39 | def example_branch(self, path='.'): |
82 | 37 | tree = self.make_branch_and_tree(path) | 40 | tree = self.make_branch_and_tree(path) |
83 | 38 | self.build_tree_contents([ | 41 | self.build_tree_contents([ |
86 | 39 | (pathjoin(path, 'hello'), 'foo'), | 42 | (osutils.pathjoin(path, 'hello'), 'foo'), |
87 | 40 | (pathjoin(path, 'goodbye'), 'baz')]) | 43 | (osutils.pathjoin(path, 'goodbye'), 'baz')]) |
88 | 41 | tree.add('hello') | 44 | tree.add('hello') |
89 | 42 | tree.commit(message='setup') | 45 | tree.commit(message='setup') |
90 | 43 | tree.add('goodbye') | 46 | tree.add('goodbye') |
91 | @@ -63,13 +66,11 @@ | |||
92 | 63 | return tree, other | 66 | return tree, other |
93 | 64 | 67 | ||
94 | 65 | def test_merge_reprocess(self): | 68 | def test_merge_reprocess(self): |
96 | 66 | d = BzrDir.create_standalone_workingtree('.') | 69 | d = bzrdir.BzrDir.create_standalone_workingtree('.') |
97 | 67 | d.commit('h') | 70 | d.commit('h') |
98 | 68 | self.run_bzr('merge . --reprocess --merge-type weave') | 71 | self.run_bzr('merge . --reprocess --merge-type weave') |
99 | 69 | 72 | ||
100 | 70 | def test_merge(self): | 73 | def test_merge(self): |
101 | 71 | from bzrlib.branch import Branch | ||
102 | 72 | |||
103 | 73 | a_tree = self.example_branch('a') | 74 | a_tree = self.example_branch('a') |
104 | 74 | ancestor = a_tree.branch.revno() | 75 | ancestor = a_tree.branch.revno() |
105 | 75 | b_tree = a_tree.bzrdir.sprout('b').open_workingtree() | 76 | b_tree = a_tree.bzrdir.sprout('b').open_workingtree() |
106 | @@ -80,7 +81,7 @@ | |||
107 | 80 | # We can't merge when there are in-tree changes | 81 | # We can't merge when there are in-tree changes |
108 | 81 | os.chdir('a') | 82 | os.chdir('a') |
109 | 82 | self.run_bzr('merge ../b', retcode=3) | 83 | self.run_bzr('merge ../b', retcode=3) |
111 | 83 | a = WorkingTree.open('.') | 84 | a = workingtree.WorkingTree.open('.') |
112 | 84 | a_tip = a.commit("Like an epidemic of u's") | 85 | a_tip = a.commit("Like an epidemic of u's") |
113 | 85 | self.run_bzr('merge ../b -r last:1..last:1 --merge-type blooof', | 86 | self.run_bzr('merge ../b -r last:1..last:1 --merge-type blooof', |
114 | 86 | retcode=3) | 87 | retcode=3) |
115 | @@ -99,7 +100,7 @@ | |||
116 | 99 | self.run_bzr('merge ../b -r last:1') | 100 | self.run_bzr('merge ../b -r last:1') |
117 | 100 | self.check_file_contents('goodbye', 'quux') | 101 | self.check_file_contents('goodbye', 'quux') |
118 | 101 | # Merging a branch pulls its revision into the tree | 102 | # Merging a branch pulls its revision into the tree |
120 | 102 | b = Branch.open('../b') | 103 | b = branch.Branch.open('../b') |
121 | 103 | b_tip = b.last_revision() | 104 | b_tip = b.last_revision() |
122 | 104 | self.failUnless(a.branch.repository.has_revision(b_tip)) | 105 | self.failUnless(a.branch.repository.has_revision(b_tip)) |
123 | 105 | self.assertEqual([a_tip, b_tip], a.get_parent_ids()) | 106 | self.assertEqual([a_tip, b_tip], a.get_parent_ids()) |
124 | @@ -249,8 +250,8 @@ | |||
125 | 249 | 250 | ||
126 | 250 | base = urlutils.local_path_from_url(branch_a.base) | 251 | base = urlutils.local_path_from_url(branch_a.base) |
127 | 251 | self.assertEndsWith(err, '+N b\nAll changes applied successfully.\n') | 252 | self.assertEndsWith(err, '+N b\nAll changes applied successfully.\n') |
130 | 252 | self.assertEquals(abspath(branch_b.get_submit_branch()), | 253 | self.assertEquals(osutils.abspath(branch_b.get_submit_branch()), |
131 | 253 | abspath(parent)) | 254 | osutils.abspath(parent)) |
132 | 254 | # test implicit --remember when committing new file | 255 | # test implicit --remember when committing new file |
133 | 255 | self.build_tree(['e']) | 256 | self.build_tree(['e']) |
134 | 256 | tree_b.add('e') | 257 | tree_b.add('e') |
135 | @@ -265,8 +266,8 @@ | |||
136 | 265 | out, err = self.run_bzr('merge ../branch_c --remember') | 266 | out, err = self.run_bzr('merge ../branch_c --remember') |
137 | 266 | self.assertEquals(out, '') | 267 | self.assertEquals(out, '') |
138 | 267 | self.assertEquals(err, '+N c\nAll changes applied successfully.\n') | 268 | self.assertEquals(err, '+N c\nAll changes applied successfully.\n') |
141 | 268 | self.assertEquals(abspath(branch_b.get_submit_branch()), | 269 | self.assertEquals(osutils.abspath(branch_b.get_submit_branch()), |
142 | 269 | abspath(branch_c.bzrdir.root_transport.base)) | 270 | osutils.abspath(branch_c.bzrdir.root_transport.base)) |
143 | 270 | # re-open tree as external run_bzr modified it | 271 | # re-open tree as external run_bzr modified it |
144 | 271 | tree_b = branch_b.bzrdir.open_workingtree() | 272 | tree_b = branch_b.bzrdir.open_workingtree() |
145 | 272 | tree_b.commit('merge branch_c') | 273 | tree_b.commit('merge branch_c') |
146 | @@ -294,7 +295,7 @@ | |||
147 | 294 | tree_b.get_parent_ids()[0]) | 295 | tree_b.get_parent_ids()[0]) |
148 | 295 | self.assertEqualDiff(testament_a.as_text(), | 296 | self.assertEqualDiff(testament_a.as_text(), |
149 | 296 | testament_b.as_text()) | 297 | testament_b.as_text()) |
151 | 297 | tree_a.set_conflicts(ConflictList()) | 298 | tree_a.set_conflicts(conflicts.ConflictList()) |
152 | 298 | tree_a.commit('message') | 299 | tree_a.commit('message') |
153 | 299 | # it is legal to attempt to merge an already-merged bundle | 300 | # it is legal to attempt to merge an already-merged bundle |
154 | 300 | output = self.run_bzr('merge ../bundle')[1] | 301 | output = self.run_bzr('merge ../bundle')[1] |
155 | @@ -349,7 +350,7 @@ | |||
156 | 349 | os.chdir('a') | 350 | os.chdir('a') |
157 | 350 | (out, err) = self.run_bzr('merge --pull ../b') | 351 | (out, err) = self.run_bzr('merge --pull ../b') |
158 | 351 | self.assertContainsRe(out, 'Now on revision 2\\.') | 352 | self.assertContainsRe(out, 'Now on revision 2\\.') |
160 | 352 | tree_a = WorkingTree.open('.') | 353 | tree_a = workingtree.WorkingTree.open('.') |
161 | 353 | self.assertEqual([self.id2], tree_a.get_parent_ids()) | 354 | self.assertEqual([self.id2], tree_a.get_parent_ids()) |
162 | 354 | 355 | ||
163 | 355 | def test_merge_kind_change(self): | 356 | def test_merge_kind_change(self): |
164 | @@ -363,14 +364,15 @@ | |||
165 | 363 | tree_a.commit('changed file to directory') | 364 | tree_a.commit('changed file to directory') |
166 | 364 | os.chdir('tree_b') | 365 | os.chdir('tree_b') |
167 | 365 | self.run_bzr('merge ../tree_a') | 366 | self.run_bzr('merge ../tree_a') |
169 | 366 | self.assertEqual('directory', file_kind('file')) | 367 | self.assertEqual('directory', osutils.file_kind('file')) |
170 | 367 | tree_b.revert() | 368 | tree_b.revert() |
172 | 368 | self.assertEqual('file', file_kind('file')) | 369 | self.assertEqual('file', osutils.file_kind('file')) |
173 | 369 | self.build_tree_contents([('file', 'content_2')]) | 370 | self.build_tree_contents([('file', 'content_2')]) |
174 | 370 | tree_b.commit('content change') | 371 | tree_b.commit('content change') |
175 | 371 | self.run_bzr('merge ../tree_a', retcode=1) | 372 | self.run_bzr('merge ../tree_a', retcode=1) |
176 | 372 | self.assertEqual(tree_b.conflicts(), | 373 | self.assertEqual(tree_b.conflicts(), |
178 | 373 | [ContentsConflict('file', file_id='file-id')]) | 374 | [conflicts.ContentsConflict('file', |
179 | 375 | file_id='file-id')]) | ||
180 | 374 | 376 | ||
181 | 375 | def test_directive_cherrypick(self): | 377 | def test_directive_cherrypick(self): |
182 | 376 | source = self.make_branch_and_tree('source') | 378 | source = self.make_branch_and_tree('source') |
183 | @@ -496,18 +498,6 @@ | |||
184 | 496 | out, err = self.run_bzr(['merge', '-d', 'a', 'b']) | 498 | out, err = self.run_bzr(['merge', '-d', 'a', 'b']) |
185 | 497 | self.assertContainsRe(err, 'Warning: criss-cross merge encountered.') | 499 | self.assertContainsRe(err, 'Warning: criss-cross merge encountered.') |
186 | 498 | 500 | ||
187 | 499 | def test_merge_force(self): | ||
188 | 500 | tree_a = self.make_branch_and_tree('a') | ||
189 | 501 | self.build_tree(['a/foo']) | ||
190 | 502 | tree_a.add(['foo']) | ||
191 | 503 | tree_a.commit('add file') | ||
192 | 504 | tree_b = tree_a.bzrdir.sprout('b').open_workingtree() | ||
193 | 505 | self.build_tree_contents([('a/foo', 'change 1')]) | ||
194 | 506 | tree_a.commit('change file') | ||
195 | 507 | tree_b.merge_from_branch(tree_a.branch) | ||
196 | 508 | tree_a.commit('empty change to allow merge to run') | ||
197 | 509 | self.run_bzr(['merge', '../a', '--force'], working_dir='b') | ||
198 | 510 | |||
199 | 511 | def test_merge_from_submit(self): | 501 | def test_merge_from_submit(self): |
200 | 512 | tree_a = self.make_branch_and_tree('a') | 502 | tree_a = self.make_branch_and_tree('a') |
201 | 513 | tree_b = tree_a.bzrdir.sprout('b').open_workingtree() | 503 | tree_b = tree_a.bzrdir.sprout('b').open_workingtree() |
202 | @@ -560,11 +550,11 @@ | |||
203 | 560 | tree_a.merge_from_branch(tree_b.branch) | 550 | tree_a.merge_from_branch(tree_b.branch) |
204 | 561 | self.build_tree_contents([('a/file', | 551 | self.build_tree_contents([('a/file', |
205 | 562 | 'base-contents\nthis-contents\n')]) | 552 | 'base-contents\nthis-contents\n')]) |
207 | 563 | tree_a.set_conflicts(ConflictList()) | 553 | tree_a.set_conflicts(conflicts.ConflictList()) |
208 | 564 | tree_b.merge_from_branch(tree_a.branch) | 554 | tree_b.merge_from_branch(tree_a.branch) |
209 | 565 | self.build_tree_contents([('b/file', | 555 | self.build_tree_contents([('b/file', |
210 | 566 | 'base-contents\nother-contents\n')]) | 556 | 'base-contents\nother-contents\n')]) |
212 | 567 | tree_b.set_conflicts(ConflictList()) | 557 | tree_b.set_conflicts(conflicts.ConflictList()) |
213 | 568 | tree_a.commit('', rev_id='rev3a') | 558 | tree_a.commit('', rev_id='rev3a') |
214 | 569 | tree_b.commit('', rev_id='rev3b') | 559 | tree_b.commit('', rev_id='rev3b') |
215 | 570 | out, err = self.run_bzr(['merge', '-d', 'a', 'b', '--lca'], retcode=1) | 560 | out, err = self.run_bzr(['merge', '-d', 'a', 'b', '--lca'], retcode=1) |
216 | @@ -598,3 +588,33 @@ | |||
217 | 598 | other.commit('rev1b') | 588 | other.commit('rev1b') |
218 | 599 | self.run_bzr('merge -d this other -r0..') | 589 | self.run_bzr('merge -d this other -r0..') |
219 | 600 | self.failUnlessExists('this/other_file') | 590 | self.failUnlessExists('this/other_file') |
220 | 591 | |||
221 | 592 | |||
222 | 593 | class TestMergeForce(tests.TestCaseWithTransport): | ||
223 | 594 | |||
224 | 595 | def setUp(self): | ||
225 | 596 | super(TestMergeForce, self).setUp() | ||
226 | 597 | self.tree_a = self.make_branch_and_tree('a') | ||
227 | 598 | self.build_tree(['a/foo']) | ||
228 | 599 | self.tree_a.add(['foo']) | ||
229 | 600 | self.tree_a.commit('add file') | ||
230 | 601 | self.tree_b = self.tree_a.bzrdir.sprout('b').open_workingtree() | ||
231 | 602 | self.build_tree_contents([('a/foo', 'change 1')]) | ||
232 | 603 | self.tree_a.commit('change file') | ||
233 | 604 | self.tree_b.merge_from_branch(self.tree_a.branch) | ||
234 | 605 | |||
235 | 606 | def test_merge_force(self): | ||
236 | 607 | self.tree_a.commit('empty change to allow merge to run') | ||
237 | 608 | # Second merge on top if the uncommitted one | ||
238 | 609 | self.run_bzr(['merge', '../a', '--force'], working_dir='b') | ||
239 | 610 | |||
240 | 611 | |||
241 | 612 | def test_merge_with_uncommitted_changes(self): | ||
242 | 613 | self.run_bzr_error(['Working tree .* has uncommitted changes'], | ||
243 | 614 | ['merge', '../a'], working_dir='b') | ||
244 | 615 | |||
245 | 616 | def test_merge_with_pending_merges(self): | ||
246 | 617 | # Revert the changes keeping the pending merge | ||
247 | 618 | self.run_bzr(['revert', 'b']) | ||
248 | 619 | self.run_bzr_error(['Working tree .* has uncommitted changes'], | ||
249 | 620 | ['merge', '../a'], working_dir='b') | ||
250 | 601 | 621 | ||
251 | === modified file 'bzrlib/tests/blackbox/test_remove_tree.py' | |||
252 | --- bzrlib/tests/blackbox/test_remove_tree.py 2009-03-23 14:59:43 +0000 | |||
253 | +++ bzrlib/tests/blackbox/test_remove_tree.py 2009-09-08 16:45:11 +0000 | |||
254 | @@ -122,3 +122,30 @@ | |||
255 | 122 | self.run_bzr('remove-tree branch1 --force') | 122 | self.run_bzr('remove-tree branch1 --force') |
256 | 123 | self.failIfExists('branch1/foo') | 123 | self.failIfExists('branch1/foo') |
257 | 124 | self.failUnlessExists('branch1/bar') | 124 | self.failUnlessExists('branch1/bar') |
258 | 125 | |||
259 | 126 | def test_remove_tree_pending_merges(self): | ||
260 | 127 | self.run_bzr(['branch', 'branch1', 'branch2']) | ||
261 | 128 | self.build_tree(['branch1/bar']) | ||
262 | 129 | self.tree.add('bar') | ||
263 | 130 | self.tree.commit('2') | ||
264 | 131 | self.failUnlessExists('branch1/bar') | ||
265 | 132 | self.run_bzr(['merge', '../branch1'], working_dir='branch2') | ||
266 | 133 | self.failUnlessExists('branch2/bar') | ||
267 | 134 | self.run_bzr(['revert', '.'], working_dir='branch2') | ||
268 | 135 | self.failIfExists('branch2/bar') | ||
269 | 136 | output = self.run_bzr_error(["Working tree .* has uncommitted changes"], | ||
270 | 137 | 'remove-tree branch2', retcode=3) | ||
271 | 138 | |||
272 | 139 | def test_remove_tree_pending_merges_force(self): | ||
273 | 140 | self.run_bzr(['branch', 'branch1', 'branch2']) | ||
274 | 141 | self.build_tree(['branch1/bar']) | ||
275 | 142 | self.tree.add('bar') | ||
276 | 143 | self.tree.commit('2') | ||
277 | 144 | self.failUnlessExists('branch1/bar') | ||
278 | 145 | self.run_bzr(['merge', '../branch1'], working_dir='branch2') | ||
279 | 146 | self.failUnlessExists('branch2/bar') | ||
280 | 147 | self.run_bzr(['revert', '.'], working_dir='branch2') | ||
281 | 148 | self.failIfExists('branch2/bar') | ||
282 | 149 | self.run_bzr('remove-tree branch2 --force') | ||
283 | 150 | self.failIfExists('branch2/foo') | ||
284 | 151 | self.failIfExists('branch2/bar') |
This fixes the last two places where we were checking uncommitted changes
while not taking pending merges into account: merge and remove-tree.