~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Vincent Ladeuil
  • Date: 2011-07-06 09:22:00 UTC
  • mfrom: (6008 +trunk)
  • mto: (6012.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 6013.
  • Revision ID: v.ladeuil+lp@free.fr-20110706092200-7iai2mwzc0sqdsvf
MergingĀ inĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
 
55
55
from cStringIO import StringIO
56
56
from itertools import izip
57
 
import gzip
58
57
import operator
59
58
import os
60
 
import sys
61
59
 
62
60
from bzrlib.lazy_import import lazy_import
63
61
lazy_import(globals(), """
 
62
import gzip
 
63
 
64
64
from bzrlib import (
65
 
    annotate,
66
65
    debug,
67
66
    diff,
68
67
    graph as _mod_graph,
69
68
    index as _mod_index,
70
 
    lru_cache,
71
69
    pack,
72
70
    patiencediff,
73
 
    progress,
74
71
    static_tuple,
75
72
    trace,
76
73
    tsort,
77
74
    tuned_gzip,
78
75
    ui,
79
76
    )
 
77
 
 
78
from bzrlib.repofmt import pack_repo
80
79
""")
81
80
from bzrlib import (
 
81
    annotate,
82
82
    errors,
83
83
    osutils,
84
84
    )
85
85
from bzrlib.errors import (
86
 
    FileExists,
87
86
    NoSuchFile,
88
 
    KnitError,
89
87
    InvalidRevisionId,
90
88
    KnitCorrupt,
91
89
    KnitHeaderError,
92
90
    RevisionNotPresent,
93
 
    RevisionAlreadyPresent,
94
91
    SHA1KnitCorrupt,
95
92
    )
96
93
from bzrlib.osutils import (
97
94
    contains_whitespace,
98
 
    contains_linebreaks,
99
95
    sha_string,
100
96
    sha_strings,
101
97
    split_lines,
102
98
    )
103
99
from bzrlib.versionedfile import (
 
100
    _KeyRefs,
104
101
    AbsentContentFactory,
105
102
    adapter_registry,
106
103
    ConstantMapper,
107
104
    ContentFactory,
108
 
    ChunkedContentFactory,
109
105
    sort_groupcompress,
110
 
    VersionedFile,
111
 
    VersionedFiles,
 
106
    VersionedFilesWithFallbacks,
112
107
    )
113
108
 
114
109
 
413
408
class KnitContent(object):
414
409
    """Content of a knit version to which deltas can be applied.
415
410
 
416
 
    This is always stored in memory as a list of lines with \n at the end,
 
411
    This is always stored in memory as a list of lines with \\n at the end,
417
412
    plus a flag saying if the final ending is really there or not, because that
418
413
    corresponds to the on-disk knit representation.
419
414
    """
806
801
        writer.begin()
807
802
        index = _KnitGraphIndex(graph_index, lambda:True, parents=parents,
808
803
            deltas=delta, add_callback=graph_index.add_nodes)
809
 
        access = _DirectPackAccess({})
 
804
        access = pack_repo._DirectPackAccess({})
810
805
        access.set_writer(writer, graph_index, (transport, 'newpack'))
811
806
        result = KnitVersionedFiles(index, access,
812
807
            max_delta_chain=max_delta_chain)
850
845
                in all_build_index_memos.itervalues()])
851
846
 
852
847
 
853
 
class KnitVersionedFiles(VersionedFiles):
 
848
class KnitVersionedFiles(VersionedFilesWithFallbacks):
854
849
    """Storage for many versioned files using knit compression.
855
850
 
856
851
    Backend storage is managed by indices and data objects.
883
878
            self._factory = KnitAnnotateFactory()
884
879
        else:
885
880
            self._factory = KnitPlainFactory()
886
 
        self._fallback_vfs = []
 
881
        self._immediate_fallback_vfs = []
887
882
        self._reload_func = reload_func
888
883
 
889
884
    def __repr__(self):
892
887
            self._index,
893
888
            self._access)
894
889
 
 
890
    def without_fallbacks(self):
 
891
        """Return a clone of this object without any fallbacks configured."""
 
892
        return KnitVersionedFiles(self._index, self._access,
 
893
            self._max_delta_chain, self._factory.annotated,
 
894
            self._reload_func)
 
895
 
895
896
    def add_fallback_versioned_files(self, a_versioned_files):
896
897
        """Add a source of texts for texts not present in this knit.
