~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: John Arbash Meinel
  • Date: 2011-05-11 11:35:28 UTC
  • mto: This revision was merged to the branch mainline in revision 5851.
  • Revision ID: john@arbash-meinel.com-20110511113528-qepibuwxicjrbb2h
Break compatibility with python <2.6.

This includes auditing the code for places where we were doing
explicit 'sys.version' checks and removing them as appropriate.

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
 
    VersionedFiles,
 
106
    VersionedFilesWithFallbacks,
111
107
    )
112
108
 
113
109
 
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)
849
845
                in all_build_index_memos.itervalues()])
850
846
 
851
847
 
852
 
class KnitVersionedFiles(VersionedFiles):
 
848
class KnitVersionedFiles(VersionedFilesWithFallbacks):
853
849
    """Storage for many versioned files using knit compression.
854
850
 
855
851
    Backend storage is managed by indices and data objects.
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):
891
887
            self._index,
892
888
            self._access)
893
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
 
894
896
    def add_fallback_versioned_files(self, a_versioned_files):
895
897
        """Add a source of texts for texts not present in this knit.
896
898
 
897
899
        :param a_versioned_files: A VersionedFiles object.
898
900
        """
899
 
        self._fallback_vfs.append(a_versioned_files)
 
901
        self._immediate_fallback_vfs.append(a_versioned_files)
900
902
 
901
903
    def add_lines(self, key, parents, lines, parent_texts=None,
902
904
        left_matching_blocks=None, nostore_sha=None, random_id=False,
1069
1071
                    raise errors.KnitCorrupt(self,
1070
1072
                        "Missing basis parent %s for %s" % (
1071
1073
                        compression_parent, key))
1072
 
        for fallback_vfs in self._fallback_vfs:
 
1074
        for fallback_vfs in self._immediate_fallback_vfs:
1073
1075
            fallback_vfs.check()
1074
1076
 
1075
1077
    def _check_add(self, key, lines, random_id, check_content):
1195
1197
    def get_known_graph_ancestry(self, keys):
1196
1198
        """Get a KnownGraph instance with the ancestry of keys."""
1197
1199
        parent_map, missing_keys = self._index.find_ancestry(keys)
1198
 
        for fallback in self._fallback_vfs:
 
1200
        for fallback in self._transitive_fallbacks():
1199
1201
            if not missing_keys:
1200
1202
                break
1201
1203
            (f_parent_map, f_missing_keys) = fallback._index.find_ancestry(
1225
1227
            and so on.
1226
1228
        """
1227
1229
        result = {}
1228
 
        sources = [self._index] + self._fallback_vfs
 
1230
        sources = [self._index] + self._immediate_fallback_vfs
1229
1231
        source_results = []
1230
1232
        missing = set(keys)
1231
1233
        for source in sources:
1525
1527
                        yield KnitContentFactory(key, global_map[key],
1526
1528
                            record_details, None, raw_data, self._factory.annotated, None)
1527
1529
                else:
1528
 
                    vf = self._fallback_vfs[parent_maps.index(source) - 1]
 
1530
                    vf = self._immediate_fallback_vfs[parent_maps.index(source) - 1]
1529
1531
                    for record in vf.get_record_stream(keys, ordering,
1530
1532
                        include_delta_closure):
1531
1533
                        yield record
1541
1543
            # record entry 2 is the 'digest'.
1542
1544
            result[key] = details[2]
1543
1545
        missing.difference_update(set(result))
1544
 
        for source in self._fallback_vfs:
 
1546
        for source in self._immediate_fallback_vfs:
1545
1547
            if not missing:
1546
1548
                break
1547
1549
            new_result = source.get_sha1s(missing)
1618
1620
                raise RevisionNotPresent([record.key], self)
1619
1621
            elif ((record.storage_kind in knit_types)
1620
1622
                  and (compression_parent is None
1621
 
                       or not self._fallback_vfs
 
1623
                       or not self._immediate_fallback_vfs
1622
1624
                       or self._index.has_key(compression_parent)
1623
1625
                       or not self.has_key(compression_parent))):
1624
1626
                # we can insert the knit record literally if either it has no
1796
1798
        # vfs, and hope to find them there.  Note that if the keys are found
1797
1799
        # but had no changes or no content, the fallback may not return
1798
1800
        # anything.
1799
 
        if keys and not self._fallback_vfs:
 
1801
        if keys and not self._immediate_fallback_vfs:
1800
1802
            # XXX: strictly the second parameter is meant to be the file id
1801
1803
            # but it's not easily accessible here.
1802
1804
            raise RevisionNotPresent(keys, repr(self))
1803
 
        for source in self._fallback_vfs:
 
1805
        for source in self._immediate_fallback_vfs:
1804
1806
            if not keys:
1805
1807
                break
1806
1808
            source_keys = set()
1879
1881
        :return: the header and the decompressor stream.
1880
1882
                 as (stream, header_record)
1881
1883
        """
1882
 
        df = tuned_gzip.GzipFile(mode='rb', fileobj=StringIO(raw_data))
 
1884
        df = gzip.GzipFile(mode='rb', fileobj=StringIO(raw_data))
1883
1885
        try:
1884
1886
            # Current serialise
1885
1887
            rec = self._check_header(key, df.readline())
1894
1896
        # 4168 calls in 2880 217 internal
1895
1897
        # 4168 calls to _parse_record_header in 2121
1896
1898
        # 4168 calls to readlines in 330
1897
 
        df = tuned_gzip.GzipFile(mode='rb', fileobj=StringIO(data))
 
1899
        df = gzip.GzipFile(mode='rb', fileobj=StringIO(data))
1898
1900
        try:
1899
1901
            record_contents = df.readlines()
1900
1902
        except Exception, e:
2015
2017
        """See VersionedFiles.keys."""
2016
2018
        if 'evil' in debug.debug_flags:
2017
2019
            trace.mutter_callsite(2, "keys scales with size of history")
2018
 
        sources = [self._index] + self._fallback_vfs
 
2020
        sources = [self._index] + self._immediate_fallback_vfs
2019
2021
        result = set()
2020
2022
        for source in sources:
2021
2023
            result.update(source.keys())
2061
2063
 
2062
2064
        missing_keys = set(nonlocal_keys)
2063
2065
        # Read from remote versioned file instances and provide to our caller.
2064
 
        for source in self.vf._fallback_vfs:
 
2066
        for source in self.vf._immediate_fallback_vfs:
2065
2067
            if not missing_keys:
2066
2068
                break
2067
2069
            # Loop over fallback repositories asking them for texts - ignore
2786
2788
        return key[:-1], key[-1]
2787
2789
 
2788
2790
 
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
2791
class _KnitGraphIndex(object):
2848
2792
    """A KnitVersionedFiles index layered on GraphIndex."""
2849
2793
 
3520
3464
        return records, ann_keys
3521
3465
 
3522
3466
    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:
 
3467
        # if True or len(self._vf._immediate_fallback_vfs) > 0:
 
3468
        if len(self._vf._immediate_fallback_vfs) > 0:
3525
3469
            # If we have fallbacks, go to the generic path
3526
3470
            for v in annotate.Annotator._get_needed_texts(self, key, pb=pb):
3527
3471
                yield v