[PATCH] diffstat: fix fails on non-terminals (issue1547) and on only binary changes

Alexander Solovyov piranha at piranha.org.ua
Fri Mar 13 11:20:36 CDT 2009


# HG changeset patch
# User Alexander Solovyov <piranha at piranha.org.ua>
# Date 1236799591 -7200
# Node ID e0b2c850cc64646c66760c04bbff1f941b869073
# Parent  a536b9a43227db025d0991c689ed844fe34e8279
diffstat: fix fails on non-terminals (issue1547) and on only binary changes

This patch adds check agains terminal width guessing so it will return meaning
value instead of failing.

Also it introduces optional width parameter for diffstat so width guess
wouldn't be performed at all. It's usage is added to every non-interactive
user of diffstat.

Additionally if you had only binary changes you get 0 total changes in
your diffstat, which would cause ZeroDivisionError upon rendering.

diff --git a/hgext/hgcia.py b/hgext/hgcia.py
--- a/hgext/hgcia.py
+++ b/hgext/hgcia.py
@@ -112,7 +112,7 @@
         n = self.ctx.node()
         pbuf = patchbuf()
         patch.export(self.cia.repo, [n], fp=pbuf)
-        return patch.diffstat(pbuf.lines) or ''
+        return patch.diffstat(pbuf.lines, width=80) or ''
 
     def logmsg(self):
         diffstat = self.cia.diffstat and self.diffstat() or ''
diff --git a/hgext/notify.py b/hgext/notify.py
--- a/hgext/notify.py
+++ b/hgext/notify.py
@@ -243,7 +243,7 @@
         difflines = ''.join(chunks).splitlines()
 
         if self.ui.configbool('notify', 'diffstat', True):
-            s = patch.diffstat(difflines)
+            s = patch.diffstat(difflines, width=80)
             # s may be nil, don't include the header if it is
             if s:
                 self.ui.write('\ndiffstat:\n\n%s' % s)
diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py
--- a/hgext/patchbomb.py
+++ b/hgext/patchbomb.py
@@ -90,7 +90,7 @@
         ui.warn(_('Please enter a valid value.\n'))
 
 def cdiffstat(ui, summary, patchlines):
-    s = patch.diffstat(patchlines)
+    s = patch.diffstat(patchlines, width=80)
     if summary:
         ui.write(summary, '\n')
         ui.write(s, '\n')
diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -1359,10 +1359,14 @@
     if filename:
         yield (filename, adds, removes)
 
-def diffstat(lines):
+def diffstat(lines, width=None):
+    '''
+    Return diff statistics of lines formatted to the width. In case if
+    bool(width) == False try to guess it.
+    '''
     output = []
     stats = list(diffstatdata(lines))
-    width = util.termwidth() - 2
+    width = (width or util.termwidth()) - 2
 
     maxtotal, maxname = 0, 0
     totaladds, totalremoves = 0, 0
@@ -1377,7 +1381,9 @@
     if graphwidth < 10:
         graphwidth = 10
 
-    factor = int(math.ceil(float(maxtotal) / graphwidth))
+    # Don't fail in case if total changes is 0 (this can happen
+    # with --git binary diff sometimes)
+    factor = max(int(math.ceil(float(maxtotal) / graphwidth)), 1)
 
     for filename, adds, removes in stats:
         # If diffstat runs out of room it doesn't print anything, which
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -2013,7 +2013,7 @@
                     continue
                 arri = fcntl.ioctl(fd, termios.TIOCGWINSZ, '\0' * 8)
                 return array.array('h', arri)[1]
-            except ValueError:
+            except (ValueError, AttributeError):
                 pass
     except ImportError:
         pass
diff --git a/tests/test-patchbomb b/tests/test-patchbomb
--- a/tests/test-patchbomb
+++ b/tests/test-patchbomb
@@ -11,8 +11,6 @@
 echo "[extensions]" >> $HGRCPATH
 echo "patchbomb=" >> $HGRCPATH
 
-COLUMNS=80; export COLUMNS
-
 hg init t
 cd t
 echo a > a


More information about the Mercurial-devel mailing list