~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 22:19:33 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-20080729221933-eecf0fzftxi014wc
Hook up the lca-way logic into the path handlers.

Add at least 1 test which would fail without using this logic.
Lots more tests to follow. Mostly stuff that we can't really test at the
lower levels.

Show diffs side-by-side

added added

removed removed

Lines of Context:
597
597
        return self.tt
598
598
 
599
599
    def _compute_transform(self):
600
 
        entries = self._entries3()
 
600
        if self._lca_trees is None:
 
601
            entries = self._entries3()
 
602
            resolver = self._three_way
 
603
        else:
 
604
            entries = self._entries_lca()
 
605
            resolver = self._lca_multi_way
601
606
        child_pb = ui.ui_factory.nested_progress_bar()
602
607
        try:
603
608
            for num, (file_id, changed, parents3, names3,
604
609
                      executable3) in enumerate(entries):
605
610
                child_pb.update('Preparing file merge', num, len(entries))
606
 
                self._merge_names(file_id, parents3, names3)
 
611
                self._merge_names(file_id, parents3, names3, resolver=resolver)
607
612
                if changed:
608
613
                    file_status = self.merge_contents(file_id)
609
614
                else:
610
615
                    file_status = 'unmodified'
611
616
                self._merge_executable(file_id,
612
 
                    executable3, file_status)
 
617
                    executable3, file_status, resolver=resolver)
613
618
        finally:
614
619
            child_pb.finished()
615
620
        self.fix_root()
717
722
            else:
718
723
                this_ie = _none_entry
719
724
 
 
725
            lca_kinds = []
 
726
            lca_parent_ids = []
 
727
            lca_names = []
 
728
            lca_executable = []
 
729
            lca_sha1s = []
 
730
            for lca_ie in lca_entries:
 
731
                lca_kinds.append(lca_ie.kind)
 
732
                lca_parent_ids.append(lca_ie.parent_id)
 
733
                lca_names.append(lca_ie.name)
 
734
                lca_executable.append(lca_ie.executable)
 
735
                lca_sha1s.append(lca_ie.text_sha1)
 
736
 
720
737
            kind_winner = Merge3Merger._lca_multi_way(
721
 
                (base_ie.kind, [ie.kind for ie in lca_entries]),
 
738
                (base_ie.kind, lca_kinds),
722
739
                other_ie.kind, this_ie.kind)
723
740
            parent_id_winner = Merge3Merger._lca_multi_way(
724
 
                (base_ie.parent_id, [ie.parent_id for ie in lca_entries]),
 
741
                (base_ie.parent_id, lca_parent_ids),
725
742
                other_ie.parent_id, this_ie.parent_id)
726
743
            name_winner = Merge3Merger._lca_multi_way(
727
 
                (base_ie.name, [ie.name for ie in lca_entries]),
 
744
                (base_ie.name, lca_names),
728
745
                other_ie.name, this_ie.name)
 
746
 
729
747
            content_changed = True
730
748
            if kind_winner == 'this':
731
749
                # No kind change in OTHER, see if there are *any* changes
733
751
                    # No content and 'this' wins the kind, so skip this?
734
752
                    # continue
735
753
                    pass
736
 
                if other_ie.kind == 'directory':
 
754
                elif other_ie.kind == 'directory':
737
755
                    if parent_id_winner == 'this' and name_winner == 'this':
738
756
                        # No change for this directory in OTHER, skip
739
757
                        continue
740
758
                    content_changed = False
741
759
                elif other_ie.kind == 'file':
742
760
                    sha1_winner = Merge3Merger._lca_multi_way(
743
 
                        (base_ie.text_sha1, [ie.text_sha1 for ie
744
 
                                                           in lca_entries]),
 
761
                        (base_ie.text_sha1, lca_sha1s),
745
762
                        other_ie.text_sha1, this_ie.text_sha1)
 
763
                    # XXX: This should be tested before we include it, not
 
764
                    #      sure how to actually get a test written for this.
 
765
                    # exec_winner = Merge3Merger._lca_multi_way(
 
766
                    #     (base_ie.executable, lca_executable),
 
767
                    #     other_ie.executable, this_ie.executable)
746
768
                    if (parent_id_winner == 'this' and name_winner == 'this'
747
769
                        and sha1_winner == 'this'):
748
770
                        # No kind, parent, name, content change for OTHER, so
750
772
                        continue
751
773
                    if sha1_winner == 'this':
752
774
                        content_changed = False
753
 
 
754
 
            lca_parent_ids = []
755
 
            lca_names = []
756
 
            lca_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)
 
775
                else:
 
776
                    raise AssertionError('unhandled kind: %s' % other_ie.kind)
 
777
                # XXX: We need to handle kind == 'symlink'
763
778
 
764
779
            # If we have gotten this far, that means something has changed
765
780
            result.append((file_id, content_changed,
948
963
                parents.append(entry.parent_id)
949
964
        return self._merge_names(file_id, parents, names)
950
965
 
951
 
    def _merge_names(self, file_id, parents, names):
 
966
    def _merge_names(self, file_id, parents, names, resolver=None):
952
967
        """Perform a merge on file_id names and parents"""
 
968
        if resolver is None:
 
969
            resolver = self._three_way
953
970
        base_name, other_name, this_name = names
954
971
        base_parent, other_parent, this_parent = parents
955
972
 
956
 
        name_winner = self._three_way(*names)
 
973
        name_winner = resolver(*names)
957
974
 
958
 
        parent_id_winner = self._three_way(*parents)
 
975
        parent_id_winner = resolver(*parents)
959
976
        if this_name is None:
960
977
            if name_winner == "this":
961
978
                name_winner = "other"
1151
1168
                      self.other_tree, self.this_tree)]
1152
1169
        self._merge_executable(file_id, executable, file_status)
1153
1170
 
1154
 
    def _merge_executable(self, file_id, executable, file_status):
 
1171
    def _merge_executable(self, file_id, executable, file_status,
 
1172
                          resolver=None):
1155
1173
        """Perform a merge on the execute bit."""
 
1174
        if resolver is None:
 
1175
            resolver = self._three_way
1156
1176
        base_executable, other_executable, this_executable = executable
1157
1177
        if file_status == "deleted":
1158
1178
            return
1159
 
        winner = self._three_way(*executable)
 
1179
        winner = resolver(*executable)
1160
1180
        if winner == "conflict":
1161
1181
        # There must be a None in here, if we have a conflict, but we
1162
1182
        # need executability since file status was not deleted.