~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/versionedfile.py

  • Committer: Jelmer Vernooij
  • Date: 2011-02-19 15:23:08 UTC
  • mto: (5582.12.2 weave-plugin)
  • mto: This revision was merged to the branch mainline in revision 5718.
  • Revision ID: jelmer@samba.org-20110219152308-5shhc4rj0ez4oa12
move xml4 to weave plugin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Versioned text file storage api."""
18
18
 
19
 
from __future__ import absolute_import
20
 
 
21
19
from copy import copy
22
20
from cStringIO import StringIO
23
21
import os
26
24
 
27
25
from bzrlib.lazy_import import lazy_import
28
26
lazy_import(globals(), """
 
27
import urllib
 
28
 
29
29
from bzrlib import (
30
30
    annotate,
31
 
    bencode,
32
31
    errors,
33
32
    graph as _mod_graph,
34
33
    groupcompress,
38
37
    multiparent,
39
38
    tsort,
40
39
    revision,
41
 
    urlutils,
 
40
    ui,
42
41
    )
 
42
from bzrlib.graph import DictParentsProvider, Graph, StackedParentsProvider
 
43
from bzrlib.transport.memory import MemoryTransport
43
44
""")
44
45
from bzrlib.registry import Registry
45
46
from bzrlib.textmerge import TextMerge
 
47
from bzrlib import bencode
46
48
 
47
49
 
48
50
adapter_registry = Registry()
822
824
 
823
825
    def map(self, key):
824
826
        """See KeyMapper.map()."""
825
 
        return urlutils.quote(self._map(key))
 
827
        return urllib.quote(self._map(key))
826
828
 
827
829
    def unmap(self, partition_id):
828
830
        """See KeyMapper.unmap()."""
829
 
        return self._unmap(urlutils.unquote(partition_id))
 
831
        return self._unmap(urllib.unquote(partition_id))
830
832
 
831
833
 
832
834
class PrefixMapper(URLEscapeMapper):
879
881
    def _escape(self, prefix):
880
882
        """Turn a key element into a filesystem safe string.
881
883
 
882
 
        This is similar to a plain urlutils.quote, except
 
884
        This is similar to a plain urllib.quote, except
883
885
        it uses specific safe characters, so that it doesn't
884
886
        have to translate a lot of valid file ids.
885
887
        """
892
894
 
893
895
    def _unescape(self, basename):
894
896
        """Escaped names are easily unescaped by urlutils."""
895
 
        return urlutils.unquote(basename)
 
897
        return urllib.unquote(basename)
896
898
 
897
899
 
898
900
def make_versioned_files_factory(versioned_file_factory, mapper):
973
975
    def _add_text(self, key, parents, text, nostore_sha=None, random_id=False):
974
976
        """Add a text to the store.
975
977
 
976
 
        This is a private function for use by VersionedFileCommitBuilder.
 
978
        This is a private function for use by CommitBuilder.
977
979
 
978
980
        :param key: The key tuple of the text to add. If the last element is
979
981
            None, a CHK string will be generated during the addition.
1423
1425
        return result
1424
1426
 
1425
1427
 
1426
 
class VersionedFilesWithFallbacks(VersionedFiles):
1427
 
 
1428
 
    def without_fallbacks(self):
1429
 
        """Return a clone of this object without any fallbacks configured."""
1430
 
        raise NotImplementedError(self.without_fallbacks)
1431
 
 
1432
 
    def add_fallback_versioned_files(self, a_versioned_files):
1433
 
        """Add a source of texts for texts not present in this knit.
1434
 
 
1435
 
        :param a_versioned_files: A VersionedFiles object.
1436
 
        """
1437
 
        raise NotImplementedError(self.add_fallback_versioned_files)
1438
 
 
1439
 
    def get_known_graph_ancestry(self, keys):
1440
 
        """Get a KnownGraph instance with the ancestry of keys."""
1441
 
        parent_map, missing_keys = self._index.find_ancestry(keys)
1442
 
        for fallback in self._transitive_fallbacks():
1443
 
            if not missing_keys:
1444
 
                break
1445
 
            (f_parent_map, f_missing_keys) = fallback._index.find_ancestry(
1446
 
                                                missing_keys)
1447
 
            parent_map.update(f_parent_map)
