/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: John Arbash Meinel
  • Date: 2009-07-08 14:37:25 UTC
  • mfrom: (4516 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4517.
  • Revision ID: john@arbash-meinel.com-20090708143725-sc9sjy3mz4cxwxzz
Merge bzr.dev 4516

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
 
54
54
 
55
55
from cStringIO import StringIO
56
 
from itertools import izip, chain
 
56
from itertools import izip
57
57
import operator
58
58
import os
59
59
import sys
686
686
        content = knit._get_content(key)
687
687
        # adjust for the fact that serialised annotations are only key suffixes
688
688
        # for this factory.
689
 
        if type(key) == tuple:
 
689
        if type(key) is tuple:
690
690
            prefix = key[:-1]
691
691
            origins = content.annotate()
692
692
            result = []
909
909
            # indexes can't directly store that, so we give them
910
910
            # an empty tuple instead.
911
911
            parents = ()
 
912
        line_bytes = ''.join(lines)
912
913
        return self._add(key, lines, parents,
913
 
            parent_texts, left_matching_blocks, nostore_sha, random_id)
 
914
            parent_texts, left_matching_blocks, nostore_sha, random_id,
 
915
            line_bytes=line_bytes)
 
916
 
 
917
    def _add_text(self, key, parents, text, nostore_sha=None, random_id=False):
 
918
        """See VersionedFiles._add_text()."""
 
919
        self._index._check_write_ok()
 
920
        self._check_add(key, None, random_id, check_content=False)
 
921
        if text.__class__ is not str:
 
922
            raise errors.BzrBadParameterUnicode("text")
 
923
        if parents is None:
 
924
            # The caller might pass None if there is no graph data, but kndx
 
925
            # indexes can't directly store that, so we give them
 
926
            # an empty tuple instead.
 
927
            parents = ()
 
928
        return self._add(key, None, parents,
 
929
            None, None, nostore_sha, random_id,
 
930
            line_bytes=text)
914
931
 
915
932
    def _add(self, key, lines, parents, parent_texts,
916
 
        left_matching_blocks, nostore_sha, random_id):
 
933
        left_matching_blocks, nostore_sha, random_id,
 
934
        line_bytes):
917
935
        """Add a set of lines on top of version specified by parents.
918
936
 
919
937
        Any versions not present will be converted into ghosts.
 
938
 
 
939
        :param lines: A list of strings where each one is a single line (has a
 
940
            single newline at the end of the string) This is now optional
 
941
            (callers can pass None). It is left in its location for backwards
 
942
            compatibility. It should ''.join(lines) must == line_bytes
 
943
        :param line_bytes: A single string containing the content
 
944
 
 
945
        We pass both lines and line_bytes because different routes bring the
 
946
        values to this function. And for memory efficiency, we don't want to
 
947
        have to split/join on-demand.
920
948
        """
921
949
        # first thing, if the content is something we don't need to store, find
922
950
        # that out.
923
 
        line_bytes = ''.join(lines)
924
951
        digest = sha_string(line_bytes)
925
952
        if nostore_sha == digest:
926
953
            raise errors.ExistingContent
947
974
 
948
975
        text_length = len(line_bytes)
949
976
        options = []
950
 
        if lines:
951
 
            if lines[-1][-1] != '\n':
952
 
                # copy the contents of lines.
 
977
        no_eol = False
 
978
        # Note: line_bytes is not modified to add a newline, that is tracked
 
979
        #       via the no_eol flag. 'lines' *is* modified, because that is the
 
980
        #       general values needed by the Content code.
 
981
        if line_bytes and line_bytes[-1] != '\n':
 
982
            options.append('no-eol')
 
983
            no_eol = True
 
984
            # Copy the existing list, or create a new one
 
985
            if lines is None:
 
986
                lines = osutils.split_lines(line_bytes)
 
987
            else:
953
988
                lines = lines[:]
954
 
                options.append('no-eol')
955
 
                lines[-1] = lines[-1] + '\n'
956
 
                line_bytes += '\n'
 
989
            # Replace the last line with one that ends in a final newline
 
990
            lines[-1] = lines[-1] + '\n'
 
991
        if lines is None:
 
992
            lines = osutils.split_lines(line_bytes)
957
993
 
958
994
        for element in key[:-1]:
