~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/log.py

  • Committer: Jelmer Vernooij
  • Date: 2011-05-16 13:39:39 UTC
  • mto: (5923.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 5925.
  • Revision ID: jelmer@samba.org-20110516133939-8u1pc9utas3uw1lt
Require a unicode prompt to be passed into all methods that prompt.

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,
78
77
    )
79
78
""")
80
79
 
81
80
from bzrlib import (
82
 
    lazy_regex,
83
81
    registry,
84
82
    )
85
83
from bzrlib.osutils import (
111
109
    revno = 1
112
110
    for revision_id in branch.revision_history():
113
111
        this_inv = branch.repository.get_inventory(revision_id)
114
 
        if this_inv.has_id(file_id):
 
112
        if file_id in this_inv:
115
113
            this_ie = this_inv[file_id]
116
114
            this_path = this_inv.id2path(file_id)
117
115
        else:
232
230
                          delta_type=None,
233
231
                          diff_type=None, _match_using_deltas=True,
234
232
                          exclude_common_ancestry=False,
235
 
                          signature=False,
236
233
                          ):
237
234
    """Convenience function for making a logging request dictionary.
238
235
 
262
259
      generate; 1 for just the mainline; 0 for all levels.
263
260
 
264
261
    :param generate_tags: If True, include tags for matched revisions.
265
 
`
 
262
 
266
263
    :param delta_type: Either 'full', 'partial' or None.
267
264
      'full' means generate the complete delta - adds/deletes/modifies/etc;
268
265
      'partial' means filter the delta using specific_fileids;
280
277
 
281
278
    :param exclude_common_ancestry: Whether -rX..Y should be interpreted as a
282
279
      range operator or as a graph difference.
283
 
 
284
 
    :param signature: show digital signature information
285
280
    """
286
281
    return {
287
282
        'direction': direction,
295
290
        'delta_type': delta_type,
296
291
        'diff_type': diff_type,
297
292
        'exclude_common_ancestry': exclude_common_ancestry,
298
 
        'signature': signature,
299
293
        # Add 'private' attributes for features that may be deprecated
300
294
        '_match_using_deltas': _match_using_deltas,
301
295
    }
309
303
    return result
310
304
 
311
305
 
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
 
 
333
306
class LogGenerator(object):
334
307
    """A generator of log revisions."""
335
308
 
387
360
            rqst['delta_type'] = None
388
361
        if not getattr(lf, 'supports_diff', False):
389
362
            rqst['diff_type'] = None
390
 
        if not getattr(lf, 'supports_signatures', False):
391
 
            rqst['signature'] = False
392
363
 
393
364
        # Find and print the interesting revisions
394
365
        generator = self._generator_factory(self.branch, rqst)
428
399
        levels = rqst.get('levels')
429
400
        limit = rqst.get('limit')
430
401
        diff_type = rqst.get('diff_type')
431
 
        show_signature = rqst.get('signature')
432
402
        log_count = 0
433
403
        revision_iterator = self._create_log_revision_iterator()
434
404
        for revs in revision_iterator:
440
410
                    diff = None
441
411
                else:
442
412
                    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
448
413
                yield LogRevision(rev, revno, merge_depth, delta,
449
 
                    self.rev_tag_dict.get(rev_id), diff, signature)
 
414
                    self.rev_tag_dict.get(rev_id), diff)
450
415
                if limit:
451
416
                    log_count += 1
452
417
                    if log_count >= limit:
713
678
    """
714
679
    br_revno, br_rev_id = branch.last_revision_info()
715
680
    repo = branch.repository
716
 
    graph = repo.get_graph()
717
681
    if start_rev_id is None and end_rev_id is None:
718
682
        cur_revno = br_revno
719
 
        for revision_id in graph.iter_lefthand_ancestry(br_rev_id,
720
 
            (_mod_revision.NULL_REVISION,)):
 
683
        for revision_id in repo.iter_reverse_revision_history(br_rev_id):
721
684
            yield revision_id, str(cur_revno), 0
722
685
            cur_revno -= 1
723
686
    else:
724
687
        if end_rev_id is None:
725
688
            end_rev_id = br_rev_id
726
689
        found_start = start_rev_id is None
727
 
        for revision_id in graph.iter_lefthand_ancestry(end_rev_id,
728
 
                (_mod_revision.NULL_REVISION,)):
 
690
        for revision_id in repo.iter_reverse_revision_history(end_rev_id):
729
691
            revno_str = _compute_revno_str(branch, revision_id)
730
692
            if not found_start and revision_id == start_rev_id:
731
693
                if not exclude_common_ancestry:
864
826
    """
865
827
    if search is None:
866
828
        return log_rev_iterator
867
 
    searchRE = lazy_regex.lazy_compile(search, re.IGNORECASE)
 
829
    searchRE = re.compile(search, re.IGNORECASE)
868
830
    return _filter_message_re(searchRE, log_rev_iterator)
869
831
 
870
832
 
1124
1086
    cur_revno = branch_revno
1125
1087
    rev_nos = {}
1126
1088
    mainline_revs = []
1127
 
    graph = branch.repository.get_graph()
1128
 
    for revision_id in graph.iter_lefthand_ancestry(
1129
 
            branch_last_revision, (_mod_revision.NULL_REVISION,)):
 
1089
    for revision_id in branch.repository.iter_reverse_revision_history(
 
1090
                        branch_last_revision):
1130
1091
        if cur_revno < start_revno:
1131
1092
            # We have gone far enough, but we always add 1 more revision
1132
1093
            rev_nos[revision_id] = cur_revno
1198
1159
    This includes the revisions which directly change the file id,
1199
1160
    and the revisions which merge these changes. So if the
1200
1161
    revision graph is::
1201
 
 
1202
1162
        A-.
1203
1163
        |\ \
1204
1164
        B C E
1355
1315
    """
1356
1316
 
1357
1317
    def __init__(self, rev=None, revno=None, merge_depth=0, delta=None,
1358
 
                 tags=None, diff=None, signature=None):
 
1318
                 tags=None, diff=None):
1359
1319
        self.rev = rev
1360
1320
        if revno is None:
1361
1321
            self.revno = None
1365
1325
        self.delta = delta
1366
1326
        self.tags = tags
1367
1327
        self.diff = diff
1368
 
        self.signature = signature
1369
1328
 
1370
1329
 
1371
1330
class LogFormatter(object):
1380
1339
    to indicate which LogRevision attributes it supports:
1381
1340
 
1382
1341
    - supports_delta must be True if this log formatter supports delta.
1383
 
      Otherwise the delta attribute may not be populated.  The 'delta_format'
1384
 
      attribute describes whether the 'short_status' format (1) or the long
1385
 
      one (2) should be used.
 
1342
        Otherwise the delta attribute may not be populated.  The 'delta_format'
 
1343
        attribute describes whether the 'short_status' format (1) or the long
 
1344
        one (2) should be used.
1386
1345
 
1387
1346
    - supports_merge_revisions must be True if this log formatter supports
1388
 
      merge revisions.  If not, then only mainline revisions will be passed
1389
 
      to the formatter.
 
1347
        merge revisions.  If not, then only mainline revisions will be passed
 
1348
        to the formatter.
1390
1349
 
1391
1350
    - preferred_levels is the number of levels this formatter defaults to.
1392
 
      The default value is zero meaning display all levels.
1393
 
      This value is only relevant if supports_merge_revisions is True.
 
1351
        The default value is zero meaning display all levels.
 
1352
        This value is only relevant if supports_merge_revisions is True.
1394
1353
 
1395
1354
    - supports_tags must be True if this log formatter supports tags.
1396
 
      Otherwise the tags attribute may not be populated.
 
1355
        Otherwise the tags attribute may not be populated.
1397
1356
 
1398
1357
    - supports_diff must be True if this log formatter supports diffs.
1399
 
      Otherwise the diff attribute may not be populated.
1400
 
 
1401
 
    - supports_signatures must be True if this log formatter supports GPG
1402
 
      signatures.
 
1358
        Otherwise the diff attribute may not be populated.
1403
1359
 
1404
1360
    Plugins can register functions to show custom revision properties using
1405
1361
    the properties_handler_registry. The registered function
1406
 
    must respect the following interface description::
1407
 
 
 
1362
    must respect the following interface description:
1408
1363
        def my_show_properties(properties_dict):
1409
1364
            # code that returns a dict {'name':'value'} of the properties
1410
1365
            # to be shown
1597
1552
    supports_delta = True
1598
1553
    supports_tags = True
1599
1554
    supports_diff = True
1600
 
    supports_signatures = True
1601
1555
 
1602
1556
    def __init__(self, *args, **kwargs):
1603
1557
        super(LongLogFormatter, self).__init__(*args, **kwargs)
1642
1596
 
1643
1597
        lines.append('timestamp: %s' % (self.date_string(revision.rev),))
1644
1598
 
1645
 
        if revision.signature is not None:
1646
 
            lines.append('signature: ' + revision.signature)
1647
 
 
1648
1599
        lines.append('message:')
1649
1600
        if not revision.rev.message:
1650
1601
            lines.append('  (no message)')
1777
1728
 
1778
1729
    def log_string(self, revno, rev, max_chars, tags=None, prefix=''):
1779
1730
        """Format log info into one string. Truncate tail of string
1780
 
 
1781
 
        :param revno:      revision number or None.
1782
 
                           Revision numbers counts from 1.
1783
 
        :param rev:        revision object
1784
 
        :param max_chars:  maximum length of resulting string
1785
 
        :param tags:       list of tags or None
1786
 
        :param prefix:     string to prefix each line
1787
 
        :return:           formatted truncated string
 
1731
        :param  revno:      revision number or None.
 
1732
                            Revision numbers counts from 1.
 
1733
        :param  rev:        revision object
 
1734
        :param  max_chars:  maximum length of resulting string
 
1735
        :param  tags:       list of tags or None
 
1736
        :param  prefix:     string to prefix each line
 
1737
        :return:            formatted truncated string
1788
1738
        """
1789
1739
        out = []
1790
1740
        if revno:
1791
1741
            # show revno only when is not None
1792
1742
            out.append("%s:" % revno)
1793
 
        if max_chars is not None:
1794
 
            out.append(self.truncate(self.short_author(rev), (max_chars+3)/4))
1795
 
        else:
1796
 
            out.append(self.short_author(rev))
 
1743
        out.append(self.truncate(self.short_author(rev), 20))
1797
1744
        out.append(self.date_string(rev))
1798
1745
        if len(rev.parent_ids) > 1:
1799
1746
            out.append('[merge]')
1992
1939
    old_revisions = set()
1993
1940
    new_history = []
1994
1941
    new_revisions = set()
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)
 
1942
    new_iter = repository.iter_reverse_revision_history(new_revision_id)
 
1943
    old_iter = repository.iter_reverse_revision_history(old_revision_id)
1998
1944
    stop_revision = None
1999
1945
    do_old = True
2000
1946
    do_new = True