ui: defer setting pager related properties until the pager has spawned
authorMatt Harbison <matt_harbison@yahoo.com>
Sat, 25 Mar 2017 21:12:00 -0400
changeset 31690 2d11d278279a
parent 31689 57a22f699179
child 31691 c3ca0ad8ab9c
ui: defer setting pager related properties until the pager has spawned When --pager=on is given, dispatch.py spawns a pager before setting up color. If the pager failed to launch, ui.pageractive was left set to True, so color configured itself based on 'color.pagermode'. A typical MSYS setting would be 'color.mode=auto, color.pagermode=ansi'. In the failure case, this would print a warning, disable the pager, and then print the raw ANSI codes to the terminal. Care needs to be taken, because it appears that leaving ui.pageractive=True was the only thing that prevented an attempt at running the pager again from inside the command. This results in a double warning message, so pager is simply disabled on failure. The ui config settings didn't need to be moved to fix this, but it seemed like the right thing to do for consistency.
mercurial/chgserver.py
mercurial/ui.py
--- a/mercurial/chgserver.py	Sat Mar 25 13:50:17 2017 -0400
+++ b/mercurial/chgserver.py	Sat Mar 25 21:12:00 2017 -0400
@@ -193,6 +193,7 @@
         def _runpager(self, cmd):
             self._csystem(cmd, util.shellenviron(), type='pager',
                           cmdtable={'attachio': attachio})
+            return True
 
     return chgui(srcui)
 
--- a/mercurial/ui.py	Sat Mar 25 13:50:17 2017 -0400
+++ b/mercurial/ui.py	Sat Mar 25 21:12:00 2017 -0400
@@ -856,15 +856,22 @@
 
         self.debug('starting pager for command %r\n' % command)
         self.flush()
-        self.pageractive = True
-        # Preserve the formatted-ness of the UI. This is important
-        # because we mess with stdout, which might confuse
-        # auto-detection of things being formatted.
-        self.setconfig('ui', 'formatted', self.formatted(), 'pager')
-        self.setconfig('ui', 'interactive', False, 'pager')
+
+        wasformatted = self.formatted()
         if util.safehasattr(signal, "SIGPIPE"):
             signal.signal(signal.SIGPIPE, _catchterm)
-        self._runpager(pagercmd)
+        if self._runpager(pagercmd):
+            self.pageractive = True
+            # Preserve the formatted-ness of the UI. This is important
+            # because we mess with stdout, which might confuse
+            # auto-detection of things being formatted.
+            self.setconfig('ui', 'formatted', wasformatted, 'pager')
+            self.setconfig('ui', 'interactive', False, 'pager')
+        else:
+            # If the pager can't be spawned in dispatch when --pager=on is
+            # given, don't try again when the command runs, to avoid a duplicate
+            # warning about a missing pager command.
+            self.disablepager()
 
     def _runpager(self, command):
         """Actually start the pager and set up file descriptors.
@@ -874,7 +881,7 @@
         """
         if command == 'cat':
             # Save ourselves some work.
-            return
+            return False
         # If the command doesn't contain any of these characters, we
         # assume it's a binary and exec it directly. This means for
         # simple pager command configurations, we can degrade
@@ -891,7 +898,7 @@
             if not fullcmd:
                 self.warn(_("missing pager command '%s', skipping pager\n")
                           % command)
-                return
+                return False
 
             command = fullcmd
 
@@ -904,7 +911,7 @@
             if e.errno == errno.ENOENT and not shell:
                 self.warn(_("missing pager command '%s', skipping pager\n")
                           % command)
-                return
+                return False
             raise
 
         # back up original file descriptors
@@ -925,6 +932,8 @@
             pager.stdin.close()
             pager.wait()
 
+        return True
+
     def interface(self, feature):
         """what interface to use for interactive console features?