959
 
            if type(element) != str:
 
995
            if type(element) is not str:
960
996
                raise TypeError("key contains non-strings: %r" % (key,))
961
997
        if key[-1] is None:
962
998
            key = key[:-1] + ('sha1:' + digest,)
963
 
        elif type(key[-1]) != str:
 
999
        elif type(key[-1]) is not str:
964
1000
                raise TypeError("key contains non-strings: %r" % (key,))
965
1001
        # Knit hunks are still last-element only
966
1002
        version_id = key[-1]
967
1003
        content = self._factory.make(lines, version_id)
968
 
        if 'no-eol' in options:
 
1004
        if no_eol:
969
1005
            # Hint to the content object that its text() call should strip the
970
1006
            # EOL.
971
1007
            content._should_strip_eol = True
986
1022
            if self._factory.__class__ is KnitPlainFactory:
987
1023
                # Use the already joined bytes saving iteration time in
988
1024
                # _record_to_data.
 
1025
                dense_lines = [line_bytes]
 
1026
                if no_eol:
 
1027
                    dense_lines.append('\n')
989
1028
                size, bytes = self._record_to_data(key, digest,
990
 
                    lines, [line_bytes])
 
1029
                    lines, dense_lines)
991
1030
            else:
992
1031
                # get mixed annotation + content and feed it into the
993
1032
                # serialiser.
1920
1959
            function spends less time resizing the final string.
1921
1960
        :return: (len, a StringIO instance with the raw data ready to read.)
1922
1961
        """
1923
 
        # Note: using a string copy here increases memory pressure with e.g.
1924
 
        # ISO's, but it is about 3 seconds faster on a 1.2Ghz intel machine
1925
 
        # when doing the initial commit of a mozilla tree. RBC 20070921
1926
 
        bytes = ''.join(chain(
1927
 
            ["version %s %d %s\n" % (key[-1],
1928
 
                                     len(lines),
1929
 
                                     digest)],
1930
 
            dense_lines or lines,
1931
 
            ["end %s\n" % key[-1]]))
1932
 
        if type(bytes) != str:
1933
 
            raise AssertionError(
1934
 
                'data must be plain bytes was %s' % type(bytes))
 
1962
        chunks = ["version %s %d %s\n" % (key[-1], len(lines), digest)]
 
1963
        chunks.extend(dense_lines or lines)
 
1964
        chunks.append("end %s\n" % key[-1])
 
1965
        for chunk in chunks:
 
1966
            if type(chunk) is not str:
 
1967
                raise AssertionError(
 
1968
                    'data must be plain bytes was %s' % type(chunk))
1935
1969
        if lines and lines[-1][-1] != '\n':
1936
1970
            raise ValueError('corrupt lines value %r' % lines)
1937
 
        compressed_bytes = tuned_gzip.bytes_to_gzip(bytes)
 
1971
        compressed_bytes = tuned_gzip.chunks_to_gzip(chunks)
1938
1972
        return len(compressed_bytes), compressed_bytes
1939
1973
 
1940
1974
    def _split_header(self, line):
2005
2039
                missing_keys.remove(record.key)
2006
2040
                yield record
2007
2041
 
2008
 
        self._raw_record_map = self.vf._get_record_map_unparsed(self.keys,
2009
 
            allow_missing=True)
 
2042
        if self._raw_record_map is None:
 
2043
            raise AssertionError('_raw_record_map should have been filled')
2010
2044
        first = True
2011
2045
        for key in self.keys:
2012
2046
            if key in self.nonlocal_keys:
2375
2409
                    line = "\n%s %s %s %s %s :" % (
2376
2410
                        key[-1], ','.join(options), pos, size,
2377
2411
                        self._dictionary_compress(parents))
2378
 
                    if type(line) != str:
 
2412
                    if type(line) is not str:
2379
2413
                        raise AssertionError(
2380
2414
                            'data must be utf8 was %s' % type(line))
2381
2415
                    lines.append(line)
2570
2604
        result = set()
2571
2605
        # Identify all key prefixes.
2572
2606
        # XXX: A bit hacky, needs polish.
2573
 
        if type(self._mapper) == ConstantMapper:
 
2607
        if type(self._mapper) is ConstantMapper:
2574
2608
            prefixes = [()]
2575
2609
        else:
2576
2610
            relpaths = set()
2608
2642
                    del self._history
2609
2643
                except NoSuchFile:
2610
2644
                    self._kndx_cache[prefix] = ({}, [])
2611
 
                    if type(self._mapper) == ConstantMapper:
 
2645
                    if type(self._mapper) is ConstantMapper:
2612
2646
                        # preserve behaviour for revisions.kndx etc.
2613
2647
                        self._init_index(path)
2614
2648
                    del self._cache
2882
2916
 
2883
2917
    def get_missing_parents(self):
2884
2918
        """Return the keys of missing parents."""
 
2919
        # If updating this, you should also update
 
2920
        # groupcompress._GCGraphIndex.get_missing_parents
2885
2921
        # We may have false positives, so filter those out.
2886
2922
        self._key_dependencies.add_keys(
2887
2923
            self.get_parent_map(self._key_dependencies.get_unsatisfied_refs()))
3092
3128
            opaque index memo. For _KnitKeyAccess the memo is (key, pos,
3093
3129
            length), where the key is the record key.
3094
3130
        """
