~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/xml5.py

Factor out another win32 special case and add platform independent tests for it.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#! /usr/bin/env python
2
 
 
3
1
# This program is free software; you can redistribute it and/or modify
4
2
# it under the terms of the GNU General Public License as published by
5
3
# the Free Software Foundation; either version 2 of the License, or
15
13
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
14
 
17
15
 
18
 
from bzrlib.xml import ElementTree, SubElement, Element, Serializer
 
16
from bzrlib.xml_serializer import ElementTree, SubElement, Element, Serializer
19
17
from bzrlib.inventory import ROOT_ID, Inventory, InventoryEntry
20
 
from bzrlib.revision import Revision, RevisionReference        
 
18
import bzrlib.inventory as inventory
 
19
from bzrlib.revision import Revision        
21
20
from bzrlib.errors import BzrError
22
21
 
23
22
 
24
 
 
25
 
 
26
 
 
27
23
class Serializer_v5(Serializer):
28
24
    """Version 5 serializer
29
25
 
34
30
    
35
31
    def _pack_inventory(self, inv):
36
32
        """Convert to XML Element"""
37
 
        e = Element('inventory')
 
33
        e = Element('inventory',
 
34
                    format='5')
38
35
        e.text = '\n'
39
36
        if inv.root.file_id not in (None, ROOT_ID):
40
37
            e.set('file_id', inv.root.file_id)
 
38
        if inv.revision_id is not None:
 
39
            e.set('revision_id', inv.revision_id)
41
40
        for path, ie in inv.iter_entries():
42
41
            e.append(self._pack_entry(ie))
43
42
        return e
44
43
 
45
 
 
46
44
    def _pack_entry(self, ie):
47
45
        """Convert InventoryEntry to XML element"""
48
 
        assert ie.kind == 'directory' or ie.kind == 'file'
 
46
        # TODO: should just be a plain assertion
 
47
        if not InventoryEntry.versionable_kind(ie.kind):
 
48
            raise AssertionError('unsupported entry kind %s' % ie.kind)
49
49
        e = Element(ie.kind)
50
50
        e.set('name', ie.name)
51
51
        e.set('file_id', ie.file_id)
53
53
        if ie.text_size != None:
54
54
            e.set('text_size', '%d' % ie.text_size)
55
55
 
56
 
        for f in ['text_version', 'text_sha1', 'entry_version']:
 
56
        for f in ['text_sha1', 'revision', 'symlink_target']:
57
57
            v = getattr(ie, f)
58
58
            if v != None:
59
59
                e.set(f, v)
60
60
 
 
61
        if ie.executable:
 
62
            e.set('executable', 'yes')
 
63
 
61
64
        # to be conservative, we don't externalize the root pointers
62
65
        # for now, leaving them as null in the xml form.  in a future
63
66
        # version it will be implied by nested elements.
64
67
        if ie.parent_id != ROOT_ID:
65
68
            assert isinstance(ie.parent_id, basestring)
66
69
            e.set('parent_id', ie.parent_id)
67
 
 
68
70
        e.tail = '\n'
69
 
 
70
71
        return e
71
72
 
72
 
 
73
73
    def _pack_revision(self, rev):
74
74
        """Revision object -> xml tree"""
75
75
        root = Element('revision',
77
77
                       timestamp = '%.9f' % rev.timestamp,
78
78
                       revision_id = rev.revision_id,
79
79
                       inventory_sha1 = rev.inventory_sha1,
 
80
                       format='5',
80
81
                       )
81
82
        if rev.timezone:
82
83
            root.set('timezone', str(rev.timezone))
83
84
        root.text = '\n'
84
 
 
85
85
        msg = SubElement(root, 'message')
86
86
        msg.text = rev.message
87
87
        msg.tail = '\n'
88
 
 
89
 
        if rev.parents:
 
88
        if rev.parent_ids:
90
89
            pelts = SubElement(root, 'parents')
91
90
            pelts.tail = pelts.text = '\n'
92
 
            for rr in rev.parents:
93
 
                assert isinstance(rr, RevisionReference)
 
91
            for parent_id in rev.parent_ids:
 
92
                assert isinstance(parent_id, basestring)
94
93
                p = SubElement(pelts, 'revision_ref')
95
94
                p.tail = '\n'
96
 
                assert rr.revision_id
97
 
                p.set('revision_id', rr.revision_id)
98
 
 
 
95
                p.set('revision_id', parent_id)
 
96
        if rev.properties:
 
97
            self._pack_revision_properties(rev, root)
99
98
        return root
100
99
 
101
 
    
 
100
 
 
101
    def _pack_revision_properties(self, rev, under_element):
 
102
        top_elt = SubElement(under_element, 'properties')
 
103
        for prop_name, prop_value in sorted(rev.properties.items()):
 
104
            assert isinstance(prop_name, basestring) 
 
105
            assert isinstance(prop_value, basestring) 
 
106
            prop_elt = SubElement(top_elt, 'property')
 
107
            prop_elt.set('name', prop_name)
 
108
            prop_elt.text = prop_value
 
109
            prop_elt.tail = '\n'
 
110
        top_elt.tail = '\n'
 
111
 
102
112
 
103
113
    def _unpack_inventory(self, elt):
104
114
        """Construct from XML Element
