diff --git a/hgext/color.py b/hgext/color.py
index b705e5ab3b07f7e3ba5f9c3db51c47d1779372d9_aGdleHQvY29sb3IucHk=..2f88821856eb997b826e47d33d57c003faa3493a_aGdleHQvY29sb3IucHk= 100644
--- a/hgext/color.py
+++ b/hgext/color.py
@@ -445,7 +445,7 @@
             return super(colorui, self).write_err(*args, **opts)
 
         label = opts.get('label', '')
-        if self._bufferstates and self._bufferstates[-1]:
+        if self._bufferstates and self._bufferstates[-1][0]:
             return self.write(*args, **opts)
         if self._colormode == 'win32':
             for a in args:
diff --git a/mercurial/ui.py b/mercurial/ui.py
index b705e5ab3b07f7e3ba5f9c3db51c47d1779372d9_bWVyY3VyaWFsL3VpLnB5..2f88821856eb997b826e47d33d57c003faa3493a_bWVyY3VyaWFsL3VpLnB5 100644
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -76,7 +76,8 @@
     def __init__(self, src=None):
         # _buffers: used for temporary capture of output
         self._buffers = []
-        # _bufferstates: Should the temporary capture includes stderr
+        # _bufferstates:
+        #   should the temporary capture include stderr and subprocess output
         self._bufferstates = []
         self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
         self._reportuntrusted = True
@@ -540,6 +541,6 @@
     def paths(self):
         return paths(self)
 
-    def pushbuffer(self, error=False):
+    def pushbuffer(self, error=False, subproc=False):
         """install a buffer to capture standard output of the ui object
 
@@ -544,4 +545,7 @@
         """install a buffer to capture standard output of the ui object
 
-        If error is True, the error output will be captured too."""
+        If error is True, the error output will be captured too.
+
+        If subproc is True, output from subprocesses (typically hooks) will be
+        captured too."""
         self._buffers.append([])
@@ -547,5 +551,5 @@
         self._buffers.append([])
-        self._bufferstates.append(error)
+        self._bufferstates.append((error, subproc))
 
     def popbuffer(self, labeled=False):
         '''pop the last buffer and return the buffered output
@@ -585,7 +589,7 @@
 
     def write_err(self, *args, **opts):
         try:
-            if self._bufferstates and self._bufferstates[-1]:
+            if self._bufferstates and self._bufferstates[-1][0]:
                 return self.write(*args, **opts)
             if not getattr(self.fout, 'closed', False):
                 self.fout.flush()
@@ -834,4 +838,7 @@
         '''execute shell command with appropriate output stream. command
         output will be redirected if fout is not stdout.
         '''
+        out = self.fout
+        if util.any(s[1] for s in self._bufferstates):
+            out = self
         return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
@@ -837,5 +844,5 @@
         return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
-                           errprefix=errprefix, out=self.fout)
+                           errprefix=errprefix, out=out)
 
     def traceback(self, exc=None, force=False):
         '''print exception traceback if traceback printing enabled or forced.