~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Vincent Ladeuil
  • Date: 2011-05-15 16:07:11 UTC
  • mto: (5743.13.4 config-editor-option)
  • mto: This revision was merged to the branch mainline in revision 5944.
  • Revision ID: v.ladeuil+lp@free.fr-20110515160711-l0og3ady9wuahz1k
Stack.get() provides the registered option default value.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
56
56
from itertools import izip
57
57
import operator
58
58
import os
59
 
import sys
60
59
 
61
60
from bzrlib.lazy_import import lazy_import
62
61
lazy_import(globals(), """
 
62
import gzip
 
63
 
63
64
from bzrlib import (
64
 
    annotate,
65
65
    debug,
66
66
    diff,
67
67
    graph as _mod_graph,
68
68
    index as _mod_index,
69
 
    lru_cache,
70
69
    pack,
71
70
    patiencediff,
72
 
    progress,
73
71
    static_tuple,
74
72
    trace,
75
73
    tsort,
76
74
    tuned_gzip,
77
75
    ui,
78
76
    )
 
77
 
 
78
from bzrlib.repofmt import pack_repo
79
79
""")
80
80
from bzrlib import (
 
81
    annotate,
81
82
    errors,
82
83
    osutils,
83
84
    )
84
85
from bzrlib.errors import (
85
 
    FileExists,
86
86
    NoSuchFile,
87
 
    KnitError,
88
87
    InvalidRevisionId,
89
88
    KnitCorrupt,
90
89
    KnitHeaderError,
91
90
    RevisionNotPresent,
92
 
    RevisionAlreadyPresent,
93
91
    SHA1KnitCorrupt,
94
92
    )
95
93
from bzrlib.osutils import (
96
94
    contains_whitespace,
97
 
    contains_linebreaks,
98
95
    sha_string,
99
96
    sha_strings,
100
97
    split_lines,
101
98
    )
102
99
from bzrlib.versionedfile import (
 
100
    _KeyRefs,
103
101
    AbsentContentFactory,
104
102
    adapter_registry,
105
103
    ConstantMapper,
106
104
    ContentFactory,
107
 
    ChunkedContentFactory,
108
105
    sort_groupcompress,
109
 
    VersionedFile,
110
106
    VersionedFiles,
111
107
    )
112
108
 
805
801
        writer.begin()
806
802
        index = _KnitGraphIndex(graph_index, lambda:True, parents=parents,
807
803
            deltas=delta, add_callback=graph_index.add_nodes)
808
 
        access = _DirectPackAccess({})
 
804
        access = pack_repo._DirectPackAccess({})
809
805
        access.set_writer(writer, graph_index, (transport, 'newpack'))
810
806
        result = KnitVersionedFiles(index, access,
811
807
            max_delta_chain=max_delta_chain)
882
878
            self._factory = KnitAnnotateFactory()
883
879
        else:
884
880
            self._factory = KnitPlainFactory()
885
 
        self._fallback_vfs = []
 
881
        self._immediate_fallback_vfs = []
886
882
        self._reload_func = reload_func
887
883
 
888
884
    def __repr__(self):
896
892
 
897
893
        :param a_versioned_files: A VersionedFiles object.
898
894
        """
899
 
        self._fallback_vfs.append(a_versioned_files)
 
895
        self._immediate_fallback_vfs.append(a_versioned_files)
900
896
 
901
897
    def add_lines(self, key, parents, lines, parent_texts=None,
902
898
        left_matching_blocks=None, nostore_sha=None, random_id=False,
1069
1065
                    raise errors.KnitCorrupt(self,
1070
1066
                        "Missing basis parent %s for %s" % (
1071
1067
                        compression_parent, key))
1072
 
        for fallback_vfs in self._fallback_vfs:
 
1068
        for fallback_vfs in self._immediate_fallback_vfs:
1073
1069
            fallback_vfs.check()
1074
1070
 
1075
1071
    def _check_add(self, key, lines, random_id, check_content):
1195
1191
    def get_known_graph_ancestry(self, keys):
1196
1192
        """Get a KnownGraph instance with the ancestry of keys."""
1197
1193
        parent_map, missing_keys = self._index.find_ancestry(keys)
1198
 
        for fallback in self._fallback_vfs:
 
1194
        for fallback in self._transitive_fallbacks():
1199
1195
            if not missing_keys:
1200
1196
                break
1201
1197
            (f_parent_map, f_missing_keys) = fallback._index.find_ancestry(
1225
1221
            and so on.
1226
1222
        """
