hgext/churn.py
author Augie Fackler <augie@google.com>
Fri, 08 Nov 2019 11:19:20 -0800
changeset 43506 9f70512ae2cf
parent 43085 eef9a2d67051
child 45475 0d119802242b
permissions -rw-r--r--
cleanup: remove pointless r-prefixes on single-quoted strings This is the promised second step on single-quoted strings. These had existed because our source transformer didn't turn r'' into b'', so we had tagged some strings as r-strings to get "native" strings on both Pythons. Now that the transformer is gone, we can dispense with this nonsense. Methodology: I ran hg locate 'set:added() or modified() or clean()' | egrep '.*\.py$' | xargs egrep --color=never -n -- \[\^b\]\[\^a-z\]r\'\[\^\'\\\\\]\*\'\[\^\'\ in an emacs grep-mode buffer, and then used a keyboard macro to iterate over the results and remove the r prefix as needed. # skip-blame removing unneeded r prefixes left over from Python 3 migration. Differential Revision: https://phab.mercurial-scm.org/D7306
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
     1
# churn.py - create a graph of revisions count grouped by template
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
     2
#
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
     3
# Copyright 2006 Josef "Jeff" Sipek <jeffpc@josefsipek.net>
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
     4
# Copyright 2008 Alexander Solovyov <piranha@piranha.org.ua>
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
     5
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8085
diff changeset
     6
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9672
diff changeset
     7
# GNU General Public License version 2 or any later version.
8228
eee2319c5895 add blank line after copyright notices and after header
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     8
8934
9dda4c73fc3b extensions: change descriptions for extensions providing a few commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8894
diff changeset
     9
'''command to display statistics about repository history'''
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
    10
40241
81e4f039a0cd churn: use integer division consistently
Augie Fackler <augie@google.com>
parents: 40240
diff changeset
    11
from __future__ import absolute_import, division
28094
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    12
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    13
import datetime
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    14
import os
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    15
import time
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    16
7051
5f201f711932 i18n, churn: mark string for translation
Martin Geisler <mg@daimi.au.dk>
parents: 6955
diff changeset
    17
from mercurial.i18n import _
43085
eef9a2d67051 py3: manually import pycompat.open into files that need it
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43077
diff changeset
    18