897
898
 
898
899
        :param a_versioned_files: A VersionedFiles object.
899
900
        """
900
 
        self._fallback_vfs.append(a_versioned_files)
 
901
        self._immediate_fallback_vfs.append(a_versioned_files)
901
902
 
902
903
    def add_lines(self, key, parents, lines, parent_texts=None,
903
904
        left_matching_blocks=None, nostore_sha=None, random_id=False,
1070
1071
                    raise errors.KnitCorrupt(self,
1071
1072
                        "Missing basis parent %s for %s" % (
1072
1073
                        compression_parent, key))
1073
 
        for fallback_vfs in self._fallback_vfs:
 
1074
        for fallback_vfs in self._immediate_fallback_vfs:
1074
1075
            fallback_vfs.check()
1075
1076
 
1076
1077
    def _check_add(self, key, lines, random_id, check_content):
1154
1155
 
1155
1156
        A dict of key to (record_details, index_memo, next, parents) is
1156
1157
        returned.
1157
 
        method is the way referenced data should be applied.
1158
 
        index_memo is the handle to pass to the data access to actually get the
1159
 
            data
1160
 
        next is the build-parent of the version, or None for fulltexts.
1161
 
        parents is the version_ids of the parents of this version
1162
 
 
1163
 
        :param allow_missing: If True do not raise an error on a missing component,
1164
 
            just ignore it.
 
1158
 
 
1159
        * method is the way referenced data should be applied.
 
1160
        * index_memo is the handle to pass to the data access to actually get
 
1161
          the data
 
1162
        * next is the build-parent of the version, or None for fulltexts.
 
1163
        * parents is the version_ids of the parents of this version
 
1164
 
 
1165
        :param allow_missing: If True do not raise an error on a missing
 
1166
            component, just ignore it.
1165
1167
        """
1166
1168
        component_data = {}
1167
1169
        pending_components = keys
1193
1195
        generator = _VFContentMapGenerator(self, [key])
1194
1196
        return generator._get_content(key)
1195
1197
 
1196
 
    def get_known_graph_ancestry(self, keys):
1197
 
        """Get a KnownGraph instance with the ancestry of keys."""
1198
 
        parent_map, missing_keys = self._index.find_ancestry(keys)
1199
 
        for fallback in self._transitive_fallbacks():
1200
 
            if not missing_keys:
1201
 
                break
1202
 
            (f_parent_map, f_missing_keys) = fallback._index.find_ancestry(
1203
 
                                                missing_keys)
1204
 
            parent_map.update(f_parent_map)
1205
 
            missing_keys = f_missing_keys
1206
 
        kg = _mod_graph.KnownGraph(parent_map)
1207
 
        return kg
1208
 
 
1209
1198
    def get_parent_map(self, keys):
1210
1199
        """Get a map of the graph parents of keys.
1211
1200
 
1226
1215
            and so on.
1227
1216
        """
1228
1217
        result = {}
1229
 
        sources = [self._index] + self._fallback_vfs
 
1218
        sources = [self._index] + self._immediate_fallback_vfs
1230
1219
        source_results = []
1231
1220
        missing = set(keys)
1232
1221
        for source in sources:
