[PATCH] python implementation of diffstat
Alexander Solovyov
piranha at piranha.org.ua
Sun Dec 21 15:40:26 CST 2008
# HG changeset patch
# User Alexander Solovyov <piranha at piranha.org.ua>
# Date 1229895590 -7200
# Node ID 7014aecd1081755451e6ce742baee291494415b5
# Parent 3896310bd797a3c0db22654321e88db9cc73d3e7
python implementation of diffstat
Implemented as an class, string representation of which is similar to
the output of system diffstat command. There is possibility to access
attributes of a diffstat object to get already parsed statistics in
python code.
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.diffstatfmt(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,56 @@
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 diffstat(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 diffstatfmt(stats):
+ stats = list(stats)
+ width = 78
+
+ 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
+ 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
More information about the Mercurial-devel
mailing list