70
84
# This lets us control the ordering, so that we are able to create
74
("committer", encode_utf8(rev.committer)[0]),
88
(b"committer", encode_utf8(rev.committer)[0]),
76
90
if rev.timezone is not None:
77
ret.append(("timezone", rev.timezone))
91
ret.append((b"timezone", rev.timezone))
78
92
# For bzr revisions, the most common property is just 'branch-nick'
79
93
# which changes infrequently.
81
for key, value in rev.properties.iteritems():
82
revprops[key] = encode_utf8(value)[0]
83
ret.append(('properties', revprops))
95
for key, value in rev.properties.items():
96
revprops[encode_utf8(key)[0]] = encode_utf8(value)[0]
97
ret.append((b'properties', revprops))
85
("timestamp", "%.3f" % rev.timestamp),
86
("revision-id", rev.revision_id),
87
("parent-ids", rev.parent_ids),
88
("inventory-sha1", rev.inventory_sha1),
89
("message", encode_utf8(rev.message)[0]),
99
(b"timestamp", b"%.3f" % rev.timestamp),
100
(b"revision-id", rev.revision_id),
101
(b"parent-ids", rev.parent_ids),
102
(b"inventory-sha1", rev.inventory_sha1),
103
(b"message", encode_utf8(rev.message)[0]),
91
105
return bencode.bencode(ret)
131
145
return self.read_revision_from_string(f.read())
134
class CHKSerializerSubtree(BEncodeRevisionSerializer1, xml7.Serializer_v7):
135
"""A CHKInventory based serializer that supports tree references"""
148
class CHKSerializer(serializer.Serializer):
149
"""A CHKInventory based serializer with 'plain' behaviour."""
137
supported_kinds = set(['file', 'directory', 'symlink', 'tree-reference'])
139
152
revision_format_num = None
140
153
support_altered_by_hack = False
142
def _unpack_entry(self, elt, entry_cache=None, return_from_cache=False):
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,
154
supported_kinds = {'file', 'directory', 'symlink', 'tree-reference'}
156
def __init__(self, node_size, search_key_name):
157
self.maximum_size = node_size
158
self.search_key_name = search_key_name
160
def _unpack_inventory(self, elt, revision_id=None, entry_cache=None,
161
return_from_cache=False):
162
"""Construct from XML Element"""
163
inv = xml_serializer.unpack_inventory_flat(elt, self.format_num,
164
xml_serializer.unpack_inventory_entry, entry_cache,
168
def read_inventory_from_string(self, xml_string, revision_id=None,
169
entry_cache=None, return_from_cache=False):
170
"""Read xml_string into an inventory object.
172
:param xml_string: The xml to read.
173
:param revision_id: If not-None, the expected revision id of the
175
:param entry_cache: An optional cache of InventoryEntry objects. If
176
supplied we will look up entries via (file_id, revision_id) which
177
should map to a valid InventoryEntry (File/Directory/etc) object.
178
:param return_from_cache: Return entries directly from the cache,
179
rather than copying them first. This is only safe if the caller
180
promises not to mutate the returned inventory entries, but it can
181
make some operations significantly faster.
184
return self._unpack_inventory(
185
xml_serializer.fromstring(xml_string), revision_id,
186
entry_cache=entry_cache,
187
return_from_cache=return_from_cache)
188
except xml_serializer.ParseError as e:
189
raise errors.UnexpectedInventoryFormat(e)
191
def read_inventory(self, f, revision_id=None):
192
"""Read an inventory from a file-like object."""
195
return self._unpack_inventory(self._read_element(f),
199
except xml_serializer.ParseError as e:
200
raise errors.UnexpectedInventoryFormat(e)
202
def write_inventory_to_lines(self, inv):
203
"""Return a list of lines with the encoded inventory."""
204
return self.write_inventory(inv, None)
206
def write_inventory_to_string(self, inv, working=False):
207
"""Just call write_inventory with a BytesIO and return the value.
209
:param working: If True skip history data - text_sha1, text_size,
210
reference_revision, symlink_target.
213
self.write_inventory(inv, sio, working)
214
return sio.getvalue()
216
def write_inventory(self, inv, f, working=False):
217
"""Write inventory to a file.
219
:param inv: the inventory to write.
220
:param f: the file to write. (May be None if the lines are the desired
222
:param working: If True skip history data - text_sha1, text_size,
223
reference_revision, symlink_target.
224
:return: The inventory as a list of lines.
227
append = output.append
228
if inv.revision_id is not None:
229
revid1 = ' revision_id="'
230
revid2 = xml_serializer.encode_and_escape(inv.revision_id)
155
return xml7.Serializer_v7._unpack_entry(self, elt,
156
entry_cache=entry_cache, return_from_cache=return_from_cache)
158
def __init__(self, node_size, search_key_name):
159
self.maximum_size = node_size
160
self.search_key_name = search_key_name
163
class CHKSerializer(xml6.Serializer_v6):
164
"""A CHKInventory based serializer with 'plain' behaviour."""
167
revision_format_num = None
168
support_altered_by_hack = False
170
def __init__(self, node_size, search_key_name):
171
self.maximum_size = node_size
172
self.search_key_name = search_key_name
234
append('<inventory format="%s"%s%s>\n' % (
235
self.format_num, revid1, revid2))
236
append('<directory file_id="%s name="%s revision="%s />\n' % (
237
xml_serializer.encode_and_escape(inv.root.file_id),
238
xml_serializer.encode_and_escape(inv.root.name),
239
xml_serializer.encode_and_escape(inv.root.revision)))
240
xml_serializer.serialize_inventory_flat(inv,
242
root_id=None, supported_kinds=self.supported_kinds,
175
249
chk_serializer_255_bigpage = CHKSerializer(65536, 'hash-255-way')