23
22
# importing this module is fairly slow because it has to load several
25
from bzrlib.trace import mutter, warning
27
from util.cElementTree import ElementTree, SubElement, Element
28
from cElementTree import (ElementTree, SubElement, Element,
29
XMLTreeBuilder, fromstring, tostring)
28
30
except ImportError:
29
from util.elementtree.ElementTree import ElementTree, SubElement, Element
31
mutter('WARNING: using slower ElementTree; consider installing cElementTree'
32
" and make sure it's on your PYTHONPATH")
33
from util.elementtree.ElementTree import (ElementTree, SubElement,
34
Element, XMLTreeBuilder,
31
from bzrlib.inventory import ROOT_ID, Inventory, InventoryEntry
37
from bzrlib.errors import BzrError
35
40
class Serializer(object):
39
44
elt = self._pack_inventory(inv)
40
45
self._write_element(elt, f)
47
def write_inventory_to_string(self, inv):
48
return tostring(self._pack_inventory(inv)) + '\n'
50
def read_inventory_from_string(self, xml_string):
51
return self._unpack_inventory(fromstring(xml_string))
42
53
def read_inventory(self, f):
43
54
return self._unpack_inventory(self._read_element(f))
56
def write_revision(self, rev, f):
57
self._write_element(self._pack_revision(rev), f)
59
def write_revision_to_string(self, rev):
60
return tostring(self._pack_revision(rev)) + '\n'
62
def read_revision(self, f):
63
return self._unpack_revision(self._read_element(f))
65
def read_revision_from_string(self, xml_string):
66
return self._unpack_revision(fromstring(xml_string))
45
68
def _write_element(self, elt, f):
46
69
ElementTree(elt).write(f, 'utf-8')
49
72
def _read_element(self, f):
50
73
return ElementTree().parse(f)
54
class _Serializer_v4(Serializer):
55
"""Version 0.0.4 serializer"""
59
def _pack_inventory(self, inv):
60
"""Convert to XML Element"""
61
e = Element('inventory')
63
if inv.root.file_id not in (None, ROOT_ID):
64
e.set('file_id', inv.root.file_id)
65
for path, ie in inv.iter_entries():
66
e.append(self._pack_entry(ie))
70
def _pack_entry(self, ie):
71
"""Convert InventoryEntry to XML element"""
73
e.set('name', ie.name)
74
e.set('file_id', ie.file_id)
75
e.set('kind', ie.kind)
77
if ie.text_size != None:
78
e.set('text_size', '%d' % ie.text_size)
80
for f in ['text_id', 'text_sha1']:
85
# to be conservative, we don't externalize the root pointers
86
# for now, leaving them as null in the xml form. in a future
87
# version it will be implied by nested elements.
88
if ie.parent_id != ROOT_ID:
89
assert isinstance(ie.parent_id, basestring)
90
e.set('parent_id', ie.parent_id)
97
def _unpack_inventory(self, elt):
98
"""Construct from XML Element
100
assert elt.tag == 'inventory'
101
root_id = elt.get('file_id') or ROOT_ID
102
inv = Inventory(root_id)
104
ie = self._unpack_entry(e)
105
if ie.parent_id == ROOT_ID:
106
ie.parent_id = root_id
111
def _unpack_entry(self, elt):
112
assert elt.tag == 'entry'
114
## original format inventories don't have a parent_id for
115
## nodes in the root directory, but it's cleaner to use one
117
parent_id = elt.get('parent_id')
118
if parent_id == None:
121
ie = InventoryEntry(elt.get('file_id'),
125
ie.text_id = elt.get('text_id')
126
ie.text_sha1 = elt.get('text_sha1')
128
## mutter("read inventoryentry: %r" % (elt.attrib))
130
v = elt.get('text_size')
131
ie.text_size = v and int(v)
136
"""singleton instance"""
137
serializer_v4 = _Serializer_v4()
144
"""Write object o to file f as XML.
146
o must provide a to_element method.
148
ElementTree(o.to_element()).write(f, 'utf-8')
152
def unpack_xml(cls, f):
153
return cls.from_element(ElementTree().parse(f))