mercurial/dispatch.py
changeset 48982 4eae533354ae
parent 48966 6000f5b25c9b
child 49004 f254fc73d956
equal deleted inserted replaced
48981:f5127b87f160 48982:4eae533354ae
   147         # be printed to console to avoid another IOError/KeyboardInterrupt.
   147         # be printed to console to avoid another IOError/KeyboardInterrupt.
   148         status = -1
   148         status = -1
   149     sys.exit(status & 255)
   149     sys.exit(status & 255)
   150 
   150 
   151 
   151 
   152 if pycompat.ispy3:
   152 def initstdio():
   153 
   153     # stdio streams on Python 3 are io.TextIOWrapper instances proxying another
   154     def initstdio():
   154     # buffer. These streams will normalize \n to \r\n by default. Mercurial's
   155         # stdio streams on Python 3 are io.TextIOWrapper instances proxying another
   155     # preferred mechanism for writing output (ui.write()) uses io.BufferedWriter
   156         # buffer. These streams will normalize \n to \r\n by default. Mercurial's
   156     # instances, which write to the underlying stdio file descriptor in binary
   157         # preferred mechanism for writing output (ui.write()) uses io.BufferedWriter
   157     # mode. ui.write() uses \n for line endings and no line ending normalization
   158         # instances, which write to the underlying stdio file descriptor in binary
   158     # is attempted through this interface. This "just works," even if the system
   159         # mode. ui.write() uses \n for line endings and no line ending normalization
   159     # preferred line ending is not \n.
   160         # is attempted through this interface. This "just works," even if the system
   160     #
   161         # preferred line ending is not \n.
   161     # But some parts of Mercurial (e.g. hooks) can still send data to sys.stdout
   162         #
   162     # and sys.stderr. They will inherit the line ending normalization settings,
   163         # But some parts of Mercurial (e.g. hooks) can still send data to sys.stdout
   163     # potentially causing e.g. \r\n to be emitted. Since emitting \n should
   164         # and sys.stderr. They will inherit the line ending normalization settings,
   164     # "just work," here we change the sys.* streams to disable line ending
   165         # potentially causing e.g. \r\n to be emitted. Since emitting \n should
   165     # normalization, ensuring compatibility with our ui type.
   166         # "just work," here we change the sys.* streams to disable line ending
   166 
   167         # normalization, ensuring compatibility with our ui type.
   167     if sys.stdout is not None:
   168 
   168         # write_through is new in Python 3.7.
   169         if sys.stdout is not None:
   169         kwargs = {
   170             # write_through is new in Python 3.7.
   170             "newline": "\n",
   171             kwargs = {
   171             "line_buffering": sys.stdout.line_buffering,
   172                 "newline": "\n",
   172         }
   173                 "line_buffering": sys.stdout.line_buffering,
   173         if util.safehasattr(sys.stdout, "write_through"):
   174             }
   174             # pytype: disable=attribute-error
   175             if util.safehasattr(sys.stdout, "write_through"):
   175             kwargs["write_through"] = sys.stdout.write_through
   176                 # pytype: disable=attribute-error
   176             # pytype: enable=attribute-error
   177                 kwargs["write_through"] = sys.stdout.write_through
   177         sys.stdout = io.TextIOWrapper(
   178                 # pytype: enable=attribute-error
   178             sys.stdout.buffer, sys.stdout.encoding, sys.stdout.errors, **kwargs
   179             sys.stdout = io.TextIOWrapper(
   179         )
   180                 sys.stdout.buffer,
   180 
   181                 sys.stdout.encoding,
   181     if sys.stderr is not None:
   182                 sys.stdout.errors,
   182         kwargs = {
   183                 **kwargs
   183             "newline": "\n",
   184             )
   184             "line_buffering": sys.stderr.line_buffering,
   185 
   185         }
   186         if sys.stderr is not None:
   186         if util.safehasattr(sys.stderr, "write_through"):
   187             kwargs = {
   187             # pytype: disable=attribute-error
   188                 "newline": "\n",
   188             kwargs["write_through"] = sys.stderr.write_through
   189                 "line_buffering": sys.stderr.line_buffering,
   189             # pytype: enable=attribute-error
   190             }
   190         sys.stderr = io.TextIOWrapper(
   191             if util.safehasattr(sys.stderr, "write_through"):
   191             sys.stderr.buffer, sys.stderr.encoding, sys.stderr.errors, **kwargs
   192                 # pytype: disable=attribute-error
   192         )
   193                 kwargs["write_through"] = sys.stderr.write_through
   193 
   194                 # pytype: enable=attribute-error
   194     if sys.stdin is not None:
   195             sys.stderr = io.TextIOWrapper(
   195         # No write_through on read-only stream.
   196                 sys.stderr.buffer,
   196         sys.stdin = io.TextIOWrapper(
   197                 sys.stderr.encoding,
   197             sys.stdin.buffer,
   198                 sys.stderr.errors,
   198             sys.stdin.encoding,
   199                 **kwargs
   199             sys.stdin.errors,
   200             )
   200             # None is universal newlines mode.
   201 
   201             newline=None,
   202         if sys.stdin is not None:
   202             line_buffering=sys.stdin.line_buffering,
   203             # No write_through on read-only stream.
   203         )
   204             sys.stdin = io.TextIOWrapper(
   204 
   205                 sys.stdin.buffer,
   205 
   206                 sys.stdin.encoding,
   206 def _silencestdio():
   207                 sys.stdin.errors,
   207     for fp in (sys.stdout, sys.stderr):
   208                 # None is universal newlines mode.
   208         if fp is None:
   209                 newline=None,
   209             continue
   210                 line_buffering=sys.stdin.line_buffering,
   210         # Check if the file is okay
   211             )
   211         try:
   212 
   212             fp.flush()
   213     def _silencestdio():
   213             continue
   214         for fp in (sys.stdout, sys.stderr):
   214         except IOError:
   215             if fp is None:
   215             pass
   216                 continue
   216         # Otherwise mark it as closed to silence "Exception ignored in"
   217             # Check if the file is okay
   217         # message emitted by the interpreter finalizer.
   218             try:
   218         try:
   219                 fp.flush()
   219             fp.close()
   220                 continue
   220         except IOError:
   221             except IOError:
   221             pass
   222                 pass
       
   223             # Otherwise mark it as closed to silence "Exception ignored in"
       
   224             # message emitted by the interpreter finalizer.
       
   225             try:
       
   226                 fp.close()
       
   227             except IOError:
       
   228                 pass
       
   229 
       
   230 
       
   231 else:
       
   232 
       
   233     def initstdio():
       
   234         for fp in (sys.stdin, sys.stdout, sys.stderr):
       
   235             procutil.setbinary(fp)
       
   236 
       
   237     def _silencestdio():
       
   238         pass
       
   239 
   222 
   240 
   223 
   241 def _formatargs(args):
   224 def _formatargs(args):
   242     return b' '.join(procutil.shellquote(a) for a in args)
   225     return b' '.join(procutil.shellquote(a) for a in args)
   243 
   226