47
47
from progress import DummyProgress, ProgressPhase
48
48
from bzrlib.revision import (NULL_REVISION, ensure_null)
49
49
from bzrlib.textfile import check_text_lines
50
from bzrlib.trace import mutter, warning, note
51
from bzrlib.transform import (TreeTransform, resolve_conflicts, cook_conflicts,
50
from bzrlib.trace import mutter, warning, note, is_quiet
51
from bzrlib.transform import (TransformPreview, TreeTransform,
52
resolve_conflicts, cook_conflicts,
52
53
conflict_pass, FinalPaths, create_by_entry,
53
54
unique_add, ROOT_PARENT)
54
55
from bzrlib.versionedfile import PlanWeaveMerge
376
377
base_branch.get_rev_id(base_revision[1]))
377
378
self._maybe_fetch(base_branch, self.this_branch, self.base_rev_id)
380
def make_merger(self):
380
381
kwargs = {'working_tree':self.this_tree, 'this_tree': self.this_tree,
381
382
'other_tree': self.other_tree,
382
383
'interesting_ids': self.interesting_ids,
383
384
'interesting_files': self.interesting_files,
385
387
if self.merge_type.requires_base:
386
388
kwargs['base_tree'] = self.base_tree
387
389
if self.merge_type.supports_reprocess:
393
395
kwargs['show_base'] = self.show_base
394
396
elif self.show_base:
395
397
raise BzrError("Showing base is not supported for this"
396
" merge type. %s" % self.merge_type)
398
" merge type. %s" % self.merge_type)
397
399
if (not getattr(self.merge_type, 'supports_reverse_cherrypick', True)
398
400
and not self.base_is_other_ancestor):
399
401
raise errors.CannotReverseCherrypick()
400
402
if self.merge_type.history_based:
401
403
kwargs['cherrypick'] = (not self.base_is_ancestor or
402
404
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()
403
411
self.this_tree.lock_tree_write()
404
412
if self.base_tree is not None:
405
413
self.base_tree.lock_read()
406
414
if self.other_tree is not None:
407
415
self.other_tree.lock_read()
409
merge = self.merge_type(pb=self._pb,
410
change_reporter=self.change_reporter,
412
418
if self.recurse == 'down':
413
419
for path, file_id in self.this_tree.iter_references():
414
420
sub_tree = self.this_tree.get_nested_tree(file_id, path)
453
459
def __init__(self, working_tree, this_tree, base_tree, other_tree,
454
460
interesting_ids=None, reprocess=False, show_base=False,
455
461
pb=DummyProgress(), pp=None, change_reporter=None,
456
interesting_files=None):
462
interesting_files=None, do_merge=True):
457
463
"""Initialize the merger object and perform the merge.
459
465
:param working_tree: The working tree to apply the merge to
482
488
self.interesting_ids = interesting_ids
483
489
self.interesting_files = interesting_files
484
490
self.this_tree = working_tree
485
self.this_tree.lock_tree_write()
486
491
self.base_tree = base_tree
487
self.base_tree.lock_read()
488
492
self.other_tree = other_tree
489
self.other_tree.lock_read()
490
493
self._raw_conflicts = []
491
494
self.cooked_conflicts = []
492
495
self.reprocess = reprocess
496
499
self.change_reporter = change_reporter
497
500
if self.pp is None:
498
501
self.pp = ProgressPhase("Merge phase", 3, self.pb)
500
self.tt = TreeTransform(working_tree, 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)
502
511
self.pp.next_phase()
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:
512
self._compute_transform()
532
513
self.pp.next_phase()
533
514
results = self.tt.apply(no_conflicts=True)
534
515
self.write_modified(results)
536
working_tree.add_conflicts(self.cooked_conflicts)
517
self.this_tree.add_conflicts(self.cooked_conflicts)
537
518
except UnsupportedOperation:
543
524
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:
546
573
def _entries3(self):
547
574
"""Gather data about files modified between three trees.
1016
1043
def __init__(self, working_tree, this_tree, base_tree, other_tree,
1017
1044
interesting_ids=None, pb=DummyProgress(), pp=None,
1018
1045
reprocess=False, change_reporter=None,
1019
interesting_files=None, cherrypick=False):
1046
interesting_files=None, cherrypick=False, do_merge=True):
1020
1047
self.cherrypick = cherrypick
1021
1048
super(WeaveMerger, self).__init__(working_tree, this_tree,
1022
1049
base_tree, other_tree,
1050
interesting_files=interesting_files,
1023
1051
interesting_ids=interesting_ids,
1024
1052
pb=pb, pp=pp, reprocess=reprocess,
1025
change_reporter=change_reporter)
1053
change_reporter=change_reporter,
1027
1056
def _merged_lines(self, file_id):
1028
1057
"""Generate the merged lines.
1261
1290
for b_index in range(last_j, j):
1262
1291
if b_index in new_b:
1263
1292
if b_index in killed_a:
1264
yield 'conflicted-b', self.lines_b[a_index]
1293
yield 'conflicted-b', self.lines_b[b_index]
1266
1295
yield 'new-b', self.lines_b[b_index]