~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/xml5.py

  • Committer: John Arbash Meinel
  • Date: 2006-08-16 20:55:23 UTC
  • mto: This revision was merged to the branch mainline in revision 1942.
  • Revision ID: john@arbash-meinel.com-20060816205523-b8df51cb552b5a7e
[merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
 
17
import cStringIO
17
18
 
18
19
from bzrlib import (
19
20
    cache_utf8,
 
21
    inventory,
20
22
    )
21
23
from bzrlib.xml_serializer import SubElement, Element, Serializer
22
24
from bzrlib.inventory import ROOT_ID, Inventory, InventoryEntry
23
 
import bzrlib.inventory as inventory
24
25
from bzrlib.revision import Revision
25
26
from bzrlib.errors import BzrError
26
27
 
31
32
    Packs objects into XML and vice versa.
32
33
    """
33
34
    
34
 
    __slots__ = []
 
35
    __slots__ = ['_utf8_re']
 
36
 
 
37
    def __init__(self):
 
38
        self._utf8_re = None
35
39
    
 
40
    def write_inventory_to_string(self, inv):
 
41
        sio = cStringIO.StringIO()
 
42
        self.write_inventory(inv, sio)
 
43
        return sio.getvalue()
 
44
 
 
45
    def write_inventory(self, inv, f):
 
46
        """Write inventory to a file.
 
47
        
 
48
        :param inv: the inventory to write.
 
49
        :param f: the file to write.
 
50
        """
 
51
        output = []
 
52
        self._append_inventory_root(output, inv)
 
53
        entries = inv.iter_entries()
 
54
        root_path, root_ie = entries.next()
 
55
        for path, ie in entries:
 
56
            self._append_entry(output, ie)
 
57
        f.write(''.join(output))
 
58
#        elt = self._pack_inventory(inv)
 
59
#        for child in elt.getchildren():
 
60
#            if isinstance(child, inventory.InventoryDirectory):
 
61
#                print "foo\nbar\n"
 
62
#            print child
 
63
#            ElementTree(child).write(f, 'utf-8')
 
64
        f.write('</inventory>\n')
 
65
 
 
66
    def _append_inventory_root(self, output, inv):
 
67
        """Append the inventory root to output."""
 
68
        output.append('<inventory')
 
69
        if inv.root.file_id not in (None, ROOT_ID):
 
70
            output.append(' file_id="')
 
71
            self._append_utf8_escaped(output, inv.root.file_id)
 
72
        output.append(' format="5"')
 
73
        if inv.revision_id is not None:
 
74
            output.append(' revision_id="')
 
75
            self._append_utf8_escaped(output, inv.revision_id)
 
76
        output.append('>\n')
 
77
        
 
78
    def _append_entry(self, output, ie):
 
79
        """Convert InventoryEntry to XML element and append to output."""
 
80
        # TODO: should just be a plain assertion
 
81
        assert InventoryEntry.versionable_kind(ie.kind), \
 
82
            'unsupported entry kind %s' % ie.kind
 
83
 
 
84
        output.append("<")
 
85
        output.append(ie.kind)
 
86
        if ie.executable:
 
87
            output.append(' executable="yes"')
 
88
        output.append(' file_id="')
 
89
        self._append_utf8_escaped(output, ie.file_id)
 
90
        output.append(' name="')
 
91
        self._append_utf8_escaped(output, ie.name)
 
92
        if ie.parent_id != ROOT_ID:
 
93
            assert isinstance(ie.parent_id, basestring)
 
94
            output.append(' parent_id="')
 
95
            self._append_utf8_escaped(output, ie.parent_id)
 
96
        if ie.revision is not None:
 
97
            output.append(' revision="')
 
98
            self._append_utf8_escaped(output, ie.revision)
 
99
        if ie.symlink_target is not None:
 
100
            output.append(' symlink_target="')
 
101
            self._append_utf8_escaped(output, ie.symlink_target)
 
102
        if ie.text_sha1 is not None:
 
103
            output.append(' text_size="')
 
104
            output.append(ie.text_sha1)
 
105
            output.append('"')
 
106
        if ie.text_size is not None:
 
107
            output.append(' text_size="%d"' % ie.text_size)
 
108
        output.append(" />\n")
 
109
        return
 
110
 
 
111
    def _append_utf8_escaped(self, output, a_string):
 
112
        """Append a_string to output as utf8."""
 
113
        if self._utf8_re is None:
 
114
            import re
 
115
            self._utf8_re = re.compile("[&'\"<>]")
 
116
        # escape attribute value
 
117
        text = a_string.encode('utf8')
 
118
        output.append(self._utf8_re.sub(self._utf8_escape_replace, text))
 
119
        output.append('"')
 
120
 
 
121
    _utf8_escape_map = {
 
122
        "&":'&amp;',
 
123
        "'":"&apos;", # FIXME: overkill
 
124
        "\"":"&quot;",
 
125
        "<":"&lt;",
 
126
        ">":"&gt;",
 
127
        }
 
128
    def _utf8_escape_replace(self, match, map=_utf8_escape_map):
 
129
        return map[match.group()]
 
130
 
36
131
    def _pack_inventory(self, inv):
37
132
        """Convert to XML Element"""
38
133
        entries = inv.iter_entries()