/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 brzlib/xml8.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from io import BytesIO
18
 
 
19
 
from .. import (
 
17
from __future__ import absolute_import
 
18
 
 
19
import cStringIO
 
20
 
 
21
from brzlib import (
20
22
    cache_utf8,
21
23
    lazy_regex,
22
24
    revision as _mod_revision,
23
25
    trace,
24
26
    )
25
 
from .xml_serializer import (
 
27
from brzlib.xml_serializer import (
26
28
    Element,
27
29
    SubElement,
28
30
    XMLSerializer,
33
35
    unpack_inventory_entry,
34
36
    unpack_inventory_flat,
35
37
    )
36
 
from ..revision import Revision
37
 
from ..errors import BzrError
 
38
from brzlib.revision import Revision
 
39
from brzlib.errors import BzrError
38
40
 
39
41
 
40
42
_xml_unescape_map = {
41
 
    b'apos': b"'",
42
 
    b'quot': b'"',
43
 
    b'amp': b'&',
44
 
    b'lt': b'<',
45
 
    b'gt': b'>'
 
43
    'apos':"'",
 
44
    'quot':'"',
 
45
    'amp':'&',
 
46
    'lt':'<',
 
47
    'gt':'>'
46
48
}
47
49
 
48
50
 
51
53
    try:
52
54
        return _map[code]
53
55
    except KeyError:
54
 
        if not code.startswith(b'#'):
 
56
        if not code.startswith('#'):
55
57
            raise
56
 
        return chr(int(code[1:])).encode('utf8')
57
 
 
58
 
 
59
 
_unescape_re = lazy_regex.lazy_compile(b'\\&([^;]*);')
60
 
 
 
58
        return unichr(int(code[1:])).encode('utf8')
 
59
 
 
60
 
 
61
_unescape_re = lazy_regex.lazy_compile('\&([^;]*);')
61
62
 
62
63
def _unescape_xml(data):
63
64
    """Unescape predefined XML entities in a string of data."""
77
78
    # This format supports the altered-by hack that reads file ids directly out
78
79
    # of the versionedfile, without doing XML parsing.
79
80
 
80
 
    supported_kinds = {'file', 'directory', 'symlink'}
81
 
    format_num = b'8'
 
81
    supported_kinds = set(['file', 'directory', 'symlink'])
 
82
    format_num = '8'
82
83
    revision_format_num = None
83
84
 
84
85
    # The search regex used by xml based repositories to determine what things
85
86
    # where changed in a single commit.
86
87
    _file_ids_altered_regex = lazy_regex.lazy_compile(
87
 
        b'file_id="(?P<file_id>[^"]+)"'
88
 
        b'.* revision="(?P<revision_id>[^"]+)"'
 
88
        r'file_id="(?P<file_id>[^"]+)"'
 
89
        r'.* revision="(?P<revision_id>[^"]+)"'
89
90
        )
90
91
 
91
92
    def _check_revisions(self, inv):
131
132
        """Return a list of lines with the encoded inventory."""
132
133
        return self.write_inventory(inv, None)
133
134
 
134
 
    def write_inventory_to_chunks(self, inv):
135
 
        return self.write_inventory(inv, None)
 
135
    def write_inventory_to_string(self, inv, working=False):
 
136
        """Just call write_inventory with a StringIO and return the value.
 
137
 
 
138
        :param working: If True skip history data - text_sha1, text_size,
 
139
            reference_revision, symlink_target.
 
140
        """
 
141
        sio = cStringIO.StringIO()
 
142
        self.write_inventory(inv, sio, working)
 
143
        return sio.getvalue()
136
144
 
137
145
    def write_inventory(self, inv, f, working=False):
138
146
        """Write inventory to a file.
148
156
        append = output.append
149
157
        self._append_inventory_root(append, inv)
150
158
        serialize_inventory_flat(inv, append,
151
 
                                 self.root_id, self.supported_kinds, working)
 
159
            self.root_id, self.supported_kinds, working)
152
160
        if f is not None:
153
161
            f.writelines(output)
154
162
        # Just to keep the cache from growing without bounds
155
163
        # but we may actually not want to do clear the cache
156
 
        # _clear_cache()
 
164
        #_clear_cache()
157
165
        return output
158
166
 
159
167
    def _append_inventory_root(self, append, inv):
160
168
        """Append the inventory root to output."""
161
169
        if inv.revision_id is not None:
162
 
            revid1 = b''.join(
163
 
                [b' revision_id="', encode_and_escape(inv.revision_id), b'"'])
 
170
            revid1 = ' revision_id="'
 
171
            revid2 = encode_and_escape(inv.revision_id)
164
172
        else:
165
 
            revid1 = b""
166
 
        append(b'<inventory format="%s"%s>\n' % (
167
 
            self.format_num, revid1))
168
 
        append(b'<directory file_id="%s" name="%s" revision="%s" />\n' % (
 
173
            revid1 = ""
 
174
            revid2 = ""
 
175
        append('<inventory format="%s"%s%s>\n' % (
 
176
            self.format_num, revid1, revid2))
 
177
        append('<directory file_id="%s name="%s revision="%s />\n' % (
169
178
            encode_and_escape(inv.root.file_id),
170
179
            encode_and_escape(inv.root.name),
171
180
            encode_and_escape(inv.root.revision)))
172
181
 
173
 
    def write_revision_to_lines(self, rev):
 
182
    def _pack_revision(self, rev):
174
183
        """Revision object -> xml tree"""
175
184
        # For the XML format, we need to write them as Unicode rather than as
176
185
        # utf-8 strings. So that cElementTree can handle properly escaping
177
186
        # them.
178
 
        lines = []
179
 
        el = (b'<revision committer="%s" format="%s" '
180
 
              b'inventory_sha1="%s" revision_id="%s" '
181
 
              b'timestamp="%.3f"' % (
182
 
                  encode_and_escape(rev.committer),
183
 
                  self.revision_format_num or self.format_num,
184
 
                  rev.inventory_sha1,
185
 
                  encode_and_escape(cache_utf8.decode(rev.revision_id)),
186
 
                  rev.timestamp))
 
187
        decode_utf8 = cache_utf8.decode
 
188
        revision_id = rev.revision_id
 
189
        if isinstance(revision_id, str):
 
190
            revision_id = decode_utf8(revision_id)
 
191
        format_num = self.format_num
 
192
        if self.revision_format_num is not None:
 
193
            format_num = self.revision_format_num
 
194
        root = Element('revision',
 
195
                       committer = rev.committer,
 
196
                       timestamp = '%.3f' % rev.timestamp,
 
197
                       revision_id = revision_id,
 
198
                       inventory_sha1 = rev.inventory_sha1,
 
199
                       format=format_num,
 
200
                       )
187
201
        if rev.timezone is not None:
188
 
            el += b' timezone="%s"' % str(rev.timezone).encode('ascii')
189
 
        lines.append(el + b'>\n')
190
 
        message = encode_and_escape(escape_invalid_chars(rev.message)[0])
191
 
        lines.extend((b'<message>' + message + b'</message>\n').splitlines(True))
 
202
            root.set('timezone', str(rev.timezone))
 
203
        root.text = '\n'
 
204
        msg = SubElement(root, 'message')
 
205
        msg.text = escape_invalid_chars(rev.message)[0]
 
206
        msg.tail = '\n'
192
207
        if rev.parent_ids:
193
 
            lines.append(b'<parents>\n')
 
208
            pelts = SubElement(root, 'parents')
 
209
            pelts.tail = pelts.text = '\n'
194
210
            for parent_id in rev.parent_ids:
195
211
                _mod_revision.check_not_reserved_id(parent_id)
196
 
                lines.append(
197
 
                    b'<revision_ref revision_id="%s" />\n'
198
 
                    % encode_and_escape(cache_utf8.decode(parent_id)))
199
 
            lines.append(b'</parents>\n')
 
212
                p = SubElement(pelts, 'revision_ref')
 
213
                p.tail = '\n'
 
214
                if isinstance(parent_id, str):
 
215
                    parent_id = decode_utf8(parent_id)
 
216
                p.set('revision_id', parent_id)
200
217
        if rev.properties:
201
 
            preamble = b'<properties>'
202
 
            for prop_name, prop_value in sorted(rev.properties.items()):
203
 
                if prop_value:
204
 
                    proplines = (preamble + b'<property name="%s">%s</property>\n' % (
205
 
                        encode_and_escape(prop_name),
206
 
                        encode_and_escape(escape_invalid_chars(prop_value)[0]))).splitlines(True)
207
 
                else:
208
 
                    proplines = [preamble + b'<property name="%s" />\n' % (encode_and_escape(prop_name), )]
209
 
                preamble = b''
210
 
                lines.extend(proplines)
211
 
            lines.append(b'</properties>\n')
212
 
        lines.append(b'</revision>\n')
213
 
        return lines
 
218
            self._pack_revision_properties(rev, root)
 
219
        return root
 
220
 
 
221
    def _pack_revision_properties(self, rev, under_element):
 
222
        top_elt = SubElement(under_element, 'properties')
 
223
        for prop_name, prop_value in sorted(rev.properties.items()):
 
224
            prop_elt = SubElement(top_elt, 'property')
 
225
            prop_elt.set('name', prop_name)
 
226
            prop_elt.text = prop_value
 
227
            prop_elt.tail = '\n'
 
228
        top_elt.tail = '\n'
214
229
 
215
230
    def _unpack_entry(self, elt, entry_cache=None, return_from_cache=False):
216
231
        # This is here because it's overridden by xml7
217
232
        return unpack_inventory_entry(elt, entry_cache,
218
 
                                      return_from_cache)
 
233
                return_from_cache)
219
234
 
220
235
    def _unpack_inventory(self, elt, revision_id=None, entry_cache=None,
221
236
                          return_from_cache=False):
222
237
        """Construct from XML Element"""
223
238
        inv = unpack_inventory_flat(elt, self.format_num, self._unpack_entry,
224
 
                                    entry_cache, return_from_cache)
 
239
            entry_cache, return_from_cache)
225
240
        self._check_cache_size(len(inv), entry_cache)
226
241
        return inv
227
242
 
232
247
        if self.revision_format_num is not None:
233
248
            format_num = self.revision_format_num
234
249
        if format is not None:
235
 
            if format.encode() != format_num:
 
250
            if format != format_num:
236
251
                raise BzrError("invalid format version %r on revision"
237
 
                               % format)
 
252
                                % format)
238
253
        get_cached = get_utf8_or_ascii
239
 
        rev = Revision(committer=elt.get('committer'),
240
 
                       timestamp=float(elt.get('timestamp')),
241
 
                       revision_id=get_cached(elt.get('revision_id')),
242
 
                       inventory_sha1=elt.get('inventory_sha1').encode('ascii')
 
254
        rev = Revision(committer = elt.get('committer'),
 
255
                       timestamp = float(elt.get('timestamp')),
 
256
                       revision_id = get_cached(elt.get('revision_id')),
 
257
                       inventory_sha1 = elt.get('inventory_sha1')
243
258
                       )
244
259
        parents = elt.find('parents') or []
245
260
        for p in parents:
250
265
            rev.timezone = 0
251
266
        else:
252
267
            rev.timezone = int(v)
253
 
        rev.message = elt.findtext('message')  # text of <message>
 
268
        rev.message = elt.findtext('message') # text of <message>
254
269
        return rev
255
270
 
256
271
    def _unpack_revision_properties(self, elt, rev):
257
272
        """Unpack properties onto a revision."""
258
273
        props_elt = elt.find('properties')
259
 
        if props_elt is None:
 
274
        if not props_elt:
260
275
            return
261
276
        for prop_elt in props_elt:
262
277
            if prop_elt.tag != 'property':