~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge.py

  • Committer: John Arbash Meinel
  • Date: 2008-07-29 21:44:50 UTC
  • mto: (3697.7.4 1.7)
  • mto: This revision was merged to the branch mainline in revision 3748.
  • Revision ID: john@arbash-meinel.com-20080729214450-ikbnt6xelmu0ms0r
Use the _lca_multi_way to work out if there is actually a kind/parent/name/content change.

This lets us filter out nodes that aren't interesting, as well as properly set the
'content_changed' flag.

Show diffs side-by-side

added added

removed removed

Lines of Context:
479
479
        return len(merge.cooked_conflicts)
480
480
 
481
481
 
 
482
class _InventoryNoneEntry(object):
 
483
    """This represents an inventory entry which *isn't there*.
 
484
 
 
485
    It simplifies the merging logic if we always have an InventoryEntry, even
 
486
    if it isn't actually present
 
487
    """
 
488
    executable = None
 
489
    kind = None
 
490
    name = None
 
491
    parent_id = None
 
492
    revision = None
 
493
    symlink_target = None
 
494
    text_sha1 = None
 
495
 
 
496
_none_entry = _InventoryNoneEntry()
 
497
 
 
498
 
482
499
class Merge3Merger(object):
483
500
    """Three-way merger that uses the merge3 text merger"""
484
501
    requires_base = True
669
686
        for path, file_id, other_ie, lca_values in walker.iter_all():
670
687
            # Is this modified at all from any of the other trees?
671
688
            if other_ie is None:
672
 
                last_rev = other_kind = other_parent_id = other_name = None
673
 
                other_executable = None
674
 
            else:
675
 
                last_rev = other_ie.revision
676
 
                other_kind = other_ie.kind
677
 
                other_parent_id = other_ie.parent_id
678
 
                other_name = other_ie.name
679
 
                other_executable = other_ie.executable
 
689
                other_ie = _none_entry
680
690
 
681
691
            # I believe we can actually change this to see if last_rev is
682
 
            # identical to *any* of the lca values.
 
692
            # identical to *any* of the lca values. Though we should actually
 
693
            # use the _lca_multi_way logic. However, it may be worthwhile to
 
694
            # shortcut entries that are identical in all of LCA + OTHER, just
 
695
            # to avoid the overhead of looking up information in BASE and THIS.
 
696
            other_revision = other_ie.revision
683
697
            for lca_path, ie in lca_values:
684
 
                if ((ie is None and other_ie is not None)
685
 
                    or ie.revision != last_rev):
 
698
                if ie is None or ie.revision != other_revision:
686
699
                    break
687
700
            else: # Identical in all trees
688
701
                continue
689
 
            kind_changed = False
690
 
            parent_id_changed = False
691
 
            name_changed = False
692
 
            for lca_path, ie in lca_values:
693
 
                if ie is None and other_ie is not None:
694
 
                    kind_changed = parent_id_changed = name_changed = True
695
 
                    break
696
 
                if ie.kind != other_kind:
697
 
                    kind_changed = True
698
 
                if ie.parent_id != other_parent_id:
699
 
                    parent_id_changed = True
700
 
                if ie.name != other_name:
701
 
                    name_changed = True
702
 
 
703
 
            if (not kind_changed and not parent_id_changed
704
 
                and not name_changed and other_kind == 'directory'):
705
 
                # Even though last-modified has changed, the actual attributes
706
 
                # of this entry hasn't changed, so skip it.
707
 
                continue
708
 
 
709
 
            is_content_changed = False
710
 
            if kind_changed:
711
 
                is_content_changed = True
 
702
 
 
703
            lca_entries = []
 
704
            for lca_path, lca_ie in lca_values:
 
705
                if lca_ie is None:
 
706
                    lca_entries.append(_none_entry)
 
707
                else:
 
708
                    lca_entries.append(lca_ie)
712
709
 
713
710
            if file_id in base_inventory:
714
 
                base_ie = self.base_tree.inventory[file_id]
715
 
                base_parent_id = base_ie.parent_id
716
 
                base_name = base_ie.name
