[PATCH] python implementation of diffstat
Benoît Allard
benoit at aeteurope.nl
Mon Dec 22 10:33:04 UTC 2008
Nice idea ! especially on windows ! thanks.
Minor comments follow
Alexander Solovyov wrote:
> # HG changeset patch
> # User Alexander Solovyov <piranha at piranha.org.ua>
> # Date 1229896341 -7200
> # Node ID c460e0ccdbf8beb293dc834f93fa854668b24dc8
> # Parent 3896310bd797a3c0db22654321e88db9cc73d3e7
> python implementation of diffstat
>
> Implemented as a two function: diffstat, which yields lines of text,
> formatted as a usual diffstat output, and diffstatdata, which is called
> inside diffstat to do real performing and yield file names with
> appropriate data (numbers of added and removed lines).
>
> diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py
> --- a/hgext/patchbomb.py
> +++ b/hgext/patchbomb.py
> @@ -9,8 +9,7 @@
>
> The remainder of the changeset description.
>
> - [Optional] If the diffstat program is installed, the result of
> - running diffstat on the patch.
> + [Optional] The result of running diffstat on the patch.
>
> The patch itself, as generated by "hg export".
>
> @@ -98,17 +97,13 @@
> ui.warn(_('Please enter a valid value.\n'))
>
> def cdiffstat(ui, summary, patchlines):
> - s = patch.diffstat(patchlines)
> - if s:
> - if summary:
> - ui.write(summary, '\n')
> - ui.write(s, '\n')
> - ans = prompt(ui, _('Does the diffstat above look okay? '), 'y')
> - if not ans.lower().startswith('y'):
> - raise util.Abort(_('diffstat rejected'))
> - elif s is None:
> - ui.warn(_('no diffstat information available\n'))
> - s = ''
> + s = ''.join(patch.diffstat(patchlines))
> + if summary:
> + ui.write(summary, '\n')
> + ui.write(s, '\n')
> + ans = prompt(ui, _('Does the diffstat above look okay? '), 'y')
> + if not ans.lower().startswith('y'):
> + raise util.Abort(_('diffstat rejected'))
> return s
>
> def makepatch(ui, repo, patch, opts, _charsets, idx, total, patchname=None):
> diff --git a/mercurial/patch.py b/mercurial/patch.py
> --- a/mercurial/patch.py
> +++ b/mercurial/patch.py
> @@ -1344,13 +1344,55 @@
> for seqno, rev in enumerate(revs):
> single(rev, seqno+1, fp)
>
> -def diffstat(patchlines):
> - if not util.find_exe('diffstat'):
> - return
> - output = util.filter('\n'.join(patchlines),
> - 'diffstat -p1 -w79 2>%s' % util.nulldev)
> - stat = [l.lstrip() for l in output.splitlines(True)]
> - last = stat.pop()
> - stat.insert(0, last)
> - stat = ''.join(stat)
> - return stat
> +def diffstatdata(lines):
> + filename = None
> + for line in lines:
> + if line.startswith('diff'):
> + if filename:
> + yield (filename, adds, removes)
> + # set numbers to 0 anyway when starting new file
> + adds = 0
> + removes = 0
> + if line.startswith('diff --git'):
> + filename = gitre.search(line).group(1)
> + else:
> + # format: "diff -r ... -r ... file name"
> + filename = line.split(None, 5)[-1]
> + elif line.startswith('+') and not line.startswith('+++'):
> + adds += 1
> + elif line.startswith('-') and not line.startswith('---'):
> + removes += 1
> + yield (filename, adds, removes)
> +
> +def diffstat(lines):
> + stats = list(diffstatdata(lines))
> + width = 78
The churn extension reads here the width of the terminal look at
get_tty_width.
> +
> + maxtotal, maxname = 0, 0
> + totaladds, totalremoves = 0, 0
> + for filename, adds, removes in stats:
> + totaladds += adds
> + totalremoves += removes
> + maxname = max(maxname, len(filename))
> + maxtotal = max(maxtotal, adds+removes)
> +
> + countwidth = len(str(maxtotal))
> + graphwidth = width - countwidth - maxname
> + if graphwidth < 10:
> + graphwidth = 10
> +
> + factor = 1
> + while (maxtotal / factor) > graphwidth:
> + factor += 1
> +
> + if stats:
> + yield (' %d files changed, %d insertions(+), %d deletions(-)\n' %
> + (len(stats), totaladds, totalremoves))
> +
> + for filename, adds, removes in stats:
> + # If diffstat runs out of room it doesn't print anything, which
> + # isn't very useful, so always print at least one + or 1
"one + or -"
When this make sense for big 'factor', this leads to printing a '-' even
if there is no deletion (see test results), something like
max(adds/factor, (adds or 0) and 1) should do the trick.
> + pluses = '+' * max(adds/factor, 1)
> + minuses = '-' * max(removes/factor, 1)
> + yield ' %-*s | %*.d %s%s\n' % (maxname, filename, countwidth,
> + adds+removes, pluses, minuses)
> diff --git a/tests/test-notify.out b/tests/test-notify.out
> --- a/tests/test-notify.out
> +++ b/tests/test-notify.out
> @@ -150,7 +150,8 @@
> b
> diffstat:
>
> -files patched: 1
> + 1 files changed, 1 insertions(+), 0 deletions(-)
> + a | 1 +-
>
> diffs (6 lines):
>
> diff --git a/tests/test-patchbomb.out b/tests/test-patchbomb.out
> --- a/tests/test-patchbomb.out
> +++ b/tests/test-patchbomb.out
> @@ -196,7 +196,8 @@
>
> c
>
> -files patched: 1
> + 1 files changed, 1 insertions(+), 0 deletions(-)
> + c | 1 +-
>
>
> Displaying [PATCH] test ...
> @@ -211,7 +212,8 @@
> To: foo
> Cc: bar
>
> -files patched: 1
> + 1 files changed, 1 insertions(+), 0 deletions(-)
> + c | 1 +-
>
>
> # HG changeset patch
> @@ -232,15 +234,19 @@
>
> a
>
> -files patched: 1
> + 1 files changed, 1 insertions(+), 0 deletions(-)
> + a | 1 +-
>
> b
>
> -files patched: 1
> + 1 files changed, 1 insertions(+), 0 deletions(-)
> + b | 1 +-
>
> Final summary:
>
> -files patched: 2
> + 2 files changed, 2 insertions(+), 0 deletions(-)
> + a | 1 +-
> + b | 1 +-
>
>
> Write the introductory message for the patch series.
> @@ -258,7 +264,9 @@
> Cc: bar
>
>
> -files patched: 2
> + 2 files changed, 2 insertions(+), 0 deletions(-)
> + a | 1 +-
> + b | 1 +-
>
> Displaying [PATCH 1 of 2] a ...
> Content-Type: text/plain; charset="us-ascii"
> @@ -274,7 +282,8 @@
> To: foo
> Cc: bar
>
> -files patched: 1
> + 1 files changed, 1 insertions(+), 0 deletions(-)
> + a | 1 +-
>
>
> # HG changeset patch
> @@ -304,7 +313,8 @@
> To: foo
> Cc: bar
>
> -files patched: 1
> + 1 files changed, 1 insertions(+), 0 deletions(-)
> + b | 1 +-
>
>
> # HG changeset patch
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 4197 bytes
Desc: S/MIME Cryptographic Signature
Url : http://selenic.com/pipermail/mercurial-devel/attachments/20081222/d46720b5/attachment.bin
More information about the Mercurial-devel
mailing list