~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Martin Pool
  • Date: 2006-04-28 09:35:20 UTC
  • mto: This revision was merged to the branch mainline in revision 1690.
  • Revision ID: mbp@sourcefrog.net-20060428093520-facdfa15d5007057
(patch) --diff-prefix option (goffredo, alexander)

Show diffs side-by-side

added added

removed removed

Lines of Context:
81
81
     sha_strings
82
82
from bzrlib.versionedfile import VersionedFile, InterVersionedFile
83
83
from bzrlib.tsort import topo_sort
84
 
import bzrlib.weave
85
84
 
86
85
 
87
86
# TODO: Split out code specific to this format into an associated object.
1358
1357
class InterKnit(InterVersionedFile):
1359
1358
    """Optimised code paths for knit to knit operations."""
1360
1359
    
1361
 
    _matching_file_from_factory = KnitVersionedFile
1362
 
    _matching_file_to_factory = KnitVersionedFile
 
1360
    _matching_file_factory = KnitVersionedFile
1363
1361
    
1364
1362
    @staticmethod
1365
1363
    def is_compatible(source, target):
1375
1373
        assert isinstance(self.source, KnitVersionedFile)
1376
1374
        assert isinstance(self.target, KnitVersionedFile)
1377
1375
 
1378
 
        version_ids = self._get_source_version_ids(version_ids, ignore_missing)
 
1376
        if version_ids is None:
 
1377
            version_ids = self.source.versions()
 
1378
        else:
 
1379
            if not ignore_missing:
 
1380
                self.source._check_versions_present(version_ids)
 
1381
            else:
 
1382
                version_ids = set(self.source.versions()).intersection(
 
1383
                    set(version_ids))
1379
1384
 
1380
1385
        if not version_ids:
1381
1386
            return 0
1412
1417
                    needed_versions.update(new_parents.difference(this_versions))
1413
1418
                    mismatched_versions.add(version)
1414
1419
    
1415
 
            if not needed_versions and not mismatched_versions:
 
1420
            if not needed_versions and not cross_check_versions:
1416
1421
                return 0
1417
1422
            full_list = topo_sort(self.source.get_graph())
1418
1423
    
1473
1478
InterVersionedFile.register_optimiser(InterKnit)
1474
1479
 
1475
1480
 
1476
 
class WeaveToKnit(InterVersionedFile):
1477
 
    """Optimised code paths for weave to knit operations."""
1478
 
    
1479
 
    _matching_file_from_factory = bzrlib.weave.WeaveFile
1480
 
    _matching_file_to_factory = KnitVersionedFile
1481
 
    
1482
 
    @staticmethod
1483
 
    def is_compatible(source, target):
1484
 
        """Be compatible with weaves to knits."""
1485
 
        try:
1486
 
            return (isinstance(source, bzrlib.weave.Weave) and
1487
 
                    isinstance(target, KnitVersionedFile))
1488
 
        except AttributeError:
1489
 
            return False
1490
 
 
1491
 
    def join(self, pb=None, msg=None, version_ids=None, ignore_missing=False):
1492
 
        """See InterVersionedFile.join."""
1493
 
        assert isinstance(self.source, bzrlib.weave.Weave)
1494
 
        assert isinstance(self.target, KnitVersionedFile)
1495
 
 
1496
 
        version_ids = self._get_source_version_ids(version_ids, ignore_missing)
1497
 
 
1498
 
        if not version_ids:
1499
 
            return 0
1500
 
 
1501
 
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
1502
 
        try:
1503
 
            version_ids = list(version_ids)
1504
 
    
1505
 
            self.source_ancestry = set(self.source.get_ancestry(version_ids))
1506
 
            this_versions = set(self.target._index.get_versions())
1507
 
            needed_versions = self.source_ancestry - this_versions
1508
 
            cross_check_versions = self.source_ancestry.intersection(this_versions)
1509
 
            mismatched_versions = set()
1510
 
            for version in cross_check_versions:
1511
 
                # scan to include needed parents.
1512
 
                n1 = set(self.target.get_parents_with_ghosts(version))
1513
 
                n2 = set(self.source.get_parents(version))
1514
 
                # if all of n2's parents are in n1, then its fine.
1515
 
                if n2.difference(n1):
1516
 
                    # FIXME TEST this check for cycles being introduced works
1517
 
                    # the logic is we have a cycle if in our graph we are an
1518
 
                    # ancestor of any of the n2 revisions.
1519
 
                    for parent in n2:
1520
 
                        if parent in n1:
1521
 
                            # safe
1522
 
                            continue
1523
 
                        else:
1524
 
                            parent_ancestors = self.source.get_ancestry(parent)
1525
 
                            if version in parent_ancestors:
1526
 
                                raise errors.GraphCycleError([parent, version])
1527
 
                    # ensure this parent will be available later.
1528
 
                    new_parents = n2.difference(n1)
1529
 
                    needed_versions.update(new_parents.difference(this_versions))
1530
 
                    mismatched_versions.add(version)
1531
 
    
1532
 
            if not needed_versions and not mismatched_versions:
1533
 
                return 0
1534
 
            full_list = topo_sort(self.source.get_graph())
1535
 
    
1536
 
            version_list = [i for i in full_list if (not self.target.has_version(i)
1537
 
                            and i in needed_versions)]
1538
 
    
1539
 
            # do the join:
1540
 
            count = 0
1541
 
            total = len(version_list)
1542
 
            for version_id in version_list:
1543
 
                pb.update("Converting to knit", count, total)
1544
 
                parents = self.source.get_parents(version_id)
1545
 
                # check that its will be a consistent copy:
1546
 
                for parent in parents:
1547
 
                    # if source has the parent, we must already have it
1548
 
                    assert (self.target.has_version(parent))
1549
 
                self.target.add_lines(
1550
 
                    version_id, parents, self.source.get_lines(version_id))
1551
 
                count = count + 1
1552
 
 
1553
 
            for version in mismatched_versions:
1554
 
                # FIXME RBC 20060309 is this needed?
1555
 
                n1 = set(self.target.get_parents_with_ghosts(version))
1556
 
                n2 = set(self.source.get_parents(version))
1557
 
                # write a combined record to our history preserving the current 
1558
 
                # parents as first in the list
1559
 
                new_parents = self.target.get_parents_with_ghosts(version) + list(n2.difference(n1))
1560
 
                self.target.fix_parents(version, new_parents)
1561
 
            return count
1562
 
        finally:
1563
 
            pb.finished()
1564
 
 
1565
 
 
1566
 
InterVersionedFile.register_optimiser(WeaveToKnit)
1567
 
 
1568
 
 
1569
1481
class SequenceMatcher(difflib.SequenceMatcher):
1570
1482
    """Knit tuned sequence matcher.
1571
1483