1242
1231
        """Produce a dictionary of knit records.
1243
1232
 
1244
1233
        :return: {key:(record, record_details, digest, next)}
1245
 
            record
1246
 
                data returned from read_records (a KnitContentobject)
1247
 
            record_details
1248
 
                opaque information to pass to parse_record
1249
 
            digest
1250
 
                SHA1 digest of the full text after all steps are done
1251
 
            next
1252
 
                build-parent of the version, i.e. the leftmost ancestor.
 
1234
 
 
1235
            * record: data returned from read_records (a KnitContentobject)
 
1236
            * record_details: opaque information to pass to parse_record
 
1237
            * digest: SHA1 digest of the full text after all steps are done
 
1238
            * next: build-parent of the version, i.e. the leftmost ancestor.
1253
1239
                Will be None if the record is not a delta.
 
1240
 
1254
1241
        :param keys: The keys to build a map for
1255
1242
        :param allow_missing: If some records are missing, rather than
1256
1243
            error, just return the data that could be generated.
1526
1513
                        yield KnitContentFactory(key, global_map[key],
1527
1514
                            record_details, None, raw_data, self._factory.annotated, None)
1528
1515
                else:
1529
 
                    vf = self._fallback_vfs[parent_maps.index(source) - 1]
 
1516
                    vf = self._immediate_fallback_vfs[parent_maps.index(source) - 1]
1530
1517
                    for record in vf.get_record_stream(keys, ordering,
1531
1518
                        include_delta_closure):
1532
1519
                        yield record
1542
1529
            # record entry 2 is the 'digest'.
1543
1530
            result[key] = details[2]
1544
1531
        missing.difference_update(set(result))
1545
 
        for source in self._fallback_vfs:
 
1532
        for source in self._immediate_fallback_vfs:
1546
1533
            if not missing:
1547
1534
                break
1548
1535
            new_result = source.get_sha1s(missing)
1619
1606
                raise RevisionNotPresent([record.key], self)
1620
1607
            elif ((record.storage_kind in knit_types)
1621
1608
                  and (compression_parent is None
1622
 
                       or not self._fallback_vfs
 
1609
                       or not self._immediate_fallback_vfs
1623
1610
                       or self._index.has_key(compression_parent)
1624
1611
                       or not self.has_key(compression_parent))):
1625
1612
                # we can insert the knit record literally if either it has no
1797
1784
        # vfs, and hope to find them there.  Note that if the keys are found
1798
1785
        # but had no changes or no content, the fallback may not return
1799
1786
        # anything.
1800
 
        if keys and not self._fallback_vfs:
 
1787
        if keys and not self._immediate_fallback_vfs:
1801
1788
            # XXX: strictly the second parameter is meant to be the file id
1802
1789
            # but it's not easily accessible here.
1803
1790
            raise RevisionNotPresent(keys, repr(self))
1804
 
        for source in self._fallback_vfs:
 
1791
        for source in self._immediate_fallback_vfs:
1805
1792
            if not keys:
1806
1793
                break
1807
1794
            source_keys = set()
1923
1910
        The result will be returned in whatever is the fastest to read.
1924
1911
        Not by the order requested. Also, multiple requests for the same
1925
1912
        record will only yield 1 response.
 
1913
 
1926
1914
        :param records: A list of (key, access_memo) entries
1927
1915
        :return: Yields (key, contents, digest) in the order
1928
1916
                 read, not the order requested
1986
1974
        :param key: The key of the record. Currently keys are always serialised
1987
1975
            using just the trailing component.
1988
1976
        :param dense_lines: The bytes of lines but in a denser form. For
1989
 
            instance, if lines is a list of 1000 bytestrings each ending in \n,
1990
 
            dense_lines may be a list with one line in it, containing all the
1991
 
            1000's lines and their \n's. Using dense_lines if it is already
1992
 
            known is a win because the string join to create bytes in this
1993
 
            function spends less time resizing the final string.
 
1977
            instance, if lines is a list of 1000 bytestrings each ending in
 
1978
            \\n, dense_lines may be a list with one line in it, containing all
 
1979
            the 1000's lines and their \\n's. Using dense_lines if it is
 
1980
            already known is a win because the string join to create bytes in
 
1981
            this function spends less time resizing the final string.
1994
1982
        :return: (len, a StringIO instance with the raw data ready to read.)
1995
1983
        """
