149
150
support_altered_by_hack = True
150
151
# This format supports the altered-by hack that reads file ids directly out
151
152
# of the versionedfile, without doing XML parsing.
153
154
supported_kinds = set(['file', 'directory', 'symlink'])
155
def write_inventory_to_string(self, inv):
156
"""Just call write_inventory with a StringIO and return the value"""
157
def write_inventory_to_lines(self, inv):
158
"""Return a list of lines with the encoded inventory."""
159
return self.write_inventory(inv, None)
161
def write_inventory_to_string(self, inv, working=False):
162
"""Just call write_inventory with a StringIO and return the value.
164
:param working: If True skip history data - text_sha1, text_size,
165
reference_revision, symlink_target.
157
167
sio = cStringIO.StringIO()
158
self.write_inventory(inv, sio)
168
self.write_inventory(inv, sio, working)
159
169
return sio.getvalue()
161
def write_inventory(self, inv, f):
171
def write_inventory(self, inv, f, working=False):
162
172
"""Write inventory to a file.
164
174
:param inv: the inventory to write.
165
:param f: the file to write.
175
:param f: the file to write. (May be None if the lines are the desired
177
:param working: If True skip history data - text_sha1, text_size,
178
reference_revision, symlink_target.
179
:return: The inventory as a list of lines.
167
181
_ensure_utf8_re()
173
187
root_path, root_ie = entries.next()
174
188
for path, ie in entries:
175
self._append_entry(append, ie)
189
if ie.parent_id != self.root_id:
190
parent_str = ' parent_id="'
191
parent_id = _encode_and_escape(ie.parent_id)
195
if ie.kind == 'file':
197
executable = ' executable="yes"'
201
append('<file%s file_id="%s name="%s%s%s revision="%s '
202
'text_sha1="%s" text_size="%d" />\n' % (
203
executable, _encode_and_escape(ie.file_id),
204
_encode_and_escape(ie.name), parent_str, parent_id,
205
_encode_and_escape(ie.revision), ie.text_sha1,
208
append('<file%s file_id="%s name="%s%s%s />\n' % (
209
executable, _encode_and_escape(ie.file_id),
210
_encode_and_escape(ie.name), parent_str, parent_id))
211
elif ie.kind == 'directory':
213
append('<directory file_id="%s name="%s%s%s revision="%s '
215
_encode_and_escape(ie.file_id),
216
_encode_and_escape(ie.name),
217
parent_str, parent_id,
218
_encode_and_escape(ie.revision)))
220
append('<directory file_id="%s name="%s%s%s />\n' % (
221
_encode_and_escape(ie.file_id),
222
_encode_and_escape(ie.name),
223
parent_str, parent_id))
224
elif ie.kind == 'symlink':
226
append('<symlink file_id="%s name="%s%s%s revision="%s '
227
'symlink_target="%s />\n' % (
228
_encode_and_escape(ie.file_id),
229
_encode_and_escape(ie.name),
230
parent_str, parent_id,
231
_encode_and_escape(ie.revision),
232
_encode_and_escape(ie.symlink_target)))
234
append('<symlink file_id="%s name="%s%s%s />\n' % (
235
_encode_and_escape(ie.file_id),
236
_encode_and_escape(ie.name),
237
parent_str, parent_id))
238
elif ie.kind == 'tree-reference':
239
if ie.kind not in self.supported_kinds:
240
raise errors.UnsupportedInventoryKind(ie.kind)
242
append('<tree-reference file_id="%s name="%s%s%s '
243
'revision="%s reference_revision="%s />\n' % (
244
_encode_and_escape(ie.file_id),
245
_encode_and_escape(ie.name),
246
parent_str, parent_id,
247
_encode_and_escape(ie.revision),
248
_encode_and_escape(ie.reference_revision)))
250
append('<tree-reference file_id="%s name="%s%s%s />\n' % (
251
_encode_and_escape(ie.file_id),
252
_encode_and_escape(ie.name),
253
parent_str, parent_id))
255
raise errors.UnsupportedInventoryKind(ie.kind)
176
256
append('</inventory>\n')
178
259
# Just to keep the cache from growing without bounds
179
260
# but we may actually not want to do clear the cache
182
264
def _append_inventory_root(self, append, inv):
183
265
"""Append the inventory root to output."""
185
266
if inv.root.file_id not in (None, ROOT_ID):
187
append(_encode_and_escape(inv.root.file_id))
188
append(' format="5"')
267
fileid1 = ' file_id="'
268
fileid2 = _encode_and_escape(inv.root.file_id)
189
272
if inv.revision_id is not None:
190
append(' revision_id="')
191
append(_encode_and_escape(inv.revision_id))
273
revid1 = ' revision_id="'
274
revid2 = _encode_and_escape(inv.revision_id)
278
append('<inventory%s%s format="5"%s%s>\n' % (
279
fileid1, fileid2, revid1, revid2))
194
def _append_entry(self, append, ie):
195
"""Convert InventoryEntry to XML element and append to output."""
196
# TODO: should just be a plain assertion
197
if ie.kind not in self.supported_kinds:
198
raise errors.UnsupportedInventoryKind(ie.kind)
203
append(' executable="yes"')
205
append(_encode_and_escape(ie.file_id))
207
append(_encode_and_escape(ie.name))
208
if self._parent_condition(ie):
209
assert isinstance(ie.parent_id, basestring)
210
append(' parent_id="')
211
append(_encode_and_escape(ie.parent_id))
212
if ie.revision is not None:
213
append(' revision="')
214
append(_encode_and_escape(ie.revision))
215
if ie.symlink_target is not None:
216
append(' symlink_target="')
217
append(_encode_and_escape(ie.symlink_target))
218
if ie.text_sha1 is not None:
219
append(' text_sha1="')
222
if ie.text_size is not None:
223
append(' text_size="%d"' % ie.text_size)
224
if getattr(ie, 'reference_revision', None) is not None:
225
append(' reference_revision="')
226
append(_encode_and_escape(ie.reference_revision))
230
def _parent_condition(self, ie):
231
return ie.parent_id != ROOT_ID
233
281
def _pack_revision(self, rev):
234
282
"""Revision object -> xml tree"""
235
283
# For the XML format, we need to write them as Unicode rather than as