[PATCH V3] pager: fix the invocation of `more` on Windows

Matt Harbison mharbison72 at gmail.com
Fri Mar 24 01:57:50 UTC 2017


# HG changeset patch
# User Matt Harbison <matt_harbison at yahoo.com>
# Date 1489983573 14400
#      Mon Mar 20 00:19:33 2017 -0400
# Node ID d0c2db2d9f13dca534c598de050eb1919ef79059
# Parent  df82f375fa005b9c71b463182e6b54aa47fa5999
pager: fix the invocation of `more` on Windows

After 9335dc6b2a9c, with 'shell' being (mostly) set to False, invoking `more` no
longer worked.  Instead, a warning was printed and the pager was disabled.
Invoking `more.com` works.  Since a user may have configured 'pager.pager=more',
do this substitution at the end.  Surprisingly, `more` does allow for arguments,
so those are preserved.  This also allows `more` to work in MSYS.

Setting 'shell=False' runs the executable via CreateProcess(), which has rather
wonky rules for resolving an executable without an extension [1].  Resolving to
*.com is not among them.  Since 'shell=True' yields a cryptic error for a bad
$PAGER, and a *.exe program will work without specifying the extension, sticking
with current 'shell=False' seems like the right thing to do.  I don't think
there are any other *.com pagers out there, so this one special case seems OK.

If somebody wants to do something crazy that requires cmd.exe, I was able to get
normal paged output with 'pager.pager="cmd.exe /c more"'.  I assume you can
replace `more` with *.bat, *.vbs or various other creatures listed in $PATHEXT.

[1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -844,6 +844,15 @@
         if not pagercmd:
             return
 
+        if pycompat.osname == 'nt':
+            # `more` cannot be invoked with shell=False, but `more.com` can.
+            # Hide this implementation detail from the user, so we can also get
+            # sane bad PAGER behavior.  If args are also given, the space in the
+            # command line forces shell=True, so that case doesn't need to be
+            # handled here.
+            if pagercmd == 'more':
+                pagercmd = 'more.com'
+
         self.debug('starting pager for command %r\n' % command)
         self.flush()
         self.pageractive = True


More information about the Mercurial-devel mailing list