/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4241.6.1 by Ian Clatworthy
chk_map code from brisbane-core
1
# Copyright (C) 2008 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17
"""Serializer object for CHK based inventory storage."""
18
4290.1.1 by Jelmer Vernooij
Add simple revision serializer based on RIO.
19
from cStringIO import (
20
    StringIO,
21
    )
22
4241.6.1 by Ian Clatworthy
chk_map code from brisbane-core
23
from bzrlib import (
4398.5.2 by John Arbash Meinel
Merge the chk serializer, and update it for the new bencode locations.
24
    bencode,
4290.1.1 by Jelmer Vernooij
Add simple revision serializer based on RIO.
25
    cache_utf8,
4241.6.1 by Ian Clatworthy
chk_map code from brisbane-core
26
    inventory,
4290.1.1 by Jelmer Vernooij
Add simple revision serializer based on RIO.
27
    osutils,
28
    revision as _mod_revision,
4241.6.1 by Ian Clatworthy
chk_map code from brisbane-core
29
    xml5,
30
    xml6,
31
    )
32
4398.5.5 by John Arbash Meinel
Update the CHK Serializer to do lots more validation.
33
_decode_utf8 = cache_utf8.decode
34
35
36
def _validate_properties(props):
37
    decode = _decode_utf8
38
    # TODO: we really want an 'isascii' check for key
39
    unicode_props = dict((key, _decode_utf8(value))
40
                         for key, value in props.iteritems())
41
    return unicode_props
42
43
44
def _is_format_10(value):
45
    if value != 10:
46
        raise ValueError('Format number was not recognized, expected 10 got %d'
47
                         % (value,))
48
    return 10
49
50
4290.1.12 by Jelmer Vernooij
Use bencode rather than rio in the new revision serialiszer.
51
class BEncodeRevisionSerializer1(object):
4398.5.5 by John Arbash Meinel
Update the CHK Serializer to do lots more validation.
52
    """Simple revision serializer based around bencode.
4290.1.1 by Jelmer Vernooij
Add simple revision serializer based on RIO.
53
    """
54
4398.5.5 by John Arbash Meinel
Update the CHK Serializer to do lots more validation.
55
    # Maps {key:(Revision attribute, bencode_type, validator)}
56
    # This tells us what kind we expect bdecode to create, what variable on
57
    # Revision we should be using, and a function to call to validate/transform
58
    # the type.
59
    # TODO: add a 'validate_utf8' for things like revision_id and file_id
60
    #       and a validator for parent-ids
61
    _schema = {'format': (None, int, _is_format_10),
62
               'committer': ('committer', str, _decode_utf8),
63
               'timezone': ('timezone', int, None),
64
               'timestamp': ('timestamp', str, float),
65
               'revision-id': ('revision_id', str, None),
66
               'parent-ids': ('parent_ids', list, tuple),
67
               'inventory-sha1': ('inventory_sha1', str, None),
68
               'message': ('message', str, _decode_utf8),
69
               'properties': ('properties', dict, _validate_properties),
70
    }
71
4290.1.12 by Jelmer Vernooij
Use bencode rather than rio in the new revision serialiszer.
72
    def write_revision_to_string(self, rev):
73
        encode_utf8 = cache_utf8.encode
4398.5.5 by John Arbash Meinel
Update the CHK Serializer to do lots more validation.
74
        # Use a list of tuples rather than a dict
75
        # This lets us control the ordering, so that we are able to create
76
        # smaller deltas
77
        ret = [
78
            ("format", 10),
79
            ("committer", encode_utf8(rev.committer)),
80
        ]
81
        if rev.timezone is not None:
82
            ret.append(("timezone", rev.timezone))
83
        # For bzr revisions, the most common property is just 'branch-nick'
84
        # which changes infrequently.
4290.1.12 by Jelmer Vernooij
Use bencode rather than rio in the new revision serialiszer.
85
        revprops = {}
86
        for key, value in rev.properties.iteritems():
87
            revprops[key] = encode_utf8(value)
4398.5.5 by John Arbash Meinel
Update the CHK Serializer to do lots more validation.
88
        ret.append(('properties', revprops))
89
        ret.extend([
90
            ("timestamp", "%.3f" % rev.timestamp),
91
            ("revision-id", rev.revision_id),
92
            ("parent-ids", rev.parent_ids),
93
            ("inventory-sha1", rev.inventory_sha1),
94
            ("message", encode_utf8(rev.message)),
95
        ])
4398.5.2 by John Arbash Meinel
Merge the chk serializer, and update it for the new bencode locations.
96
        return bencode.bencode(ret)
4290.1.8 by Jelmer Vernooij
Some performance tweaks.
97
98
    def write_revision(self, rev, f):
