~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-08-30 22:49:20 UTC
  • mfrom: (5397.1.6 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100830224920-w9zw1vhsd5oiyljv
(vila, jam) Get PQM running correctly again (bug #626667),
        skip test_bzr_connect_to_bzr_ssh (bug #626876)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2006-2010 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
68
68
    index as _mod_index,
69
69
    lru_cache,
70
70
    pack,
 
71
    patiencediff,
71
72
    progress,
 
73
    static_tuple,
72
74
    trace,
73
75
    tsort,
74
76
    tuned_gzip,
 
77
    ui,
75
78
    )
76
79
""")
77
80
from bzrlib import (
78
81
    errors,
79
82
    osutils,
80
 
    patiencediff,
81
83
    )
82
84
from bzrlib.errors import (
83
85
    FileExists,
1045
1047
    def get_annotator(self):
1046
1048
        return _KnitAnnotator(self)
1047
1049
 
1048
 
    def check(self, progress_bar=None):
 
1050
    def check(self, progress_bar=None, keys=None):
1049
1051
        """See VersionedFiles.check()."""
 
1052
        if keys is None:
 
1053
            return self._logical_check()
 
1054
        else:
 
1055
            # At the moment, check does not extra work over get_record_stream
 
1056
            return self.get_record_stream(keys, 'unordered', True)
 
1057
 
 
1058
    def _logical_check(self):
1050
1059
        # This doesn't actually test extraction of everything, but that will
1051
1060
        # impact 'bzr check' substantially, and needs to be integrated with
1052
1061
        # care. However, it does check for the obvious problem of a delta with
1183
1192
        generator = _VFContentMapGenerator(self, [key])
1184
1193
        return generator._get_content(key)
1185
1194
 
 
1195
    def get_known_graph_ancestry(self, keys):
 
1196
        """Get a KnownGraph instance with the ancestry of keys."""
 
1197
        parent_map, missing_keys = self._index.find_ancestry(keys)
 
1198
        for fallback in self._fallback_vfs:
 
1199
            if not missing_keys:
 
1200
                break
 
1201
            (f_parent_map, f_missing_keys) = fallback._index.find_ancestry(
 
1202
                                                missing_keys)
 
1203
            parent_map.update(f_parent_map)
 
1204
            missing_keys = f_missing_keys
 
1205
        kg = _mod_graph.KnownGraph(parent_map)
 
1206
        return kg
 
1207
 
1186
1208
    def get_parent_map(self, keys):
1187
1209
        """Get a map of the graph parents of keys.
1188
1210
 
1498
1520
                if source is parent_maps[0]:
1499
1521
                    # this KnitVersionedFiles
1500
1522
                    records = [(key, positions[key][1]) for key in keys]
1501
 
                    for key, raw_data, sha1 in self._read_records_iter_raw(records):
 
1523
                    for key, raw_data in self._read_records_iter_unchecked(records):
1502
1524
                        (record_details, index_memo, _) = positions[key]
1503
1525
                        yield KnitContentFactory(key, global_map[key],
1504
 
                            record_details, sha1, raw_data, self._factory.annotated, None)
 
1526
                            record_details, None, raw_data, self._factory.annotated, None)
1505
1527
                else:
1506
1528
                    vf = self._fallback_vfs[parent_maps.index(source) - 1]
1507
1529
                    for record in vf.get_record_stream(keys, ordering,
1576
1598
        # key = basis_parent, value = index entry to add
1577
1599
        buffered_index_entries = {}
1578
1600
        for record in stream:
 
1601
            kind = record.storage_kind
 
1602
            if kind.startswith('knit-') and kind.endswith('-gz'):
 
1603
                # Check that the ID in the header of the raw knit bytes matches
 
1604
                # the record metadata.
 
1605
                raw_data = record._raw_record
 
1606
                df, rec = self._parse_record_header(record.key, raw_data)
 
1607
                df.close()
1579
1608
            buffered = False
1580
1609
            parents = record.parents
1581
1610
            if record.storage_kind in delta_types:
1683
1712
            # There were index entries buffered at the end of the stream,
1684
1713
            # So these need to be added (if the index supports holding such
1685
1714
            # entries for later insertion)
 
1715
            all_entries = []
1686
1716
            for key in buffered_index_entries:
1687
1717
                index_entries = buffered_index_entries[key]
1688
 
                self._index.add_records(index_entries,
1689
 
                    missing_compression_parents=True)
 
1718
                all_entries.extend(index_entries)
 
1719
            self._index.add_records(
 
1720
                all_entries, missing_compression_parents=True)
1690
1721
 
1691
1722
    def get_missing_compression_parent_keys(self):
1692
1723
        """Return an iterable of keys of missing compression parents.
1725
1756
        :return: An iterator over (line, key).
1726
1757
        """
1727
1758
        if pb is None:
1728
 
            pb = progress.DummyProgress()
 
1759
            pb = ui.ui_factory.nested_progress_bar()
1729
1760
        keys = set(keys)
1730
1761
        total = len(keys)
1731
1762
        done = False
2338
2369
    FLAGS is a comma separated list of flags about the record. Values include
2339
2370
        no-eol, line-delta, fulltext.
2340
2371
    BYTE_OFFSET is the ascii representation of the byte offset in the data file
2341
 
        that the the compressed data starts at.
 
2372
        that the compressed data starts at.
2342
2373
    LENGTH is the ascii representation of the length of the data file.
2343
2374
    PARENT_ID a utf-8 revision id prefixed by a '.' that is a parent of
2344
2375
        REVISION_ID.
2553
2584
        except KeyError:
2554
2585
            raise RevisionNotPresent(key, self)
2555
2586
 
 
2587
    def find_ancestry(self, keys):
 
2588
        """See CombinedGraphIndex.find_ancestry()"""
 
2589
        prefixes = set(key[:-1] for key in keys)
 
2590
        self._load_prefixes(prefixes)
 
2591
        result = {}
 
2592
        parent_map = {}
 
2593
        missing_keys = set()
 
2594
        pending_keys = list(keys)
 
2595
        # This assumes that keys will not reference parents in a different
 
2596
        # prefix, which is accurate so far.
 
2597
        while pending_keys:
 
2598
            key = pending_keys.pop()
 
2599
            if key in parent_map:
 
2600
                continue
 
2601
            prefix = key[:-1]
 
2602
            try:
 
2603
                suffix_parents = self._kndx_cache[prefix][0][key[-1]][4]
 
2604
            except KeyError:
 
2605
                missing_keys.add(key)
 
2606
            else:
 
2607
                parent_keys = tuple([prefix + (suffix,)
 
2608
                                     for suffix in suffix_parents])
 
2609
                parent_map[key] = parent_keys
 
2610
                pending_keys.extend([p for p in parent_keys
 
2611
                                        if p not in parent_map])
 
2612
        return parent_map, missing_keys
 
2613
 
2556
2614
    def get_parent_map(self, keys):
2557
2615
        """Get a map of the parents of keys.
2558
2616
 
2730
2788
 
2731
2789
class _KeyRefs(object):
2732
2790
 
2733
 
    def __init__(self):
 
2791
    def __init__(self, track_new_keys=False):
2734
2792
        # dict mapping 'key' to 'set of keys referring to that key'
2735
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()
2736
2805
 
2737
2806
    def add_references(self, key, refs):
2738
2807
        # Record the new references
2745
2814
        # Discard references satisfied by the new key
2746
2815
        self.add_key(key)
2747
2816
 
 
2817
    def get_new_keys(self):
 
2818
        return self.new_keys
 
2819
    
2748
2820
    def get_unsatisfied_refs(self):
2749
2821
        return self.refs.iterkeys()
2750
2822
 
2751
 
    def add_key(self, key):
 
2823
    def _satisfy_refs_for_key(self, key):
2752
2824
        try:
2753
2825
            del self.refs[key]
2754
2826
        except KeyError:
2755
2827
            # No keys depended on this key.  That's ok.
2756
2828
            pass
2757
2829
 
2758
 
    def add_keys(self, keys):
 
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):
2759
2837
        for key in keys:
2760
 
            self.add_key(key)
 
2838
            self._satisfy_refs_for_key(key)
2761
2839
 
2762
2840
    def get_referrers(self):
2763
2841
        result = set()
2868
2946
        if not random_id:
2869
2947
            present_nodes = self._get_entries(keys)
2870
2948
            for (index, key, value, node_refs) in present_nodes:
 
2949
                parents = node_refs[:1]
 
2950
                # Sometimes these are passed as a list rather than a tuple
 
2951
                passed = static_tuple.as_tuples(keys[key])
 
2952
                passed_parents = passed[1][:1]
2871
2953
                if (value[0] != keys[key][0][0] or
2872
 
                    node_refs[:1] != keys[key][1][:1]):
 
2954
                    parents != passed_parents):
 
2955
                    node_refs = static_tuple.as_tuples(node_refs)
2873
2956
                    raise KnitCorrupt(self, "inconsistent details in add_records"
2874
 
                        ": %s %s" % ((value, node_refs), keys[key]))
 
2957
                        ": %s %s" % ((value, node_refs), passed))
2875
2958
                del keys[key]
2876
2959
        result = []
2877
2960
        if self._parents:
2925
3008
        # If updating this, you should also update
2926
3009
        # groupcompress._GCGraphIndex.get_missing_parents
2927
3010
        # We may have false positives, so filter those out.
2928
 
        self._key_dependencies.add_keys(
 
3011
        self._key_dependencies.satisfy_refs_for_keys(
2929
3012
            self.get_parent_map(self._key_dependencies.get_unsatisfied_refs()))
2930
3013
        return frozenset(self._key_dependencies.get_unsatisfied_refs())
2931
3014
 
3042
3125
            options.append('no-eol')
3043
3126
        return options
3044
3127
 
 
3128
    def find_ancestry(self, keys):
 
3129
        """See CombinedGraphIndex.find_ancestry()"""
 
3130
        return self._graph_index.find_ancestry(keys, 0)
 
3131
 
3045
3132
    def get_parent_map(self, keys):
3046
3133
        """Get a map of the parents of keys.
3047
3134
 
3330
3417
            raise exc_class, exc_value, exc_traceback
3331
3418
 
3332
3419
 
3333
 
# Deprecated, use PatienceSequenceMatcher instead
3334
 
KnitSequenceMatcher = patiencediff.PatienceSequenceMatcher
3335
 
 
3336
 
 
3337
3420
def annotate_knit(knit, revision_id):
3338
3421
    """Annotate a knit with no cached annotations.
3339
3422
 
3621
3704
                    to_process.extend(self._process_pending(key))
3622
3705
 
3623
3706
try:
3624
 
    from bzrlib._knit_load_data_c import _load_data_c as _load_data
3625
 
except ImportError:
 
3707
    from bzrlib._knit_load_data_pyx import _load_data_c as _load_data
 
3708
except ImportError, e:
 
3709
    osutils.failed_to_load_extension(e)
3626
3710
    from bzrlib._knit_load_data_py import _load_data_py as _load_data