~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/xml4.py

  • Committer: John Arbash Meinel
  • Date: 2007-03-15 22:35:35 UTC
  • mto: This revision was merged to the branch mainline in revision 2363.
  • Revision ID: john@arbash-meinel.com-20070315223535-d3d4964oe1hc8zhg
Add an overzealous test, for Unicode support of _iter_changes.
For both knowns and unknowns.
And include a basic, if suboptimal, fix.
I would rather defer the decoding until we've determined that we are going to return the tuple.
There is still something broken with added files, but I'll get to that.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
from bzrlib.xml_serializer import ElementTree, SubElement, Element, Serializer
 
18
from bzrlib.inventory import ROOT_ID, Inventory, InventoryEntry
 
19
import bzrlib.inventory as inventory
 
20
from bzrlib.revision import Revision        
 
21
from bzrlib.errors import BzrError
 
22
 
 
23
 
 
24
class _Serializer_v4(Serializer):
 
25
    """Version 0.0.4 serializer
 
26
 
 
27
    You should use the serializer_v4 singleton."""
 
28
    
 
29
    __slots__ = []
 
30
    
 
31
    def _pack_inventory(self, inv):
 
32
        """Convert to XML Element"""
 
33
        # v4 serialization is not used any more.
 
34
        raise NotImplementedError(self._pack_inventory)
 
35
        e = Element('inventory')
 
36
        e.text = '\n'
 
37
        if inv.root.file_id not in (None, ROOT_ID):
 
38
            e.set('file_id', inv.root.file_id)
 
39
        for path, ie in inv.iter_entries():
 
40
            e.append(self._pack_entry(ie))
 
41
        return e
 
42
 
 
43
 
 
44
    def _pack_entry(self, ie):
 
45
        """Convert InventoryEntry to XML element"""
 
46
        e = Element('entry')
 
47
        e.set('name', ie.name)
 
48
        e.set('file_id', ie.file_id)
 
49
        e.set('kind', ie.kind)
 
50
 
 
51
        if ie.text_size is not None:
 
52
            e.set('text_size', '%d' % ie.text_size)
 
53
 
 
54
        for f in ['text_id', 'text_sha1', 'symlink_target']:
 
55
            v = getattr(ie, f)
 
56
            if v is not None:
 
57
                e.set(f, v)
 
58
 
 
59
        # to be conservative, we don't externalize the root pointers
 
60
        # for now, leaving them as null in the xml form.  in a future
 
61
        # version it will be implied by nested elements.
 
62
        if ie.parent_id != ROOT_ID:
 
63
            assert isinstance(ie.parent_id, basestring)
 
64
            e.set('parent_id', ie.parent_id)
 
65
 
 
66
        e.tail = '\n'
 
67
 
 
68
        return e
 
69
 
 
70
 
 
71
    def _unpack_inventory(self, elt):
 
72
        """Construct from XML Element
 
73
        """
 
74
        assert elt.tag == 'inventory'
 
75
        root_id = elt.get('file_id') or ROOT_ID
 
76
        inv = Inventory(root_id)
 
77
        for e in elt:
 
78
            ie = self._unpack_entry(e)
 
79
            if ie.parent_id == ROOT_ID:
 
80
                ie.parent_id = root_id
 
81
            inv.add(ie)
 
82
        return inv
 
83
 
 
84
 
 
85
    def _unpack_entry(self, elt):
 
86
        assert elt.tag == 'entry'
 
87
 
 
88
        ## original format inventories don't have a parent_id for
 
89
        ## nodes in the root directory, but it's cleaner to use one
 
90
        ## internally.
 
91
        parent_id = elt.get('parent_id')
 
92
        if parent_id is None:
 
93
            parent_id = ROOT_ID
 
94
 
 
95
        kind = elt.get('kind')
 
96
        if kind == 'directory':
 
97
            ie = inventory.InventoryDirectory(elt.get('file_id'),
 
98
                                              elt.get('name'),
 
99
                                              parent_id)
 
100
        elif kind == 'file':
 
