[PATCH] diff: add a --numstat option
Steve Losh
steve at stevelosh.com
Thu Jun 10 17:30:44 CDT 2010
Sorry, I forgot that one-patch bombs need the --intro option.
This patch adds --numstat to 'hg diff', which acts exactly like the git version. The output looks like this:
$ ./hg diff --numstat -c tip
12 6 mercurial/cmdutil.py
4 1 mercurial/commands.py
...
The first column is lines added, second is lines removed, and third is the filename relative to the root of the repo.
This command is a more machine-friendly version of 'hg diff --stat'. The application I have in mind that would benefit from this is PeepOpen[1], but I'm sure there are others that could find it useful.
I picked git's output format over that of 'diffstat -t' because I wanted to make it easier for applications that already do something with 'git diff --numstat' to simply drop in support for Mercurial as well.
[1]: http://peepcode.com/products/peepopen
--
Steve Losh
http://stevelosh.com/
On Jun 10, 2010, at 6:25 PM, Steve Losh wrote:
> # HG changeset patch
> # User Steve Losh <steve at stevelosh.com>
> # Date 1276121593 14400
> # Node ID d5da202dea40fd5ee68617ebdc09119a17ade27b
> # Parent 666b62c527678b4655a7c293ee636eef25a65b8f
> diff: add a --numstat option
>
> This patch adds a --numstat option to the diff command to output a numeric
> summary of changes.
>
> The output is formatted exactly like the git version:
>
> ADDS\tREMOVES\tFILENAME
>
> If the --stat and --numstat options are given together both summaries will be
> printed, with the numeric summary first (matching git's behavior).
>
> The relevant tests are also updated.
>
> diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
> --- a/mercurial/cmdutil.py
> +++ b/mercurial/cmdutil.py
> @@ -645,28 +645,34 @@
>
> for seqno, rev in enumerate(revs):
> single(rev, seqno + 1, fp)
>
> def diffordiffstat(ui, repo, diffopts, node1, node2, match,
> - changes=None, stat=False, fp=None):
> + changes=None, stat=False, fp=None, numstat=False):
> '''show diff or diffstat.'''
> if fp is None:
> write = ui.write
> else:
> def write(s, **kw):
> fp.write(s)
>
> - if stat:
> + if stat or numstat:
> diffopts.context = 0
> width = 80
> if not ui.plain():
> width = util.termwidth()
> chunks = patch.diff(repo, node1, node2, match, changes, diffopts)
> - for chunk, label in patch.diffstatui(util.iterlines(chunks),
> - width=width,
> - git=diffopts.git):
> - write(chunk, label=label)
> + if stat and numstat:
> + chunks = list(chunks)
> + if numstat:
> + for chunk, label in patch.numstatui(util.iterlines(chunks)):
> + write(chunk, label=label)
> + if stat:
> + for chunk, label in patch.diffstatui(util.iterlines(chunks),
> + width=width,
> + git=diffopts.git):
> + write(chunk, label=label)
> else:
> for chunk, label in patch.diffui(repo, node1, node2, match,
> changes, diffopts):
> write(chunk, label=label)
>
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -1212,10 +1212,11 @@
> """
>
> revs = opts.get('rev')
> change = opts.get('change')
> stat = opts.get('stat')
> + numstat = opts.get('numstat')
> reverse = opts.get('reverse')
>
> if revs and change:
> msg = _('cannot specify --rev and --change at the same time')
> raise util.Abort(msg)
> @@ -1228,11 +1229,12 @@
> if reverse:
> node1, node2 = node2, node1
>
> diffopts = patch.diffopts(ui, opts)
> m = cmdutil.match(repo, pats, opts)
> - cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat)
> + cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m,
> + stat=stat, numstat=numstat)
>
> def export(ui, repo, *changesets, **opts):
> """dump the header and diffs for one or more changesets
>
> Print the changeset header and diffs for one or more revisions.
> @@ -3655,10 +3657,11 @@
> _('ignore changes in the amount of white space')),
> ('B', 'ignore-blank-lines', None,
> _('ignore changes whose lines are all blank')),
> ('U', 'unified', '', _('number of lines of context to show')),
> ('', 'stat', None, _('output diffstat-style summary of changes')),
> + ('', 'numstat', None, _('output numeric-style summary of changes')),
> ]
>
> similarityopts = [
> ('s', 'similarity', '',
> _('guess renamed files by similarity (0<=s<=100)'))
> diff --git a/mercurial/patch.py b/mercurial/patch.py
> --- a/mercurial/patch.py
> +++ b/mercurial/patch.py
> @@ -1708,5 +1708,12 @@
> if m:
> yield (m.group(0), 'diffstat.deleted')
> else:
> yield (line, '')
> yield ('\n', '')
> +
> +def numstatui(lines):
> + output = ('%d\t%d\t%s\n' % (adds, removes, filename)
> + for filename, adds, removes, isbinary in diffstatdata(lines)
> + if not isbinary)
> + for line in output:
> + yield (line, '')
> diff --git a/tests/test-debugcomplete.out b/tests/test-debugcomplete.out
> --- a/tests/test-debugcomplete.out
> +++ b/tests/test-debugcomplete.out
> @@ -166,11 +166,11 @@
> % Show all commands + options
> add: include, exclude, dry-run
> annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
> clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd
> commit: addremove, close-branch, include, exclude, message, logfile, date, user
> -diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
> +diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, numstat, include, exclude
> export: output, switch-parent, rev, text, git, nodates
> forget: include, exclude
> init: ssh, remotecmd
> log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, style, template, include, exclude
> merge: force, rev, preview
> diff --git a/tests/test-diffstat b/tests/test-diffstat
> --- a/tests/test-diffstat
> +++ b/tests/test-diffstat
> @@ -4,11 +4,11 @@
> cd repo
> i=0; while [ "$i" -lt 213 ]; do echo a >> a; i=`expr $i + 1`; done
> hg add a
>
> echo '% wide diffstat'
> -hg diff --stat
> +hg diff --stat --numstat
>
> echo '% diffstat width'
> COLUMNS=24 hg diff --config ui.interactive=true --stat
>
> hg ci -m adda
> @@ -18,17 +18,17 @@
> a
> a
> EOF
>
> echo '% narrow diffstat'
> -hg diff --stat
> +hg diff --stat --numstat
>
> hg ci -m appenda
>
> printf '\0' > b
> hg add b
>
> echo '% binary diffstat'
> -hg diff --stat
> +hg diff --stat --numstat
>
> echo '% binary git diffstat'
> -hg diff --stat --git
> +hg diff --stat --git --numstat
> diff --git a/tests/test-diffstat.out b/tests/test-diffstat.out
> --- a/tests/test-diffstat.out
> +++ b/tests/test-diffstat.out
> @@ -1,12 +1,14 @@
> % wide diffstat
> +213 0 a
> a | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 213 insertions(+), 0 deletions(-)
> % diffstat width
> a | 213 ++++++++++++++
> 1 files changed, 213 insertions(+), 0 deletions(-)
> % narrow diffstat
> +3 0 a
> a | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
> % binary diffstat
> b | 0
> 1 files changed, 0 insertions(+), 0 deletions(-)
> diff --git a/tests/test-help.out b/tests/test-help.out
> --- a/tests/test-help.out
> +++ b/tests/test-help.out
> @@ -411,10 +411,11 @@
> -w --ignore-all-space ignore white space when comparing lines
> -b --ignore-space-change ignore changes in the amount of white space
> -B --ignore-blank-lines ignore changes whose lines are all blank
> -U --unified number of lines of context to show
> --stat output diffstat-style summary of changes
> + --numstat output numeric-style summary of changes
> -I --include include names matching the given patterns
> -X --exclude exclude names matching the given patterns
>
> use "hg -v help diff" to show global options
> hg status [OPTION]... [FILE]...
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list