/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: Robert Collins
  • Date: 2010-07-04 06:22:11 UTC
  • mto: This revision was merged to the branch mainline in revision 5332.
  • Revision ID: robertc@robertcollins.net-20100704062211-tk9hw6bnsn5x47fm
``bzrlib.lsprof.profile`` will no longer silently generate bad threaded
profiles when concurrent profile requests are made. Instead the profile
requests will be serialised. Reentrant requests will now deadlock.
(Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
70
70
    diff,
71
71
    errors,
72
72
    foreign,
 
73
    osutils,
73
74
    repository as _mod_repository,
74
75
    revision as _mod_revision,
75
76
    revisionspec,
432
433
        else:
433
434
            specific_files = None
434
435
        s = StringIO()
 
436
        path_encoding = osutils.get_diff_header_encoding()
435
437
        diff.show_diff_trees(tree_1, tree_2, s, specific_files, old_label='',
436
 
            new_label='')
 
438
            new_label='', path_encoding=path_encoding)
437
439
        return s.getvalue()
438
440
 
439
441
    def _create_log_revision_iterator(self):
522
524
    elif not generate_merge_revisions:
523
525
        # If we only want to see linear revisions, we can iterate ...
524
526
        iter_revs = _generate_flat_revisions(branch, start_rev_id, end_rev_id,
525
 
                                             direction)
 
527
                                             direction, exclude_common_ancestry)
526
528
        if direction == 'forward':
527
529
            iter_revs = reversed(iter_revs)
528
530
    else:
544
546
        return [(rev_id, revno_str, 0)]
545
547
 
546
548
 
547
 
def _generate_flat_revisions(branch, start_rev_id, end_rev_id, direction):
548
 
    result = _linear_view_revisions(branch, start_rev_id, end_rev_id)
 
549
def _generate_flat_revisions(branch, start_rev_id, end_rev_id, direction,
 
550
                             exclude_common_ancestry=False):
 
551
    result = _linear_view_revisions(
 
552
        branch, start_rev_id, end_rev_id,
 
553
        exclude_common_ancestry=exclude_common_ancestry)
549
554
    # If a start limit was given and it's not obviously an
550
555
    # ancestor of the end limit, check it before outputting anything
551
556
    if direction == 'forward' or (start_rev_id
572
577
    if delayed_graph_generation:
573
578
        try:
574
579
            for rev_id, revno, depth in  _linear_view_revisions(
575
 
                branch, start_rev_id, end_rev_id):
 
580
                branch, start_rev_id, end_rev_id, exclude_common_ancestry):
576
581
                if _has_merges(branch, rev_id):
577
582
                    # The end_rev_id can be nested down somewhere. We need an
578
583
                    # explicit ancestry check. There is an ambiguity here as we
643
648
    return True
644
649
 
645
650
 
646
 
def _linear_view_revisions(branch, start_rev_id, end_rev_id):
 
651
def _linear_view_revisions(branch, start_rev_id, end_rev_id,
 
652
                           exclude_common_ancestry=False):
647
653
    """Calculate a sequence of revisions to view, newest to oldest.
648
654
 
649
655
    :param start_rev_id: the lower revision-id
650
656
    :param end_rev_id: the upper revision-id
 
657
    :param exclude_common_ancestry: Whether the start_rev_id should be part of
 
658
        the iterated revisions.
651
659
    :return: An iterator of (revision_id, dotted_revno, merge_depth) tuples.
652
660
    :raises _StartNotLinearAncestor: if a start_rev_id is specified but
653
 
      is not found walking the left-hand history
 
661
        is not found walking the left-hand history
654
662
    """
655
663
    br_revno, br_rev_id = branch.last_revision_info()
656
664
    repo = branch.repository
667
675
            revno = branch.revision_id_to_dotted_revno(revision_id)
668
676
            revno_str = '.'.join(str(n) for n in revno)
669
677
            if not found_start and revision_id == start_rev_id:
670
 
                yield revision_id, revno_str, 0
 
678
                if not exclude_common_ancestry:
 
679
                    yield revision_id, revno_str, 0
671
680
                found_start = True
672
681
                break
673
682
            else:
1341
1350
 
1342
1351
    def __init__(self, to_file, show_ids=False, show_timezone='original',
1343
1352
                 delta_format=None, levels=None, show_advice=False,
1344
 
                 to_exact_file=None):
 
1353
                 to_exact_file=None, author_list_handler=None):
1345
1354
        """Create a LogFormatter.
1346
1355
 
1347
1356
        :param to_file: the file to output to
1355
1364
          let the log formatter decide.
1356
1365
        :param show_advice: whether to show advice at the end of the
1357
1366
          log or not
 
1367
        :param author_list_handler: callable generating a list of
 
1368
          authors to display for a given revision
1358
1369
        """
1359
1370
        self.to_file = to_file
1360
1371
        # 'exact' stream used to show diff, it should print content 'as is'
1375
1386
        self.levels = levels
1376
1387
        self._show_advice = show_advice
1377
1388
        self._merge_count = 0
 
1389
        self._author_list_handler = author_list_handler
1378
1390
 
1379
1391
    def get_levels(self):
1380
1392
        """Get the number of levels to display or 0 for all."""
1412
1424
        return address
1413
1425
 
1414
1426
    def short_author(self, rev):
1415
 
        name, address = config.parse_username(rev.get_apparent_authors()[0])
1416
 
        if name:
1417
 
            return name
1418
 
        return address
 
