/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/xml5.py

Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
146
146
    
147
147
    __slots__ = []
148
148
 
 
149
    root_id = ROOT_ID
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'])
154
155
    format_num = '5'
155
156
 
156
 
    def write_inventory_to_string(self, inv):
157
 
        """Just call write_inventory with a StringIO and return the value"""
 
157
    def _check_revisions(self, inv):
 
158
        """Extension point for subclasses to check during serialisation.
 
159
 
 
160
        By default no checking is done.
 
161
 
 
162
        :param inv: An inventory about to be serialised, to be checked.
 
163
        :raises: AssertionError if an error has occured.
 
164
        """
 
165
 
 
166
    def write_inventory_to_lines(self, inv):
 
167
        """Return a list of lines with the encoded inventory."""
 
168
        return self.write_inventory(inv, None)
 
169
 
 
170
    def write_inventory_to_string(self, inv, working=False):
 
171
        """Just call write_inventory with a StringIO and return the value.
 
172
 
 
173
        :param working: If True skip history data - text_sha1, text_size,
 
174
            reference_revision, symlink_target.
 
175
        """
158
176
        sio = cStringIO.StringIO()
159
 
        self.write_inventory(inv, sio)
 
177
        self.write_inventory(inv, sio, working)
160
178
        return sio.getvalue()
161
179
 
162
 
    def write_inventory(self, inv, f):
 
180
    def write_inventory(self, inv, f, working=False):
163
181
        """Write inventory to a file.
164
182
        
165
183
        :param inv: the inventory to write.
166
 
        :param f: the file to write.
 
184
        :param f: the file to write. (May be None if the lines are the desired
 
185
            output).
 
186
        :param working: If True skip history data - text_sha1, text_size,
 
187
            reference_revision, symlink_target.
 
188
        :return: The inventory as a list of lines.
167
189
        """
168
190
        _ensure_utf8_re()
 
191
        self._check_revisions(inv)
169
192
        output = []
170
193
        append = output.append
171
194
        self._append_inventory_root(append, inv)
173
196
        # Skip the root
174
197
        root_path, root_ie = entries.next()
175
198
        for path, ie in entries:
176
 
            self._append_entry(append, ie)
 
199
            if ie.parent_id != self.root_id:
 
200
                parent_str = ' parent_id="'
 
201
                parent_id  = _encode_and_escape(ie.parent_id)
 
202
            else:
 
203
                parent_str = ''
 
204
                parent_id  = ''
 
205
            if ie.kind == 'file':
 
206
                if ie.executable:
 
207
                    executable = ' executable="yes"'
 
208
                else:
 
209
                    executable = ''
 
210
                if not working:
 
211
                    append('<file%s file_id="%s name="%s%s%s revision="%s '
 
212
                        'text_sha1="%s" text_size="%d" />\n' % (
 
213
                        executable, _encode_and_escape(ie.file_id),
 
214
                        _encode_and_escape(ie.name), parent_str, parent_id,
 
215
                        _encode_and_escape(ie.revision), ie.text_sha1,
 
216
                        ie.text_size))
 
217
                else:
 
218
                    append('<file%s file_id="%s name="%s%s%s />\n' % (
 
219
                        executable, _encode_and_escape(ie.file_id),
 
220
                        _encode_and_escape(ie.name), parent_str, parent_id))
 
221
            elif ie.kind == 'directory':
 
222
                if not working:
 
223
                    append('<directory file_id="%s name="%s%s%s revision="%s '
 
224
                        '/>\n' % (
 
225
                        _encode_and_escape(ie.file_id),
 
226
                        _encode_and_escape(ie.name),
 
227
                        parent_str, parent_id,
 
228
                        _encode_and_escape(ie.revision)))
 
229
                else:
 
230
                    append('<directory file_id="%s name="%s%s%s />\n' % (
 
231
                        _encode_and_escape(ie.file_id),
 
232
                        _encode_and_escape(ie.name),
 
233
                        parent_str, parent_id))
 
234
            elif ie.kind == 'symlink':
 
235
                if not working:
 
236
                    append('<symlink file_id="%s name="%s%s%s revision="%s '
 
237
                        'symlink_target="%s />\n' % (
 
238
                        _encode_and_escape(ie.file_id),
 
239
                        _encode_and_escape(ie.name),
 
240
                        parent_str, parent_id,
 
241
                        _encode_and_escape(ie.revision),
 
242
                        _encode_and_escape(ie.symlink_target)))
 
243
                else:
 
244
                    append('<symlink file_id="%s name="%s%s%s />\n' % (
 
245
                        _encode_and_escape(ie.file_id),
 
246
                        _encode_and_escape(ie.name),
 
247
                        parent_str, parent_id))
 
248
            elif ie.kind == 'tree-reference':
 
249
                if ie.kind not in self.supported_kinds:
 
