~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-11-17 03:20:35 UTC
  • mfrom: (4792.4.3 456036)
  • Revision ID: pqm@pqm.ubuntu.com-20091117032035-s3sgtlixj1lrminn
(Gordon Tyler) Fix IndexError during 'bzr ignore /' (#456036)

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
    osutils,
26
26
    patiencediff,
27
27
    progress,
 
28
    registry,
28
29
    revision as _mod_revision,
29
30
    textfile,
30
31
    trace,
239
240
        if self.other_rev_id is None:
240
241
            other_basis_tree = self.revision_tree(self.other_basis)
241
242
            if other_basis_tree.has_changes(self.other_tree):
242
 
                raise errors.WorkingTreeNotRevision(self.this_tree)
 
243
                raise WorkingTreeNotRevision(self.this_tree)
243
244
            other_rev_id = self.other_basis
244
245
            self.other_tree = other_basis_tree
245
246
 
1149
1150
                self.tt.delete_contents(trans_id)
1150
1151
            if file_id in self.other_tree:
1151
1152
                # OTHER changed the file
1152
 
                wt = self.this_tree
1153
 
                if wt.supports_content_filtering():
1154
 
                    # We get the path from the working tree if it exists.
1155
 
                    # That fails though when OTHER is adding a file, so
1156
 
                    # we fall back to the other tree to find the path if
1157
 
                    # it doesn't exist locally.
1158
 
                    try:
1159
 
                        filter_tree_path = wt.id2path(file_id)
1160
 
                    except errors.NoSuchId:
1161
 
                        filter_tree_path = self.other_tree.id2path(file_id)
1162
 
                else:
1163
 
                    # Skip the id2path lookup for older formats
1164
 
                    filter_tree_path = None
1165
1153
                transform.create_from_tree(self.tt, trans_id,
1166
 
                                 self.other_tree, file_id,
1167
 
                                 filter_tree_path=filter_tree_path)
 
1154
                                           self.other_tree, file_id)
1168
1155
                if not file_in_this:
1169
1156
                    self.tt.version_file(file_id, trans_id)
1170
1157
                return "modified"
1257
1244
                ('THIS', self.this_tree, this_lines)]
1258
1245
        if not no_base:
1259
1246
            data.append(('BASE', self.base_tree, base_lines))
1260
 
 
1261
 
        # We need to use the actual path in the working tree of the file here,
1262
 
        # ignoring the conflict suffixes
1263
 
        wt = self.this_tree
1264
 
        if wt.supports_content_filtering():
1265
 
            try:
1266
 
                filter_tree_path = wt.id2path(file_id)
1267
 
            except errors.NoSuchId:
1268
 
                # file has been deleted
1269
 
                filter_tree_path = None
1270
 
        else:
1271
 
            # Skip the id2path lookup for older formats
1272
 
            filter_tree_path = None
1273
 
 
1274
1247
        versioned = False
1275
1248
        file_group = []
1276
1249
        for suffix, tree, lines in data:
1277
1250
            if file_id in tree:
1278
1251
                trans_id = self._conflict_file(name, parent_id, tree, file_id,
1279
 
                                               suffix, lines, filter_tree_path)
 
1252
                                               suffix, lines)
1280
1253
                file_group.append(trans_id)
1281
1254
                if set_version and not versioned:
1282
1255
                    self.tt.version_file(file_id, trans_id)
1284
1257
        return file_group
1285
1258
 
1286
1259
    def _conflict_file(self, name, parent_id, tree, file_id, suffix,
1287
 
                       lines=None, filter_tree_path=None):
 
1260
                       lines=None):
1288
1261
        """Emit a single conflict file."""
1289
1262
        name = name + '.' + suffix
1290
1263
        trans_id = self.tt.create_path(name, parent_id)
1291
 
        transform.create_from_tree(self.tt, trans_id, tree, file_id, lines,
1292
 
            filter_tree_path)
 
1264
        transform.create_from_tree(self.tt, trans_id, tree, file_id, lines)
1293
1265
        return trans_id
1294
1266
 
1295
1267
    def merge_executable(self, file_id, file_status):
1406
1378
    supports_reverse_cherrypick = False
1407
1379
    history_based = True
1408
1380
 
1409
 
    def _generate_merge_plan(self, file_id, base):
