mercurial/chgserver.py
changeset 45852 b56feaa9b520
parent 45682 d2e1dcd4490d
child 45854 4b4160a83303
equal deleted inserted replaced
45847:d68618954ade 45852:b56feaa9b520
   407             # to see output immediately on pager, the mode stays unchanged
   407             # to see output immediately on pager, the mode stays unchanged
   408             # when client re-attached. ferr is unchanged because it should
   408             # when client re-attached. ferr is unchanged because it should
   409             # be unbuffered no matter if it is a tty or not.
   409             # be unbuffered no matter if it is a tty or not.
   410             if fn == b'ferr':
   410             if fn == b'ferr':
   411                 newfp = fp
   411                 newfp = fp
       
   412             elif pycompat.ispy3:
       
   413                 # On Python 3, the standard library doesn't offer line-buffered
       
   414                 # binary streams, so wrap/unwrap it.
       
   415                 if fp.isatty():
       
   416                     newfp = procutil.make_line_buffered(fp)
       
   417                 else:
       
   418                     newfp = procutil.unwrap_line_buffered(fp)
   412             else:
   419             else:
   413                 # make it line buffered explicitly because the default is
   420                 # Python 2 uses the I/O streams provided by the C library, so
   414                 # decided on first write(), where fout could be a pager.
   421                 # make it line-buffered explicitly. Otherwise the default would
       
   422                 # be decided on first write(), where fout could be a pager.
   415                 if fp.isatty():
   423                 if fp.isatty():
   416                     bufsize = 1  # line buffered
   424                     bufsize = 1  # line buffered
   417                 else:
   425                 else:
   418                     bufsize = -1  # system default
   426                     bufsize = -1  # system default
   419                 newfp = os.fdopen(fp.fileno(), mode, bufsize)
   427                 newfp = os.fdopen(fp.fileno(), mode, bufsize)
       
   428             if newfp is not fp:
   420                 setattr(ui, fn, newfp)
   429                 setattr(ui, fn, newfp)
   421             setattr(self, cn, newfp)
   430             setattr(self, cn, newfp)
   422 
   431 
   423         self._ioattached = True
   432         self._ioattached = True
   424         self.cresult.write(struct.pack(b'>i', len(clientfds)))
   433         self.cresult.write(struct.pack(b'>i', len(clientfds)))
   438             return
   447             return
   439         nullfd = os.open(os.devnull, os.O_WRONLY)
   448         nullfd = os.open(os.devnull, os.O_WRONLY)
   440         ui = self.ui
   449         ui = self.ui
   441         for (ch, fp, fd), (cn, fn, mode) in zip(self._oldios, _iochannels):
   450         for (ch, fp, fd), (cn, fn, mode) in zip(self._oldios, _iochannels):
   442             newfp = getattr(ui, fn)
   451             newfp = getattr(ui, fn)
   443             # close newfp while it's associated with client; otherwise it
   452             # On Python 2, newfp and fp may be separate file objects associated
   444             # would be closed when newfp is deleted
   453             # with the same fd, so we must close newfp while it's associated
   445             if newfp is not fp:
   454             # with the client. Otherwise the new associated fd would be closed
       
   455             # when newfp gets deleted. On Python 3, newfp is just a wrapper
       
   456             # around fp even if newfp is not fp, so deleting newfp is safe.
       
   457             if not (pycompat.ispy3 or newfp is fp):
   446                 newfp.close()
   458                 newfp.close()
   447             # restore original fd: fp is open again
   459             # restore original fd: fp is open again
   448             try:
   460             try:
   449                 if newfp is fp and 'w' in mode:
   461                 if (pycompat.ispy3 or newfp is fp) and 'w' in mode:
   450                     # Discard buffered data which couldn't be flushed because
   462                     # Discard buffered data which couldn't be flushed because
   451                     # of EPIPE. The data should belong to the current session
   463                     # of EPIPE. The data should belong to the current session
   452                     # and should never persist.
   464                     # and should never persist.
   453                     os.dup2(nullfd, fp.fileno())
   465                     os.dup2(nullfd, fp.fileno())
   454                     fp.flush()
   466                     fp.flush()