1427
        return self.authors(rev, 'first', short=True, sep=', ')
 
1428
 
 
1429
    def authors(self, rev, who, short=False, sep=None):
 
1430
        """Generate list of authors, taking --authors option into account.
 
1431
 
 
1432
        The caller has to specify the name of a author list handler,
 
1433
        as provided by the author list registry, using the ``who``
 
1434
        argument.  That name only sets a default, though: when the
 
1435
        user selected a different author list generation using the
 
1436
        ``--authors`` command line switch, as represented by the
 
1437
        ``author_list_handler`` constructor argument, that value takes
 
1438
        precedence.
 
1439
 
 
1440
        :param rev: The revision for which to generate the list of authors.
 
1441
        :param who: Name of the default handler.
 
1442
        :param short: Whether to shorten names to either name or address.
 
1443
        :param sep: What separator to use for automatic concatenation.
 
1444
        """
 
1445
        if self._author_list_handler is not None:
 
1446
            # The user did specify --authors, which overrides the default
 
1447
            author_list_handler = self._author_list_handler
 
1448
        else:
 
1449
            # The user didn't specify --authors, so we use the caller's default
 
1450
            author_list_handler = author_list_registry.get(who)
 
1451
        names = author_list_handler(rev)
 
1452
        if short:
 
1453
            for i in range(len(names)):
 
1454
                name, address = config.parse_username(names[i])
 
1455
                if name:
 
1456
                    names[i] = name
 
1457
                else:
 
1458
                    names[i] = address
 
1459
        if sep is not None:
 
1460
            names = sep.join(names)
 
1461
        return names
1419
1462
 
1420
1463
    def merge_marker(self, revision):
1421
1464
        """Get the merge marker to include in the output or '' if none."""
1523
1566
        lines.extend(self.custom_properties(revision.rev))
1524
1567
 
1525
1568
        committer = revision.rev.committer
1526
 
        authors = revision.rev.get_apparent_authors()
 
1569
        authors = self.authors(revision.rev, 'all')
1527
1570
        if authors != [committer]:
1528
1571
            lines.append('author: %s' % (", ".join(authors),))
1529
1572
        lines.append('committer: %s' % (committer,))
1703
1746
                               self.show_timezone,
1704
1747
                               date_fmt='%Y-%m-%d',
1705
1748
                               show_offset=False)
1706
 
        committer_str = revision.rev.get_apparent_authors()[0].replace (' <', '  <')
 
1749
        committer_str = self.authors(revision.rev, 'first', sep=', ')
 
1750
        committer_str = committer_str.replace(' <', '  <')
1707
1751
        to_file.write('%s  %s\n\n' % (date_str,committer_str))
1708
1752
 
1709
1753
        if revision.delta is not None and revision.delta.has_changed():
1774
1818
        raise errors.BzrCommandError("unknown log formatter: %r" % name)
1775
1819
 
1776
1820
 
 
1821
def author_list_all(rev):
 
1822
    return rev.get_apparent_authors()[:]
 
1823
 
 
1824
 
 
1825
def author_list_first(rev):
 
1826
    lst = rev.get_apparent_authors()
 
1827
    try:
 
1828
        return [lst[0]]
 
1829
    except IndexError:
 
1830
        return []
 
1831
 
 
1832
 
 
1833
def author_list_committer(rev):
 
1834
    return [rev.committer]
 
1835
 
 
1836
 
 
1837
author_list_registry = registry.Registry()
 
1838
 
 
1839
author_list_registry.register('all', author_list_all,
 
1840
                              'All authors')
 
1841
 
 
1842
author_list_registry.register('first', author_list_first,
 
1843
                              'The first author')
 
1844
 
 
1845
author_list_registry.register('committer', author_list_committer,
 
1846
                              'The committer')
 
1847
 
 
1848
 
1777
1849
def show_one_log(revno, rev, delta, verbose, to_file, show_timezone):
1778
1850
    # deprecated; for compatibility
1779
1851
    lf = LongLogFormatter(to_file=to_file, show_timezone=show_timezone)
1930
2002
        lf.log_revision(lr)
1931
2003
 
1932
2004
 
1933
 
def _get_info_for_log_files(revisionspec_list, file_list):
 
2005
def _get_info_for_log_files(revisionspec_list, file_list, add_cleanup):
1934
2006
    """Find file-ids and kinds given a list of files and a revision range.
1935
2007
 
1936
2008
    We search for files at the end of the range. If not found there,
1940
2012
    :param file_list: the list of paths given on the command line;
1941
2013
      the first of these can be a branch location or a file path,
1942
2014
      the remainder must be file paths
 
2015
    :param add_cleanup: When the branch returned is read locked,
 
2016
      an unlock call will be queued to the cleanup.
1943
2017
    :return: (branch, info_list, start_rev_info, end_rev_info) where
1944
2018
      info_list is a list of (relative_path, file_id, kind) tuples where
1945
2019
      kind is one of values 'directory', 'file', 'symlink', 'tree-reference'.
1947
2021
    """
1948
2022
    from builtins import _get_revision_range, safe_relpath_files
1949
2023
    tree, b, path = bzrdir.BzrDir.open_containing_tree_or_branch(file_list[0])
1950
 
    b.lock_read()
 
2024
    add_cleanup(b.lock_read().unlock)
1951
2025
    # XXX: It's damn messy converting a list of paths to relative paths when
1952
2026
    # those paths might be deleted ones, they might be on a case-insensitive
1953
2027
    # filesystem and/or they might be in silly locations (like another branch).