1227
1223
        result = {}
1228
 
        sources = [self._index] + self._fallback_vfs
 
1224
        sources = [self._index] + self._immediate_fallback_vfs
1229
1225
        source_results = []
1230
1226
        missing = set(keys)
1231
1227
        for source in sources:
1525
1521
                        yield KnitContentFactory(key, global_map[key],
1526
1522
                            record_details, None, raw_data, self._factory.annotated, None)
1527
1523
                else:
1528
 
                    vf = self._fallback_vfs[parent_maps.index(source) - 1]
 
1524
                    vf = self._immediate_fallback_vfs[parent_maps.index(source) - 1]
1529
1525
                    for record in vf.get_record_stream(keys, ordering,
1530
1526
                        include_delta_closure):
1531
1527
                        yield record
1541
1537
            # record entry 2 is the 'digest'.
1542
1538
            result[key] = details[2]
1543
1539
        missing.difference_update(set(result))
1544
 
        for source in self._fallback_vfs:
 
1540
        for source in self._immediate_fallback_vfs:
1545
1541
            if not missing:
1546
1542
                break
1547
1543
            new_result = source.get_sha1s(missing)
1618
1614
                raise RevisionNotPresent([record.key], self)
1619
1615
            elif ((record.storage_kind in knit_types)
1620
1616
                  and (compression_parent is None
1621
 
                       or not self._fallback_vfs
 
1617
                       or not self._immediate_fallback_vfs
1622
1618
                       or self._index.has_key(compression_parent)
1623
1619
                       or not self.has_key(compression_parent))):
1624
1620
                # we can insert the knit record literally if either it has no
1796
1792
        # vfs, and hope to find them there.  Note that if the keys are found
1797
1793
        # but had no changes or no content, the fallback may not return
1798
1794
        # anything.
1799
 
        if keys and not self._fallback_vfs:
 
1795
        if keys and not self._immediate_fallback_vfs:
1800
1796
            # XXX: strictly the second parameter is meant to be the file id
1801
1797
            # but it's not easily accessible here.
1802
1798
            raise RevisionNotPresent(keys, repr(self))
1803
 
        for source in self._fallback_vfs:
 
1799
        for source in self._immediate_fallback_vfs:
1804
1800
            if not keys:
1805
1801
                break
1806
1802
            source_keys = set()
1879
1875
        :return: the header and the decompressor stream.
1880
1876
                 as (stream, header_record)
