~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/log.py

Move all features to bzrlib.tests.features in 2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
74
74
    revision as _mod_revision,
75
75
    revisionspec,
76
76
    tsort,
 
77
    i18n,
77
78
    )
78
79
""")
79
80
 
80
81
from bzrlib import (
 
82
    lazy_regex,
81
83
    registry,
82
84
    )
83
85
from bzrlib.osutils import (
109
111
    revno = 1
110
112
    for revision_id in branch.revision_history():
111
113
        this_inv = branch.repository.get_inventory(revision_id)
112
 
        if file_id in this_inv:
 
114
        if this_inv.has_id(file_id):
113
115
            this_ie = this_inv[file_id]
114
116
            this_path = this_inv.id2path(file_id)
115
117
        else:
230
232
                          delta_type=None,
231
233
                          diff_type=None, _match_using_deltas=True,
232
234
                          exclude_common_ancestry=False,
 
235
                          signature=False,
233
236
                          ):
234
237
    """Convenience function for making a logging request dictionary.
235
238
 
259
262
      generate; 1 for just the mainline; 0 for all levels.
260
263
 
261
264
    :param generate_tags: If True, include tags for matched revisions.
262
 
 
 
265
`
263
266
    :param delta_type: Either 'full', 'partial' or None.
264
267
      'full' means generate the complete delta - adds/deletes/modifies/etc;
265
268
      'partial' means filter the delta using specific_fileids;
277
280
 
278
281
    :param exclude_common_ancestry: Whether -rX..Y should be interpreted as a
279
282
      range operator or as a graph difference.
 
283
 
 
284
    :param signature: show digital signature information
280
285
    """
281
286
    return {
282
287
        'direction': direction,
290
295
        'delta_type': delta_type,
291
296
        'diff_type': diff_type,
292
297
        'exclude_common_ancestry': exclude_common_ancestry,
 
298
        'signature': signature,
293
299
        # Add 'private' attributes for features that may be deprecated
294
300
        '_match_using_deltas': _match_using_deltas,
295
301
    }
303
309
    return result
304
310
 
305
311
 
 
312
def format_signature_validity(rev_id, repo):
 
313
    """get the signature validity
 
314
    
 
315
    :param rev_id: revision id to validate
 
316
    :param repo: repository of revision
 
317
    :return: human readable string to print to log
 
318
    """
 
319
    from bzrlib import gpg
 
320
 
 
321
    gpg_strategy = gpg.GPGStrategy(None)
 
322
    result = repo.verify_revision(rev_id, gpg_strategy)
 
323
    if result[0] == gpg.SIGNATURE_VALID:
 
324
        return "valid signature from {0}".format(result[1])
 
325
    if result[0] == gpg.SIGNATURE_KEY_MISSING:
 
326
        return "unknown key {0}".format(result[1])
 
327
    if result[0] == gpg.SIGNATURE_NOT_VALID:
 
328
        return "invalid signature!"
 
329
    if result[0] == gpg.SIGNATURE_NOT_SIGNED:
 
330
        return "no signature"
 
331
 
 
332
 
306
333
class LogGenerator(object):
307
334
    """A generator of log revisions."""
308
335
 
360
387
            rqst['delta_type'] = None
361
388
        if not getattr(lf, 'supports_diff', False):
362
389
            rqst['diff_type'] = None
 
390
        if not getattr(lf, 'supports_signatures', False):
 
391
            rqst['signature'] = False
363
392
 
364
393
        # Find and print the interesting revisions
365
394
        generator = self._generator_factory(self.branch, rqst)
399
428
        levels = rqst.get('levels')
400
429
        limit = rqst.get('limit')
401
430
        diff_type = rqst.get('diff_type')
 
431
        show_signature = rqst.get('signature')
402
432
        log_count = 0
403
433
        revision_iterator = self._create_log_revision_iterator()
404
434
        for revs in revision_iterator:
410
440
                    diff = None
411
441
                else:
412
442
                    diff = self._format_diff(rev, rev_id, diff_type)
 
443
                if show_signature:
 
444
                    signature = format_signature_validity(rev_id,
 
445
                                                self.branch.repository)
 
446
                else:
 
447
                    signature = None
413
448
                yield LogRevision(rev, revno, merge_depth, delta,
414
 
                    self.rev_tag_dict.get(rev_id), diff)
 
449
                    self.rev_tag_dict.get(rev_id), diff, signature)
415
450
                if limit:
416
451
                    log_count += 1
417
452
                    if log_count >= limit:
678
713
    """
679
714
    br_revno, br_rev_id = branch.last_revision_info()
680
715
    repo = branch.repository
 
716
    graph = repo.get_graph()
681
717
    if start_rev_id is None and end_rev_id is None:
682
718
        cur_revno = br_revno
683
 
        for revision_id in repo.iter_reverse_revision_history(br_rev_id):
 
719
        for revision_id in graph.iter_lefthand_ancestry(br_rev_id,
 
720
            (_mod_revision.NULL_REVISION,)):
684
721
            yield revision_id, str(cur_revno), 0
685
722
            cur_revno -= 1
686
723
    else:
687
724
        if end_rev_id is None:
688
725
            end_rev_id = br_rev_id
689
726
        found_start = start_rev_id is None
690
 
        for revision_id in repo.iter_reverse_revision_history(end_rev_id):
 
727
        for revision_id in graph.iter_lefthand_ancestry(end_rev_id,
 
728
                (_mod_revision.NULL_REVISION,)):
691
729
            revno_str = _compute_revno_str(branch, revision_id)
692
730
            if not found_start and revision_id == start_rev_id:
693
731
                if not exclude_common_ancestry:
826
864
    """
827
865
    if search is None:
828
866
        return log_rev_iterator
829
 
    searchRE = re.compile(search, re.IGNORECASE)
 
867
    searchRE = lazy_regex.lazy_compile(search, re.IGNORECASE)
830
868
    return _filter_message_re(searchRE, log_rev_iterator)
831
869
 
832
870
 
1086
1124
    cur_revno = branch_revno
1087
1125
    rev_nos = {}
1088
1126
    mainline_revs = []
1089
 
    for revision_id in branch.repository.iter_reverse_revision_history(
1090
 
                        branch_last_revision):
 
1127
    graph = branch.repository.get_graph()
 
1128
    for revision_id in graph.iter_lefthand_ancestry(
 
1129
            branch_last_revision, (_mod_revision.NULL_REVISION,)):
1091
1130
        if cur_revno < start_revno:
1092
1131
            # We have gone far enough, but we always add 1 more revision
1093
1132
            rev_nos[revision_id] = cur_revno
1316
1355
    """
1317
1356
 
1318
1357
    def __init__(self, rev=None, revno=None, merge_depth=0, delta=None,
1319
 
                 tags=None, diff=None):
 
1358
                 tags=None, diff=None, signature=None):
1320
1359
        self.rev = rev
1321
1360
        if revno is None:
1322
1361
            self.revno = None
1326
1365
        self.delta = delta
1327
1366
        self.tags = tags
1328
1367
        self.diff = diff
 
1368
        self.signature = signature
1329
1369
 
1330
1370
 
1331
1371
class LogFormatter(object):
1358
1398
    - supports_diff must be True if this log formatter supports diffs.
1359
1399
      Otherwise the diff attribute may not be populated.
1360
1400
 
 
1401
    - supports_signatures must be True if this log formatter supports GPG
 
1402
      signatures.
 
1403
 
1361
1404
    Plugins can register functions to show custom revision properties using
1362
1405
    the properties_handler_registry. The registered function
1363
1406
    must respect the following interface description::
1554
1597
    supports_delta = True
1555
1598
    supports_tags = True
1556
1599
    supports_diff = True
 
1600
    supports_signatures = True
1557
1601
 
1558
1602
    def __init__(self, *args, **kwargs):
1559
1603
        super(LongLogFormatter, self).__init__(*args, **kwargs)
1598
1642
 
1599
1643
        lines.append('timestamp: %s' % (self.date_string(revision.rev),))
1600
1644
 
 
1645
        if revision.signature is not None:
 
1646
            lines.append('signature: ' + revision.signature)
 
1647
 
1601
1648
        lines.append('message:')
1602
1649
        if not revision.rev.message:
1603
1650
            lines.append('  (no message)')
1945
1992
    old_revisions = set()
1946
1993
    new_history = []
1947
1994
    new_revisions = set()
1948
 
    new_iter = repository.iter_reverse_revision_history(new_revision_id)
1949
 
    old_iter = repository.iter_reverse_revision_history(old_revision_id)
 
1995
    graph = repository.get_graph()
 
1996
    new_iter = graph.iter_lefthand_ancestry(new_revision_id)
 
1997
    old_iter = graph.iter_lefthand_ancestry(old_revision_id)
1950
1998
    stop_revision = None
1951
1999
    do_old = True
1952
2000
    do_new = True