/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/log.py

  • Committer: Martin Pool
  • Date: 2009-12-09 05:47:32 UTC
  • mfrom: (4879 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4880.
  • Revision ID: mbp@sourcefrog.net-20091209054732-7414e9uma23mfv6x
trivial merge of trunk

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,
1295
 
                 to_exact_file=None):
 
1296
            delta_format=None, levels=None, show_advice=False,
 
1297
            to_exact_file=None):
1296
1298
        """Create a LogFormatter.
1297
1299
 
1298
1300
        :param to_file: the file to output to
1376
1378
        else:
1377
1379
            return ''
1378
1380
 
1379
 
    def show_foreign_info(self, rev, indent):
 
1381
    def show_properties(self, revision, indent):
 
1382
        """Displays the custom properties returned by each registered handler.
 
1383
 
 
1384
        If a registered handler raises an error it is propagated.
 
1385
        """
 
1386
        for line in self.custom_properties(revision):
 
1387
            self.to_file.write("%s%s\n" % (indent, line))
 
1388
 
 
1389
    def custom_properties(self, revision):
 
1390
        """Format the custom properties returned by each registered handler.
 
1391
 
 
1392
        If a registered handler raises an error it is propagated.
 
1393
 
 
1394
        :return: a list of formatted lines (excluding trailing newlines)
 
1395
        """
 
1396
        lines = self._foreign_info_properties(revision)
 
1397
        for key, handler in properties_handler_registry.iteritems():
 
1398
            lines.extend(self._format_properties(handler(revision)))
 
1399
        return lines
 
1400
 
 
1401
    def _foreign_info_properties(self, rev):
1380
1402
        """Custom log displayer for foreign revision identifiers.
1381
1403
 
1382
1404
        :param rev: Revision object.
1383
1405
        """
1384
1406
        # Revision comes directly from a foreign repository
1385
1407
        if isinstance(rev, foreign.ForeignRevision):
1386
 
            self._write_properties(indent, rev.mapping.vcs.show_foreign_revid(
1387
 
                rev.foreign_revid))
1388
 
            return
 
1408
            return rev.mapping.vcs.show_foreign_revid(rev.foreign_revid)
1389
1409
 
1390
1410
        # Imported foreign revision revision ids always contain :
1391
1411
        if not ":" in rev.revision_id:
1392
 
            return
 
1412
            return []
1393
1413
 
1394
1414
        # Revision was once imported from a foreign repository
1395
1415
        try:
1396
1416
            foreign_revid, mapping = \
1397
1417
                foreign.foreign_vcs_registry.parse_revision_id(rev.revision_id)
1398
1418
        except errors.InvalidRevisionId:
1399
 
            return
 
1419
            return []
1400
1420
 
1401
 
        self._write_properties(indent, 
 
1421
        return self._format_properties(
1402
1422
            mapping.vcs.show_foreign_revid(foreign_revid))
1403
1423
 
1404
 
    def show_properties(self, revision, indent):
1405
 
        """Displays the custom properties returned by each registered handler.
1406
 
 
1407
 
        If a registered handler raises an error it is propagated.