from mercurial.pycompat import open
28094
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    19
from mercurial import (
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    20
    cmdutil,
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    21
    encoding,
35888
c8e2d6ed1f9e cmdutil: drop aliases for logcmdutil functions (API)
Yuya Nishihara <yuya@tcha.org>
parents: 34974
diff changeset
    22
    logcmdutil,
28094
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    23
    patch,
34974
26ed66ab1e72 py3: handle keyword arguments in hgext/churn.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32837
diff changeset
    24
    pycompat,
32337
46ba2cdda476 registrar: move cmdutil.command to registrar module (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32198
diff changeset
    25
    registrar,
28094
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    26
    scmutil,
79fc627578ac churn: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
    27
)
36607
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36392
diff changeset
    28
from mercurial.utils import dateutil
4955
9bbc0217209b churn: get current terminal width if possible
Christian Ebert <blacktrash@gmx.net>
parents: 3963
diff changeset
    29
21245
75c8720092ba churn: declare command using decorator
Gregory Szorc <gregory.szorc@gmail.com>
parents: 21163
diff changeset
    30
cmdtable = {}
32337
46ba2cdda476 registrar: move cmdutil.command to registrar module (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32198
diff changeset
    31
command = registrar.command(cmdtable)
29841
d5883fd055c6 extensions: change magic "shipped with hg" string
Augie Fackler <augie@google.com>
parents: 28628
diff changeset
    32
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
25186
80c5b2666a96 extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents: 24987
diff changeset
    33
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
80c5b2666a96 extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents: 24987
diff changeset
    34
# be specifying the version(s) of Mercurial they are tested with, or
80c5b2666a96 extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents: 24987
diff changeset
    35
# leave the attribute unspecified.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    36
testedwith = b'ships-with-hg-core'
16743
38caf405d010 hgext: mark all first-party extensions as such
Augie Fackler <raf@durin42.com>
parents: 16231
diff changeset
    37
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    38
7870
7bcce39e8f07 Returns lines changed for paths specified as arguments correctly.
madhu@madhu
parents: 7762
diff changeset
    39
def changedlines(ui, repo, ctx1, ctx2, fns):
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
    40
    added, removed = 0, 0
14322
a90131b85fd8 scmutil: drop aliases in cmdutil for match functions
Matt Mackall <mpm@selenic.com>
parents: 14040
diff changeset
    41
    fmatch = scmutil.matchfiles(repo, fns)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    42
    diff = b''.join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    43
    for l in diff.split(b'\n'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    44
        if l.startswith(b"+") and not l.startswith(b"+++ "):
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
    45
            added += 1
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    46
        elif l.startswith(b"-") and not l.startswith(b"--- "):
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
    47
            removed += 1
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
    48
    return (added, removed)
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
    49
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    50
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    51
def countrate(ui, repo, amap, *pats, **opts):
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    52
    """Calculate stats"""
34974
26ed66ab1e72 py3: handle keyword arguments in hgext/churn.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32837
diff changeset
    53
    opts = pycompat.byteskwargs(opts)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    54
    if opts.get(b'dateformat'):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    55
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    56
        def getkey(ctx):
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    57
            t, tz = ctx.date()
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    58
            date = datetime.datetime(*time.gmtime(float(t) - tz)[:6])
40240
6f3e733848ae churn: fix stack traces on Python 3
Augie Fackler <augie@google.com>
parents: 38401
diff changeset
    59
            return encoding.strtolocal(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    60
                date.strftime(encoding.strfromlocal(opts[b'dateformat']))
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    61
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    62
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    63
    else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    64
        tmpl = opts.get(b'oldtemplate') or opts.get(b'template')
35888
c8e2d6ed1f9e cmdutil: drop aliases for logcmdutil functions (API)
Yuya Nishihara <yuya@tcha.org>
parents: 34974
diff changeset
    65
        tmpl = logcmdutil.maketemplater(ui, repo, tmpl)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    66
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    67
        def getkey(ctx):
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    68
            ui.pushbuffer()
7369
87158be081b8 cmdutil: use change contexts for cset-printer and cset-templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7308
diff changeset
    69
            tmpl.show(ctx)
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    70
            return ui.popbuffer()
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    71
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    72
    progress = ui.makeprogress(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    73
        _(b'analyzing'), unit=_(b'revisions'), total=len(repo)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    74
    )
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    75
    rate = {}
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    76
    df = False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    77
    if opts.get(b'date'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    78
        df = dateutil.matchdate(opts[b'date'])
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    79
14671
35c2cc322ba8 scmutil: switch match users to supplying contexts
Matt Mackall <mpm@selenic.com>
parents: 14322
diff changeset
    80
    m = scmutil.match(repo[None], pats, opts)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    81
9662
f3d60543924f walkchangerevs: move 'add' to callback
Matt Mackall <mpm@selenic.com>
parents: 9655
diff changeset
    82
    def prep(ctx, fns):
9654
96fe91be9c1e walkchangerevs: yield contexts
Matt Mackall <mpm@selenic.com>
parents: 9652
diff changeset
    83
        rev = ctx.rev()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    84
        if df and not df(ctx.date()[0]):  # doesn't match date format
9662
f3d60543924f walkchangerevs: move 'add' to callback
Matt Mackall <mpm@selenic.com>
parents: 9655
diff changeset
    85
            return
3049
461573aa02ef [churn] Ignore merge csets
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3048
diff changeset
    86
14040
9d2be7e17fc1 churn: strip key earlier to avoid false negative seach in aliases
Alexander Solovyov <alexander@solovyov.net>
parents: 13123
diff changeset
    87
        key = getkey(ctx).strip()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
    88
        key = amap.get(key, key)  # alias remap
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    89
        if opts.get(b'changesets'):
9670
7d56b6ffef72 churn: fix changeset count (broken by 9b127e888640)
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9669
diff changeset
    90
            rate[key] = (rate.get(key, (0,))[0] + 1, 0)
7070
2627ef59195d churn and stats commands merged
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7065
diff changeset
    91
        else:
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    92
            parents = ctx.parents()
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    93
            if len(parents) > 1:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    94
                ui.note(_(b'revision %d is a merge, ignoring...\n') % (rev,))
9662
f3d60543924f walkchangerevs: move 'add' to callback
Matt Mackall <mpm@selenic.com>
parents: 9655
diff changeset
    95
                return
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
    96
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
    97
            ctx1 = parents[0]
7870
7bcce39e8f07 Returns lines changed for paths specified as arguments correctly.
madhu@madhu
parents: 7762
diff changeset
    98
            lines = changedlines(ui, repo, ctx1, ctx, fns)
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
    99
            rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)]
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
   100
38401
5c0f06a8b497 churn: use progess helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 38124
diff changeset
   101
        progress.increment()
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
   102
9665
1de5ebfa5585 walkchangerevs: drop ui arg
Matt Mackall <mpm@selenic.com>
parents: 9662
diff changeset
   103
    for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
9662
f3d60543924f walkchangerevs: move 'add' to callback
Matt Mackall <mpm@selenic.com>
parents: 9655
diff changeset
   104
        continue
f3d60543924f walkchangerevs: move 'add' to callback
Matt Mackall <mpm@selenic.com>
parents: 9655
diff changeset
   105
38401
5c0f06a8b497 churn: use progess helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 38124
diff changeset
   106
    progress.complete()
3050
dd1a142988d3 [churn] progress meter
Josef "Jeff" Sipek <jeffpc@josefsipek.net>
parents: 3049
diff changeset
   107
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   108
    return rate
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   109
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   110
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   111
@command(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   112
    b'churn',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   113
    [
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   114
        (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   115
            b'r',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   116
            b'rev',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   117
            [],
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   118
            _(b'count rate for the specified revision or revset'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   119
            _(b'REV'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   120
        ),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   121
        (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   122
            b'd',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   123
            b'date',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   124
            b'',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   125
            _(b'count rate for revisions matching date spec'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   126
            _(b'DATE'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   127
        ),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   128
        (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   129
            b't',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   130
            b'oldtemplate',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   131
            b'',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   132
            _(b'template to group changesets (DEPRECATED)'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   133
            _(b'TEMPLATE'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   134
        ),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   135
        (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   136
            b'T',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   137
            b'template',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   138
            b'{author|email}',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   139
            _(b'template to group changesets'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   140
            _(b'TEMPLATE'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   141
        ),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   142
        (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   143
            b'f',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   144
            b'dateformat',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   145
            b'',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   146
            _(b'strftime-compatible format for grouping by date'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   147
            _(b'FORMAT'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   148
        ),
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   149
        (b'c', b'changesets', False, _(b'count rate by number of changesets')),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   150
        (b's', b'sort', False, _(b'sort by key (default: sort by count)')),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   151
        (b'', b'diffstat', False, _(b'display added/removed lines separately')),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   152
        (b'', b'aliases', b'', _(b'file with email aliases'), _(b'FILE')),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   153
    ]
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   154
    + cmdutil.walkopts,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   155
    _(b"hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]"),
40293
c303d65d2e34 help: assigning categories to existing commands
rdamazio@google.com
parents: 40264
diff changeset
   156
    helpcategory=command.CATEGORY_MAINTENANCE,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   157
    inferrepo=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   158
)
7070
2627ef59195d churn and stats commands merged
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7065
diff changeset
   159
def churn(ui, repo, *pats, **opts):
8823
d9f4c182aeca churn: improve description
Cédric Duval <cedricduval@free.fr>
parents: 8254
diff changeset
   160
    '''histogram of changes to the repository
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
   161
8823
d9f4c182aeca churn: improve description
Cédric Duval <cedricduval@free.fr>
parents: 8254
diff changeset
   162
    This command will display a histogram representing the number
d9f4c182aeca churn: improve description
Cédric Duval <cedricduval@free.fr>
parents: 8254
diff changeset
   163
    of changed lines or revisions, grouped according to the given
d9f4c182aeca churn: improve description
Cédric Duval <cedricduval@free.fr>
parents: 8254
diff changeset
   164
    template. The default template will group changes by author.
d9f4c182aeca churn: improve description
Cédric Duval <cedricduval@free.fr>
parents: 8254
diff changeset
   165
    The --dateformat option may be used to group the results by
d9f4c182aeca churn: improve description
Cédric Duval <cedricduval@free.fr>
parents: 8254
diff changeset
   166
    date instead.
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   167
8823
d9f4c182aeca churn: improve description
Cédric Duval <cedricduval@free.fr>
parents: 8254
diff changeset
   168
    Statistics are based on the number of changed lines, or
d9f4c182aeca churn: improve description
Cédric Duval <cedricduval@free.fr>
parents: 8254
diff changeset
   169
    alternatively the number of matching revisions if the
d9f4c182aeca churn: improve description
Cédric Duval <cedricduval@free.fr>
parents: 8254
diff changeset
   170
    --changesets option is specified.
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   171
9205
83132980e9cd churn: use reST syntax for literal blocks
Martin Geisler <mg@lazybytes.net>
parents: 9056
diff changeset
   172
    Examples::
6666
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6598
diff changeset
   173
7070
2627ef59195d churn and stats commands merged
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7065
diff changeset
   174
      # display count of changed lines for every committer
32198
a0e46f6b248b churn: use the non-deprecated template option in the examples
Matt Harbison <matt_harbison@yahoo.com>
parents: 29841
diff changeset
   175
      hg churn -T "{author|email}"
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   176
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   177
      # display daily activity graph
19959
9ef92384415c doc: use double quotation mark to quote arguments in examples for Windows users
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19464
diff changeset
   178
      hg churn -f "%H" -s -c
6666
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6598
diff changeset
   179
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   180
      # display activity of developers by month
19959
9ef92384415c doc: use double quotation mark to quote arguments in examples for Windows users
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19464
diff changeset
   181
      hg churn -f "%Y-%m" -s -c
3223
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3090
diff changeset
   182
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   183
      # display count of lines changed in every year
19959
9ef92384415c doc: use double quotation mark to quote arguments in examples for Windows users
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19464
diff changeset
   184
      hg churn -f "%Y" -s
7070
2627ef59195d churn and stats commands merged
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7065
diff changeset
   185
8823
d9f4c182aeca churn: improve description
Cédric Duval <cedricduval@free.fr>
parents: 8254
diff changeset
   186
    It is possible to map alternate email addresses to a main address
9254
db13255617b3 churn: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9205
diff changeset
   187
    by providing a file using the following format::
8843
eb7b247a98ea kill trailing whitespace
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8823
diff changeset
   188
11264
30c620e48d1c churn: support spaces in aliases (issue2222)
Alexander Solovyov <piranha@piranha.org.ua>
parents: 10905
diff changeset
   189
      <alias email> = <actual email>
8254
f108e89400d8 churn: use .hgchurn in repo root as default map file
Martin Geisler <mg@lazybytes.net>
parents: 8228
diff changeset
   190
9254
db13255617b3 churn: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9205
diff changeset
   191
    Such a file may be specified with the --aliases option, otherwise
db13255617b3 churn: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9205
diff changeset
   192
    a .hgchurn file will be looked for in the working directory root.
19464
68f7129af6a8 churn: split email aliases from the right
Matthew Turk <matthewturk@gmail.com>
parents: 18369
diff changeset
   193
    Aliases will be split from the rightmost "=".
8254
f108e89400d8 churn: use .hgchurn in repo root as default map file
Martin Geisler <mg@lazybytes.net>
parents: 8228
diff changeset
   194
    '''
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   195
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
   196
    def pad(s, l):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   197
        return s + b" " * (l - encoding.colwidth(s))
3223
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3090
diff changeset
   198
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
   199
    amap = {}
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43085
diff changeset
   200
    aliases = opts.get('aliases')
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   201
    if not aliases and os.path.exists(repo.wjoin(b'.hgchurn')):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   202
        aliases = repo.wjoin(b'.hgchurn')
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
   203
    if aliases:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   204
        for l in open(aliases, b"rb"):
12069
7c3c44413bc1 churn: do not crash on malformed lines in alias file
Martin Geisler <mg@lazybytes.net>
parents: 12068
diff changeset
   205
            try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   206
                alias, actual = l.rsplit(b'=' in l and b'=' or None, 1)
12069
7c3c44413bc1 churn: do not crash on malformed lines in alias file
Martin Geisler <mg@lazybytes.net>
parents: 12068
diff changeset
   207
                amap[alias.strip()] = actual.strip()
7c3c44413bc1 churn: do not crash on malformed lines in alias file
Martin Geisler <mg@lazybytes.net>
parents: 12068
diff changeset
   208
            except ValueError:
7c3c44413bc1 churn: do not crash on malformed lines in alias file
Martin Geisler <mg@lazybytes.net>
parents: 12068
diff changeset
   209
                l = l.strip()
7c3c44413bc1 churn: do not crash on malformed lines in alias file
Martin Geisler <mg@lazybytes.net>
parents: 12068
diff changeset
   210
                if l:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   211
                    ui.warn(_(b"skipping malformed alias: %s\n") % l)
12068
2e7647d25458 churn: do not crash on empty lines in alias file
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 11321
diff changeset
   212
                continue
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
   213
36392
e9bcc2efb7e8 py3: convert dict.items() to list explicitly
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35888
diff changeset
   214
    rate = list(countrate(ui, repo, amap, *pats, **opts).items())
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   215
    if not rate:
5588
083b6e3142a2 churn: avoid division by zero
Matt Mackall <mpm@selenic.com>
parents: 5482
diff changeset
   216
        return
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
   217
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43085
diff changeset
   218
    if opts.get('sort'):
18369
2150e70c0ee1 churn: sort users with same churn by name
Mads Kiilerich <mads@kiilerich.com>
parents: 17773
diff changeset
   219
        rate.sort()
2150e70c0ee1 churn: sort users with same churn by name
Mads Kiilerich <mads@kiilerich.com>
parents: 17773
diff changeset
   220
    else:
2150e70c0ee1 churn: sort users with same churn by name
Mads Kiilerich <mads@kiilerich.com>
parents: 17773
diff changeset
   221
        rate.sort(key=lambda x: (-sum(x[1]), x))
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   222
9388
f7968bba2307 churn: issue833 was reintroduced in 9bc46d069a76, correct it and add a test
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8934
diff changeset
   223
    # Be careful not to have a zero maxcount (issue833)
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
   224
    maxcount = float(max(sum(v) for k, v in rate)) or 1.0
9390
637f2726ec7f churn: use genexps now that we dropped 2.3 compatibility
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9389
diff changeset
   225
    maxname = max(len(k) for k, v in rate)
3040
f74077473b36 Churn extension
Josef "Jeff" Sipek <jeff@josefsipek.net>
parents:
diff changeset
   226
12689
c52c629ce19e termwidth: move to ui.ui from util
Augie Fackler <durin42@gmail.com>
parents: 12070
diff changeset
   227
    ttywidth = ui.termwidth()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   228
    ui.debug(b"assuming %i character terminal\n" % ttywidth)
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
   229
    width = ttywidth - maxname - 2 - 2 - 2
7065
9bc46d069a76 churn: generalisation, now it is possible to see statistics grouped by custom template
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7051
diff changeset
   230
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43085
diff changeset
   231
    if opts.get('diffstat'):
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
   232
        width -= 15
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   233
11501
deb5d02ae91c churn: remove tuple parameter unpacking (deprecated in py3k)
Renato Cunha <renatoc@gmail.com>
parents: 11321
diff changeset
   234
        def format(name, diffstat):
deb5d02ae91c churn: remove tuple parameter unpacking (deprecated in py3k)
Renato Cunha <renatoc@gmail.com>
parents: 11321
diff changeset
   235
            added, removed = diffstat
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   236
            return b"%s %15s %s%s\n" % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   237
                pad(name, maxname),
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   238
                b'+%d/-%d' % (added, removed),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   239
                ui.label(b'+' * charnum(added), b'diffstat.inserted'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   240
                ui.label(b'-' * charnum(removed), b'diffstat.deleted'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   241
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   242
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
   243
    else:
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
   244
        width -= 6
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   245
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
   246
        def format(name, count):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   247
            return b"%s %6d %s\n" % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   248
                pad(name, maxname),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   249
                sum(count),
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   250
                b'*' * charnum(sum(count)),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40293
diff changeset
   251
            )
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
   252
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
   253
    def charnum(count):
40264
12e2e5cd5777 churn: remove redundant round()
Augie Fackler <augie@google.com>
parents: 40241
diff changeset
   254
        return int(count * width // maxcount)
9669
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
   255
9b127e888640 churn: ability to display added/removed lines separately
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9665
diff changeset
   256
    for name, count in rate:
11310
ac873ecfc3c2 Backed out changeset: e1dde7363601
Steve Borho <steve@borho.org>
parents: 11302
diff changeset
   257
        ui.write(format(name, count))