mirror of
https://github.com/facebook/sapling.git
synced 2024-12-26 14:34:34 +03:00
hgext: remove the churn extension
Summary: Not that useful and does not align with the direction we are headed. Reviewed By: quark-zju Differential Revision: D22213796 fbshipit-source-id: ffd86fc1a9207c134448836d0e54e48510a11135
This commit is contained in:
parent
dde49c1c44
commit
cd49247df6
@ -1,249 +0,0 @@
|
||||
# Portions Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This software may be used and distributed according to the terms of the
|
||||
# GNU General Public License version 2.
|
||||
|
||||
# churn.py - create a graph of revisions count grouped by template
|
||||
#
|
||||
# Copyright 2006 Josef "Jeff" Sipek <jeffpc@josefsipek.net>
|
||||
# Copyright 2008 Alexander Solovyov <piranha@piranha.org.ua>
|
||||
#
|
||||
# This software may be used and distributed according to the terms of the
|
||||
# GNU General Public License version 2 or any later version.
|
||||
|
||||
"""command to display statistics about repository history"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import time
|
||||
|
||||
from edenscm.mercurial import (
|
||||
cmdutil,
|
||||
encoding,
|
||||
patch,
|
||||
progress,
|
||||
pycompat,
|
||||
registrar,
|
||||
scmutil,
|
||||
util,
|
||||
)
|
||||
from edenscm.mercurial.i18n import _
|
||||
|
||||
|
||||
cmdtable = {}
|
||||
command = registrar.command(cmdtable)
|
||||
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
|
||||
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
|
||||
# be specifying the version(s) of Mercurial they are tested with, or
|
||||
# leave the attribute unspecified.
|
||||
testedwith = "ships-with-hg-core"
|
||||
|
||||
|
||||
def changedlines(ui, repo, ctx1, ctx2, fns):
|
||||
added, removed = 0, 0
|
||||
fmatch = scmutil.matchfiles(repo, fns)
|
||||
diff = "".join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch))
|
||||
for l in diff.split("\n"):
|
||||
if l.startswith("+") and not l.startswith("+++ "):
|
||||
added += 1
|
||||
elif l.startswith("-") and not l.startswith("--- "):
|
||||
removed += 1
|
||||
return (added, removed)
|
||||
|
||||
|
||||
def countrate(ui, repo, amap, *pats, **opts):
|
||||
"""Calculate stats"""
|
||||
if opts.get("dateformat"):
|
||||
|
||||
def getkey(ctx):
|
||||
t, tz = ctx.date()
|
||||
date = datetime.datetime(*time.gmtime(float(t) - tz)[:6])
|
||||
return date.strftime(opts["dateformat"])
|
||||
|
||||
else:
|
||||
tmpl = opts.get("oldtemplate") or opts.get("template")
|
||||
tmpl = cmdutil.makelogtemplater(ui, repo, tmpl)
|
||||
|
||||
def getkey(ctx):
|
||||
ui.pushbuffer()
|
||||
tmpl.show(ctx)
|
||||
return ui.popbuffer()
|
||||
|
||||
rate = {}
|
||||
df = False
|
||||
if opts.get("date"):
|
||||
df = util.matchdate(opts["date"])
|
||||
|
||||
prog = progress.bar(ui, _("analyzing"), _("revisions"), len(repo))
|
||||
m = scmutil.match(repo[None], pats, opts)
|
||||
|
||||
def prep(ctx, fns):
|
||||
rev = ctx.rev()
|
||||
if df and not df(ctx.date()[0]): # doesn't match date format
|
||||
return
|
||||
|
||||
key = getkey(ctx).strip()
|
||||
key = amap.get(key, key) # alias remap
|
||||
if opts.get("changesets"):
|
||||
rate[key] = (rate.get(key, (0,))[0] + 1, 0)
|
||||
else:
|
||||
parents = ctx.parents()
|
||||
if len(parents) > 1:
|
||||
ui.note(_("revision %d is a merge, ignoring...\n") % (rev,))
|
||||
return
|
||||
|
||||
ctx1 = parents[0]
|
||||
lines = changedlines(ui, repo, ctx1, ctx, fns)
|
||||
rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)]
|
||||
|
||||
prog.value += 1
|
||||
|
||||
with prog:
|
||||
for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
|
||||
continue
|
||||
|
||||
return rate
|
||||
|
||||
|
||||
@command(
|
||||
"churn",
|
||||
[
|
||||
(
|
||||
"r",
|
||||
"rev",
|
||||
[],
|
||||
_("count rate for the specified revision or revset"),
|
||||
_("REV"),
|
||||
),
|
||||
("d", "date", "", _("count rate for revisions matching date spec"), _("DATE")),
|
||||
(
|
||||
"t",
|
||||
"oldtemplate",
|
||||
"",
|
||||
_("template to group changesets (DEPRECATED)"),
|
||||
_("TEMPLATE"),
|
||||
),
|
||||
(
|
||||
"T",
|
||||
"template",
|
||||
"{author|email}",
|
||||
_("template to group changesets"),
|
||||
_("TEMPLATE"),
|
||||
),
|
||||
(
|
||||
"f",
|
||||
"dateformat",
|
||||
"",
|
||||
_("strftime-compatible format for grouping by date"),
|
||||
_("FORMAT"),
|
||||
),
|
||||
("c", "changesets", False, _("count rate by number of changesets")),
|
||||
("s", "sort", False, _("sort by key (default: sort by count)")),
|
||||
("", "diffstat", False, _("display added/removed lines separately")),
|
||||
("", "aliases", "", _("file with email aliases"), _("FILE")),
|
||||
]
|
||||
+ cmdutil.walkopts,
|
||||
_("hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]"),
|
||||
inferrepo=True,
|
||||
)
|
||||
def churn(ui, repo, *pats, **opts):
|
||||
"""histogram of changes to the repository
|
||||
|
||||
This command will display a histogram representing the number
|
||||
of changed lines or revisions, grouped according to the given
|
||||
template. The default template will group changes by author.
|
||||
The --dateformat option may be used to group the results by
|
||||
date instead.
|
||||
|
||||
Statistics are based on the number of changed lines, or
|
||||
alternatively the number of matching revisions if the
|
||||
--changesets option is specified.
|
||||
|
||||
Examples::
|
||||
|
||||
# display count of changed lines for every committer
|
||||
hg churn -T "{author|email}"
|
||||
|
||||
# display daily activity graph
|
||||
hg churn -f "%H" -s -c
|
||||
|
||||
# display activity of developers by month
|
||||
hg churn -f "%Y-%m" -s -c
|
||||
|
||||
# display count of lines changed in every year
|
||||
hg churn -f "%Y" -s
|
||||
|
||||
It is possible to map alternate email addresses to a main address
|
||||
by providing a file using the following format::
|
||||
|
||||
<alias email> = <actual email>
|
||||
|
||||
Such a file may be specified with the --aliases option, otherwise
|
||||
a .hgchurn file will be looked for in the working directory root.
|
||||
Aliases will be split from the rightmost "=".
|
||||
"""
|
||||
|
||||
def pad(s, l):
|
||||
return s + " " * (l - encoding.colwidth(s))
|
||||
|
||||
amap = {}
|
||||
aliases = opts.get(r"aliases")
|
||||
if not aliases and os.path.exists(repo.wjoin(".hgchurn")):
|
||||
aliases = repo.wjoin(".hgchurn")
|
||||
if aliases:
|
||||
for l in open(aliases, "r"):
|
||||
try:
|
||||
alias, actual = l.rsplit("=" in l and "=" or None, 1)
|
||||
amap[alias.strip()] = actual.strip()
|
||||
except ValueError:
|
||||
l = l.strip()
|
||||
if l:
|
||||
ui.warn(_("skipping malformed alias: %s\n") % l)
|
||||
continue
|
||||
|
||||
rate = countrate(ui, repo, amap, *pats, **opts).items()
|
||||
if not rate:
|
||||
return
|
||||
|
||||
if opts.get(r"sort"):
|
||||
rate.sort()
|
||||
else:
|
||||
rate.sort(key=lambda x: (-sum(x[1]), x))
|
||||
|
||||
# Be careful not to have a zero maxcount (issue833)
|
||||
maxcount = float(max(sum(v) for k, v in rate)) or 1.0
|
||||
maxname = max(len(k) for k, v in rate)
|
||||
|
||||
ttywidth = ui.termwidth()
|
||||
ui.debug("assuming %i character terminal\n" % ttywidth)
|
||||
width = ttywidth - maxname - 2 - 2 - 2
|
||||
|
||||
if opts.get(r"diffstat"):
|
||||
width -= 15
|
||||
|
||||
def format(name, diffstat):
|
||||
added, removed = diffstat
|
||||
return "%s %15s %s%s\n" % (
|
||||
pad(name, maxname),
|
||||
"+%d/-%d" % (added, removed),
|
||||
ui.label("+" * charnum(added), "diffstat.inserted"),
|
||||
ui.label("-" * charnum(removed), "diffstat.deleted"),
|
||||
)
|
||||
|
||||
else:
|
||||
width -= 6
|
||||
|
||||
def format(name, count):
|
||||
return "%s %6d %s\n" % (
|
||||
pad(name, maxname),
|
||||
sum(count),
|
||||
"*" * charnum(sum(count)),
|
||||
)
|
||||
|
||||
def charnum(count):
|
||||
return int(round(count * width / maxcount))
|
||||
|
||||
for name, count in rate:
|
||||
ui.write(format(name, count))
|
@ -1065,8 +1065,8 @@ or ``foo = !`` when path is not supplied.
|
||||
Example for ``~/.hgrc``::
|
||||
|
||||
[extensions]
|
||||
# (the churn extension will get loaded from Mercurial's path)
|
||||
churn =
|
||||
# (the amend extension will get loaded from Mercurial's path)
|
||||
amend =
|
||||
# (this extension will get loaded from the file specified)
|
||||
myfeature = ~/.hgext/myfeature.py
|
||||
|
||||
|
@ -74,7 +74,7 @@ username =
|
||||
# uncomment these lines to enable some popular extensions
|
||||
# (see 'hg help extensions' for more info)
|
||||
#
|
||||
# churn =
|
||||
# amend =
|
||||
""",
|
||||
"cloned": """# example repository config (see 'hg help config' for more info)
|
||||
[paths]
|
||||
@ -121,7 +121,7 @@ default = %s
|
||||
# (see 'hg help extensions' for more info)
|
||||
#
|
||||
# blackbox =
|
||||
# churn =
|
||||
# amend =
|
||||
""",
|
||||
}
|
||||
|
||||
|
@ -1,199 +0,0 @@
|
||||
#require py2
|
||||
#chg-compatible
|
||||
|
||||
$ enable churn
|
||||
|
||||
create test repository
|
||||
|
||||
$ hg init repo
|
||||
$ cd repo
|
||||
$ echo a > a
|
||||
$ hg ci -Am adda -u user1 -d 6:00
|
||||
adding a
|
||||
$ echo b >> a
|
||||
$ echo b > b
|
||||
$ hg ci -m changeba -u user2 -d 9:00 a
|
||||
$ hg ci -Am addb -u user2 -d 9:30
|
||||
adding b
|
||||
$ echo c >> a
|
||||
$ echo c >> b
|
||||
$ echo c > c
|
||||
$ hg ci -m changeca -u user3 -d 12:00 a
|
||||
$ hg ci -m changecb -u user3 -d 12:15 b
|
||||
$ hg ci -Am addc -u user3 -d 12:30
|
||||
adding c
|
||||
$ mkdir -p d/e
|
||||
$ echo abc > d/e/f1.txt
|
||||
$ hg ci -Am "add d/e/f1.txt" -u user1 -d 12:45 d/e/f1.txt
|
||||
$ mkdir -p d/g
|
||||
$ echo def > d/g/f2.txt
|
||||
$ hg ci -Am "add d/g/f2.txt" -u user1 -d 13:00 d/g/f2.txt
|
||||
|
||||
|
||||
churn separate directories
|
||||
|
||||
$ cd d
|
||||
$ hg churn e
|
||||
user1 1 ***************************************************************
|
||||
|
||||
churn all
|
||||
|
||||
$ hg churn
|
||||
user1 3 ***************************************************************
|
||||
user3 3 ***************************************************************
|
||||
user2 2 ******************************************
|
||||
|
||||
churn excluding one dir
|
||||
|
||||
$ hg churn -X e
|
||||
user3 3 ***************************************************************
|
||||
user1 2 ******************************************
|
||||
user2 2 ******************************************
|
||||
|
||||
churn up to rev 2
|
||||
|
||||
$ hg churn -r :2
|
||||
user2 2 ***************************************************************
|
||||
user1 1 ********************************
|
||||
$ cd ..
|
||||
|
||||
churn with aliases
|
||||
|
||||
$ cat > ../aliases <<EOF
|
||||
> user1 alias1
|
||||
> user3 alias3
|
||||
> not-an-alias
|
||||
> EOF
|
||||
|
||||
churn with .hgchurn
|
||||
|
||||
$ mv ../aliases .hgchurn
|
||||
$ hg churn
|
||||
skipping malformed alias: not-an-alias
|
||||
alias1 3 **************************************************************
|
||||
alias3 3 **************************************************************
|
||||
user2 2 *****************************************
|
||||
$ rm .hgchurn
|
||||
|
||||
churn with column specifier
|
||||
|
||||
$ COLUMNS=40 hg churn
|
||||
user1 3 ***********************
|
||||
user3 3 ***********************
|
||||
user2 2 ***************
|
||||
|
||||
churn by hour
|
||||
|
||||
$ hg churn -f '%H' -s
|
||||
06 1 *****************
|
||||
09 2 *********************************
|
||||
12 4 ******************************************************************
|
||||
13 1 *****************
|
||||
|
||||
|
||||
churn with separated added/removed lines
|
||||
|
||||
$ hg rm d/g/f2.txt
|
||||
$ hg ci -Am "removed d/g/f2.txt" -u user1 -d 14:00 d/g/f2.txt
|
||||
$ hg churn --diffstat
|
||||
user1 +3/-1 +++++++++++++++++++++++++++++++++++++++++--------------
|
||||
user3 +3/-0 +++++++++++++++++++++++++++++++++++++++++
|
||||
user2 +2/-0 +++++++++++++++++++++++++++
|
||||
|
||||
churn --diffstat with color
|
||||
|
||||
$ hg --config extensions.color= churn --config color.mode=ansi \
|
||||
> --diffstat --color=always
|
||||
user1 +3/-1 \x1b[0;32m+++++++++++++++++++++++++++++++++++++++++\x1b[0m\x1b[0;31m--------------\x1b[0m (esc)
|
||||
user3 +3/-0 \x1b[0;32m+++++++++++++++++++++++++++++++++++++++++\x1b[0m (esc)
|
||||
user2 +2/-0 \x1b[0;32m+++++++++++++++++++++++++++\x1b[0m (esc)
|
||||
|
||||
|
||||
changeset number churn
|
||||
|
||||
$ hg churn -c
|
||||
user1 4 ***************************************************************
|
||||
user3 3 ***********************************************
|
||||
user2 2 ********************************
|
||||
|
||||
$ echo 'with space = no-space' >> ../aliases
|
||||
$ echo a >> a
|
||||
$ hg commit -m a -u 'with space' -d 15:00
|
||||
|
||||
churn with space in alias
|
||||
|
||||
$ hg churn --aliases ../aliases -r tip
|
||||
no-space 1 ************************************************************
|
||||
|
||||
$ cd ..
|
||||
|
||||
|
||||
Issue833: ZeroDivisionError
|
||||
|
||||
$ hg init issue-833
|
||||
$ cd issue-833
|
||||
$ touch foo
|
||||
$ hg ci -Am foo
|
||||
adding foo
|
||||
|
||||
this was failing with a ZeroDivisionError
|
||||
|
||||
$ hg churn
|
||||
test 0
|
||||
$ cd ..
|
||||
|
||||
Ignore trailing or leading spaces in emails
|
||||
|
||||
$ cd repo
|
||||
$ touch bar
|
||||
$ hg ci -Am'bar' -u 'user4 <user4@x.com>'
|
||||
adding bar
|
||||
$ touch foo
|
||||
$ hg ci -Am'foo' -u 'user4 < user4@x.com >'
|
||||
adding foo
|
||||
$ hg log -l2 --template '[{author|email}]\n'
|
||||
[ user4@x.com ]
|
||||
[user4@x.com]
|
||||
$ hg churn -c
|
||||
user1 4 *********************************************************
|
||||
user3 3 *******************************************
|
||||
user2 2 *****************************
|
||||
user4@x.com 2 *****************************
|
||||
with space 1 **************
|
||||
|
||||
Test multibyte sequences in names
|
||||
|
||||
$ echo bar >> bar
|
||||
$ hg --encoding utf-8 ci -m'changed bar' -u 'El Niño <nino@x.com>'
|
||||
$ hg --encoding utf-8 churn -ct '{author|person}'
|
||||
user1 4 **********************************************************
|
||||
user3 3 ********************************************
|
||||
user2 2 *****************************
|
||||
user4 2 *****************************
|
||||
El Ni\xc3\xb1o 1 *************** (esc)
|
||||
with space 1 ***************
|
||||
|
||||
Test --template argument, with backwards compatibility
|
||||
|
||||
$ hg churn -t '{author|user}'
|
||||
user1 4 ***************************************************************
|
||||
user3 3 ***********************************************
|
||||
user2 2 ********************************
|
||||
nino 1 ****************
|
||||
with 1 ****************
|
||||
0
|
||||
user4 0
|
||||
$ hg churn -T '{author|user}'
|
||||
user1 4 ***************************************************************
|
||||
user3 3 ***********************************************
|
||||
user2 2 ********************************
|
||||
nino 1 ****************
|
||||
with 1 ****************
|
||||
0
|
||||
user4 0
|
||||
$ hg churn -t 'alltogether'
|
||||
alltogether 11 *********************************************************
|
||||
$ hg churn -T 'alltogether'
|
||||
alltogether 11 *********************************************************
|
||||
|
||||
$ cd ..
|
@ -894,8 +894,8 @@ Disabled extension commands:
|
||||
$ ORGHGRCPATH=$HGRCPATH
|
||||
$ HGRCPATH=
|
||||
$ export HGRCPATH
|
||||
$ hg churn
|
||||
unknown command 'churn'
|
||||
$ hg amend
|
||||
unknown command 'amend'
|
||||
(use 'hg help' to get help)
|
||||
[255]
|
||||
|
||||
@ -903,8 +903,47 @@ Disabled extension commands:
|
||||
|
||||
Disabled extensions:
|
||||
|
||||
$ hg help churn
|
||||
churn extension - command to display statistics about repository history
|
||||
$ hg help amend
|
||||
amend extension - extends the existing commit amend functionality
|
||||
|
||||
Adds an hg amend command that amends the current parent changeset with the
|
||||
changes in the working copy. Similar to the existing hg commit --amend except
|
||||
it doesn't prompt for the commit message unless --edit is provided.
|
||||
|
||||
Allows amending changesets that have children and can automatically rebase the
|
||||
children onto the new version of the changeset.
|
||||
|
||||
To make 'hg previous' and 'hg next' always pick the newest commit at each step
|
||||
of walking up or down the stack instead of aborting when encountering non-
|
||||
linearity (equivalent to the --newest flag), enable the following config
|
||||
option:
|
||||
|
||||
[amend]
|
||||
alwaysnewest = true
|
||||
|
||||
To automatically update the commit date, enable the following config option:
|
||||
|
||||
[amend]
|
||||
date = implicitupdate
|
||||
|
||||
Commits are restacked automatically on amend, if doing so doesn't create
|
||||
conflicts. To never automatically restack:
|
||||
|
||||
[amend]
|
||||
autorestack = none
|
||||
|
||||
Note that if --date is specified on the command line, it takes precedence.
|
||||
|
||||
If a split creates multiple commits that have the same phabricator diff, the
|
||||
following advice for resolution will be shown:
|
||||
|
||||
[split]
|
||||
phabricatoradvice = edit the commit messages to remove the association
|
||||
|
||||
To make `hg next` prefer draft commits in case of ambiguity, enable the following config option:
|
||||
|
||||
[update]
|
||||
nextpreferdraft = true
|
||||
|
||||
(use 'hg help extensions' for information on enabling extensions)
|
||||
|
||||
|
@ -290,7 +290,6 @@ Test extension help:
|
||||
checkserverbookmark
|
||||
(no help text available)
|
||||
chistedit
|
||||
churn command to display statistics about repository history
|
||||
clienttelemetry
|
||||
provide information about the client in server telemetry
|
||||
clindex (no help text available)
|
||||
|
Loading…
Reference in New Issue
Block a user