22
22
# importing this module is fairly slow because it has to load several
25
from bzrlib.trace import mutter, warning
26
from util.cElementTree import ElementTree, SubElement, Element
28
from cElementTree import (ElementTree, SubElement, Element,
29
XMLTreeBuilder, fromstring, tostring)
27
30
except ImportError:
28
from util.elementtree.ElementTree import ElementTree, SubElement, Element
31
## from warnings import warn
32
## warn('using slower ElementTree; consider installing cElementTree')
33
from util.elementtree.ElementTree import (ElementTree, SubElement,
34
Element, XMLTreeBuilder,
30
37
from bzrlib.inventory import ROOT_ID, Inventory, InventoryEntry
31
from bzrlib.revision import Revision, RevisionReference
32
38
from bzrlib.errors import BzrError
39
45
elt = self._pack_inventory(inv)
40
46
self._write_element(elt, f)
48
def write_inventory_to_string(self, inv):
49
return tostring(self._pack_inventory(inv))
51
def read_inventory_from_string(self, xml_string):
52
return self._unpack_inventory(fromstring(xml_string))
42
54
def read_inventory(self, f):
43
55
return self._unpack_inventory(self._read_element(f))
45
57
def write_revision(self, rev, f):
46
58
self._write_element(self._pack_revision(rev), f)
60
def write_revision_to_string(self, rev):
61
return tostring(self._pack_revision(rev), f)
48
63
def read_revision(self, f):
49
64
return self._unpack_revision(self._read_element(f))
66
def read_revision_from_string(self, xml_string):
67
return self._unpack_revision(fromstring(xml_string))
51
69
def _write_element(self, elt, f):
52
70
ElementTree(elt).write(f, 'utf-8')
55
73
def _read_element(self, f):
56
74
return ElementTree().parse(f)
60
class _Serializer_v4(Serializer):
61
"""Version 0.0.4 serializer
63
You should use the serialzer_v4 singleton."""
67
def _pack_inventory(self, inv):
68
"""Convert to XML Element"""
69
e = Element('inventory')
71
if inv.root.file_id not in (None, ROOT_ID):
72
e.set('file_id', inv.root.file_id)
73
for path, ie in inv.iter_entries():
74
e.append(self._pack_entry(ie))
78
def _pack_entry(self, ie):
79
"""Convert InventoryEntry to XML element"""
81
e.set('name', ie.name)
82
e.set('file_id', ie.file_id)
83
e.set('kind', ie.kind)
85
if ie.text_size != None:
86
e.set('text_size', '%d' % ie.text_size)
88
for f in ['text_id', 'text_sha1']:
93
# to be conservative, we don't externalize the root pointers
94
# for now, leaving them as null in the xml form. in a future
95
# version it will be implied by nested elements.
96
if ie.parent_id != ROOT_ID:
97
assert isinstance(ie.parent_id, basestring)
98
e.set('parent_id', ie.parent_id)
105
def _unpack_inventory(self, elt):
106
"""Construct from XML Element
108
assert elt.tag == 'inventory'
109
root_id = elt.get('file_id') or ROOT_ID
110
inv = Inventory(root_id)
112
ie = self._unpack_entry(e)
113
if ie.parent_id == ROOT_ID:
114
ie.parent_id = root_id
119
def _unpack_entry(self, elt):
120
assert elt.tag == 'entry'
122
## original format inventories don't have a parent_id for
123
## nodes in the root directory, but it's cleaner to use one
125
parent_id = elt.get('parent_id')
126
if parent_id == None:
129
ie = InventoryEntry(elt.get('file_id'),
133
ie.text_id = elt.get('text_id')
134
ie.text_sha1 = elt.get('text_sha1')
136
## mutter("read inventoryentry: %r" % (elt.attrib))
138
v = elt.get('text_size')
139
ie.text_size = v and int(v)
144
def _pack_revision(self, rev):
145
"""Revision object -> xml tree"""
146
root = Element('revision',
147
committer = rev.committer,
148
timestamp = '%.9f' % rev.timestamp,
149
revision_id = rev.revision_id,
150
inventory_id = rev.inventory_id,
151
inventory_sha1 = rev.inventory_sha1,
154
root.set('timezone', str(rev.timezone))
157
msg = SubElement(root, 'message')
158
msg.text = rev.message
162
pelts = SubElement(root, 'parents')
163
pelts.tail = pelts.text = '\n'
164
for rr in rev.parents:
165
assert isinstance(rr, RevisionReference)
166
p = SubElement(pelts, 'revision_ref')
168
assert rr.revision_id
169
p.set('revision_id', rr.revision_id)
171
p.set('revision_sha1', rr.revision_sha1)
176
def _unpack_revision(self, elt):
177
"""XML Element -> Revision object"""
179
# <changeset> is deprecated...
180
if elt.tag not in ('revision', 'changeset'):
181
raise BzrError("unexpected tag in revision file: %r" % elt)
183
rev = Revision(committer = elt.get('committer'),
184
timestamp = float(elt.get('timestamp')),
185
revision_id = elt.get('revision_id'),
186
inventory_id = elt.get('inventory_id'),
187
inventory_sha1 = elt.get('inventory_sha1')
190
precursor = elt.get('precursor')
191
precursor_sha1 = elt.get('precursor_sha1')
193
pelts = elt.find('parents')
197
assert p.tag == 'revision_ref', \
198
"bad parent node tag %r" % p.tag
199
rev_ref = RevisionReference(p.get('revision_id'),
200
p.get('revision_sha1'))
201
rev.parents.append(rev_ref)
205
prec_parent = rev.parents[0].revision_id
206
assert prec_parent == precursor
208
# revisions written prior to 0.0.5 have a single precursor
209
# give as an attribute
210
rev_ref = RevisionReference(precursor, precursor_sha1)
211
rev.parents.append(rev_ref)
213
v = elt.get('timezone')
214
rev.timezone = v and int(v)
216
rev.message = elt.findtext('message') # text of <message>
222
"""singleton instance"""
223
serializer_v4 = _Serializer_v4()