1408
 
        """
1409
 
        for key, handler in properties_handler_registry.iteritems():
1410
 
            self._write_properties(indent, handler(revision))
1411
 
 
1412
 
    def _write_properties(self, indent, properties):
 
1424
    def _format_properties(self, properties):
 
1425
        lines = []
1413
1426
        for key, value in properties.items():
1414
 
            self.to_file.write(indent + key + ': ' + value + '\n')
 
1427
            lines.append(key + ': ' + value)
 
1428
        return lines
1415
1429
 
1416
1430
    def show_diff(self, to_file, diff, indent):
1417
1431
        for l in diff.rstrip().split('\n'):
1418
1432
            to_file.write(indent + '%s\n' % (l,))
1419
1433
 
1420
1434
 
 
1435
# Separator between revisions in long format
 
1436
_LONG_SEP = '-' * 60
 
1437
 
 
1438
 
1421
1439
class LongLogFormatter(LogFormatter):
1422
1440
 
1423
1441
    supports_merge_revisions = True
1426
1444
    supports_tags = True
1427
1445
    supports_diff = True
1428
1446
 
 
1447
    def __init__(self, *args, **kwargs):
 
1448
        super(LongLogFormatter, self).__init__(*args, **kwargs)
 
1449
        if self.show_timezone == 'original':
 
1450
            self.date_string = self._date_string_original_timezone
 
1451
        else:
 
1452
            self.date_string = self._date_string_with_timezone
 
1453
 
 
1454
    def _date_string_with_timezone(self, rev):
 
1455
        return format_date(rev.timestamp, rev.timezone or 0,
 
1456
                           self.show_timezone)
 
1457
 
 
1458
    def _date_string_original_timezone(self, rev):
 
1459
        return format_date_with_offset_in_original_timezone(rev.timestamp,
 
1460
            rev.timezone or 0)
 
1461
 
1429
1462
    def log_revision(self, revision):
1430
1463
        """Log a revision, either merged or not."""
1431
1464
        indent = '    ' * revision.merge_depth
1432
 
        to_file = self.to_file
1433
 
        to_file.write(indent + '-' * 60 + '\n')
 
1465
        lines = [_LONG_SEP]
1434
1466
        if revision.revno is not None:
1435
 
            to_file.write(indent + 'revno: %s%s\n' % (revision.revno,
 
1467
            lines.append('revno: %s%s' % (revision.revno,
1436
1468
                self.merge_marker(revision)))
1437
1469
        if revision.tags:
1438
 
            to_file.write(indent + 'tags: %s\n' % (', '.join(revision.tags)))
 
1470
            lines.append('tags: %s' % (', '.join(revision.tags)))
1439
1471
        if self.show_ids:
1440
 
            to_file.write(indent + 'revision-id: ' + revision.rev.revision_id)
1441
 
            to_file.write('\n')
 
1472
            lines.append('revision-id: %s' % (revision.rev.revision_id,))
1442
1473
            for parent_id in revision.rev.parent_ids:
1443
 
                to_file.write(indent + 'parent: %s\n' % (parent_id,))
1444
 
        self.show_foreign_info(revision.rev, indent)
1445
 
        self.show_properties(revision.rev, indent)
 
1474
                lines.append('parent: %s' % (parent_id,))
 
1475
        lines.extend(self.custom_properties(revision.rev))
1446
1476
 
1447
1477
        committer = revision.rev.committer
1448
1478
        authors = revision.rev.get_apparent_authors()
1449
1479
        if authors != [committer]:
1450
 
            to_file.write(indent + 'author: %s\n' % (", ".join(authors),))
1451
 
        to_file.write(indent + 'committer: %s\n' % (committer,))
 
1480
            lines.append('author: %s' % (", ".join(authors),))
 
1481
        lines.append('committer: %s' % (committer,))
1452
1482
 
1453
1483
        branch_nick = revision.rev.properties.get('branch-nick', None)
1454
1484
        if branch_nick is not None:
1455
 
            to_file.write(indent + 'branch nick: %s\n' % (branch_nick,))
1456
 
 
1457
 
        date_str = format_date(revision.rev.timestamp,
1458
 
                               revision.rev.timezone or 0,
1459
 
                               self.show_timezone)
1460
 
        to_file.write(indent + 'timestamp: %s\n' % (date_str,))
1461
 
 
1462
 
        to_file.write(indent + 'message:\n')
 
1485
            lines.append('branch nick: %s' % (branch_nick,))
 
1486
 
 
1487
        lines.append('timestamp: %s' % (self.date_string(revision.rev),))
 
1488
 
 
1489
        lines.append('message:')
1463
1490
        if not revision.rev.message:
1464
 
            to_file.write(indent + '  (no message)\n')
 
1491
            lines.append('  (no message)')
1465
1492
        else:
1466
1493
            message = revision.rev.message.rstrip('\r\n')
1467
1494
            for l in message.split('\n'):
1468
 
                to_file.write(indent + '  %s\n' % (l,))
 
1495
                lines.append('  %s' % (l,))
 
1496
 
 
1497
        # Dump the output, appending the delta and diff if requested
 
1498
        to_file = self.to_file
 
1499
        to_file.write("%s%s\n" % (indent, ('\n' + indent).join(lines)))
1469
1500
        if revision.delta is not None:
1470
1501
            # We don't respect delta_format for compatibility
1471
1502
            revision.delta.show(to_file, self.show_ids, indent=indent,
1526
1557
                            self.show_timezone, date_fmt="%Y-%m-%d",
1527
1558
                            show_offset=False),
1528
1559
                tags, self.merge_marker(revision)))
1529
 
        self.show_foreign_info(revision.rev, indent+offset)
1530
1560
        self.show_properties(revision.rev, indent+offset)
1531
1561
        if self.show_ids:
1532
1562
            to_file.write(indent + offset + 'revision-id:%s\n'
1554
1584
 
1555
1585
    def __init__(self, *args, **kwargs):
1556
1586
        super(LineLogFormatter, self).__init__(*args, **kwargs)
1557
 
        self._max_chars = terminal_width() - 1
 
1587
        width = terminal_width()
 
1588
        if width is not None:
 
1589
            # we need one extra space for terminals that wrap on last char
 
1590
            width = width - 1
 
1591
        self._max_chars = width
1558
1592
 
1559
1593
    def truncate(self, str, max_len):
1560
 
        if len(str) <= max_len:
 
1594
        if max_len is None or len(str) <= max_len:
1561
1595
            return str
1562
 
        return str[:max_len-3]+'...'
 
1596
        return str[:max_len-3] + '...'
1563
1597
 
1564
1598
    def date_string(self, rev):
1565
1599
        return format_date(rev.timestamp, rev.timezone or 0,