20
class RevisionReference(object):
22
Reference to a stored revision.
24
Includes the revision_id and revision_sha1.
28
def __init__(self, revision_id, revision_sha1=None):
29
if revision_id == None \
30
or isinstance(revision_id, basestring):
31
self.revision_id = revision_id
33
raise ValueError('bad revision_id %r' % revision_id)
35
if revision_sha1 != None:
36
if isinstance(revision_sha1, basestring) \
37
and len(revision_sha1) == 40:
38
self.revision_sha1 = revision_sha1
40
raise ValueError('bad revision_sha1 %r' % revision_sha1)
44
class Revision(object):
21
from xml import XMLMixin
24
from cElementTree import Element, ElementTree, SubElement
26
from elementtree.ElementTree import Element, ElementTree, SubElement
29
class Revision(XMLMixin):
45
30
"""Single revision on a branch.
47
32
Revisions may know their revision_hash, but only once they've been
48
33
written out. This is not stored because you cannot write the hash
49
34
into the file it describes.
51
After bzr 0.0.5 revisions are allowed to have multiple parents.
54
List of parent revisions, each is a RevisionReference.
36
:todo: Perhaps make predecessor be a child element, not an attribute?
64
38
def __init__(self, **args):
39
self.inventory_id = None
40
self.revision_id = None
65
44
self.__dict__.update(args)
69
47
def __repr__(self):
70
return "<Revision id %s>" % self.revision_id
49
return "<Revision id %s>" % self.revision_id
73
52
def to_element(self):
74
from bzrlib.xml import Element, SubElement
76
53
root = Element('revision',
77
54
committer = self.committer,
78
55
timestamp = '%.9f' % self.timestamp,
79
56
revision_id = self.revision_id,
80
57
inventory_id = self.inventory_id,
81
inventory_sha1 = self.inventory_sha1,
84
root.set('timezone', str(self.timezone))
58
timezone = str(self.timezone))
60
root.set('precursor', self.precursor)
87
63
msg = SubElement(root, 'message')
88
64
msg.text = self.message
92
pelts = SubElement(root, 'parents')
93
pelts.tail = pelts.text = '\n'
94
for rr in self.parents:
95
assert isinstance(rr, RevisionReference)
96
p = SubElement(pelts, 'revision_ref')
99
p.set('revision_id', rr.revision_id)
101
p.set('revision_sha1', rr.revision_sha1)
106
70
def from_element(cls, elt):
107
return unpack_revision(elt)
71
# <changeset> is deprecated...
72
if elt.tag not in ('revision', 'changeset'):
73
bailout("unexpected tag in revision file: %r" % elt)
75
cs = cls(committer = elt.get('committer'),
76
timestamp = float(elt.get('timestamp')),
77
precursor = elt.get('precursor'),
78
revision_id = elt.get('revision_id'),
79
inventory_id = elt.get('inventory_id'))
81
v = elt.get('timezone')
82
cs.timezone = v and int(v)
84
cs.message = elt.findtext('message') # text of <message>
109
87
from_element = classmethod(from_element)
113
def unpack_revision(elt):
114
"""Convert XML element into Revision object."""
115
# <changeset> is deprecated...
116
from bzrlib.errors import BzrError
118
if elt.tag not in ('revision', 'changeset'):
119
raise BzrError("unexpected tag in revision file: %r" % elt)
121
rev = Revision(committer = elt.get('committer'),
122
timestamp = float(elt.get('timestamp')),
123
revision_id = elt.get('revision_id'),
124
inventory_id = elt.get('inventory_id'),
125
inventory_sha1 = elt.get('inventory_sha1')
128
precursor = elt.get('precursor')
129
precursor_sha1 = elt.get('precursor_sha1')
131
pelts = elt.find('parents')
135
assert p.tag == 'revision_ref', \
136
"bad parent node tag %r" % p.tag
137
rev_ref = RevisionReference(p.get('revision_id'),
138
p.get('revision_sha1'))
139
rev.parents.append(rev_ref)
143
prec_parent = rev.parents[0].revision_id
144
assert prec_parent == precursor
146
# revisions written prior to 0.0.5 have a single precursor
147
# give as an attribute
148
rev_ref = RevisionReference(precursor, precursor_sha1)
149
rev.parents.append(rev_ref)
151
v = elt.get('timezone')
152
rev.timezone = v and int(v)
154
rev.message = elt.findtext('message') # text of <message>
159
REVISION_ID_RE = None
161
def validate_revision_id(rid):
162
"""Check rid is syntactically valid for a revision id."""
163
global REVISION_ID_RE
164
if not REVISION_ID_RE:
166
REVISION_ID_RE = re.compile('[\w.-]+@[\w.-]+--?\d+--?[0-9a-f]+\Z')
168
if not REVISION_ID_RE.match(rid):
169
raise ValueError("malformed revision-id %r" % rid)