3095
 
        if type(raw_data) != str:
 
3131
        if type(raw_data) is not str:
3096
3132
            raise AssertionError(
3097
3133
                'data must be plain bytes was %s' % type(raw_data))
3098
3134
        result = []
3181
3217
            length), where the index field is the write_index object supplied
3182
3218
            to the PackAccess object.
3183
3219
        """
3184
 
        if type(raw_data) != str:
 
3220
        if type(raw_data) is not str:
3185
3221
            raise AssertionError(
3186
3222
                'data must be plain bytes was %s' % type(raw_data))
3187
3223
        result = []
3550
3586
        """Create a heads provider for resolving ancestry issues."""
3551
3587
        if self._heads_provider is not None:
3552
3588
            return self._heads_provider
3553
 
        parent_provider = _mod_graph.DictParentsProvider(
3554
 
            self._revision_id_graph)
3555
 
        graph_obj = _mod_graph.Graph(parent_provider)
3556
 
        head_cache = _mod_graph.FrozenHeadsCache(graph_obj)
3557
 
        self._heads_provider = head_cache
3558
 
        return head_cache
 
3589
        self._heads_provider = _mod_graph.KnownGraph(self._revision_id_graph)
 
3590
        return self._heads_provider
3559
3591
 
3560
3592
    def annotate(self, key):
3561
3593
        """Return the annotated fulltext at the given key.
3584
3616
        being able to produce line deltas.
3585
3617
        """
3586
3618
        # TODO: this code generates a parent maps of present ancestors; it
3587
 
        # could be split out into a separate method, and probably should use
3588
 
        # iter_ancestry instead. -- mbp and robertc 20080704
 
3619
        #       could be split out into a separate method
 
3620
        #       -- mbp and robertc 20080704
3589
3621
        graph = _mod_graph.Graph(self._knit)
3590
 
        head_cache = _mod_graph.FrozenHeadsCache(graph)
3591
 
        search = graph._make_breadth_first_searcher([key])
3592
 
        keys = set()
3593
 
        while True:
3594
 
            try:
3595
 
                present, ghosts = search.next_with_ghosts()
3596
 
            except StopIteration:
3597
 
                break
3598
 
            keys.update(present)
3599
 
        parent_map = self._knit.get_parent_map(keys)
 
3622
        parent_map = dict((k, v) for k, v in graph.iter_ancestry([key])
 
3623
                          if v is not None)
 
3624
        if not parent_map:
 
3625
            raise errors.RevisionNotPresent(key, self)
 
3626
        keys = parent_map.keys()
 
3627
        heads_provider = _mod_graph.KnownGraph(parent_map)
3600
3628
        parent_cache = {}
3601
3629
        reannotate = annotate.reannotate
3602
3630
        for record in self._knit.get_record_stream(keys, 'topological', True):
3608
3636
            else:
3609
3637
                parent_lines = []
3610
3638
            parent_cache[key] = list(
3611
 
                reannotate(parent_lines, fulltext, key, None, head_cache))
 
3639
                reannotate(parent_lines, fulltext, key, None, heads_provider))
3612
3640
        try:
3613
3641
            return parent_cache[key]
3614
3642
        except KeyError, e: