~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/log.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-12-01 02:40:20 UTC
  • mfrom: (4843.1.1 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20091201024020-8uqp6v8p2xqppu36
(igc) Faster log by less outf.write() calls

Show diffs side-by-side

added added

removed removed

Lines of Context:
83
83
    )
84
84
from bzrlib.osutils import (
85
85
    format_date,
 
86
    format_date_with_offset_in_original_timezone,
86
87
    get_terminal_encoding,
87
88
    re_compile_checked,
88
89
    terminal_width,
384
385
        :return: An iterator yielding LogRevision objects.
385
386
        """
386
387
        rqst = self.rqst
 
388
        levels = rqst.get('levels')
 
389
        limit = rqst.get('limit')
 
390
        diff_type = rqst.get('diff_type')
387
391
        log_count = 0
388
392
        revision_iterator = self._create_log_revision_iterator()
389
393
        for revs in revision_iterator:
390
394
            for (rev_id, revno, merge_depth), rev, delta in revs:
391
395
                # 0 levels means show everything; merge_depth counts from 0
392
 
                levels = rqst.get('levels')
393
396
                if levels != 0 and merge_depth >= levels:
394
397
                    continue
395
 
                diff = self._format_diff(rev, rev_id)
 
398
                if diff_type is None:
 
399
                    diff = None
 
400
                else:
 
401
                    diff = self._format_diff(rev, rev_id, diff_type)
396
402
                yield LogRevision(rev, revno, merge_depth, delta,
397
403
                    self.rev_tag_dict.get(rev_id), diff)
398
 
                limit = rqst.get('limit')
399
404
                if limit:
400
405
                    log_count += 1
401
406
                    if log_count >= limit:
402
407
                        return
403
408
 
404
 
    def _format_diff(self, rev, rev_id):
405
 
        diff_type = self.rqst.get('diff_type')
406
 
        if diff_type is None:
407
 
            return None
 
409
    def _format_diff(self, rev, rev_id, diff_type):
408
410
        repo = self.branch.repository
409
411
        if len(rev.parent_ids) == 0:
410
412
            ancestor_id = _mod_revision.NULL_REVISION
1291
1293
    preferred_levels = 0
1292
1294
 
1293
1295
    def __init__(self, to_file, show_ids=False, show_timezone='original',
1294
 
                 delta_format=None, levels=None, show_advice=False):
 
1296
            delta_format=None, levels=None, show_advice=False):
1295
1297
        """Create a LogFormatter.
1296
1298
 
1297
1299
        :param to_file: the file to output to
1367
1369
        else:
1368
1370
            return ''
1369
1371
 
1370
 
    def show_foreign_info(self, rev, indent):
 
1372
    def show_properties(self, revision, indent):
 
1373
        """Displays the custom properties returned by each registered handler.
 
1374
 
 
1375
        If a registered handler raises an error it is propagated.
 
1376
        """
 
1377
        for line in self.custom_properties(revision):
 
1378
            self.to_file.write("%s%s\n" % (indent, line))
 
1379
 
 
1380
    def custom_properties(self, revision):
 
1381
        """Format the custom properties returned by each registered handler.
 
1382
 
 
1383
        If a registered handler raises an error it is propagated.
 
1384
 
 
1385
        :return: a list of formatted lines (excluding trailing newlines)
 
1386
        """
 
1387
        lines = self._foreign_info_properties(revision)
 
1388
        for key, handler in properties_handler_registry.iteritems():
 
1389
            lines.extend(self._format_properties(handler(revision)))
 
1390
        return lines
 
1391
 
 
1392
    def _foreign_info_properties(self, rev):
1371
1393
        """Custom log displayer for foreign revision identifiers.
1372
1394
 
1373
1395
        :param rev: Revision object.
1374
1396
        """
1375
1397
        # Revision comes directly from a foreign repository
1376
1398
        if isinstance(rev, foreign.ForeignRevision):
1377
 
            self._write_properties(indent, rev.mapping.vcs.show_foreign_revid(
1378
 
                rev.foreign_revid))
1379
 
            return
 
1399
            return rev.mapping.vcs.show_foreign_revid(rev.foreign_revid)
1380
1400
 
1381
1401
        # Imported foreign revision revision ids always contain :
1382
1402
        if not ":" in rev.revision_id:
1383
 
            return
 
1403
            return []
1384
1404
 
1385
1405
        # Revision was once imported from a foreign repository
1386
1406
        try:
1387
1407
            foreign_revid, mapping = \
1388
1408
                foreign.foreign_vcs_registry.parse_revision_id(rev.revision_id)
1389
1409
        except errors.InvalidRevisionId:
1390
 
            return
 
1410
            return []
1391
1411
 
1392
 
        self._write_properties(indent, 
 
1412
        return self._format_properties(
1393
1413
            mapping.vcs.show_foreign_revid(foreign_revid))
1394
1414
 
1395
 
    def show_properties(self, revision, indent):
1396
 
        """Displays the custom properties returned by each registered handler.
1397
 
 
1398
 
        If a registered handler raises an error it is propagated.
1399
 
        """
1400
 
        for key, handler in properties_handler_registry.iteritems():
1401
 
            self._write_properties(indent, handler(revision))
1402
 
 
1403
 
    def _write_properties(self, indent, properties):
 
1415
    def _format_properties(self, properties):
 
1416
        lines = []
1404
1417
        for key, value in properties.items():
1405
 
            self.to_file.write(indent + key + ': ' + value + '\n')
 
1418
            lines.append(key + ': ' + value)
 
1419
        return lines
1406
1420
 
1407
1421
    def show_diff(self, to_file, diff, indent):
1408
1422
        for l in diff.rstrip().split('\n'):
1409
1423
            to_file.write(indent + '%s\n' % (l,))
1410
1424
 
1411
1425
 
 
1426
# Separator between revisions in long format
 
1427
_LONG_SEP = '-' * 60
 
1428
 
 
1429
 
1412
1430
class LongLogFormatter(LogFormatter):
1413
1431
 
1414
1432
    supports_merge_revisions = True
1417
1435
    supports_tags = True
1418
1436
    supports_diff = True
1419
1437
 
 
1438
    def __init__(self, *args, **kwargs):
 
1439
        super(LongLogFormatter, self).__init__(*args, **kwargs)
 
1440
        if self.show_timezone == 'original':
 
1441
            self.date_string = self._date_string_original_timezone
 
1442
        else:
 
1443
            self.date_string = self._date_string_with_timezone
 
1444
 
 
1445
    def _date_string_with_timezone(self, rev):
 
1446
        return format_date(rev.timestamp, rev.timezone or 0,
 
1447
                           self.show_timezone)
 
1448
 
 
1449
    def _date_string_original_timezone(self, rev):
 
1450
        return format_date_with_offset_in_original_timezone(rev.timestamp,
 
1451
            rev.timezone or 0)
 
1452
 
1420
1453
    def log_revision(self, revision):
1421
1454
        """Log a revision, either merged or not."""
1422
1455
        indent = '    ' * revision.merge_depth
1423
 
        to_file = self.to_file
1424
 
        to_file.write(indent + '-' * 60 + '\n')
 
1456
        lines = [_LONG_SEP]
1425
1457
        if revision.revno is not None:
1426
 
            to_file.write(indent + 'revno: %s%s\n' % (revision.revno,
 
1458
            lines.append('revno: %s%s' % (revision.revno,
1427
1459
                self.merge_marker(revision)))
1428
1460
        if revision.tags:
1429
 
            to_file.write(indent + 'tags: %s\n' % (', '.join(revision.tags)))
 
1461
            lines.append('tags: %s' % (', '.join(revision.tags)))
1430
1462
        if self.show_ids:
1431
 
            to_file.write(indent + 'revision-id: ' + revision.rev.revision_id)
1432
 
            to_file.write('\n')
 
1463
            lines.append('revision-id: %s' % (revision.rev.revision_id,))
1433
1464
            for parent_id in revision.rev.parent_ids:
1434
 
                to_file.write(indent + 'parent: %s\n' % (parent_id,))
1435
 
        self.show_foreign_info(revision.rev, indent)
1436
 
        self.show_properties(revision.rev, indent)
 
1465
                lines.append('parent: %s' % (parent_id,))
 
1466
        lines.extend(self.custom_properties(revision.rev))
1437
1467
 
1438
1468
        committer = revision.rev.committer
1439
1469
        authors = revision.rev.get_apparent_authors()
1440
1470
        if authors != [committer]:
1441
 
            to_file.write(indent + 'author: %s\n' % (", ".join(authors),))
1442
 
        to_file.write(indent + 'committer: %s\n' % (committer,))
 
1471
            lines.append('author: %s' % (", ".join(authors),))
 
1472
        lines.append('committer: %s' % (committer,))
1443
1473
 
1444
1474
        branch_nick = revision.rev.properties.get('branch-nick', None)
1445
1475
        if branch_nick is not None:
1446
 
            to_file.write(indent + 'branch nick: %s\n' % (branch_nick,))
1447
 
 
1448
 
        date_str = format_date(revision.rev.timestamp,
1449
 
                               revision.rev.timezone or 0,
1450
 
                               self.show_timezone)
1451
 
        to_file.write(indent + 'timestamp: %s\n' % (date_str,))
1452
 
 
1453
 
        to_file.write(indent + 'message:\n')
 
1476
            lines.append('branch nick: %s' % (branch_nick,))
 
1477
 
 
1478
        lines.append('timestamp: %s' % (self.date_string(revision.rev),))
 
1479
 
 
1480
        lines.append('message:')
1454
1481
        if not revision.rev.message:
1455
 
            to_file.write(indent + '  (no message)\n')
 
1482
            lines.append('  (no message)')
1456
1483
        else:
1457
1484
            message = revision.rev.message.rstrip('\r\n')
1458
1485
            for l in message.split('\n'):
1459
 
                to_file.write(indent + '  %s\n' % (l,))
 
1486
                lines.append('  %s' % (l,))
 
1487
 
 
1488
        # Dump the output, appending the delta and diff if requested
 
1489
        to_file = self.to_file
 
1490
        to_file.write("%s%s\n" % (indent, ('\n' + indent).join(lines)))
1460
1491
        if revision.delta is not None:
1461
1492
            # We don't respect delta_format for compatibility
1462
1493
            revision.delta.show(to_file, self.show_ids, indent=indent,
1515
1546
                            self.show_timezone, date_fmt="%Y-%m-%d",
1516
1547
                            show_offset=False),
1517
1548
                tags, self.merge_marker(revision)))
1518
 
        self.show_foreign_info(revision.rev, indent+offset)
1519
1549
        self.show_properties(revision.rev, indent+offset)
1520
1550
        if self.show_ids:
1521
1551
            to_file.write(indent + offset + 'revision-id:%s\n'