~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Vincent Ladeuil
  • Date: 2011-02-10 12:37:27 UTC
  • mto: This revision was merged to the branch mainline in revision 5661.
  • Revision ID: v.ladeuil+lp@free.fr-20110210123727-8e0pu4wtlt6fj7nf
thread is already a python module, avoid confusion and use cethread instead.

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
57
58
import operator
58
59
import os
 
60
import sys
59
61
 
60
62
from bzrlib.lazy_import import lazy_import
61
63
lazy_import(globals(), """
62
 
import gzip
63
 
 
64
64
from bzrlib import (
 
65
    annotate,
65
66
    debug,
66
67
    diff,
67
68
    graph as _mod_graph,
68
69
    index as _mod_index,
 
70
    lru_cache,
69
71
    pack,
70
72
    patiencediff,
 
73
    progress,
71
74
    static_tuple,
72
75
    trace,
73
76
    tsort,
74
77
    tuned_gzip,
75
78
    ui,
76
79
    )
77
 
 
78
 
from bzrlib.repofmt import pack_repo
79
80
""")
80
81
from bzrlib import (
81
 
    annotate,
82
82
    errors,
83
83
    osutils,
84
84
    )
85
85
from bzrlib.errors import (
 
86
    FileExists,
86
87
    NoSuchFile,
 
88
    KnitError,
87
89
    InvalidRevisionId,
88
90
    KnitCorrupt,
89
91
    KnitHeaderError,
90
92
    RevisionNotPresent,
 
93
    RevisionAlreadyPresent,
91
94
    SHA1KnitCorrupt,
92
95
    )
93
96
from bzrlib.osutils import (
94
97
    contains_whitespace,
 
98
    contains_linebreaks,
95
99
    sha_string,
96
100
    sha_strings,
97
101
    split_lines,
98
102
    )
99
103
from bzrlib.versionedfile import (
100
 
    _KeyRefs,
101
104
    AbsentContentFactory,
102
105
    adapter_registry,
103
106
    ConstantMapper,
104
107
    ContentFactory,
 
108
    ChunkedContentFactory,
105
109
    sort_groupcompress,
 
110
    VersionedFile,
106
111
    VersionedFiles,
107
112
    )
108
113
 
801
806
        writer.begin()
802
807
        index = _KnitGraphIndex(graph_index, lambda:True, parents=parents,
803
808
            deltas=delta, add_callback=graph_index.add_nodes)
804
 
        access = pack_repo._DirectPackAccess({})
 
809
        access = _DirectPackAccess({})
805
810
        access.set_writer(writer, graph_index, (transport, 'newpack'))
806
811
        result = KnitVersionedFiles(index, access,
807
812
            max_delta_chain=max_delta_chain)
878
883
            self._factory = KnitAnnotateFactory()
879
884
        else:
880
885
            self._factory = KnitPlainFactory()
881
 
        self._immediate_fallback_vfs = []
 
886
        self._fallback_vfs = []
882
887
        self._reload_func = reload_func
883
888
 
884
889
    def __repr__(self):
892
897
 
893
898
        :param a_versioned_files: A VersionedFiles object.
894
899
        """
895
 
        self._immediate_fallback_vfs.append(a_versioned_files)
 
900
        self._fallback_vfs.append(a_versioned_files)
896
901
 
897
902
    def add_lines(self, key, parents, lines, parent_texts=None,
898
903
        left_matching_blocks=None, nostore_sha=None, random_id=False,
1065
1070
                    raise errors.KnitCorrupt(self,
1066
1071
                        "Missing basis parent %s for %s" % (
1067
1072
                        compression_parent, key))
1068
 
        for fallback_vfs in self._immediate_fallback_vfs:
 
1073
        for fallback_vfs in self._fallback_vfs:
1069
1074
            fallback_vfs.check()
1070
1075
 
1071
1076
    def _check_add(self, key, lines, random_id, check_content):
1191
1196
    def get_known_graph_ancestry(self, keys):
1192
1197
        """Get a KnownGraph instance with the ancestry of keys."""
1193
1198
        parent_map, missing_keys = self._index.find_ancestry(keys)
1194
 
        for fallback in self._transitive_fallbacks():
 
1199
        for fallback in self._fallback_vfs:
1195
1200
            if not missing_keys:
1196
1201
                break
1197
1202
            (f_parent_map, f_missing_keys) = fallback._index.find_ancestry(
1221
1226
            and so on.
1222
1227
        """
1223
1228
        result = {}
1224
 
        sources = [self._index] + self._immediate_fallback_vfs
 
1229
        sources = [self._index] + self._fallback_vfs
1225
1230
        source_results = []
1226
1231
        missing = set(keys)
1227
1232
        for source in sources:
1521
1526
                        yield KnitContentFactory(key, global_map[key],
1522
1527
                            record_details, None, raw_data, self._factory.annotated, None)
1523
1528
                else:
1524
 
                    vf = self._immediate_fallback_vfs[parent_maps.index(source) - 1]
 
1529
                    vf = self._fallback_vfs[parent_maps.index(source) - 1]
1525
1530
                    for record in vf.get_record_stream(keys, ordering,
1526
1531
                        include_delta_closure):
1527
1532
                        yield record
1537
1542
            # record entry 2 is the 'digest'.
1538
1543
            result[key] = details[2]
1539
1544
        missing.difference_update(set(result))
1540
 
        for source in self._immediate_fallback_vfs:
 
1545
        for source in self._fallback_vfs:
1541
1546
            if not missing:
1542
1547
                break
1543
1548
            new_result = source.get_sha1s(missing)
1614
1619
                raise RevisionNotPresent([record.key], self)
1615
1620
            elif ((record.storage_kind in knit_types)
1616
1621
                  and (compression_parent is None
1617
 
                       or not self._immediate_fallback_vfs
 
1622
                       or not self._fallback_vfs
1618
1623
                       or self._index.has_key(compression_parent)
1619
1624
                       or not self.has_key(compression_parent))):
1620
1625
                # we can insert the knit record literally if either it has no
1792
1797
        # vfs, and hope to find them there.  Note that if the keys are found
1793
1798
        # but had no changes or no content, the fallback may not return
1794
1799
        # anything.
1795
 
        if keys and not self._immediate_fallback_vfs:
 
1800
        if keys and not self._fallback_vfs:
1796
1801
            # XXX: strictly the second parameter is meant to be the file id
1797
1802
            # but it's not easily accessible here.
1798
1803
            raise RevisionNotPresent(keys, repr(self))
1799
 
        for source in self._immediate_fallback_vfs:
 
1804
        for source in self._fallback_vfs:
1800
1805
            if not keys:
1801
1806
                break
1802
1807
            source_keys = set()
2011
2016
        """See VersionedFiles.keys."""
2012
2017
        if 'evil' in debug.debug_flags:
2013
2018
            trace.mutter_callsite(2, "keys scales with size of history")
2014
 
        sources = [self._index] + self._immediate_fallback_vfs
 
2019
        sources = [self._index] + self._fallback_vfs
2015
2020
        result = set()
2016
2021
        for source in sources:
2017
2022
            result.update(source.keys())
2057
2062
 
2058
2063
        missing_keys = set(nonlocal_keys)
2059
2064
        # Read from remote versioned file instances and provide to our caller.
2060
 
        for source in self.vf._immediate_fallback_vfs:
 
2065
        for source in self.vf._fallback_vfs:
2061
2066
            if not missing_keys:
2062
2067
                break
2063
2068
            # Loop over fallback repositories asking them for texts - ignore
2782
2787
        return key[:-1], key[-1]
2783
2788
 
2784
2789
 
 
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
 
2785
2848
class _KnitGraphIndex(object):
2786
2849
    """A KnitVersionedFiles index layered on GraphIndex."""
2787
2850
 
3458
3521
        return records, ann_keys
3459
3522
 
3460
3523
    def _get_needed_texts(self, key, pb=None):
3461
 
        # if True or len(self._vf._immediate_fallback_vfs) > 0:
3462
 
        if len(self._vf._immediate_fallback_vfs) > 0:
 
3524
        # if True or len(self._vf._fallback_vfs) > 0:
 
3525
        if len(self._vf._fallback_vfs) > 0:
3463
3526
            # If we have fallbacks, go to the generic path
3464
3527
            for v in annotate.Annotator._get_needed_texts(self, key, pb=pb):
3465
3528
                yield v