~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-04-27 01:14:33 UTC
  • mfrom: (1686.1.1 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20060427011433-95634ee1da8a2049
Merge in faster joins from weave to knit.

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
84
85
 
85
86
 
86
87
# TODO: Split out code specific to this format into an associated object.
1357
1358
class InterKnit(InterVersionedFile):
1358
1359
    """Optimised code paths for knit to knit operations."""
1359
1360
    
1360
 
    _matching_file_factory = KnitVersionedFile
 
1361
    _matching_file_from_factory = KnitVersionedFile
 
1362
    _matching_file_to_factory = KnitVersionedFile
1361
1363
    
1362
1364
    @staticmethod
1363
1365
    def is_compatible(source, target):
1373
1375
        assert isinstance(self.source, KnitVersionedFile)
1374
1376
        assert isinstance(self.target, KnitVersionedFile)
1375
1377
 
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))
 
1378
        version_ids = self._get_source_version_ids(version_ids, ignore_missing)
1384
1379
 
1385
1380
        if not version_ids:
1386
1381
            return 0
1417
1412
                    needed_versions.update(new_parents.difference(this_versions))
1418
1413
                    mismatched_versions.add(version)
1419
1414
    
1420
 
            if not needed_versions and not cross_check_versions:
 
1415
            if not needed_versions and not mismatched_versions:
1421
1416
                return 0
1422
1417
            full_list = topo_sort(self.source.get_graph())
1423
1418
    
1478
1473
InterVersionedFile.register_optimiser(InterKnit)
1479
1474
 
1480
1475
 
 
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
 
1481
1569
class SequenceMatcher(difflib.SequenceMatcher):
1482
1570
    """Knit tuned sequence matcher.
1483
1571