1410
 
        return self.this_tree.plan_file_merge(file_id, self.other_tree,
 
1381
    def _merged_lines(self, file_id):
 
1382
        """Generate the merged lines.
 
1383
        There is no distinction between lines that are meant to contain <<<<<<<
 
1384
        and conflicts.
 
1385
        """
 
1386
        if self.cherrypick:
 
1387
            base = self.base_tree
 
1388
        else:
 
1389
            base = None
 
1390
        plan = self.this_tree.plan_file_merge(file_id, self.other_tree,
1411
1391
                                              base=base)
1412
 
 
1413
 
    def _merged_lines(self, file_id):
1414
 
        """Generate the merged lines.
1415
 
        There is no distinction between lines that are meant to contain <<<<<<<
1416
 
        and conflicts.
1417
 
        """
1418
 
        if self.cherrypick:
1419
 
            base = self.base_tree
1420
 
        else:
1421
 
            base = None
1422
 
        plan = self._generate_merge_plan(file_id, base)
1423
1392
        if 'merge' in debug.debug_flags:
1424
1393
            plan = list(plan)
1425
1394
            trans_id = self.tt.trans_id_file_id(file_id)
1426
1395
            name = self.tt.final_name(trans_id) + '.plan'
1427
 
            contents = ('%11s|%s' % l for l in plan)
 
1396
            contents = ('%10s|%s' % l for l in plan)
1428
1397
            self.tt.new_file(name, self.tt.final_parent(trans_id), contents)
1429
1398
        textmerge = versionedfile.PlanWeaveMerge(plan, '<<<<<<< TREE\n',
1430
1399
                                                 '>>>>>>> MERGE-SOURCE\n')
1431
 
        lines, conflicts = textmerge.merge_lines(self.reprocess)
1432
 
        if conflicts:
1433
 
            base_lines = textmerge.base_from_plan()
1434
 
        else:
1435
 
            base_lines = None
1436
 
        return lines, base_lines
 
1400
        return textmerge.merge_lines(self.reprocess)
1437
1401
 
1438
1402
    def text_merge(self, file_id, trans_id):
1439
1403
        """Perform a (weave) text merge for a given file and file-id.
1440
1404
        If conflicts are encountered, .THIS and .OTHER files will be emitted,
1441
1405
        and a conflict will be noted.
1442
1406
        """
1443
 
        lines, base_lines = self._merged_lines(file_id)
 
1407
        lines, conflicts = self._merged_lines(file_id)
1444
1408
        lines = list(lines)
1445
1409
        # Note we're checking whether the OUTPUT is binary in this case,
1446
1410
        # because we don't want to get into weave merge guts.
1447
1411
        textfile.check_text_lines(lines)
1448
1412
        self.tt.create_file(lines, trans_id)
1449
 
        if base_lines is not None:
1450
 
            # Conflict
 
1413
        if conflicts:
1451
1414
            self._raw_conflicts.append(('text conflict', trans_id))
1452
1415
            name = self.tt.final_name(trans_id)
1453
1416
            parent_id = self.tt.final_parent(trans_id)
1454
1417
            file_group = self._dump_conflicts(name, parent_id, file_id,
1455
 
                                              no_base=False,
1456
 
                                              base_lines=base_lines)
 
1418
                                              no_base=True)
1457
1419
            file_group.append(trans_id)
1458
1420
 
1459
1421
 
1460
1422
class LCAMerger(WeaveMerger):
1461
1423
 
1462
 
    def _generate_merge_plan(self, file_id, base):
1463
 
        return self.this_tree.plan_file_lca_merge(file_id, self.other_tree,
 
1424
    def _merged_lines(self, file_id):
 
1425
        """Generate the merged lines.
 
1426
        There is no distinction between lines that are meant to contain <<<<<<<
 
1427
        and conflicts.
 
1428
        """
 
1429
        if self.cherrypick:
 
1430
            base = self.base_tree
 
1431
        else:
 
1432
            base = None
 
1433
        plan = self.this_tree.plan_file_lca_merge(file_id, self.other_tree,
1464
1434
                                                  base=base)
 
1435
        if 'merge' in debug.debug_flags:
 
1436
            plan = list(plan)
 
1437
            trans_id = self.tt.trans_id_file_id(file_id)
 
1438
            name = self.tt.final_name(trans_id) + '.plan'
 
1439
            contents = ('%10s|%s' % l for l in plan)
 
1440
            self.tt.new_file(name, self.tt.final_parent(trans_id), contents)
 
1441
        textmerge = versionedfile.PlanWeaveMerge(plan, '<<<<<<< TREE\n',
 
1442
                                                 '>>>>>>> MERGE-SOURCE\n')
 
1443
        return textmerge.merge_lines(self.reprocess)
 
1444
 
1465
1445
 
1466
1446
class Diff3Merger(Merge3Merger):
1467
1447
    """Three-way merger using external diff3 for text merging"""