33
34
class TestMerge(ExternalBase):
35
def example_branch(test):
37
file('hello', 'wt').write('foo')
38
test.run_bzr('add hello')
39
test.run_bzr('commit -m setup hello')
40
file('goodbye', 'wt').write('baz')
41
test.run_bzr('add goodbye')
42
test.run_bzr('commit -m setup goodbye')
36
def example_branch(self, path='.'):
37
tree = self.make_branch_and_tree(path)
38
self.build_tree_contents([
39
(pathjoin(path, 'hello'), 'foo'),
40
(pathjoin(path, 'goodbye'), 'baz')])
42
tree.commit(message='setup')
44
tree.commit(message='setup')
44
47
def test_merge_reprocess(self):
45
48
d = BzrDir.create_standalone_workingtree('.')
49
52
def test_merge(self):
50
53
from bzrlib.branch import Branch
55
ancestor = Branch.open('.').revno()
57
self.run_bzr('branch a b')
59
file('goodbye', 'wt').write('quux')
60
self.run_bzr(['commit', '-m', "more u's are always good"])
63
file('hello', 'wt').write('quuux')
55
a_tree = self.example_branch('a')
56
ancestor = a_tree.branch.revno()
57
b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
58
self.build_tree_contents([('b/goodbye', 'quux')])
59
b_tree.commit(message="more u's are always good")
61
self.build_tree_contents([('a/hello', 'quuux')])
64
62
# We can't merge when there are in-tree changes
65
64
self.run_bzr('merge ../b', retcode=3)
66
65
a = WorkingTree.open('.')
67
66
a_tip = a.commit("Like an epidemic of u's")
68
67
self.run_bzr('merge ../b -r last:1..last:1 --merge-type blooof',
70
69
self.run_bzr('merge ../b -r last:1..last:1 --merge-type merge3')
71
self.run_bzr('revert --no-backup')
70
a_tree.revert(backups=False)
72
71
self.run_bzr('merge ../b -r last:1..last:1 --merge-type weave')
73
self.run_bzr('revert --no-backup')
72
a_tree.revert(backups=False)
73
self.run_bzr_error(['Show-base is not supported for this merge type'],
74
'merge ../b -r last:1..last:1 --merge-type weave'
76
a_tree.revert(backups=False)
74
77
self.run_bzr('merge ../b -r last:1..last:1 --reprocess')
75
self.run_bzr('revert --no-backup')
78
a_tree.revert(backups=False)
76
79
self.run_bzr('merge ../b -r last:1')
77
80
self.check_file_contents('goodbye', 'quux')
78
81
# Merging a branch pulls its revision into the tree
99
102
def test_merge_with_missing_file(self):
100
103
"""Merge handles missing file conflicts"""
104
print >> file('sub/a.txt', 'wb'), "hello"
105
print >> file('b.txt', 'wb'), "hello"
106
print >> file('sub/c.txt', 'wb'), "hello"
109
self.run_bzr(['commit', '-m', 'added a'])
110
self.run_bzr('branch . ../b')
111
print >> file('sub/a.txt', 'ab'), "there"
112
print >> file('b.txt', 'ab'), "there"
113
print >> file('sub/c.txt', 'ab'), "there"
114
self.run_bzr(['commit', '-m', 'Added there'])
115
os.unlink('sub/a.txt')
116
os.unlink('sub/c.txt')
119
self.run_bzr(['commit', '-m', 'Removed a.txt'])
121
print >> file('sub/a.txt', 'ab'), "something"
122
print >> file('b.txt', 'ab'), "something"
123
print >> file('sub/c.txt', 'ab'), "something"
124
self.run_bzr(['commit', '-m', 'Modified a.txt'])
104
self.build_tree_contents([
107
('a/sub/a.txt', 'hello\n'),
108
('a/b.txt', 'hello\n'),
109
('a/sub/c.txt', 'hello\n')])
110
a_tree = self.make_branch_and_tree('a')
111
a_tree.add(['sub', 'b.txt', 'sub/c.txt', 'sub/a.txt'])
112
a_tree.commit(message='added a')
113
b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
114
self.build_tree_contents([
115
('a/sub/a.txt', 'hello\nthere\n'),
116
('a/b.txt', 'hello\nthere\n'),
117
('a/sub/c.txt', 'hello\nthere\n')])
118
a_tree.commit(message='Added there')
119
os.remove('a/sub/a.txt')
120
os.remove('a/sub/c.txt')
123
a_tree.commit(message='Removed a.txt')
124
self.build_tree_contents([
125
('b/sub/a.txt', 'hello\nsomething\n'),
126
('b/b.txt', 'hello\nsomething\n'),
127
('b/sub/c.txt', 'hello\nsomething\n')])
128
b_tree.commit(message='Modified a.txt')
125
130
self.run_bzr('merge ../a/', retcode=1)
126
self.assert_(os.path.exists('sub/a.txt.THIS'))
127
self.assert_(os.path.exists('sub/a.txt.BASE'))
131
self.failUnlessExists('sub/a.txt.THIS')
132
self.failUnlessExists('sub/a.txt.BASE')
129
134
self.run_bzr('merge ../b/', retcode=1)
130
self.assert_(os.path.exists('sub/a.txt.OTHER'))
131
self.assert_(os.path.exists('sub/a.txt.BASE'))
135
self.failUnlessExists('sub/a.txt.OTHER')
136
self.failUnlessExists('sub/a.txt.BASE')
133
138
def test_merge_remember(self):
134
139
"""Merge changes from one branch to another and test parent location."""
187
192
def test_merge_bundle(self):
188
193
from bzrlib.testament import Testament
189
194
tree_a = self.make_branch_and_tree('branch_a')
190
f = file('branch_a/a', 'wb')
195
self.build_tree_contents([('branch_a/a', 'hello')])
194
197
tree_a.commit('message')
196
199
tree_b = tree_a.bzrdir.sprout('branch_b').open_workingtree()
197
f = file('branch_a/a', 'wb')
200
self.build_tree_contents([('branch_a/a', 'hey there')])
200
201
tree_a.commit('message')
202
f = file('branch_b/a', 'wb')
203
self.build_tree_contents([('branch_b/a', 'goodbye')])
205
204
tree_b.commit('message')
206
205
os.chdir('branch_b')
207
file('../bundle', 'wb').write(self.run_bzr('bundle ../branch_a')[0])
206
self.run_bzr('bundle ../branch_a -o ../bundle')
208
207
os.chdir('../branch_a')
209
208
self.run_bzr('merge ../bundle', retcode=1)
210
209
testament_a = Testament.from_revision(tree_a.branch.repository,
236
235
self.run_bzr('merge a --uncommitted -d b')
237
236
self.failUnlessExists('b/file_1')
238
237
self.failUnlessExists('b/file_ii')
240
239
self.run_bzr_error(('Cannot use --uncommitted and --revision',),
241
240
'merge /a --uncommitted -r1 -d b')
243
242
def pullable_branch(self):
246
self.example_branch()
248
self.run_bzr('branch a b')
250
file('goodbye', 'wt').write('quux')
251
self.run_bzr(['commit', '-m', "mode u's are always good"])
254
def pullable_branch(self):
255
243
tree_a = self.make_branch_and_tree('a')
256
244
self.build_tree(['a/file'])
257
245
tree_a.add(['file'])
258
246
self.id1 = tree_a.commit('commit 1')
260
248
tree_b = self.make_branch_and_tree('b')
261
249
tree_b.pull(tree_a.branch)
262
250
file('b/file', 'wb').write('foo')
282
270
os.chdir('tree_b')
283
271
self.run_bzr('merge ../tree_a')
284
272
self.assertEqual('directory', file_kind('file'))
286
274
self.assertEqual('file', file_kind('file'))
287
275
self.build_tree_contents([('file', 'content_2')])
288
276
tree_b.commit('content change')
289
277
self.run_bzr('merge ../tree_a', retcode=1)
290
278
self.assertEqual(tree_b.conflicts(),
291
279
[ContentsConflict('file', file_id='file-id')])
281
def test_directive_cherrypick(self):
282
source = self.make_branch_and_tree('source')
283
self.build_tree(['source/a'])
285
source.commit('Added a', rev_id='rev1')
286
self.build_tree(['source/b'])
288
source.commit('Added b', rev_id='rev2')
289
target = self.make_branch_and_tree('target')
290
target.commit('empty commit')
291
self.write_directive('directive', source.branch, 'target', 'rev2',
293
self.run_bzr('merge -d target directive')
294
self.failIfExists('target/a')
295
self.failUnlessExists('target/b')
297
def write_directive(self, filename, source, target, revision_id,
298
base_revision_id=None, mangle_patch=False):
299
md = merge_directive.MergeDirective2.from_objects(
300
source.repository, revision_id, 0, 0, target,
301
base_revision_id=base_revision_id)
304
self.build_tree_contents([(filename, ''.join(md.to_lines()))])
306
def test_directive_verify_warning(self):
307
source = self.make_branch_and_tree('source')
308
self.build_tree(['source/a'])
310
source.commit('Added a', rev_id='rev1')
311
target = self.make_branch_and_tree('target')
312
target.commit('empty commit')
313
self.write_directive('directive', source.branch, 'target', 'rev1')
314
err = self.run_bzr('merge -d target directive')[1]
315
self.assertNotContainsRe(err, 'Preview patch does not match changes')
317
self.write_directive('directive', source.branch, 'target', 'rev1',
319
err = self.run_bzr('merge -d target directive')[1]
320
self.assertContainsRe(err, 'Preview patch does not match changes')
322
def test_merge_arbitrary(self):
323
target = self.make_branch_and_tree('target')
324
target.commit('empty')
325
# We need a revision that has no integer revno
326
branch_a = target.bzrdir.sprout('branch_a').open_workingtree()
327
self.build_tree(['branch_a/file1'])
328
branch_a.add('file1')
329
branch_a.commit('added file1', rev_id='rev2a')
330
branch_b = target.bzrdir.sprout('branch_b').open_workingtree()
331
self.build_tree(['branch_b/file2'])
332
branch_b.add('file2')
333
branch_b.commit('added file2', rev_id='rev2b')
334
branch_b.merge_from_branch(branch_a.branch)
335
self.failUnlessExists('branch_b/file1')
336
branch_b.commit('merged branch_a', rev_id='rev3b')
338
# It works if the revid has an interger revno
339
self.run_bzr('merge -d target -r revid:rev2a branch_a')
340
self.failUnlessExists('target/file1')
341
self.failIfExists('target/file2')
344
# It should work if the revid has no integer revno
345
self.run_bzr('merge -d target -r revid:rev2a branch_b')
346
self.failUnlessExists('target/file1')
347
self.failIfExists('target/file2')