/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/merge.py

  • Committer: Parth Malwankar
  • Date: 2010-04-19 13:04:30 UTC
  • mfrom: (5165 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5166.
  • Revision ID: parth.malwankar@gmail.com-20100419130430-njvxdaka6xbqwvjw
merged in trunk and moved NEWS entry to right location.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1015
1015
                        continue
1016
1016
                else:
1017
1017
                    raise AssertionError('unhandled kind: %s' % other_ie.kind)
1018
 
                # XXX: We need to handle kind == 'symlink'
1019
1018
 
1020
1019
            # If we have gotten this far, that means something has changed
1021
1020
            result.append((file_id, content_changed,
1043
1042
        other_root = self.tt.trans_id_file_id(other_root_file_id)
1044
1043
        if other_root == self.tt.root:
1045
1044
            return
 
1045
        if self.other_tree.inventory.root.file_id in self.this_tree.inventory:
 
1046
            # the other tree's root is a non-root in the current tree (as when
 
1047
            # a previously unrelated branch is merged into another)
 
1048
            return
1046
1049
        try:
1047
1050
            self.tt.final_kind(other_root)
 
1051
            other_root_is_present = True
1048
1052
        except errors.NoSuchFile:
1049
 
            return
1050
 
        if self.this_tree.has_id(self.other_tree.inventory.root.file_id):
1051
 
            # the other tree's root is a non-root in the current tree
1052
 
            return
1053
 
        self.reparent_children(self.other_tree.inventory.root, self.tt.root)
1054
 
        self.tt.cancel_creation(other_root)
1055
 
        self.tt.cancel_versioning(other_root)
1056
 
 
1057
 
    def reparent_children(self, ie, target):
1058
 
        for thing, child in ie.children.iteritems():
 
1053
            # other_root doesn't have a physical representation. We still need
 
1054
            # to move any references to the actual root of the tree.
 
1055
            other_root_is_present = False
 
1056
        # 'other_tree.inventory.root' is not present in this tree. We are
 
1057
        # calling adjust_path for children which *want* to be present with a
 
1058
        # correct place to go.
 
1059
        for thing, child in self.other_tree.inventory.root.children.iteritems():
1059
1060
            trans_id = self.tt.trans_id_file_id(child.file_id)
1060
 
            self.tt.adjust_path(self.tt.final_name(trans_id), target, trans_id)
 
1061
            if not other_root_is_present:
 
1062
                # FIXME: Make final_kind returns None instead of raising
 
1063
                # NoSuchFile to avoid the ugly construct below -- vila 20100402
 
1064
                try:
 
1065
                    self.tt.final_kind(trans_id)
 
1066
                    # The item exist in the final tree and has a defined place
 
1067
                    # to go already.
 
1068
                    continue
 
1069
                except errors.NoSuchFile, e:
 
1070
                    pass
 
1071
            # Move the item into the root
 
1072
            self.tt.adjust_path(self.tt.final_name(trans_id),
 
1073
                                self.tt.root, trans_id)
 
1074
        if other_root_is_present:
 
1075
            self.tt.cancel_creation(other_root)
 
1076
            self.tt.cancel_versioning(other_root)
1061
1077
 
1062
1078
    def write_modified(self, results):
1063
1079
        modified_hashes = {}
1110
1126
 
1111
1127
    @staticmethod
1112
1128
    def _three_way(base, other, this):
1113
 
        #if base == other, either they all agree, or only THIS has changed.
1114
1129
        if base == other:
 
1130
            # if 'base == other', either they all agree, or only 'this' has
 
1131
            # changed.
1115
1132
            return 'this'
1116
1133
        elif this not in (base, other):
 
1134
            # 'this' is neither 'base' nor 'other', so both sides changed
1117
1135
            return 'conflict'
1118
 
        # "Ambiguous clean merge" -- both sides have made the same change.
1119
1136
        elif this == other:
 
1137
            # "Ambiguous clean merge" -- both sides have made the same change.
1120
1138
            return "this"
1121
 
        # this == base: only other has changed.
1122
1139
        else:
 
1140
            # this == base: only other has changed.
1123
1141
            return "other"
1124
1142
 
1125
1143
    @staticmethod
1169
1187
                # only has an lca value
1170
1188
                return 'other'
1171
1189
 
1172
 
        # At this point, the lcas disagree, and the tips disagree
 
1190
        # At this point, the lcas disagree, and the tip disagree
1173
1191
        return 'conflict'
1174
1192
 
1175
1193
    @staticmethod
1229
1247
                parent_id_winner = "other"
1230
1248
        if name_winner == "this" and parent_id_winner == "this":
1231
1249
            return
1232
 
        if name_winner == "conflict":
1233
 
            trans_id = self.tt.trans_id_file_id(file_id)
1234
 
            self._raw_conflicts.append(('name conflict', trans_id,
1235
 
                                        this_name, other_name))
1236
 
        if parent_id_winner == "conflict":
1237
 
            trans_id = self.tt.trans_id_file_id(file_id)
1238
 
            self._raw_conflicts.append(('parent conflict', trans_id,
1239
 
                                        this_parent, other_parent))
 
1250
        if name_winner == 'conflict' or parent_id_winner == 'conflict':
 
1251
            # Creating helpers (.OTHER or .THIS) here cause problems down the
 
1252
            # road if a ContentConflict needs to be created so we should not do
 
1253
            # that
 
1254
            trans_id = self.tt.trans_id_file_id(file_id)
 
1255
            self._raw_conflicts.append(('path conflict', trans_id, file_id,
 
1256
                                        this_parent, this_name,
 
1257
                                        other_parent, other_name))
1240
1258
        if other_name is None:
1241
1259
            # it doesn't matter whether the result was 'other' or
1242
1260
            # 'conflict'-- if there's no 'other', we leave it alone.
1243
1261
            return
1244
 
        # if we get here, name_winner and parent_winner are set to safe values.
1245
 
        trans_id = self.tt.trans_id_file_id(file_id)
1246
1262
        parent_id = parents[self.winner_idx[parent_id_winner]]
1247
1263
        if parent_id is not None:
1248
 
            parent_trans_id = self.tt.trans_id_file_id(parent_id)
 
1264
            # if we get here, name_winner and parent_winner are set to safe
 
1265
            # values.
1249
1266
            self.tt.adjust_path(names[self.winner_idx[name_winner]],
1250
 
                                parent_trans_id, trans_id)
 
1267
                                self.tt.trans_id_file_id(parent_id),
 
1268
                                self.tt.trans_id_file_id(file_id))
1251
1269
 
1252
1270
    def _do_merge_contents(self, file_id):
1253
1271
        """Performs a merge on file_id contents."""
1532
1550
 
1533
1551
    def cook_conflicts(self, fs_conflicts):
1534
1552
        """Convert all conflicts into a form that doesn't depend on trans_id"""
1535
 
        name_conflicts = {}
1536
1553
        self.cooked_conflicts.extend(transform.cook_conflicts(
1537
1554
                fs_conflicts, self.tt))
1538
1555
        fp = transform.FinalPaths(self.tt)
1539
1556
        for conflict in self._raw_conflicts:
1540
1557
            conflict_type = conflict[0]
1541
 
            if conflict_type in ('name conflict', 'parent conflict'):
1542
 
                trans_id = conflict[1]
1543
 
                conflict_args = conflict[2:]
1544
 
                if trans_id not in name_conflicts:
1545
 
                    name_conflicts[trans_id] = {}
1546
 
                transform.unique_add(name_conflicts[trans_id], conflict_type,
1547
 
                                     conflict_args)
1548
 
            if conflict_type == 'contents conflict':
 
1558
            if conflict_type == 'path conflict':
 
1559
                (trans_id, file_id,
 
1560
                this_parent, this_name,
 
1561
                other_parent, other_name) = conflict[1:]
 
1562
                if this_parent is None or this_name is None:
 
1563
                    this_path = '<deleted>'
 
1564
                else:
 
1565
                    parent_path =  fp.get_path(
 
1566
                        self.tt.trans_id_file_id(this_parent))
 
1567
                    this_path = osutils.pathjoin(parent_path, this_name)
 
1568
                if other_parent is None or other_name is None:
 
1569
                    other_path = '<deleted>'
 
1570
                else:
 
1571
                    parent_path =  fp.get_path(
 
1572
                        self.tt.trans_id_file_id(other_parent))
 
1573
                    other_path = osutils.pathjoin(parent_path, other_name)
 
1574
                c = _mod_conflicts.Conflict.factory(
 
1575
                    'path conflict', path=this_path,
 
1576
                    conflict_path=other_path,
 
1577
                    file_id=file_id)
 
1578
            elif conflict_type == 'contents conflict':
1549
1579
                for trans_id in conflict[1]:
1550
1580
                    file_id = self.tt.final_file_id(trans_id)
1551
1581
                    if file_id is not None:
1557
1587
                        break
1558
1588
                c = _mod_conflicts.Conflict.factory(conflict_type,
1559
1589
                                                    path=path, file_id=file_id)
1560
 
                self.cooked_conflicts.append(c)
1561
 
            if conflict_type == 'text conflict':
 
1590
            elif conflict_type == 'text conflict':
1562
1591
                trans_id = conflict[1]
1563
1592
                path = fp.get_path(trans_id)
1564
1593
                file_id = self.tt.final_file_id(trans_id)
1565
1594
                c = _mod_conflicts.Conflict.factory(conflict_type,
1566
1595
                                                    path=path, file_id=file_id)
1567
 
                self.cooked_conflicts.append(c)
1568
 
 
1569
 
        for trans_id, conflicts in name_conflicts.iteritems():
1570
 
            try:
1571
 
                this_parent, other_parent = conflicts['parent conflict']
1572
 
                if this_parent == other_parent:
1573
 
                    raise AssertionError()
1574
 
            except KeyError:
1575
 
                this_parent = other_parent = \
1576
 
                    self.tt.final_file_id(self.tt.final_parent(trans_id))
1577
 
            try:
1578
 
                this_name, other_name = conflicts['name conflict']
1579
 
                if this_name == other_name:
1580
 
                    raise AssertionError()
1581
 
            except KeyError:
1582
 
                this_name = other_name = self.tt.final_name(trans_id)
1583
 
            other_path = fp.get_path(trans_id)
1584
 
            if this_parent is not None and this_name is not None:
1585
 
                this_parent_path = \
1586
 
                    fp.get_path(self.tt.trans_id_file_id(this_parent))
1587
 
                this_path = osutils.pathjoin(this_parent_path, this_name)
1588
1596
            else:
1589
 
                this_path = "<deleted>"
1590
 
            file_id = self.tt.final_file_id(trans_id)
1591
 
            c = _mod_conflicts.Conflict.factory('path conflict', path=this_path,
1592
 
                                                conflict_path=other_path,
1593
 
                                                file_id=file_id)
 
1597
                raise AssertionError('bad conflict type: %r' % (conflict,))
1594
1598
            self.cooked_conflicts.append(c)
1595
1599
        self.cooked_conflicts.sort(key=_mod_conflicts.Conflict.sort_key)
1596
1600