1478
1473
InterVersionedFile.register_optimiser(InterKnit)
1476
class WeaveToKnit(InterVersionedFile):
1477
"""Optimised code paths for weave to knit operations."""
1479
_matching_file_from_factory = bzrlib.weave.WeaveFile
1480
_matching_file_to_factory = KnitVersionedFile
1483
def is_compatible(source, target):
1484
"""Be compatible with weaves to knits."""
1486
return (isinstance(source, bzrlib.weave.Weave) and
1487
isinstance(target, KnitVersionedFile))
1488
except AttributeError:
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)
1496
version_ids = self._get_source_version_ids(version_ids, ignore_missing)
1501
pb = bzrlib.ui.ui_factory.nested_progress_bar()
1503
version_ids = list(version_ids)
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.
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)
1532
if not needed_versions and not mismatched_versions:
1534
full_list = topo_sort(self.source.get_graph())
1536
version_list = [i for i in full_list if (not self.target.has_version(i)
1537
and i in needed_versions)]
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))
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)
1566
InterVersionedFile.register_optimiser(WeaveToKnit)
1481
1569
class SequenceMatcher(difflib.SequenceMatcher):
1482
1570
"""Knit tuned sequence matcher.