1996
1984
        chunks = ["version %s %d %s\n" % (key[-1], len(lines), digest)]
2016
2004
        """See VersionedFiles.keys."""
2017
2005
        if 'evil' in debug.debug_flags:
2018
2006
            trace.mutter_callsite(2, "keys scales with size of history")
2019
 
        sources = [self._index] + self._fallback_vfs
 
2007
        sources = [self._index] + self._immediate_fallback_vfs
2020
2008
        result = set()
2021
2009
        for source in sources:
2022
2010
            result.update(source.keys())
2062
2050
 
2063
2051
        missing_keys = set(nonlocal_keys)
2064
2052
        # Read from remote versioned file instances and provide to our caller.
2065
 
        for source in self.vf._fallback_vfs:
 
2053
        for source in self.vf._immediate_fallback_vfs:
2066
2054
            if not missing_keys:
2067
2055
                break
2068
2056
            # Loop over fallback repositories asking them for texts - ignore
2787
2775
        return key[:-1], key[-1]
2788
2776
 
2789
2777
 
2790
 
class _KeyRefs(object):
2791
 
 
2792
 
    def __init__(self, track_new_keys=False):
2793
 
        # dict mapping 'key' to 'set of keys referring to that key'
2794
 
        self.refs = {}
2795
 
        if track_new_keys:
2796
 
            # set remembering all new keys
2797
 
            self.new_keys = set()
2798
 
        else:
2799
 
            self.new_keys = None
2800
 
 
2801
 
    def clear(self):
2802
 
        if self.refs:
2803
 
            self.refs.clear()
2804
 
        if self.new_keys:
2805
 
            self.new_keys.clear()
2806
 
 
2807
 
    def add_references(self, key, refs):
2808
 
        # Record the new references
2809
 
        for referenced in refs:
2810
 
            try:
2811
 
                needed_by = self.refs[referenced]
2812
 
            except KeyError:
2813
 
                needed_by = self.refs[referenced] = set()
2814
 
            needed_by.add(key)
2815
 
        # Discard references satisfied by the new key
2816
 
        self.add_key(key)
2817
 
 
2818
 
    def get_new_keys(self):
2819
 
        return self.new_keys
2820
 
    
2821
 
    def get_unsatisfied_refs(self):
2822
 
        return self.refs.iterkeys()
2823
 
 
2824
 
    def _satisfy_refs_for_key(self, key):
2825
 
        try:
2826
 
            del self.refs[key]
2827
 
        except KeyError:
2828
 
            # No keys depended on this key.  That's ok.
2829
 
            pass
2830
 
 
2831
 
    def add_key(self, key):
2832
 
        # satisfy refs for key, and remember that we've seen this key.
2833
 
        self._satisfy_refs_for_key(key)
2834
 
        if self.new_keys is not None:
2835
 
            self.new_keys.add(key)
2836
 
 
2837
 
    def satisfy_refs_for_keys(self, keys):
2838
 
        for key in keys:
2839
 
            self._satisfy_refs_for_key(key)
2840
 
 
2841
 
    def get_referrers(self):
2842
 
        result = set()
2843
 
        for referrers in self.refs.itervalues():
2844
 
            result.update(referrers)
2845
 
        return result
2846
 
 
2847
 
 
2848
2778
class _KnitGraphIndex(object):
2849
2779
    """A KnitVersionedFiles index layered on GraphIndex."""
2850
2780
 
3521
3451
        return records, ann_keys
3522
3452
 
3523
3453
    def _get_needed_texts(self, key, pb=None):
3524
 
        # if True or len(self._vf._fallback_vfs) > 0:
3525
 
        if len(self._vf._fallback_vfs) > 0:
 
3454
        # if True or len(self._vf._immediate_fallback_vfs) > 0:
 
3455
        if len(self._vf._immediate_fallback_vfs) > 0:
3526
3456
            # If we have fallbacks, go to the generic path
3527
3457
            for v in annotate.Annotator._get_needed_texts(self, key, pb=pb):
3528
3458
                yield v