~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/xml5.py

  • Committer: Martin Pool
  • Date: 2007-09-14 06:31:28 UTC
  • mfrom: (2822 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2823.
  • Revision ID: mbp@sourcefrog.net-20070914063128-0p7mh6zfb4pzdg9p
merge trunk

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.
152
153
 
153
154
    supported_kinds = set(['file', 'directory', 'symlink'])
154
 
 
155
 
    def write_inventory_to_string(self, inv):
156
 
        """Just call write_inventory with a StringIO and return the value"""
 
155
    format_num = '5'
 
156
 
 
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)
 
160
 
 
161
    def write_inventory_to_string(self, inv, working=False):
 
162
        """Just call write_inventory with a StringIO and return the value.
 
163
 
 
164
        :param working: If True skip history data - text_sha1, text_size,
 
165
            reference_revision, symlink_target.
 
166
        """
157
167
        sio = cStringIO.StringIO()
158
 
        self.write_inventory(inv, sio)
 
168
        self.write_inventory(inv, sio, working)
159
169
        return sio.getvalue()
160
170
 
161
 
    def write_inventory(self, inv, f):
 
171
    def write_inventory(self, inv, f, working=False):
162
172
        """Write inventory to a file.
163
173
        
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
 
176
            output).
 
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.
166
180
        """
167
181
        _ensure_utf8_re()
168
182
        output = []
172
186
        # Skip the root
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)
 
192
            else:
 
193
                parent_str = ''
 
194
                parent_id  = ''
 
195
            if ie.kind == 'file':
 
196
                if ie.executable:
 
197
                    executable = ' executable="yes"'
 
198
                else:
 
199
                    executable = ''
 
200
                if not working:
 
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,
 
206
                        ie.text_size))
 
207
                else:
 
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':
 
212
                if not working:
 
213
                    append('<directory file_id="%s name="%s%s%s revision="%s '
 
214
                        '/>\n' % (
 
215
                        _encode_and_escape(ie.file_id),
 
216
                        _encode_and_escape(ie.name),
 
217
                        parent_str, parent_id,
 
218
                        _encode_and_escape(ie.revision)))
 
219
                else:
 
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':
 
225
                if not working:
 
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)))
 
233
                else:
 
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)
 
241
                if not working:
 
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)))
 
249
                else:
 
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))
 
254
            else:
 
255
                raise errors.UnsupportedInventoryKind(ie.kind)
176
256
        append('</inventory>\n')
177
 
        f.writelines(output)
 
257
        if f is not None:
 
258
            f.writelines(output)
178
259
        # Just to keep the cache from growing without bounds
179
260
        # but we may actually not want to do clear the cache
180
261
        #_clear_cache()
 
262
        return output
181
263
 
182
264
    def _append_inventory_root(self, append, inv):
183
265
        """Append the inventory root to output."""
184
 
        append('<inventory')
185
266
        if inv.root.file_id not in (None, ROOT_ID):
186
 
            append(' file_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)
 
269
        else:
 
270
            fileid1 = ""
 
271
            fileid2 = ""
189
272
        if inv.revision_id is not None:
190
 
            append(' revision_id="')
191
 
            append(_encode_and_escape(inv.revision_id))
192
 
        append('>\n')
 
273
            revid1 = ' revision_id="'
 
274
            revid2 = _encode_and_escape(inv.revision_id)
 
275
        else:
 
276
            revid1 = ""
 
277
            revid2 = ""
 
278
        append('<inventory%s%s format="5"%s%s>\n' % (
 
279
            fileid1, fileid2, revid1, revid2))
193
280
        
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)
199
 
 
200
 
        append("<")
201
 
        append(ie.kind)
202
 
        if ie.executable:
203
 
            append(' executable="yes"')
204
 
        append(' file_id="')
205
 
        append(_encode_and_escape(ie.file_id))
206
 
        append(' name="')
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="')
220
 
            append(ie.text_sha1)
221
 
            append('"')
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))
227
 
        append(" />\n")
228
 
        return
229
 
 
230
 
    def _parent_condition(self, ie):
231
 
        return ie.parent_id != ROOT_ID
232
 
 
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