101
            ie = inventory.InventoryFile(elt.get('file_id'),
 
102
                                         elt.get('name'),
 
103
                                         parent_id)
 
104
            ie.text_id = elt.get('text_id')
 
105
            ie.text_sha1 = elt.get('text_sha1')
 
106
            v = elt.get('text_size')
 
107
            ie.text_size = v and int(v)
 
108
        elif kind == 'symlink':
 
109
            ie = inventory.InventoryLink(elt.get('file_id'),
 
110
                                         elt.get('name'),
 
111
                                         parent_id)
 
112
            ie.symlink_target = elt.get('symlink_target')
 
113
        else:
 
114
            raise BzrError("unknown kind %r" % kind)
 
115
 
 
116
        ## mutter("read inventoryentry: %r", elt.attrib)
 
117
 
 
118
        return ie
 
119
 
 
120
 
 
121
    def _pack_revision(self, rev):
 
122
        """Revision object -> xml tree"""
 
123
        root = Element('revision',
 
124
                       committer = rev.committer,
 
125
                       timestamp = '%.9f' % rev.timestamp,
 
126
                       revision_id = rev.revision_id,
 
127
                       inventory_id = rev.inventory_id,
 
128
                       inventory_sha1 = rev.inventory_sha1,
 
129
                       )
 
130
        if rev.timezone:
 
131
            root.set('timezone', str(rev.timezone))
 
132
        root.text = '\n'
 
133
 
 
134
        msg = SubElement(root, 'message')
 
135
        msg.text = rev.message
 
136
        msg.tail = '\n'
 
137
 
 
138
        if rev.parents:
 
139
            pelts = SubElement(root, 'parents')
 
140
            pelts.tail = pelts.text = '\n'
 
141
            for i, parent_id in enumerate(rev.parents):
 
142
                p = SubElement(pelts, 'revision_ref')
 
143
                p.tail = '\n'
 
144
                assert parent_id
 
145
                p.set('revision_id', parent_id)
 
146
                if i < len(rev.parent_sha1s):
 
147
                    p.set('revision_sha1', rev.parent_sha1s[i])
 
148
        return root
 
149
 
 
150
    
 
151
    def _unpack_revision(self, elt):
 
152
        """XML Element -> Revision object"""
 
153
        
 
154
        # <changeset> is deprecated...
 
155
        if elt.tag not in ('revision', 'changeset'):
 
156
            raise BzrError("unexpected tag in revision file: %r" % elt)
 
157
 
 
158
        rev = Revision(committer = elt.get('committer'),
 
159
                       timestamp = float(elt.get('timestamp')),
 
160
                       revision_id = elt.get('revision_id'),
 
161
                       inventory_id = elt.get('inventory_id'),
 
162
                       inventory_sha1 = elt.get('inventory_sha1')
 
163
                       )
 
164
 
 
165
        precursor = elt.get('precursor')
 
166
        precursor_sha1 = elt.get('precursor_sha1')
 
167
 
 
168
        pelts = elt.find('parents')
 
169
 
 
170
        if pelts:
 
171
            for p in pelts:
 
172
                assert p.tag == 'revision_ref', \
 
173
                       "bad parent node tag %r" % p.tag
 
174
                rev.parent_ids.append(p.get('revision_id'))
 
175
                rev.parent_sha1s.append(p.get('revision_sha1'))
 
176
            if precursor:
 
177
                # must be consistent
 
178
                prec_parent = rev.parent_ids[0]
 
179
                assert prec_parent == precursor
 
180
        elif precursor:
 
181
            # revisions written prior to 0.0.5 have a single precursor
 
182
            # give as an attribute
 
183
            rev.parent_ids.append(precursor)
 
184
            rev.parent_sha1s.append(precursor_sha1)
 
185
 
 
186
        v = elt.get('timezone')
 
187
        rev.timezone = v and int(v)
 
188
 
 
189
        rev.message = elt.findtext('message') # text of <message>
 
190
        return rev
 
191
 
 
192
 
 
193
 
 
194
 
 
195
"""singleton instance"""
 
196
serializer_v4 = _Serializer_v4()
 
197