250
                    raise errors.UnsupportedInventoryKind(ie.kind)
 
251
                if not working:
 
252
                    append('<tree-reference file_id="%s name="%s%s%s '
 
253
                        'revision="%s reference_revision="%s />\n' % (
 
254
                        _encode_and_escape(ie.file_id),
 
255
                        _encode_and_escape(ie.name),
 
256
                        parent_str, parent_id,
 
257
                        _encode_and_escape(ie.revision),
 
258
                        _encode_and_escape(ie.reference_revision)))
 
259
                else:
 
260
                    append('<tree-reference file_id="%s name="%s%s%s />\n' % (
 
261
                        _encode_and_escape(ie.file_id),
 
262
                        _encode_and_escape(ie.name),
 
263
                        parent_str, parent_id))
 
264
            else:
 
265
                raise errors.UnsupportedInventoryKind(ie.kind)
177
266
        append('</inventory>\n')
178
 
        f.writelines(output)
 
267
        if f is not None:
 
268
            f.writelines(output)
179
269
        # Just to keep the cache from growing without bounds
180
270
        # but we may actually not want to do clear the cache
181
271
        #_clear_cache()
 
272
        return output
182
273
 
183
274
    def _append_inventory_root(self, append, inv):
184
275
        """Append the inventory root to output."""
185
 
        append('<inventory')
186
276
        if inv.root.file_id not in (None, ROOT_ID):
187
 
            append(' file_id="')
188
 
            append(_encode_and_escape(inv.root.file_id))
189
 
        append(' format="5"')
 
277
            fileid1 = ' file_id="'
 
278
            fileid2 = _encode_and_escape(inv.root.file_id)
 
279
        else:
 
280
            fileid1 = ""
 
281
            fileid2 = ""
190
282
        if inv.revision_id is not None:
191
 
            append(' revision_id="')
192
 
            append(_encode_and_escape(inv.revision_id))
193
 
        append('>\n')
 
283
            revid1 = ' revision_id="'
 
284
            revid2 = _encode_and_escape(inv.revision_id)
 
285
        else:
 
286
            revid1 = ""
 
287
            revid2 = ""
 
288
        append('<inventory%s%s format="5"%s%s>\n' % (
 
289
            fileid1, fileid2, revid1, revid2))
194
290
        
195
 
    def _append_entry(self, append, ie):
196
 
        """Convert InventoryEntry to XML element and append to output."""
197
 
        # TODO: should just be a plain assertion
198
 
        if ie.kind not in self.supported_kinds:
199
 
            raise errors.UnsupportedInventoryKind(ie.kind)
200
 
 
201
 
        append("<")
202
 
        append(ie.kind)
203
 
        if ie.executable:
204
 
            append(' executable="yes"')
205
 
        append(' file_id="')
206
 
        append(_encode_and_escape(ie.file_id))
207
 
        append(' name="')
208
 
        append(_encode_and_escape(ie.name))
209
 
        if self._parent_condition(ie):
210
 
            assert isinstance(ie.parent_id, basestring)
211
 
            append(' parent_id="')
212
 
            append(_encode_and_escape(ie.parent_id))
213
 
        if ie.revision is not None:
214
 
            append(' revision="')
215
 
            append(_encode_and_escape(ie.revision))
216
 
        if ie.symlink_target is not None:
217
 
            append(' symlink_target="')
218
 
            append(_encode_and_escape(ie.symlink_target))
219
 
        if ie.text_sha1 is not None:
220
 
            append(' text_sha1="')
221
 
            append(ie.text_sha1)
222
 
            append('"')
223
 
        if ie.text_size is not None:
224
 
            append(' text_size="%d"' % ie.text_size)
225
 
        if getattr(ie, 'reference_revision', None) is not None:
226
 
            append(' reference_revision="')
227
 
            append(_encode_and_escape(ie.reference_revision))
228
 
        append(" />\n")
229
 
        return
230
 
 
231
 
    def _parent_condition(self, ie):
232
 
        return ie.parent_id != ROOT_ID
233
 
 
234
291
    def _pack_revision(self, rev):
235
292
        """Revision object -> xml tree"""
236
293
        # For the XML format, we need to write them as Unicode rather than as
279
336
            prop_elt.tail = '\n'
280
337
        top_elt.tail = '\n'
281
338
 
282
 
    def _unpack_inventory(self, elt):
 
339
    def _unpack_inventory(self, elt, revision_id):
283
340
        """Construct from XML Element
284
341
        """
285
342
        assert elt.tag == 'inventory'
300
357
            if ie.parent_id is None:
301
358
                ie.parent_id = root_id
302
359
            inv.add(ie)
 
360
        if revision_id is not None:
 
361
            inv.root.revision = revision_id
303
362
        return inv
304
363
 
305
364
    def _unpack_entry(self, elt):