~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-28 13:20:38 UTC
  • Revision ID: mbp@sourcefrog.net-20050328132038-3a8a5fb9f1023ee1
more check functions

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