1448
 
            missing_keys = f_missing_keys
1449
 
        kg = _mod_graph.KnownGraph(parent_map)
1450
 
        return kg
1451
 
 
1452
 
 
1453
1428
class _PlanMergeVersionedFile(VersionedFiles):
1454
1429
    """A VersionedFile for uncommitted and committed texts.
1455
1430
 
1476
1451
        # line data for locally held keys.
1477
1452
        self._lines = {}
1478
1453
        # key lookup providers
1479
 
        self._providers = [_mod_graph.DictParentsProvider(self._parents)]
 
1454
        self._providers = [DictParentsProvider(self._parents)]
1480
1455
 
1481
1456
    def plan_merge(self, ver_a, ver_b, base=None):
1482
1457
        """See VersionedFile.plan_merge"""
1489
1464
 
1490
1465
    def plan_lca_merge(self, ver_a, ver_b, base=None):
1491
1466
        from bzrlib.merge import _PlanLCAMerge
1492
 
        graph = _mod_graph.Graph(self)
 
1467
        graph = Graph(self)
1493
1468
        new_plan = _PlanLCAMerge(ver_a, ver_b, self, (self._file_id,), graph).plan_merge()
1494
1469
        if base is None:
1495
1470
            return new_plan
1547
1522
            result[revision.NULL_REVISION] = ()
1548
1523
        self._providers = self._providers[:1] + self.fallback_versionedfiles
1549
1524
        result.update(
1550
 
            _mod_graph.StackedParentsProvider(
1551
 
                self._providers).get_parent_map(keys))
 
1525
            StackedParentsProvider(self._providers).get_parent_map(keys))
1552
1526
        for key, parents in result.iteritems():
1553
1527
            if parents == ():
1554
1528
                result[key] = (revision.NULL_REVISION,)
1900
1874
    for prefix in sorted(per_prefix_map):
1901
1875
        present_keys.extend(reversed(tsort.topo_sort(per_prefix_map[prefix])))
1902
1876
    return present_keys
1903
 
 
1904
 
 
1905
 
class _KeyRefs(object):
1906
 
 
1907
 
    def __init__(self, track_new_keys=False):
1908
 
        # dict mapping 'key' to 'set of keys referring to that key'
1909
 
        self.refs = {}
1910
 
        if track_new_keys:
1911
 
            # set remembering all new keys
1912
 
            self.new_keys = set()
1913
 
        else:
1914
 
            self.new_keys = None
1915
 
 
1916
 
    def clear(self):
1917
 
        if self.refs:
1918
 
            self.refs.clear()
1919
 
        if self.new_keys:
1920
 
            self.new_keys.clear()
1921
 
 
1922
 
    def add_references(self, key, refs):
1923
 
        # Record the new references
1924
 
        for referenced in refs:
1925
 
            try:
1926
 
                needed_by = self.refs[referenced]
1927
 
            except KeyError:
1928
 
                needed_by = self.refs[referenced] = set()
1929
 
            needed_by.add(key)
1930
 
        # Discard references satisfied by the new key
1931
 
        self.add_key(key)
1932
 
 
1933
 
    def get_new_keys(self):
1934
 
        return self.new_keys
1935
 
    
1936
 
    def get_unsatisfied_refs(self):
1937
 
        return self.refs.iterkeys()
1938
 
 
1939
 
    def _satisfy_refs_for_key(self, key):
1940
 
        try:
1941
 
            del self.refs[key]
1942
 
        except KeyError:
1943
 
            # No keys depended on this key.  That's ok.
1944
 
            pass
1945
 
 
1946
 
    def add_key(self, key):
1947
 
        # satisfy refs for key, and remember that we've seen this key.
1948
 
        self._satisfy_refs_for_key(key)
1949
 
        if self.new_keys is not None:
1950
 
            self.new_keys.add(key)
1951
 
 
1952
 
    def satisfy_refs_for_keys(self, keys):
1953
 
        for key in keys:
1954
 
            self._satisfy_refs_for_key(key)
1955
 
 
1956
 
    def get_referrers(self):
1957
 
        result = set()
1958
 
        for referrers in self.refs.itervalues():
1959
 
            result.update(referrers)
1960
 
        return result
1961
 
 
1962
 
 
1963