~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revision.py

  • Committer: Alexander Belchenko
  • Date: 2007-01-30 23:05:35 UTC
  • mto: This revision was merged to the branch mainline in revision 2259.
  • Revision ID: bialix@ukr.net-20070130230535-kx1rd478rtigyc3v
standalone installer: win98 support

Show diffs side-by-side

added added

removed removed

Lines of Context:
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:"
114
107
    def get_summary(self):
115
108
        """Get the first line of the log message for this revision.
116
109
        """
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)
126
 
 
127
 
 
128
 
@deprecated_function(symbol_versioning.one_zero)
 
110
        return self.message.split('\n', 1)[0]
 
111
 
 
112
 
129
113
def is_ancestor(revision_id, candidate_id, branch):
130
114
    """Return true if candidate_id is an ancestor of revision_id.
131
115
 
134
118
    
135
119
    revisions_source is an object supporting a get_revision operation that
136
120
    behaves like Branch's.
137
 
 
138
 
    This function is deprecated, it is better for callers to directly use
139
 
    Graph.is_ancestor() (just watch out that the parameter order is switched)
140
121
    """
141
 
    return branch.repository.get_graph().is_ancestor(candidate_id, revision_id)
 
122
    return (candidate_id in branch.repository.get_ancestry(revision_id))
142
123
 
143
124
 
144
125
def iter_ancestors(revision_id, revision_source, only_present=False):
233
214
    return root, ancestors, descendants
234
215
 
235
216
 
236
 
@deprecated_function(symbol_versioning.one_three)
237
217
def combined_graph(revision_a, revision_b, revision_source):
238
218
    """Produce a combined ancestry graph.
239
219
    Return graph root, ancestors map, descendants map, set of common nodes"""
257
237
    return root, ancestors, descendants, common
258
238
 
259
239
 
260
 
@deprecated_function(symbol_versioning.one_three)
261
240
def common_ancestor(revision_a, revision_b, revision_source, 
262
241
                    pb=DummyProgress()):
263
242
    if None in (revision_a, revision_b):
272
251
            pb.update('Picking ancestor', 1, 3)
273
252
            graph = revision_source.get_revision_graph_with_ghosts(
274
253
                [revision_a, revision_b])
275
 
            # Shortcut the case where one of the tips is already included in
276
 
            # the other graphs ancestry.
277
 
            ancestry_a = graph.get_ancestry(revision_a, topo_sorted=False)
278
 
            if revision_b in ancestry_a:
279
 
                return revision_b
280
 
            ancestry_b = graph.get_ancestry(revision_b, topo_sorted=False)
281
 
            if revision_a in ancestry_b:
282
 
                return revision_a
283
254
            # convert to a NULL_REVISION based graph.
284
255
            ancestors = graph.get_ancestors()
285
256
            descendants = graph.get_descendants()
286
 
            common = set(ancestry_a)
287
 
            common.intersection_update(ancestry_b)
 
257
            common = set(graph.get_ancestry(revision_a)).intersection(
 
258
                     set(graph.get_ancestry(revision_b)))
288
259
            descendants[NULL_REVISION] = {}
289
260
            ancestors[NULL_REVISION] = []
290
261
            for root in graph.roots:
322
293
 
323
294
class MultipleRevisionSources(object):
324
295
    """Proxy that looks in multiple branches for revisions."""
325
 
 
326
 
    @symbol_versioning.deprecated_method(symbol_versioning.one_three)
327
296
    def __init__(self, *args):
328
297
        object.__init__(self)
329
298
        assert len(args) != 0
442
411
            source.unlock()
443
412
 
444
413
 
 
414
@deprecated_function(zero_eight)
 
415
def get_intervening_revisions(ancestor_id, rev_id, rev_source,
 
416
                              revision_history=None):
 
417
    """Find the longest line of descent from maybe_ancestor to revision.
 
418
    Revision history is followed where possible.
 
419
 
 
420
    If ancestor_id == rev_id, list will be empty.
 
421
    Otherwise, rev_id will be the last entry.  ancestor_id will never appear.
 
422
    If ancestor_id is not an ancestor, NotAncestor will be thrown
 
423
    """
 
424
    root, ancestors, descendants = revision_graph(rev_id, rev_source)
 
425
    if len(descendants) == 0:
 
426
        raise errors.NoSuchRevision(rev_source, rev_id)
 
427
    if ancestor_id not in descendants:
 
428
        rev_source.get_revision(ancestor_id)
 
429
        raise errors.NotAncestor(rev_id, ancestor_id)
 
430
    root_descendants = all_descendants(descendants, ancestor_id)
 
431
    root_descendants.add(ancestor_id)
 
432
    if rev_id not in root_descendants:
 
433
        raise errors.NotAncestor(rev_id, ancestor_id)
 
434
    distances = node_distances(descendants, ancestors, ancestor_id,
 
435
                               root_descendants=root_descendants)
 
436
 
 
437
    def best_ancestor(rev_id):
 
438
        best = None
 
439
        for anc_id in ancestors[rev_id]:
 
440
            try:
 
441
                distance = distances[anc_id]
 
442
            except KeyError:
 
443
                continue
 
444
            if revision_history is not None and anc_id in revision_history:
 
445
                return anc_id
 
446
            elif best is None or distance > best[1]:
 
447
                best = (anc_id, distance)
 
448
        return best[0]
 
449
 
 
450
    next = rev_id
 
451
    path = []
 
452
    while next != ancestor_id:
 
453
        path.append(next)
 
454
        next = best_ancestor(next)
 
455
    path.reverse()
 
456
    return path
 
457
 
 
458
 
445
459
def is_reserved_id(revision_id):
446
460
    """Determine whether a revision id is reserved
447
461
 
454
468
    """Raise ReservedId if the supplied revision_id is reserved"""
455
469
    if is_reserved_id(revision_id):
456
470
        raise errors.ReservedId(revision_id)
457
 
 
458
 
 
459
 
def ensure_null(revision_id):
460
 
    """Ensure only NULL_REVISION is used to represent the null revision"""
461
 
    if revision_id is None:
462
 
        symbol_versioning.warn('NULL_REVISION should be used for the null'
463
 
            ' revision instead of None, as of bzr 0.91.',
464
 
            DeprecationWarning, stacklevel=2)
465
 
        return NULL_REVISION
466
 
    else:
467
 
        return revision_id
468
 
 
469
 
 
470
 
def is_null(revision_id):
471
 
    if revision_id is None:
472
 
        symbol_versioning.warn('NULL_REVISION should be used for the null'
473
 
            ' revision instead of None, as of bzr 0.90.',
474
 
            DeprecationWarning, stacklevel=2)
475
 
    return revision_id in (None, NULL_REVISION)