~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revision.py

  • Committer: mbp at sourcefrog
  • Date: 2005-03-09 06:49:00 UTC
  • Revision ID: mbp@sourcefrog.net-20050309064900-74935ffb7350b24b
import more files from baz

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# (C) 2005 Canonical
 
1
#! /usr/bin/env python
 
2
# -*- coding: UTF-8 -*-
2
3
 
3
4
# This program is free software; you can redistribute it and/or modify
4
5
# it under the terms of the GNU General Public License as published by
22
23
try:
23
24
    from cElementTree import Element, ElementTree, SubElement
24
25
except ImportError:
25
 
    from elementtree.ElementTree import Element, ElementTree, SubElement
26
 
 
27
 
from errors import BzrError
28
 
 
29
 
 
30
 
class RevisionReference:
31
 
    """
32
 
    Reference to a stored revision.
33
 
 
34
 
    Includes the revision_id and revision_sha1.
35
 
    """
36
 
    revision_id = None
37
 
    revision_sha1 = None
38
 
    def __init__(self, revision_id, revision_sha1):
39
 
        if revision_id == None \
40
 
           or isinstance(revision_id, basestring):
41
 
            self.revision_id = revision_id
42
 
        else:
43
 
            raise ValueError('bad revision_id %r' % revision_id)
44
 
 
45
 
        if revision_sha1 != None:
46
 
            if isinstance(revision_sha1, basestring) \
47
 
               and len(revision_sha1) == 40:
48
 
                self.revision_sha1 = revision_sha1
49
 
            else:
50
 
                raise ValueError('bad revision_sha1 %r' % revision_sha1)
51
 
                
 
26
    from elementtree import Element, ElementTree, SubElement
52
27
 
53
28
 
54
29
class Revision(XMLMixin):
58
33
    written out.  This is not stored because you cannot write the hash
59
34
    into the file it describes.
60
35
 
61
 
    After bzr 0.0.5 revisions are allowed to have multiple parents.
62
 
    To support old clients this is written out in a slightly redundant
63
 
    form: the first parent as the predecessor.  This will eventually
64
 
    be dropped.
65
 
 
66
 
    parents
67
 
        List of parent revisions, each is a RevisionReference.
 
36
    :todo: Perhaps make predecessor be a child element, not an attribute?