105
115
        """
106
116
        assert elt.tag == 'inventory'
107
117
        root_id = elt.get('file_id') or ROOT_ID
108
 
        inv = Inventory(root_id)
 
118
        format = elt.get('format')
 
119
        if format is not None:
 
120
            if format != '5':
 
121
                raise BzrError("invalid format version %r on inventory"
 
122
                                % format)
 
123
        revision_id = elt.get('revision_id')
 
124
        inv = Inventory(root_id, revision_id=revision_id)
109
125
        for e in elt:
110
126
            ie = self._unpack_entry(e)
111
127
            if ie.parent_id == ROOT_ID:
116
132
 
117
133
    def _unpack_entry(self, elt):
118
134
        kind = elt.tag
119
 
        assert kind == 'directory' or kind == 'file'
 
135
        if not InventoryEntry.versionable_kind(kind):
 
136
            raise AssertionError('unsupported entry kind %s' % kind)
120
137
 
121
138
        parent_id = elt.get('parent_id')
122
139
        if parent_id == None:
123
140
            parent_id = ROOT_ID
124
141
 
125
 
        ie = InventoryEntry(elt.get('file_id'),
126
 
                            elt.get('name'),
127
 
                            kind,
128
 
                            parent_id)
129
 
        ie.text_version = elt.get('text_version')
130
 
        ie.entry_version = elt.get('entry_version')
131
 
        ie.text_sha1 = elt.get('text_sha1')
132
 
        v = elt.get('text_size')
133
 
        ie.text_size = v and int(v)
 
142
        if kind == 'directory':
 
143
            ie = inventory.InventoryDirectory(elt.get('file_id'),
 
144
                                              elt.get('name'),
 
145
                                              parent_id)
 
146
        elif kind == 'file':
 
147
            ie = inventory.InventoryFile(elt.get('file_id'),
 
148
                                         elt.get('name'),
 
149
                                         parent_id)
 
150
            ie.text_sha1 = elt.get('text_sha1')
 
151
            if elt.get('executable') == 'yes':
 
152
                ie.executable = True
 
153
            v = elt.get('text_size')
 
154
            ie.text_size = v and int(v)
 
155
        elif kind == 'symlink':
 
156
            ie = inventory.InventoryLink(elt.get('file_id'),
 
157
                                         elt.get('name'),
 
158
                                         parent_id)
 
159
            ie.symlink_target = elt.get('symlink_target')
 
160
        else:
 
161
            raise BzrError("unknown kind %r" % kind)
 
162
        ie.revision = elt.get('revision')
134
163
 
135
164
        return ie
136
165
 
138
167
    def _unpack_revision(self, elt):
139
168
        """XML Element -> Revision object"""
140
169
        assert elt.tag == 'revision'
141
 
        
 
170
        format = elt.get('format')
 
171
        if format is not None:
 
172
            if format != '5':
 
173
                raise BzrError("invalid format version %r on inventory"
 
174
                                % format)
142
175
        rev = Revision(committer = elt.get('committer'),
143
176
                       timestamp = float(elt.get('timestamp')),
144
177
                       revision_id = elt.get('revision_id'),
145
178
                       inventory_sha1 = elt.get('inventory_sha1')
146
179
                       )
147
 
 
148
180
        parents = elt.find('parents') or []
149
181
        for p in parents:
150
182
            assert p.tag == 'revision_ref', \
151
183
                   "bad parent node tag %r" % p.tag
152
 
            rev_ref = RevisionReference(p.get('revision_id'))
153
 
            rev.parents.append(rev_ref)
154
 
 
 
184
            rev.parent_ids.append(p.get('revision_id'))
 
185
        self._unpack_revision_properties(elt, rev)
155
186
        v = elt.get('timezone')
156
187
        rev.timezone = v and int(v)
157
 
 
158
188
        rev.message = elt.findtext('message') # text of <message>
159
189
        return rev
160
190
 
161
191
 
 
192
    def _unpack_revision_properties(self, elt, rev):
 
193
        """Unpack properties onto a revision."""
 
194
        props_elt = elt.find('properties')
 
195
        assert len(rev.properties) == 0
 
196
        if not props_elt:
 
197
            return
 
198
        for prop_elt in props_elt:
 
199
            assert prop_elt.tag == 'property', \
 
200
                "bad tag under properties list: %r" % p.tag
 
201
            name = prop_elt.get('name')
 
202
            value = prop_elt.text
 
203
            assert name not in rev.properties, \
 
204
                "repeated property %r" % p.name
 
205
            rev.properties[name] = value
 
206
 
162
207
 
163
208
serializer_v5 = Serializer_v5()