717
 
                base_executable = base_ie.executable
 
711
                base_ie = base_inventory[file_id]
718
712
            else:
719
 
                base_parent_id = base_name = base_executable = None
 
713
                base_ie = _none_entry
 
714
 
720
715
            if file_id in this_inventory:
721
716
                this_ie = this_inventory[file_id]
722
 
                this_parent_id = this_ie.parent_id
723
 
                this_name = this_ie.name
724
 
                this_executable = this_ie.executable
725
717
            else:
726
 
                this_parent_id = this_name = this_executable = None
 
718
                this_ie = _none_entry
727
719
 
 
720
            kind_winner = Merge3Merger._lca_multi_way(
 
721
                (base_ie.kind, [ie.kind for ie in lca_entries]),
 
722
                other_ie.kind, this_ie.kind)
 
723
            parent_id_winner = Merge3Merger._lca_multi_way(
 
724
                (base_ie.parent_id, [ie.parent_id for ie in lca_entries]),
 
725
                other_ie.parent_id, this_ie.parent_id)
 
726
            name_winner = Merge3Merger._lca_multi_way(
 
727
                (base_ie.name, [ie.name for ie in lca_entries]),
 
728
                other_ie.name, this_ie.name)
 
729
            content_changed = True
 
730
            if kind_winner == 'this':
 
731
                # No kind change in OTHER, see if there are *any* changes
 
732
                if other_ie.kind == None:
 
733
                    # No content and 'this' wins the kind, so skip this?
 
734
                    # continue
 
735
                    pass
 
736
                if other_ie.kind == 'directory':
 
737
                    if parent_id_winner == 'this' and name_winner == 'this':
 
738
                        # No change for this directory in OTHER, skip
 
739
                        continue
 
740
                    content_changed = False
 
741
                elif other_ie.kind == 'file':
 
742
                    sha1_winner = Merge3Merger._lca_multi_way(
 
743
                        (base_ie.text_sha1, [ie.text_sha1 for ie
 
744
                                                           in lca_entries]),
 
745
                        other_ie.text_sha1, this_ie.text_sha1)
 
746
                    if (parent_id_winner == 'this' and name_winner == 'this'
 
747
                        and sha1_winner == 'this'):
 
748
                        # No kind, parent, name, content change for OTHER, so
 
749
                        # this node is not considered interesting
 
750
                        continue
 
751
                    if sha1_winner == 'this':
 
752
                        content_changed = False
728
753
 
729
754
            lca_parent_ids = []
730
755
            lca_names = []
731
756
            lca_executable = []
732
 
            for path, ie in lca_values:
733
 
                if ie is None:
734
 
                    lca_parent_ids.append(None)
735
 
                    lca_names.append(None)
736
 
                    lca_executable.append(None)
737
 
                else:
738
 
                    lca_parent_ids.append(ie.parent_id)
739
 
                    lca_names.append(ie.name)
740
 
                    lca_executable.append(ie.executable)
 
757
            lca_sha1 = []
 
758
            for ie in lca_entries:
 
759
                lca_parent_ids.append(ie.parent_id)
 
760
                lca_names.append(ie.name)
 
761
                lca_executable.append(ie.executable)
 
762
                lca_sha1.append(ie.text_sha1)
741
763
 
742
764
            # If we have gotten this far, that means something has changed
743
 
            result.append((file_id, True,
744
 
                           ((base_parent_id, lca_parent_ids),
745
 
                            other_parent_id, this_parent_id),
746
 
                           ((base_name, lca_names),
747
 
                            other_name, this_name),
748
 
                           ((base_executable, lca_executable),
749
 
                            other_executable, this_executable)
 
765
            result.append((file_id, content_changed,
 
766
                           ((base_ie.parent_id, lca_parent_ids),
 
767
                            other_ie.parent_id, this_ie.parent_id),
 
768
                           ((base_ie.name, lca_names),
 
769
                            other_ie.name, this_ie.name),
 
770
                           ((base_ie.executable, lca_executable),
 
771
                            other_ie.executable, this_ie.executable)
750
772
                          ))
751
773
        return result
752
774