1881
1877
        """
1882
 
        df = tuned_gzip.GzipFile(mode='rb', fileobj=StringIO(raw_data))
 
1878
        df = gzip.GzipFile(mode='rb', fileobj=StringIO(raw_data))
1883
1879
        try:
1884
1880
            # Current serialise
1885
1881
            rec = self._check_header(key, df.readline())
1894
1890
        # 4168 calls in 2880 217 internal
1895
1891
        # 4168 calls to _parse_record_header in 2121
1896
1892
        # 4168 calls to readlines in 330
1897
 
        df = tuned_gzip.GzipFile(mode='rb', fileobj=StringIO(data))
 
1893
        df = gzip.GzipFile(mode='rb', fileobj=StringIO(data))
1898
1894
        try:
1899
1895
            record_contents = df.readlines()
1900
1896
        except Exception, e:
2015
2011
        """See VersionedFiles.keys."""
2016
2012
        if 'evil' in debug.debug_flags:
2017
2013
            trace.mutter_callsite(2, "keys scales with size of history")
2018
 
        sources = [self._index] + self._fallback_vfs
 
2014
        sources = [self._index] + self._immediate_fallback_vfs
2019
2015
        result = set()
2020
2016
        for source in sources:
2021
2017
            result.update(source.keys())
2061
2057
 
2062
2058
        missing_keys = set(nonlocal_keys)
2063
2059
        # Read from remote versioned file instances and provide to our caller.
2064
 
        for source in self.vf._fallback_vfs:
 
2060
        for source in self.vf._immediate_fallback_vfs:
2065
2061
            if not missing_keys:
2066
2062
                break
2067
2063
            # Loop over fallback repositories asking them for texts - ignore
2786
2782
        return key[:-1], key[-1]
2787
2783
 
2788
2784
 
2789
 
class _KeyRefs(object):
2790
 
 
2791
 
    def __init__(self, track_new_keys=False):
2792
 
        # dict mapping 'key' to 'set of keys referring to that key'
2793
 
        self.refs = {}
2794
 
        if track_new_keys:
2795
 
            # set remembering all new keys
2796
 
            self.new_keys = set()
2797
 
        else:
2798
 
            self.new_keys = None
2799
 
 
2800
 
    def clear(self):
2801
 
        if self.refs:
2802
 
            self.refs.clear()
2803
 
        if self.new_keys:
2804
 
            self.new_keys.clear()
2805
 
 
2806
 
    def add_references(self, key, refs):
2807
 
        # Record the new references
2808
 
        for referenced in refs:
2809
 
            try:
2810
 
                needed_by = self.refs[referenced]
2811
 
            except KeyError:
2812
 
                needed_by = self.refs[referenced] = set()
2813
 
            needed_by.add(key)
2814
 
        # Discard references satisfied by the new key
2815
 
        self.add_key(key)
2816
 
 
2817
 
    def get_new_keys(self):
2818
 
        return self.new_keys
2819
 
    
2820
 
    def get_unsatisfied_refs(self):
2821
 
        return self.refs.iterkeys()
2822
 
 
2823
 
    def _satisfy_refs_for_key(self, key):
2824
 
        try:
2825
 
            del self.refs[key]
2826
 
        except KeyError:
2827
 
            # No keys depended on this key.  That's ok.
2828
 
            pass
2829
 
 
2830
 
    def add_key(self, key):
2831
 
        # satisfy refs for key, and remember that we've seen this key.
2832
 
        self._satisfy_refs_for_key(key)
2833
 
        if self.new_keys is not None:
2834
 
            self.new_keys.add(key)
2835
 
 
2836
 
    def satisfy_refs_for_keys(self, keys):
2837
 
        for key in keys:
2838
 
            self._satisfy_refs_for_key(key)
2839
 
 
2840
 
    def get_referrers(self):
2841
 
        result = set()
2842
 
        for referrers in self.refs.itervalues():
2843
 
            result.update(referrers)
2844
 
        return result
2845
 
 
2846
 
 
2847
2785
class _KnitGraphIndex(object):
2848
2786
    """A KnitVersionedFiles index layered on GraphIndex."""
2849
2787
 
3520
3458
        return records, ann_keys
3521
3459
 
3522
3460
    def _get_needed_texts(self, key, pb=None):
3523
 
        # if True or len(self._vf._fallback_vfs) > 0:
3524
 
        if len(self._vf._fallback_vfs) > 0:
 
3461
        # if True or len(self._vf._immediate_fallback_vfs) > 0:
 
3462
        if len(self._vf._immediate_fallback_vfs) > 0:
3525
3463
            # If we have fallbacks, go to the generic path
3526
3464
            for v in annotate.Annotator._get_needed_texts(self, key, pb=pb):
3527
3465
                yield v