353
359
ensure_null(self.other_basis)]
354
360
if NULL_REVISION in revisions:
355
361
self.base_rev_id = NULL_REVISION
362
self.base_tree = self.revision_tree(self.base_rev_id)
363
self._is_criss_cross = False
357
self.base_rev_id, steps = self.revision_graph.find_unique_lca(
358
revisions[0], revisions[1], count_steps=True)
365
lcas = self.revision_graph.find_lca(revisions[0], revisions[1])
366
self._is_criss_cross = False
368
self.base_rev_id = NULL_REVISION
370
self.base_rev_id = list(lcas)[0]
371
else: # len(lcas) > 1
373
# find_unique_lca can only handle 2 nodes, so we have to
374
# start back at the beginning. It is a shame to traverse
375
# the graph again, but better than re-implementing
377
self.base_rev_id = self.revision_graph.find_unique_lca(
378
revisions[0], revisions[1])
380
self.base_rev_id = self.revision_graph.find_unique_lca(
382
self._is_criss_cross = True
359
383
if self.base_rev_id == NULL_REVISION:
360
384
raise UnrelatedBranches()
385
if self._is_criss_cross:
362
386
warning('Warning: criss-cross merge encountered. See bzr'
363
387
' help criss-cross.')
364
self.base_tree = self.revision_tree(self.base_rev_id)
388
interesting_revision_ids = [self.base_rev_id]
389
interesting_revision_ids.extend(lcas)
390
interesting_trees = dict((t.get_revision_id(), t)
391
for t in self.this_branch.repository.revision_trees(
392
interesting_revision_ids))
393
self._cached_trees.update(interesting_trees)
394
self.base_tree = interesting_trees.pop(self.base_rev_id)
395
sorted_lca_keys = self.revision_graph.find_merge_order(
397
self._lca_trees = [interesting_trees[key]
398
for key in sorted_lca_keys]
400
self.base_tree = self.revision_tree(self.base_rev_id)
365
401
self.base_is_ancestor = True
366
402
self.base_is_other_ancestor = True
409
445
if self.merge_type.supports_cherrypick:
410
446
kwargs['cherrypick'] = (not self.base_is_ancestor or
411
447
not self.base_is_other_ancestor)
448
if self._is_criss_cross and getattr(self.merge_type,
449
'supports_lca_trees', False):
450
kwargs['lca_trees'] = self._lca_trees
412
451
return self.merge_type(pb=self._pb,
413
452
change_reporter=self.change_reporter,
455
def _do_merge_to(self, merge):
457
if self.recurse == 'down':
458
for relpath, file_id in self.this_tree.iter_references():
459
sub_tree = self.this_tree.get_nested_tree(file_id, relpath)
460
other_revision = self.other_tree.get_reference_revision(
462
if other_revision == sub_tree.last_revision():
464
sub_merge = Merger(sub_tree.branch, this_tree=sub_tree)
465
sub_merge.merge_type = self.merge_type
466
other_branch = self.other_branch.reference_parent(file_id, relpath)
467
sub_merge.set_other_revision(other_revision, other_branch)
468
base_revision = self.base_tree.get_reference_revision(file_id)
469
sub_merge.base_tree = \
470
sub_tree.branch.repository.revision_tree(base_revision)
471
sub_merge.base_rev_id = base_revision
416
474
def do_merge(self):
417
475
self.this_tree.lock_tree_write()
418
if self.base_tree is not None:
419
self.base_tree.lock_read()
420
if self.other_tree is not None:
421
self.other_tree.lock_read()
423
merge = self.make_merger()
425
if self.recurse == 'down':
426
for relpath, file_id in self.this_tree.iter_references():
427
sub_tree = self.this_tree.get_nested_tree(file_id, relpath)
428
other_revision = self.other_tree.get_reference_revision(
430
if other_revision == sub_tree.last_revision():
432
sub_merge = Merger(sub_tree.branch, this_tree=sub_tree)
433
sub_merge.merge_type = self.merge_type
434
other_branch = self.other_branch.reference_parent(file_id, relpath)
435
sub_merge.set_other_revision(other_revision, other_branch)
436
base_revision = self.base_tree.get_reference_revision(file_id)
437
sub_merge.base_tree = \
438
sub_tree.branch.repository.revision_tree(base_revision)
439
sub_merge.base_rev_id = base_revision
443
if self.other_tree is not None:
444
self.other_tree.unlock()
445
477
if self.base_tree is not None:
446
self.base_tree.unlock()
478
self.base_tree.lock_read()
480
if self.other_tree is not None:
481
self.other_tree.lock_read()
483
merge = self.make_merger()
484
self._do_merge_to(merge)
486
if self.other_tree is not None:
487
self.other_tree.unlock()
489
if self.base_tree is not None:
490
self.base_tree.unlock()
447
492
self.this_tree.unlock()
448
493
if len(merge.cooked_conflicts) == 0:
449
494
if not self.ignore_zero and not is_quiet():
614
694
result.append((file_id, changed, parents3, names3, executable3))
697
def _entries_lca(self):
698
"""Gather data about files modified between multiple trees.
700
This compares OTHER versus all LCA trees, and for interesting entries,
701
it then compares with THIS and BASE.
703
For the multi-valued entries, the format will be (BASE, [lca1, lca2])
704
:return: [(file_id, changed, parents, names, executable)]
705
file_id Simple file_id of the entry
706
changed Boolean, True if the kind or contents changed
708
parents ((base, [parent_id, in, lcas]), parent_id_other,
710
names ((base, [name, in, lcas]), name_in_other, name_in_this)
711
executable ((base, [exec, in, lcas]), exec_in_other, exec_in_this)
713
if self.interesting_files is not None:
714
lookup_trees = [self.this_tree, self.base_tree]
715
lookup_trees.extend(self._lca_trees)
716
# I think we should include the lca trees as well
717
interesting_ids = self.other_tree.paths2ids(self.interesting_files,
720
interesting_ids = self.interesting_ids
722
walker = _mod_tree.MultiWalker(self.other_tree, self._lca_trees)
724
base_inventory = self.base_tree.inventory
725
this_inventory = self.this_tree.inventory
726
for path, file_id, other_ie, lca_values in walker.iter_all():
727
# Is this modified at all from any of the other trees?
729
other_ie = _none_entry
730
if interesting_ids is not None and file_id not in interesting_ids:
733
# If other_revision is found in any of the lcas, that means this
734
# node is uninteresting. This is because when merging, if there are
735
# multiple heads(), we have to create a new node. So if we didn't,
736
# we know that the ancestry is linear, and that OTHER did not
738
# See doc/developers/lca_merge_resolution.txt for details
739
other_revision = other_ie.revision
740
if other_revision is not None:
741
# We can't use this shortcut when other_revision is None,
742
# because it may be None because things are WorkingTrees, and
743
# not because it is *actually* None.
744
is_unmodified = False
745
for lca_path, ie in lca_values:
746
if ie is not None and ie.revision == other_revision:
753
for lca_path, lca_ie in lca_values:
755
lca_entries.append(_none_entry)
757
lca_entries.append(lca_ie)
759
if file_id in base_inventory:
760
base_ie = base_inventory[file_id]
762
base_ie = _none_entry
764
if file_id in this_inventory:
765
this_ie = this_inventory[file_id]
767
this_ie = _none_entry
773
for lca_ie in lca_entries:
774
lca_kinds.append(lca_ie.kind)
775
lca_parent_ids.append(lca_ie.parent_id)
776
lca_names.append(lca_ie.name)
777
lca_executable.append(lca_ie.executable)
779
kind_winner = self._lca_multi_way(
780
(base_ie.kind, lca_kinds),
781
other_ie.kind, this_ie.kind)
782
parent_id_winner = self._lca_multi_way(
783
(base_ie.parent_id, lca_parent_ids),
784
other_ie.parent_id, this_ie.parent_id)
785
name_winner = self._lca_multi_way(
786
(base_ie.name, lca_names),
787
other_ie.name, this_ie.name)
789
content_changed = True
790
if kind_winner == 'this':
791
# No kind change in OTHER, see if there are *any* changes
792
if other_ie.kind == None:
793
# No content and 'this' wins the kind, so skip this?
796
elif other_ie.kind == 'directory':
797
if parent_id_winner == 'this' and name_winner == 'this':
798
# No change for this directory in OTHER, skip
800
content_changed = False
801
elif other_ie.kind == 'file':
802
def get_sha1(ie, tree):
803
if ie.kind != 'file':
805
return tree.get_file_sha1(file_id)
806
base_sha1 = get_sha1(base_ie, self.base_tree)
807
lca_sha1s = [get_sha1(ie, tree) for ie, tree
808
in zip(lca_entries, self._lca_trees)]
809
this_sha1 = get_sha1(this_ie, self.this_tree)
810
other_sha1 = get_sha1(other_ie, self.other_tree)
811
sha1_winner = self._lca_multi_way(
812
(base_sha1, lca_sha1s), other_sha1, this_sha1,
813
allow_overriding_lca=False)
814
exec_winner = self._lca_multi_way(
815
(base_ie.executable, lca_executable),
816
other_ie.executable, this_ie.executable)
817
if (parent_id_winner == 'this' and name_winner == 'this'
818
and sha1_winner == 'this' and exec_winner == 'this'):
819
# No kind, parent, name, exec, or content change for
820
# OTHER, so this node is not considered interesting
822
if sha1_winner == 'this':
823
content_changed = False
824
elif other_ie.kind == 'symlink':
825
def get_target(ie, tree):
826
if ie.kind != 'symlink':
828
return tree.get_symlink_target(file_id)
829
base_target = get_target(base_ie, self.base_tree)
830
lca_targets = [get_target(ie, tree) for ie, tree
831
in zip(lca_entries, self._lca_trees)]
832
this_target = get_target(this_ie, self.this_tree)
833
other_target = get_target(other_ie, self.other_tree)
834
target_winner = self._lca_multi_way(
835
(base_target, lca_targets),
836
other_target, this_target)
837
if (parent_id_winner == 'this' and name_winner == 'this'
838
and target_winner == 'this'):
839
# No kind, parent, name, or symlink target change
842
if target_winner == 'this':
843
content_changed = False
844
elif other_ie.kind == 'tree-reference':
845
# The 'changed' information seems to be handled at a higher
846
# level. At least, _entries3 returns False for content
847
# changed, even when at a new revision_id.
848
content_changed = False
849
if (parent_id_winner == 'this' and name_winner == 'this'):
850
# Nothing interesting
853
raise AssertionError('unhandled kind: %s' % other_ie.kind)
854
# XXX: We need to handle kind == 'symlink'
856
# If we have gotten this far, that means something has changed
857
result.append((file_id, content_changed,
858
((base_ie.parent_id, lca_parent_ids),
859
other_ie.parent_id, this_ie.parent_id),
860
((base_ie.name, lca_names),
861
other_ie.name, this_ie.name),
862
((base_ie.executable, lca_executable),
863
other_ie.executable, this_ie.executable)
617
868
def fix_root(self):
619
870
self.tt.final_kind(self.tt.root)
962
def _lca_multi_way(bases, other, this, allow_overriding_lca=True):
963
"""Consider LCAs when determining whether a change has occurred.
965
If LCAS are all identical, this is the same as a _three_way comparison.
967
:param bases: value in (BASE, [LCAS])
968
:param other: value in OTHER
969
:param this: value in THIS
970
:param allow_overriding_lca: If there is more than one unique lca
971
value, allow OTHER to override THIS if it has a new value, and
972
THIS only has an lca value, or vice versa. This is appropriate for
973
truly scalar values, not as much for non-scalars.
974
:return: 'this', 'other', or 'conflict' depending on whether an entry
977
# See doc/developers/lca_merge_resolution.txt for details about this
980
# Either Ambiguously clean, or nothing was actually changed. We
983
base_val, lca_vals = bases
984
# Remove 'base_val' from the lca_vals, because it is not interesting
985
filtered_lca_vals = [lca_val for lca_val in lca_vals
986
if lca_val != base_val]
987
if len(filtered_lca_vals) == 0:
988
return Merge3Merger._three_way(base_val, other, this)
990
unique_lca_vals = set(filtered_lca_vals)
991
if len(unique_lca_vals) == 1:
992
return Merge3Merger._three_way(unique_lca_vals.pop(), other, this)
994
if allow_overriding_lca:
995
if other in unique_lca_vals:
996
if this in unique_lca_vals:
997
# Each side picked a different lca, conflict
1000
# This has a value which supersedes both lca values, and
1001
# other only has an lca value
1003
elif this in unique_lca_vals:
1004
# OTHER has a value which supersedes both lca values, and this
1005
# only has an lca value
1008
# At this point, the lcas disagree, and the tips disagree
708
1012
def scalar_three_way(this_tree, base_tree, other_tree, file_id, key):
709
1013
"""Do a three-way test on a scalar.
710
1014
Return "this", "other" or "conflict", depending whether a value wins.