~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/versionedfile.py

Merge bzr.dev, update to use new hooks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
2
 
#
3
 
# Authors:
4
 
#   Johan Rydberg <jrydberg@gnu.org>
 
1
# Copyright (C) 2006-2011 Canonical Ltd
5
2
#
6
3
# This program is free software; you can redistribute it and/or modify
7
4
# it under the terms of the GNU General Public License as published by
31
28
 
32
29
from bzrlib import (
33
30
    annotate,
 
31
    bencode,
34
32
    errors,
35
33
    graph as _mod_graph,
36
34
    groupcompress,
40
38
    multiparent,
41
39
    tsort,
42
40
    revision,
43
 
    ui,
44
41
    )
45
 
from bzrlib.graph import DictParentsProvider, Graph, StackedParentsProvider
46
 
from bzrlib.transport.memory import MemoryTransport
47
42
""")
48
43
from bzrlib.registry import Registry
49
44
from bzrlib.textmerge import TextMerge
50
 
from bzrlib import bencode
51
45
 
52
46
 
53
47
adapter_registry = Registry()
930
924
 
931
925
    The use of tuples allows a single code base to support several different
932
926
    uses with only the mapping logic changing from instance to instance.
 
927
 
 
928
    :ivar _immediate_fallback_vfs: For subclasses that support stacking,
 
929
        this is a list of other VersionedFiles immediately underneath this
 
930
        one.  They may in turn each have further fallbacks.
933
931
    """
934
932
 
935
933
    def add_lines(self, key, parents, lines, parent_texts=None,
974
972
    def _add_text(self, key, parents, text, nostore_sha=None, random_id=False):
975
973
        """Add a text to the store.
976
974
 
977
 
        This is a private function for use by CommitBuilder.
 
975
        This is a private function for use by VersionedFileCommitBuilder.
978
976
 
979
977
        :param key: The key tuple of the text to add. If the last element is
980
978
            None, a CHK string will be generated during the addition.
1193
1191
    def _extract_blocks(self, version_id, source, target):
1194
1192
        return None
1195
1193
 
 
1194
    def _transitive_fallbacks(self):
 
1195
        """Return the whole stack of fallback versionedfiles.
 
1196
 
 
1197
        This VersionedFiles may have a list of fallbacks, but it doesn't
 
1198
        necessarily know about the whole stack going down, and it can't know
 
1199
        at open time because they may change after the objects are opened.
 
1200
        """
 
1201
        all_fallbacks = []
 
1202
        for a_vfs in self._immediate_fallback_vfs:
 
1203
            all_fallbacks.append(a_vfs)
 
1204
            all_fallbacks.extend(a_vfs._transitive_fallbacks())
 
1205
        return all_fallbacks
 
1206
 
1196
1207
 
1197
1208
class ThunkedVersionedFiles(VersionedFiles):
1198
1209
    """Storage for many versioned files thunked onto a 'VersionedFile' class.
1411
1422
        return result
1412
1423
 
1413
1424
 
 
1425
class VersionedFilesWithFallbacks(VersionedFiles):
 
1426
 
 
1427
    def without_fallbacks(self):
 
1428
        """Return a clone of this object without any fallbacks configured."""
 
1429
        raise NotImplementedError(self.without_fallbacks)
 
1430
 
 
1431
    def add_fallback_versioned_files(self, a_versioned_files):
 
1432
        """Add a source of texts for texts not present in this knit.
 
1433
 
 
1434
        :param a_versioned_files: A VersionedFiles object.
 
1435
        """
 
1436
        raise NotImplementedError(self.add_fallback_versioned_files)
 
1437
 
 
1438
    def get_known_graph_ancestry(self, keys):
 
1439
        """Get a KnownGraph instance with the ancestry of keys."""
 
1440
        parent_map, missing_keys = self._index.find_ancestry(keys)
 
1441
        for fallback in self._transitive_fallbacks():
 
1442
            if not missing_keys:
 
1443
                break
 
1444
            (f_parent_map, f_missing_keys) = fallback._index.find_ancestry(
 
1445
                                                missing_keys)
 
1446
            parent_map.update(f_parent_map)
 
1447
            missing_keys = f_missing_keys
 
1448
        kg = _mod_graph.KnownGraph(parent_map)
 
1449
        return kg
 
1450
 
 
1451
 
1414
1452
class _PlanMergeVersionedFile(VersionedFiles):
1415
1453
    """A VersionedFile for uncommitted and committed texts.
1416
1454
 
1437
1475
        # line data for locally held keys.
1438
1476
        self._lines = {}
1439
1477
        # key lookup providers
1440
 
        self._providers = [DictParentsProvider(self._parents)]
 
1478
        self._providers = [_mod_graph.DictParentsProvider(self._parents)]
1441
1479
 
1442
1480
    def plan_merge(self, ver_a, ver_b, base=None):
1443
1481
        """See VersionedFile.plan_merge"""
1450
1488
 
1451
1489
    def plan_lca_merge(self, ver_a, ver_b, base=None):
1452
1490
        from bzrlib.merge import _PlanLCAMerge
1453
 
        graph = Graph(self)
 
1491
        graph = _mod_graph.Graph(self)
1454
1492
        new_plan = _PlanLCAMerge(ver_a, ver_b, self, (self._file_id,), graph).plan_merge()
1455
1493
        if base is None:
1456
1494
            return new_plan
1508
1546
            result[revision.NULL_REVISION] = ()
1509
1547
        self._providers = self._providers[:1] + self.fallback_versionedfiles
1510
1548
        result.update(
1511
 
            StackedParentsProvider(self._providers).get_parent_map(keys))
 
1549
            _mod_graph.StackedParentsProvider(
 
1550
                self._providers).get_parent_map(keys))
1512
1551
        for key, parents in result.iteritems():
1513
1552
            if parents == ():
1514
1553
                result[key] = (revision.NULL_REVISION,)
1860
1899
    for prefix in sorted(per_prefix_map):
1861
1900
        present_keys.extend(reversed(tsort.topo_sort(per_prefix_map[prefix])))
1862
1901
    return present_keys
 
1902
 
 
1903
 
 
1904
class _KeyRefs(object):
 
1905
 
 
1906
    def __init__(self, track_new_keys=False):
 
1907
        # dict mapping 'key' to 'set of keys referring to that key'
 
1908
        self.refs = {}
 
1909
        if track_new_keys:
 
1910
            # set remembering all new keys
 
1911
            self.new_keys = set()
 
1912
        else:
 
1913
            self.new_keys = None
 
1914
 
 
1915
    def clear(self):
 
1916
        if self.refs:
 
1917
            self.refs.clear()
 
1918
        if self.new_keys:
 
1919
            self.new_keys.clear()
 
1920
 
 
1921
    def add_references(self, key, refs):
 
1922
        # Record the new references
 
1923
        for referenced in refs:
 
1924
            try:
 
1925
                needed_by = self.refs[referenced]
 
1926
            except KeyError:
 
1927
                needed_by = self.refs[referenced] = set()
 
1928
            needed_by.add(key)
 
1929
        # Discard references satisfied by the new key
 
1930
        self.add_key(key)
 
1931
 
 
1932
    def get_new_keys(self):
 
1933
        return self.new_keys
 
1934
    
 
1935
    def get_unsatisfied_refs(self):
 
1936
        return self.refs.iterkeys()
 
1937
 
 
1938
    def _satisfy_refs_for_key(self, key):
 
1939
        try:
 
1940
            del self.refs[key]
 
1941
        except KeyError:
 
1942
            # No keys depended on this key.  That's ok.
 
1943
            pass
 
1944
 
 
1945
    def add_key(self, key):
 
1946
        # satisfy refs for key, and remember that we've seen this key.
 
1947
        self._satisfy_refs_for_key(key)
 
1948
        if self.new_keys is not None:
 
1949
            self.new_keys.add(key)
 
1950
 
 
1951
    def satisfy_refs_for_keys(self, keys):
 
1952
        for key in keys:
 
1953
            self._satisfy_refs_for_key(key)
 
1954
 
 
1955
    def get_referrers(self):
 
1956
        result = set()
 
1957
        for referrers in self.refs.itervalues():
 
1958
            result.update(referrers)
 
1959
        return result
 
1960
 
 
1961
 
 
1962