~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Robert Collins
  • Date: 2006-03-01 12:09:59 UTC
  • mto: (1594.2.4 integration)
  • mto: This revision was merged to the branch mainline in revision 1596.
  • Revision ID: robertc@robertcollins.net-20060301120959-b58a073b9f7f7a00
Consolidate reweave and join as we have no separate usage, make reweave tests apply to all versionedfile implementations and deprecate the old reweave apis.

Show diffs side-by-side

added added

removed removed

Lines of Context:
59
59
# 10:16 < lifeless> implement 'knit.check()' like weave.check()
60
60
# 10:17 < lifeless> record known ghosts so we can detect when they are filled in rather than the current 'reweave 
61
61
#                    always' approach.
 
62
# move sha1 out of the content so that join is faster at verifying parents
 
63
# record content length ?
62
64
                  
63
65
 
 
66
from cStringIO import StringIO
64
67
import difflib
65
68
from difflib import SequenceMatcher
66
69
from gzip import GzipFile
67
70
import os
68
 
from StringIO import StringIO
69
71
 
 
72
import bzrlib.errors as errors
70
73
from bzrlib.errors import FileExists, NoSuchFile, KnitError, \
71
74
        InvalidRevisionId, KnitCorrupt, KnitHeaderError, \
72
75
        RevisionNotPresent, RevisionAlreadyPresent
508
511
            version_ids.remove(None)
509
512
 
510
513
        other_ancestry = set(other.get_ancestry(version_ids))
511
 
        needed_versions = other_ancestry - set(self._index.get_versions())
512
 
        if not needed_versions:
 
514
        this_versions = set(self._index.get_versions())
 
515
        needed_versions = other_ancestry - this_versions
 
516
        cross_check_versions = other_ancestry.intersection(this_versions)
 
517
        mismatched_versions = set()
 
518
        for version in cross_check_versions:
 
519
            # scan to include needed parents.
 
520
            n1 = set(self.get_parents(version))
 
521
            n2 = set(other.get_parents(version))
 
522
            if n1 != n2:
 
523
                # FIXME TEST this check for cycles being introduced works
 
524
                # the logic is we have a cycle if in our graph we are an
 
525
                # ancestor of any of the n2 revisions.
 
526
                for parent in n2:
 
527
                    if parent in n1:
 
528
                        # safe
 
529
                        continue
 
530
                    else:
 
531
                        parent_ancestors = other.get_ancestry(parent)
 
532
                        if version in parent_ancestors:
 
533
                            raise errors.GraphCycleError([parent, version])
 
534
                # ensure this parent will be available later.
 
535
                new_parents = n2.difference(n1)
 
536
                needed_versions.update(new_parents.difference(this_versions))
 
537
                mismatched_versions.add(version)
 
538
 
 
539
        if not needed_versions and not cross_check_versions:
513
540
            return 0
514
541
        full_list = topo_sort(other._index.get_graph())
515
542
 
549
576
            pos, size = self._data.add_record(version_id, digest, lines)
550
577
            self._index.add_version(version_id, options, pos, size, parents)
551
578
 
 
579
        for version in mismatched_versions:
 
580
            n1 = set(self.get_parents(version))
 
581
            n2 = set(other.get_parents(version))
 
582
            # write a combined record to our history.
 
583
            new_parents = self.get_parents(version) + list(n2.difference(n1))
 
584
            current_values = self._index._cache[version]
 
585
            self._index.add_version(version,
 
586
                                    current_values[1], 
 
587
                                    current_values[2],
 
588
                                    current_values[3],
 
589
                                    new_parents)
552
590
        pb.clear()
553
591
        return count
554
592
 
614
652
    The index data format is dictionary compressed when it comes to
615
653
    parent references; a index entry may only have parents that with a
616
654
    lover index number.  As a result, the index is topological sorted.
 
655
 
 
656
    Duplicate entries may be written to the index for a single version id
 
657
    if this is done then the latter one completely replaces the former:
 
658
    this allows updates to correct version and parent information. 
 
659
    Note that the two entries may share the delta, and that successive
 
660
    annotations and references MUST point to the first entry.
617
661
    """
618
662
 
619
663
    HEADER = "# bzr knit index 7\n"
621
665
    def _cache_version(self, version_id, options, pos, size, parents):
622
666
        val = (version_id, options, pos, size, parents)
623
667
        self._cache[version_id] = val
624
 
        self._history.append(version_id)
 
668
        if not version_id in self._history:
 
669
            self._history.append(version_id)
625
670
 
626
671
    def _iter_index(self, fp):
627
672
        lines = fp.read()
631
676
    def __init__(self, transport, filename, mode):
632
677
        _KnitComponentFile.__init__(self, transport, filename, mode)
633
678
        self._cache = {}
 
679
        # position in _history is the 'official' index for a revision
 
680
        # but the values may have come from a newer entry.
 
681
        # so - wc -l of a knit index is != the number of uniqe names
 
682
        # in the weave.
634
683
        self._history = []
635
684
        try:
636
685
            fp = self._transport.get(self._filename)