1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
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
138
138
_to_escaped_map.clear()
141
class Serializer_v5(Serializer):
142
"""Version 5 serializer
141
class Serializer_v8(Serializer):
142
"""This serialiser adds rich roots.
144
Packs objects into XML and vice versa.
144
Its revision format number matches its inventory number.
150
150
support_altered_by_hack = True
151
151
# This format supports the altered-by hack that reads file ids directly out
152
152
# of the versionedfile, without doing XML parsing.
154
154
supported_kinds = set(['file', 'directory', 'symlink'])
156
revision_format_num = None
157
158
def _check_revisions(self, inv):
158
159
"""Extension point for subclasses to check during serialisation.
160
By default no checking is done.
162
161
:param inv: An inventory about to be serialised, to be checked.
163
162
:raises: AssertionError if an error has occured.
164
assert inv.revision_id is not None
165
assert inv.root.revision is not None
166
167
def write_inventory_to_lines(self, inv):
167
168
"""Return a list of lines with the encoded inventory."""
274
275
def _append_inventory_root(self, append, inv):
275
276
"""Append the inventory root to output."""
276
if inv.root.file_id not in (None, ROOT_ID):
277
fileid1 = ' file_id="'
278
fileid2 = _encode_and_escape(inv.root.file_id)
282
277
if inv.revision_id is not None:
283
278
revid1 = ' revision_id="'
284
279
revid2 = _encode_and_escape(inv.revision_id)
288
append('<inventory%s%s format="5"%s%s>\n' % (
289
fileid1, fileid2, revid1, revid2))
283
append('<inventory format="%s"%s%s>\n' % (
284
self.format_num, revid1, revid2))
285
append('<directory file_id="%s name="%s revision="%s />\n' % (
286
_encode_and_escape(inv.root.file_id),
287
_encode_and_escape(inv.root.name),
288
_encode_and_escape(inv.root.revision)))
291
290
def _pack_revision(self, rev):
292
291
"""Revision object -> xml tree"""
293
292
# For the XML format, we need to write them as Unicode rather than as
297
296
revision_id = rev.revision_id
298
297
if isinstance(revision_id, str):
299
298
revision_id = decode_utf8(revision_id)
299
format_num = self.format_num
300
if self.revision_format_num is not None:
301
format_num = self.revision_format_num
300
302
root = Element('revision',
301
303
committer = rev.committer,
302
304
timestamp = '%.3f' % rev.timestamp,
303
305
revision_id = revision_id,
304
306
inventory_sha1 = rev.inventory_sha1,
307
309
if rev.timezone is not None:
308
310
root.set('timezone', str(rev.timezone))
336
338
prop_elt.tail = '\n'
337
339
top_elt.tail = '\n'
339
def _unpack_inventory(self, elt, revision_id):
340
"""Construct from XML Element
342
assert elt.tag == 'inventory'
343
root_id = elt.get('file_id') or ROOT_ID
344
root_id = _get_utf8_or_ascii(root_id)
341
def _unpack_inventory(self, elt, revision_id=None):
342
"""Construct from XML Element"""
343
if elt.tag != 'inventory':
344
raise errors.UnexpectedInventoryFormat('Root tag is %r' % elt.tag)
346
345
format = elt.get('format')
347
if format is not None:
349
raise BzrError("invalid format version %r on inventory"
351
data_revision_id = elt.get('revision_id')
352
if data_revision_id is not None:
353
revision_id = cache_utf8.encode(data_revision_id)
354
inv = Inventory(root_id, revision_id=revision_id)
346
if format != self.format_num:
347
raise errors.UnexpectedInventoryFormat('Invalid format version %r'
349
revision_id = elt.get('revision_id')
350
if revision_id is not None:
351
revision_id = cache_utf8.encode(revision_id)
352
inv = inventory.Inventory(root_id=None, revision_id=revision_id)
356
354
ie = self._unpack_entry(e)
357
if ie.parent_id is None:
358
ie.parent_id = root_id
360
if revision_id is not None:
361
inv.root.revision = revision_id
356
assert inv.root.revision is not None
364
359
def _unpack_entry(self, elt):
404
399
"""XML Element -> Revision object"""
405
400
assert elt.tag == 'revision'
406
401
format = elt.get('format')
402
format_num = self.format_num
403
if self.revision_format_num is not None:
404
format_num = self.revision_format_num
407
405
if format is not None:
409
raise BzrError("invalid format version %r on inventory"
406
if format != format_num:
407
raise BzrError("invalid format version %r on revision"
411
409
get_cached = _get_utf8_or_ascii
412
410
rev = Revision(committer = elt.get('committer'),