48
48
from bzrlib.revision import (NULL_REVISION, ensure_null)
49
49
from bzrlib.textfile import check_text_lines
50
50
from bzrlib.trace import mutter, warning, note
51
from bzrlib.transform import (TransformPreview, TreeTransform,
52
resolve_conflicts, cook_conflicts,
51
from bzrlib.transform import (TreeTransform, resolve_conflicts, cook_conflicts,
53
52
conflict_pass, FinalPaths, create_by_entry,
54
53
unique_add, ROOT_PARENT)
55
54
from bzrlib.versionedfile import PlanWeaveMerge
377
376
base_branch.get_rev_id(base_revision[1]))
378
377
self._maybe_fetch(base_branch, self.this_branch, self.base_rev_id)
380
def make_merger(self):
381
380
kwargs = {'working_tree':self.this_tree, 'this_tree': self.this_tree,
382
381
'other_tree': self.other_tree,
383
382
'interesting_ids': self.interesting_ids,
384
383
'interesting_files': self.interesting_files,
387
385
if self.merge_type.requires_base:
388
386
kwargs['base_tree'] = self.base_tree
389
387
if self.merge_type.supports_reprocess:
395
393
kwargs['show_base'] = self.show_base
396
394
elif self.show_base:
397
395
raise BzrError("Showing base is not supported for this"
398
" merge type. %s" % self.merge_type)
396
" merge type. %s" % self.merge_type)
399
397
if (not getattr(self.merge_type, 'supports_reverse_cherrypick', True)
400
398
and not self.base_is_other_ancestor):
401
399
raise errors.CannotReverseCherrypick()
402
400
if self.merge_type.history_based:
403
401
kwargs['cherrypick'] = (not self.base_is_ancestor or
404
402
not self.base_is_other_ancestor)
405
return self.merge_type(pb=self._pb,
406
change_reporter=self.change_reporter,
410
merge = self.make_merger()
411
403
self.this_tree.lock_tree_write()
412
404
if self.base_tree is not None:
413
405
self.base_tree.lock_read()
414
406
if self.other_tree is not None:
415
407
self.other_tree.lock_read()
409
merge = self.merge_type(pb=self._pb,
410
change_reporter=self.change_reporter,
418
412
if self.recurse == 'down':
419
413
for path, file_id in self.this_tree.iter_references():
420
414
sub_tree = self.this_tree.get_nested_tree(file_id, path)
459
453
def __init__(self, working_tree, this_tree, base_tree, other_tree,
460
454
interesting_ids=None, reprocess=False, show_base=False,
461
455
pb=DummyProgress(), pp=None, change_reporter=None,
462
interesting_files=None, do_merge=True):
456
interesting_files=None):
463
457
"""Initialize the merger object and perform the merge.
465
459
:param working_tree: The working tree to apply the merge to
488
482
self.interesting_ids = interesting_ids
489
483
self.interesting_files = interesting_files
490
484
self.this_tree = working_tree
485
self.this_tree.lock_tree_write()
491
486
self.base_tree = base_tree
487
self.base_tree.lock_read()
492
488
self.other_tree = other_tree
489
self.other_tree.lock_read()
493
490
self._raw_conflicts = []
494
491
self.cooked_conflicts = []
495
492
self.reprocess = reprocess
499
496
self.change_reporter = change_reporter
500
497
if self.pp is None:
501
498
self.pp = ProgressPhase("Merge phase", 3, self.pb)
506
self.this_tree.lock_tree_write()
507
self.base_tree.lock_read()
508
self.other_tree.lock_read()
509
self.tt = TreeTransform(self.this_tree, self.pb)
500
self.tt = TreeTransform(working_tree, self.pb)
511
502
self.pp.next_phase()
512
self._compute_transform()
503
entries = self._entries3()
504
child_pb = ui.ui_factory.nested_progress_bar()
506
for num, (file_id, changed, parents3, names3,
507
executable3) in enumerate(entries):
508
child_pb.update('Preparing file merge', num, len(entries))
509
self._merge_names(file_id, parents3, names3)
511
file_status = self.merge_contents(file_id)
513
file_status = 'unmodified'
514
self._merge_executable(file_id,
515
executable3, file_status)
520
child_pb = ui.ui_factory.nested_progress_bar()
522
fs_conflicts = resolve_conflicts(self.tt, child_pb,
523
lambda t, c: conflict_pass(t, c, self.other_tree))
526
if change_reporter is not None:
527
from bzrlib import delta
528
delta.report_changes(self.tt._iter_changes(), change_reporter)
529
self.cook_conflicts(fs_conflicts)
530
for conflict in self.cooked_conflicts:
513
532
self.pp.next_phase()
514
533
results = self.tt.apply(no_conflicts=True)
515
534
self.write_modified(results)
517
self.this_tree.add_conflicts(self.cooked_conflicts)
536
working_tree.add_conflicts(self.cooked_conflicts)
518
537
except UnsupportedOperation:
524
543
self.this_tree.unlock()
527
def make_preview_transform(self):
528
self.base_tree.lock_read()
529
self.other_tree.lock_read()
530
self.tt = TransformPreview(self.this_tree)
533
self._compute_transform()
536
self.other_tree.unlock()
537
self.base_tree.unlock()
541
def _compute_transform(self):
542
entries = self._entries3()
543
child_pb = ui.ui_factory.nested_progress_bar()
545
for num, (file_id, changed, parents3, names3,
546
executable3) in enumerate(entries):
547
child_pb.update('Preparing file merge', num, len(entries))
548
self._merge_names(file_id, parents3, names3)
550
file_status = self.merge_contents(file_id)
552
file_status = 'unmodified'
553
self._merge_executable(file_id,
554
executable3, file_status)
559
child_pb = ui.ui_factory.nested_progress_bar()
561
fs_conflicts = resolve_conflicts(self.tt, child_pb,
562
lambda t, c: conflict_pass(t, c, self.other_tree))
565
if self.change_reporter is not None:
566
from bzrlib import delta
567
delta.report_changes(
568
self.tt._iter_changes(), self.change_reporter)
569
self.cook_conflicts(fs_conflicts)
570
for conflict in self.cooked_conflicts:
573
546
def _entries3(self):
574
547
"""Gather data about files modified between three trees.
1043
1016
def __init__(self, working_tree, this_tree, base_tree, other_tree,
1044
1017
interesting_ids=None, pb=DummyProgress(), pp=None,
1045
1018
reprocess=False, change_reporter=None,
1046
interesting_files=None, cherrypick=False, do_merge=True):
1019
interesting_files=None, cherrypick=False):
1047
1020
self.cherrypick = cherrypick
1048
1021
super(WeaveMerger, self).__init__(working_tree, this_tree,
1049
1022
base_tree, other_tree,
1050
1023
interesting_ids=interesting_ids,
1051
1024
pb=pb, pp=pp, reprocess=reprocess,
1052
change_reporter=change_reporter,
1025
change_reporter=change_reporter)
1055
1027
def _merged_lines(self, file_id):
1056
1028
"""Generate the merged lines.