~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revision.py

Merge in format-5 work - release bzr 0.1rc1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
NULL_REVISION="null:"
22
22
 
23
 
class RevisionReference(object):
24
 
    """
25
 
    Reference to a stored revision.
26
 
 
27
 
    Includes the revision_id and revision_sha1.
28
 
    """
29
 
    revision_id = None
30
 
    revision_sha1 = None
31
 
    def __init__(self, revision_id, revision_sha1=None):
32
 
        if revision_id == None \
33
 
           or isinstance(revision_id, basestring):
34
 
            self.revision_id = revision_id
35
 
        else:
36
 
            raise ValueError('bad revision_id %r' % revision_id)
37
 
 
38
 
        if revision_sha1 != None:
39
 
            if isinstance(revision_sha1, basestring) \
40
 
               and len(revision_sha1) == 40:
41
 
                self.revision_sha1 = revision_sha1
42
 
            else:
43
 
                raise ValueError('bad revision_sha1 %r' % revision_sha1)
44
 
                
45
 
 
46
 
 
47
23
class Revision(object):
48
24
    """Single revision on a branch.
49
25
 
53
29
 
54
30
    After bzr 0.0.5 revisions are allowed to have multiple parents.
55
31
 
56
 
    parents
57
 
        List of parent revisions, each is a RevisionReference.
 
32
    parent_ids
 
33
        List of parent revision_ids
58
34
    """
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
35
    
67
 
    def __init__(self, **args):
 
36
    def __init__(self, revision_id, **args):
 
37
        self.revision_id = revision_id
68
38
        self.__dict__.update(args)
69
 
        self.parents = []
70
 
 
 
39
        self.parent_ids = []
 
40
        self.parent_sha1s = []
71
41
 
72
42
    def __repr__(self):
73
43
        return "<Revision id %s>" % self.revision_id
75
45
    def __eq__(self, other):
76
46
        if not isinstance(other, Revision):
77
47
            return False
78
 
        return (self.inventory_id == other.inventory_id
79
 
                and self.inventory_sha1 == other.inventory_sha1
 
48
        # FIXME: rbc 20050930 parent_ids are not being compared
 
49
        return (
 
50
                self.inventory_sha1 == other.inventory_sha1
80
51
                and self.revision_id == other.revision_id
81
52
                and self.timestamp == other.timestamp
82
53
                and self.message == other.message
87
58
        return not self.__eq__(other)
88
59
 
89
60
        
90
 
 
91
61
REVISION_ID_RE = None
92
62
 
93
63
def validate_revision_id(rid):
95
65
    global REVISION_ID_RE
96
66
    if not REVISION_ID_RE:
97
67
        import re
98
 
        REVISION_ID_RE = re.compile('[\w.-]+@[\w.-]+--?\d+--?[0-9a-f]+\Z')
 
68
        REVISION_ID_RE = re.compile('[\w:.-]+@[\w%.-]+--?[\w]+--?[0-9a-f]+\Z')
99
69
 
100
70
    if not REVISION_ID_RE.match(rid):
101
71
        raise ValueError("malformed revision-id %r" % rid)
102
72
 
103
 
def is_ancestor(revision_id, candidate_id, revision_source):
 
73
 
 
74
def is_ancestor(revision_id, candidate_id, branch):
104
75
    """Return true if candidate_id is an ancestor of revision_id.
 
76
 
105
77
    A false negative will be returned if any intermediate descendent of
106
78
    candidate_id is not present in any of the revision_sources.
107
79
    
108
80
    revisions_source is an object supporting a get_revision operation that
109
81
    behaves like Branch's.
110
82
    """
111
 
    if candidate_id is None:
112
 
        return True
113
 
    for ancestor_id, distance in iter_ancestors(revision_id, revision_source):
114
 
        if ancestor_id == candidate_id:
115
 
            return True
116
 
    return False
 
83
    return candidate_id in branch.get_ancestry(revision_id)
 
84
 
117
85
 
118
86
def iter_ancestors(revision_id, revision_source, only_present=False):
119
87
    ancestors = (revision_id,)
132
100
                    continue
133
101
            if only_present:
134
102
                yield ancestor, distance
135
 
            new_ancestors.extend([p.revision_id for p in revision.parents])
 
103
            new_ancestors.extend(revision.parent_ids)
136
104
        ancestors = new_ancestors
137
105
        distance += 1
138
106
 
215
183
            else:
216
184
                try:
217
185
                    rev = revision_source.get_revision(line)
218
 
                    parents = [p.revision_id for p in rev.parents]
 
186
                    parents = list(rev.parent_ids)
219
187
                    if len(parents) == 0:
220
188
                        parents = [NULL_REVISION]
221
189
                except bzrlib.errors.NoSuchRevision:
236
204
    assert root not in ancestors[root]
237
205
    return root, ancestors, descendants
238
206
 
 
207
 
239
208
def combined_graph(revision_a, revision_b, revision_source):
240
209
    """Produce a combined ancestry graph.
241
210
    Return graph root, ancestors map, descendants map, set of common nodes"""
257
226
        descendants[node].update(node_dec)
258
227
    return root, ancestors, descendants, common
259
228
 
 
229
 
260
230
def common_ancestor(revision_a, revision_b, revision_source):
261
231
    try:
262
232
        root, ancestors, descendants, common = \
270
240
        raise bzrlib.errors.NoCommonAncestor(revision_a, revision_b)
271
241
    return farthest
272
242
 
 
243
 
273
244
class MultipleRevisionSources(object):
274
245
    """Proxy that looks in multiple branches for revisions."""
275
246
    def __init__(self, *args):