4290.1.12 by Jelmer Vernooij
Use bencode rather than rio in the new revision serialiszer.
99
        f.write(self.write_revision_to_string(rev))
100
101
    def read_revision_from_string(self, text):
4398.5.5 by John Arbash Meinel
Update the CHK Serializer to do lots more validation.
102
        # TODO: consider writing a Revision decoder, rather than using the
103
        #       generic bencode decoder
4290.1.12 by Jelmer Vernooij
Use bencode rather than rio in the new revision serialiszer.
104
        decode_utf8 = cache_utf8.decode
4398.5.2 by John Arbash Meinel
Merge the chk serializer, and update it for the new bencode locations.
105
        ret = bencode.bdecode(text)
4398.5.5 by John Arbash Meinel
Update the CHK Serializer to do lots more validation.
106
        if not isinstance(ret, list):
107
            raise ValueError("invalid revision text")
108
        schema = dict(self._schema)
109
        bits = {}
110
        for key, value in ret:
111
            # The entry must be present in allowed keys, but only present a
112
            # single time
113
            var_name, expected_type, validator = schema.pop(key)
114
            if value.__class__ is not expected_type:
115
                raise ValueError('key %s did not conform to the expected type'
116
                                 ' %s, but was %s'
117
                                 % (key, expected_type, type(value)))
118
            if validator is not None:
119
                value = validator(value)
120
            if var_name is not None:
121
                bits[var_name] = value
122
        if schema.keys() not in ([], ['timezone']):
123
            raise ValueError('Revision text was missing expected keys %s,'
124
                             ' text %r' % (schema.keys(), text))
125
        rev = _mod_revision.Revision(**bits)
126
        if "timezone" not in bits:
4290.1.12 by Jelmer Vernooij
Use bencode rather than rio in the new revision serialiszer.
127
            rev.timezone = None
4290.1.8 by Jelmer Vernooij
Some performance tweaks.
128
        return rev
129
130
    def read_revision(self, f):
4290.1.12 by Jelmer Vernooij
Use bencode rather than rio in the new revision serialiszer.
131
        return self.read_revision_from_string(f.read())
132
133
134
class CHKSerializerSubtree(BEncodeRevisionSerializer1, xml6.Serializer_v6):
4241.6.1 by Ian Clatworthy
chk_map code from brisbane-core
135
    """A CHKInventory based serializer that supports tree references"""
136
137
    supported_kinds = set(['file', 'directory', 'symlink', 'tree-reference'])
138
    format_num = '9'
139
    revision_format_num = None
140
    support_altered_by_hack = False
141
142
    def _unpack_entry(self, elt):
143
        kind = elt.tag
144
        if not kind in self.supported_kinds:
145
            raise AssertionError('unsupported entry kind %s' % kind)
146
        if kind == 'tree-reference':
147
            file_id = elt.attrib['file_id']
148
            name = elt.attrib['name']
149
            parent_id = elt.attrib['parent_id']
150
            revision = elt.get('revision')
151
            reference_revision = elt.get('reference_revision')
152
            return inventory.TreeReference(file_id, name, parent_id, revision,
153
                                           reference_revision)
154
        else:
155
            return xml6.Serializer_v6._unpack_entry(self, elt)
156
157
    def __init__(self, node_size, search_key_name):
158
        self.maximum_size = node_size
159
        self.search_key_name = search_key_name
160
161
4290.1.7 by Jelmer Vernooij
Add development7-rich-root format that uses the RIO Serializer.
162
class CHKSerializer(xml5.Serializer_v5):
4241.6.1 by Ian Clatworthy
chk_map code from brisbane-core
163
    """A CHKInventory based serializer with 'plain' behaviour."""
164
165
    format_num = '9'
166
    revision_format_num = None
167
    support_altered_by_hack = False
168
169
    def __init__(self, node_size, search_key_name):
170
        self.maximum_size = node_size
171
        self.search_key_name = search_key_name
172
173
174
chk_serializer_255_bigpage = CHKSerializer(65536, 'hash-255-way')
4290.1.7 by Jelmer Vernooij
Add development7-rich-root format that uses the RIO Serializer.
175
176
4290.1.12 by Jelmer Vernooij
Use bencode rather than rio in the new revision serialiszer.
177
class CHKBEncodeSerializer(BEncodeRevisionSerializer1, CHKSerializer):
178
    """A CHKInventory and BEncode based serializer with 'plain' behaviour."""
4290.1.7 by Jelmer Vernooij
Add development7-rich-root format that uses the RIO Serializer.
179
180
    format_num = '10'
181
182
4290.1.12 by Jelmer Vernooij
Use bencode rather than rio in the new revision serialiszer.
183
chk_bencode_serializer = CHKBEncodeSerializer(65536, 'hash-255-way')