47
46
merger = _mod_merge.Merger.from_revision_ids(
48
47
target_tree, source_tree.last_revision(),
49
48
other_branch=source_tree.branch)
50
merger.merge_type=self.merge_type
49
merger.merge_type = self.merge_type
51
50
for name, value in kwargs.items():
52
51
setattr(merger, name, value)
127
126
builder = self.make_branch_builder('test')
128
127
builder.start_series()
129
128
builder.build_snapshot(None,
130
[('add', ('', None, 'directory', None)),
131
('add', ('foo', b'foo-id', 'file', b'a\nb\nc\nd\ne\n')),
132
], revision_id=b'BASE-id')
129
[('add', ('', None, 'directory', None)),
130
('add', ('foo', b'foo-id', 'file', b'a\nb\nc\nd\ne\n')),
131
], revision_id=b'BASE-id')
134
133
builder.build_snapshot([b'BASE-id'],
135
[('modify', ('foo', b'a\nc\nd\ne\n'))],
136
revision_id=b'OTHER-id')
134
[('modify', ('foo', b'a\nc\nd\ne\n'))],
135
revision_id=b'OTHER-id')
137
136
# Modify 'b\n', add 'X\n'
138
137
builder.build_snapshot([b'BASE-id'],
139
[('modify', ('foo', b'a\nb2\nc\nd\nX\ne\n'))],
140
revision_id=b'THIS-id')
138
[('modify', ('foo', b'a\nb2\nc\nd\nX\ne\n'))],
139
revision_id=b'THIS-id')
141
140
builder.finish_series()
142
141
branch = builder.get_branch()
143
142
this_tree = branch.controldir.create_workingtree()
144
143
this_tree.lock_write()
145
144
self.addCleanup(this_tree.unlock)
146
other_tree = this_tree.controldir.sprout('other', b'OTHER-id').open_workingtree()
145
other_tree = this_tree.controldir.sprout(
146
'other', b'OTHER-id').open_workingtree()
147
147
self.do_merge(this_tree, other_tree)
148
148
if self.merge_type is _mod_merge.LCAMerger:
149
149
self.expectFailure("lca merge doesn't track deleted lines",
150
self.assertFileEqual,
155
'>>>>>>> MERGE-SOURCE\n'
150
self.assertFileEqual,
155
'>>>>>>> MERGE-SOURCE\n'
161
161
self.assertFileEqual(
179
179
def test_merge_with_existing_limbo_empty(self):
180
180
"""Empty limbo dir is just cleaned up - see bug 427773"""
181
181
wt = self.make_branch_and_tree('this')
182
(limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
182
(limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
183
183
os.mkdir(limbodir)
184
184
self.do_merge(wt, wt)
186
186
def test_merge_with_existing_limbo_non_empty(self):
187
187
wt = self.make_branch_and_tree('this')
188
(limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
188
(limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
189
189
os.mkdir(limbodir)
190
190
os.mkdir(os.path.join(limbodir, 'something'))
191
191
self.assertRaises(errors.ExistingLimbo, self.do_merge, wt, wt)
194
194
def test_merge_with_pending_deletion_empty(self):
195
195
wt = self.make_branch_and_tree('this')
196
(limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
196
(limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
197
197
os.mkdir(deletiondir)
198
198
self.do_merge(wt, wt)
200
200
def test_merge_with_pending_deletion_non_empty(self):
201
201
"""Also see bug 427773"""
202
202
wt = self.make_branch_and_tree('this')
203
(limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
203
(limbodir, deletiondir) = self.get_limbodir_deletiondir(wt)
204
204
os.mkdir(deletiondir)
205
205
os.mkdir(os.path.join(deletiondir, 'something'))
206
self.assertRaises(errors.ExistingPendingDeletion, self.do_merge, wt, wt)
206
self.assertRaises(errors.ExistingPendingDeletion,
207
self.do_merge, wt, wt)
207
208
self.assertRaises(errors.LockError, wt.unlock)
225
226
def install_hook_noop(self):
227
229
class HookNA(_mod_merge.AbstractPerFileMerger):
228
230
def merge_contents(self, merge_params):
229
231
# This hook unconditionally does nothing.
230
232
test.hook_log.append(('no-op',))
231
233
return 'not_applicable', None
232
235
def hook_na_factory(merger):
233
236
return HookNA(merger)
234
237
_mod_merge.Merger.hooks.install_named_hook(
237
240
def install_hook_success(self):
239
243
class HookSuccess(_mod_merge.AbstractPerFileMerger):
240
244
def merge_contents(self, merge_params):
241
245
test.hook_log.append(('success',))
242
246
if merge_params.file_id == b'1':
243
247
return 'success', [b'text-merged-by-hook']
244
248
return 'not_applicable', None
245
250
def hook_success_factory(merger):
246
251
return HookSuccess(merger)
247
252
_mod_merge.Merger.hooks.install_named_hook(
250
255
def install_hook_conflict(self):
252
258
class HookConflict(_mod_merge.AbstractPerFileMerger):
253
259
def merge_contents(self, merge_params):
254
260
test.hook_log.append(('conflict',))
255
261
if merge_params.file_id == b'1':
256
262
return ('conflicted',
257
[b'text-with-conflict-markers-from-hook'])
263
[b'text-with-conflict-markers-from-hook'])
258
264
return 'not_applicable', None
259
266
def hook_conflict_factory(merger):
260
267
return HookConflict(merger)
261
268
_mod_merge.Merger.hooks.install_named_hook(
264
271
def install_hook_delete(self):
266
274
class HookDelete(_mod_merge.AbstractPerFileMerger):
267
275
def merge_contents(self, merge_params):
268
276
test.hook_log.append(('delete',))
269
277
if merge_params.file_id == b'1':
270
278
return 'delete', None
271
279
return 'not_applicable', None
272
281
def hook_delete_factory(merger):
273
282
return HookDelete(merger)
274
283
_mod_merge.Merger.hooks.install_named_hook(