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.
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.
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
20
from xml import XMLMixin
23
from cElementTree import Element, ElementTree, SubElement
25
from elementtree.ElementTree import Element, ElementTree, SubElement
27
from errors import BzrError
30
class RevisionReference:
32
Reference to a stored revision.
34
Includes the revision_id and revision_sha1.
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
43
raise ValueError('bad revision_id %r' % revision_id)
45
if revision_sha1 != None:
46
if isinstance(revision_sha1, basestring) \
47
and len(revision_sha1) == 40:
48
self.revision_sha1 = revision_sha1
50
raise ValueError('bad revision_sha1 %r' % revision_sha1)
54
class Revision(XMLMixin):
55
"""Single revision on a branch.
57
Revisions may know their revision_hash, but only once they've been
58
written out. This is not stored because you cannot write the hash
59
into the file it describes.
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
67
List of parent revisions, each is a RevisionReference.
77
def __init__(self, **args):
78
self.__dict__.update(args)
81
def _get_precursor(self):
82
from warnings import warn
83
warn("Revision.precursor is deprecated", stacklevel=2)
85
return self.parents[0].revision_id
90
def _get_precursor_sha1(self):
91
from warnings import warn
92
warn("Revision.precursor_sha1 is deprecated", stacklevel=2)
94
return self.parents[0].revision_sha1
100
raise Exception("can't assign to precursor anymore")
103
precursor = property(_get_precursor, _fail, _fail)
104
precursor_sha1 = property(_get_precursor_sha1, _fail, _fail)
109
return "<Revision id %s>" % self.revision_id
112
def to_element(self):
113
root = Element('revision',
114
committer = self.committer,
115
timestamp = '%.9f' % self.timestamp,
116
revision_id = self.revision_id,
117
inventory_id = self.inventory_id,
118
inventory_sha1 = self.inventory_sha1,
121
root.set('timezone', str(self.timezone))
124
msg = SubElement(root, 'message')
125
msg.text = self.message
129
# first parent stored as precursor for compatability with 0.0.5 and
132
assert pr.revision_id
133
root.set('precursor', pr.revision_id)
135
root.set('precursor_sha1', pr.revision_sha1)
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')
144
assert rr.revision_id
145
p.set('revision_id', rr.revision_id)
147
p.set('revision_sha1', rr.revision_sha1)
152
def from_element(cls, elt):
153
return unpack_revision(elt)
155
from_element = classmethod(from_element)
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)
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')
172
precursor = elt.get('precursor')
173
precursor_sha1 = elt.get('precursor_sha1')
175
pelts = elt.find('parents')
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)
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)
190
v = elt.get('timezone')
191
rev.timezone = v and int(v)
193
rev.message = elt.findtext('message') # text of <message>