~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revision.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-08-17 07:52:09 UTC
  • mfrom: (1910.3.4 trivial)
  • Revision ID: pqm@pqm.ubuntu.com-20060817075209-e85a1f9e05ff8b87
(andrew) Trivial fixes to NotImplemented errors.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 Canonical
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
18
18
# perhaps show them in log -v and allow them as options to the commit command.
19
19
 
20
20
 
21
 
from bzrlib import (
22
 
    errors,
23
 
    symbol_versioning
24
 
    )
25
 
from bzrlib.deprecated_graph import (
26
 
    all_descendants,
27
 
    Graph,
28
 
    node_distances,
29
 
    select_farthest,
30
 
    )
 
21
import bzrlib.errors as errors
 
22
from bzrlib.graph import node_distances, select_farthest, all_descendants, Graph
31
23
from bzrlib.osutils import contains_whitespace
32
24
from bzrlib.progress import DummyProgress
33
25
from bzrlib.symbol_versioning import (deprecated_function,
 
26
        zero_eight,
34
27
        )
35
28
 
36
29
NULL_REVISION="null:"
37
 
CURRENT_REVISION="current:"
38
30
 
39
31
 
40
32
class Revision(object):
114
106
    def get_summary(self):
115
107
        """Get the first line of the log message for this revision.
116
108
        """
117
 
        return self.message.lstrip().split('\n', 1)[0]
118
 
 
119
 
    def get_apparent_author(self):
120
 
        """Return the apparent author of this revision.
121
 
 
122
 
        If the revision properties contain the author name,
123
 
        return it. Otherwise return the committer name.
124
 
        """
125
 
        return self.properties.get('author', self.committer)
 
109
        return self.message.split('\n', 1)[0]
126
110
 
127
111
 
128
112
def is_ancestor(revision_id, candidate_id, branch):
134
118
    revisions_source is an object supporting a get_revision operation that
135
119
    behaves like Branch's.
136
120
    """
137
 
    if is_null(candidate_id):
138
 
        return True
139
 
    return (candidate_id in branch.repository.get_ancestry(revision_id,
140
 
            topo_sorted=False))
 
121
    return candidate_id in branch.repository.get_ancestry(revision_id)
141
122
 
142
123
 
143
124
def iter_ancestors(revision_id, revision_source, only_present=False):
173
154
    anc_iter = enumerate(iter_ancestors(revision_id, revision_source,
174
155
                         only_present=True))
175
156
    for anc_order, (anc_id, anc_distance) in anc_iter:
176
 
        if anc_id not in found_ancestors:
 
157
        if not found_ancestors.has_key(anc_id):
177
158
            found_ancestors[anc_id] = (anc_order, anc_distance)
178
159
    return found_ancestors
179
160
    
269
250
            pb.update('Picking ancestor', 1, 3)
270
251
            graph = revision_source.get_revision_graph_with_ghosts(
271
252
                [revision_a, revision_b])
272
 
            # Shortcut the case where one of the tips is already included in
273
 
            # the other graphs ancestry.
274
 
            ancestry_a = graph.get_ancestry(revision_a, topo_sorted=False)
275
 
            if revision_b in ancestry_a:
276
 
                return revision_b
277
 
            ancestry_b = graph.get_ancestry(revision_b, topo_sorted=False)
278
 
            if revision_a in ancestry_b:
279
 
                return revision_a
280
253
            # convert to a NULL_REVISION based graph.
281
254
            ancestors = graph.get_ancestors()
282
255
            descendants = graph.get_descendants()
283
 
            common = set(ancestry_a)
284
 
            common.intersection_update(ancestry_b)
 
256
            common = set(graph.get_ancestry(revision_a)).intersection(
 
257
                     set(graph.get_ancestry(revision_b)))
285
258
            descendants[NULL_REVISION] = {}
286
259
            ancestors[NULL_REVISION] = []
287
260
            for root in graph.roots:
437
410
            source.unlock()
438
411
 
439
412
 
440
 
def is_reserved_id(revision_id):
441
 
    """Determine whether a revision id is reserved
 
413
@deprecated_function(zero_eight)
 
414
def get_intervening_revisions(ancestor_id, rev_id, rev_source,
 
415
                              revision_history=None):
 
416
    """Find the longest line of descent from maybe_ancestor to revision.
 
417
    Revision history is followed where possible.
442
418
 
443
 
    :return: True if the revision is is reserved, False otherwise
 
419
    If ancestor_id == rev_id, list will be empty.
 
420
    Otherwise, rev_id will be the last entry.  ancestor_id will never appear.
 
421
    If ancestor_id is not an ancestor, NotAncestor will be thrown
444
422
    """
445
 
    return isinstance(revision_id, basestring) and revision_id.endswith(':')
446
 
 
447
 
 
448
 
def check_not_reserved_id(revision_id):
449
 
    """Raise ReservedId if the supplied revision_id is reserved"""
450
 
    if is_reserved_id(revision_id):
451
 
        raise errors.ReservedId(revision_id)
452
 
 
453
 
 
454
 
def ensure_null(revision_id):
455
 
    """Ensure only NULL_REVISION is used to represent the null revisionn"""
456
 
    if revision_id is None:
457
 
        symbol_versioning.warn('NULL_REVISION should be used for the null'
458
 
            ' revision instead of None, as of bzr 0.91.',
459
 
            DeprecationWarning, stacklevel=2)
460
 
        return NULL_REVISION
461
 
    else:
462
 
        return revision_id
463
 
 
464
 
 
465
 
def is_null(revision_id):
466
 
    if revision_id is None:
467
 
        symbol_versioning.warn('NULL_REVISION should be used for the null'
468
 
            ' revision instead of None, as of bzr 0.90.',
469
 
            DeprecationWarning, stacklevel=2)
470
 
    return revision_id in (None, NULL_REVISION)
 
423
    root, ancestors, descendants = revision_graph(rev_id, rev_source)
 
424
    if len(descendants) == 0:
 
425
        raise errors.NoSuchRevision(rev_source, rev_id)
 
426
    if ancestor_id not in descendants:
 
427
        rev_source.get_revision(ancestor_id)
 
428
        raise errors.NotAncestor(rev_id, ancestor_id)
 
429
    root_descendants = all_descendants(descendants, ancestor_id)
 
430
    root_descendants.add(ancestor_id)
 
431
    if rev_id not in root_descendants:
 
432
        raise errors.NotAncestor(rev_id, ancestor_id)
 
433
    distances = node_distances(descendants, ancestors, ancestor_id,
 
434
                               root_descendants=root_descendants)
 
435
 
 
436
    def best_ancestor(rev_id):
 
437
        best = None
 
438
        for anc_id in ancestors[rev_id]:
 
439
            try:
 
440
                distance = distances[anc_id]
 
441
            except KeyError:
 
442
                continue
 
443
            if revision_history is not None and anc_id in revision_history:
 
444
                return anc_id
 
445
            elif best is None or distance > best[1]:
 
446
                best = (anc_id, distance)
 
447
        return best[0]
 
448
 
 
449
    next = rev_id
 
450
    path = []
 
451
    while next != ancestor_id:
 
452
        path.append(next)
 
453
        next = best_ancestor(next)
 
454
    path.reverse()
 
455
    return path