68
37
    """
69
 
    inventory_id = None
70
 
    inventory_sha1 = None
71
 
    revision_id = None
72
 
    timestamp = None
73
 
    message = None
74
 
    timezone = None
75
 
    committer = None
76
 
    
77
38
    def __init__(self, **args):
 
39
        self.inventory_id = None
 
40
        self.revision_id = None
 
41
        self.timestamp = None
 
42
        self.message = None
 
43
        self.timezone = None
78
44
        self.__dict__.update(args)
79
 
        self.parents = []
80
 
 
81
 
    def _get_precursor(self):
82
 
        from warnings import warn
83
 
        warn("Revision.precursor is deprecated", stacklevel=2)
84
 
        if self.parents:
85
 
            return self.parents[0].revision_id
86
 
        else:
87
 
            return None
88
 
 
89
 
 
90
 
    def _get_precursor_sha1(self):
91
 
        from warnings import warn
92
 
        warn("Revision.precursor_sha1 is deprecated", stacklevel=2)
93
 
        if self.parents:
94
 
            return self.parents[0].revision_sha1
95
 
        else:
96
 
            return None    
97
 
 
98
 
 
99
 
    def _fail(self):
100
 
        raise Exception("can't assign to precursor anymore")
101
 
 
102
 
 
103
 
    precursor = property(_get_precursor, _fail, _fail)
104
 
    precursor_sha1 = property(_get_precursor_sha1, _fail, _fail)
105
 
 
106
45
 
107
46
 
108
47
    def __repr__(self):
109
 
        return "<Revision id %s>" % self.revision_id
 
48
        if self.revision_id:
 
49
            return "<Revision id %s>" % self.revision_id
110
50
 
111
51
        
112
52
    def to_element(self):
113
 
        root = Element('revision',
 
53
        root = Element('changeset',
114
54
                       committer = self.committer,
115
55
                       timestamp = '%.9f' % self.timestamp,
116
56
                       revision_id = self.revision_id,
117
57
                       inventory_id = self.inventory_id,
118
 
                       inventory_sha1 = self.inventory_sha1,
119
 
                       )
120
 
        if self.timezone:
121
 
            root.set('timezone', str(self.timezone))
 
58
                       timezone = str(self.timezone))
 
59
        if self.precursor:
 
60
            root.set('precursor', self.precursor)
122
61
        root.text = '\n'
123
62
        
124
63
        msg = SubElement(root, 'message')
125
64
        msg.text = self.message
126
65
        msg.tail = '\n'
127
66
 
128
 
        if self.parents:
129
 
            # first parent stored as precursor for compatability with 0.0.5 and
130
 
            # earlier
131
 
            pr = self.parents[0]
132
 
            assert pr.revision_id
133
 
            root.set('precursor', pr.revision_id)
134
 
            if pr.revision_sha1:
135
 
                root.set('precursor_sha1', pr.revision_sha1)
136
 
                
137
 
        if self.parents:
138
 
            pelts = SubElement(root, 'parents')
139
 
            pelts.tail = pelts.text = '\n'
140
 
            for rr in self.parents:
141
 
                assert isinstance(rr, RevisionReference)
142
 
                p = SubElement(pelts, 'revision_ref')
143
 
                p.tail = '\n'
144
 
                assert rr.revision_id
145
 
                p.set('revision_id', rr.revision_id)
146
 
                if rr.revision_sha1:
147
 
                    p.set('revision_sha1', rr.revision_sha1)
148
 
 
149
67
        return root
150
68
 
151
 
 
152
 
    def from_element(cls, elt):
153
 
        return unpack_revision(elt)
 
69
    def from_element(cls, root):
 
70
        cs = cls(committer = root.get('committer'),
 
71
                 timestamp = float(root.get('timestamp')),
 
72
                 precursor = root.get('precursor'),
 
73
                 revision_id = root.get('revision_id'),
 
74
                 inventory_id = root.get('inventory_id'))
 
75
 
 
76
        v = root.get('timezone')
 
77
        cs.timezone = v and int(v)
 
78
 
 
79
        cs.message = root.findtext('message') # text of <message>
 
80
        return cs
154
81
 
155
82
    from_element = classmethod(from_element)
156
83
 
157
 
 
158
 
 
159
 
def unpack_revision(elt):
160
 
    """Convert XML element into Revision object."""
161
 
    # <changeset> is deprecated...
162
 
    if elt.tag not in ('revision', 'changeset'):
163
 
        raise BzrError("unexpected tag in revision file: %r" % elt)
164
 
 
165
 
    rev = Revision(committer = elt.get('committer'),
166
 
                   timestamp = float(elt.get('timestamp')),
167
 
                   revision_id = elt.get('revision_id'),
168
 
                   inventory_id = elt.get('inventory_id'),
169
 
                   inventory_sha1 = elt.get('inventory_sha1')
170
 
                   )
171
 
 
172
 
    precursor = elt.get('precursor')
173
 
    precursor_sha1 = elt.get('precursor_sha1')
174
 
 
175
 
    pelts = elt.find('parents')
176
 
 
177
 
    if precursor:
178
 
        # revisions written prior to 0.0.5 have a single precursor
179
 
        # give as an attribute
180
 
        rev_ref = RevisionReference(precursor, precursor_sha1)
181
 
        rev.parents.append(rev_ref)
182
 
    elif pelts:
183
 
        for p in pelts:
184
 
            assert p.tag == 'revision_ref', \
185
 
                   "bad parent node tag %r" % p.tag
186
 
            rev_ref = RevisionReference(p.get('revision_id'),
187
 
                                        p.get('revision_sha1'))
188
 
            rev.parents.append(rev_ref)
189
 
 
190
 
    v = elt.get('timezone')
191
 
    rev.timezone = v and int(v)
192
 
 
193
 
    rev.message = elt.findtext('message') # text of <message>
194
 
    return rev