mercurial/chgserver.py
changeset 39738 a93fe297dfb3
parent 37120 a8a902d7176e
child 39739 7cdd47d9ccf8
equal deleted inserted replaced
39737:fd805a44b89d 39738:a93fe297dfb3
   309     def __init__(self, ui, repo, fin, fout, sock, hashstate, baseaddress):
   309     def __init__(self, ui, repo, fin, fout, sock, hashstate, baseaddress):
   310         super(chgcmdserver, self).__init__(
   310         super(chgcmdserver, self).__init__(
   311             _newchgui(ui, channeledsystem(fin, fout, 'S'), self.attachio),
   311             _newchgui(ui, channeledsystem(fin, fout, 'S'), self.attachio),
   312             repo, fin, fout)
   312             repo, fin, fout)
   313         self.clientsock = sock
   313         self.clientsock = sock
       
   314         self._ioattached = False
   314         self._oldios = []  # original (self.ch, ui.fp, fd) before "attachio"
   315         self._oldios = []  # original (self.ch, ui.fp, fd) before "attachio"
   315         self.hashstate = hashstate
   316         self.hashstate = hashstate
   316         self.baseaddress = baseaddress
   317         self.baseaddress = baseaddress
   317         if hashstate is not None:
   318         if hashstate is not None:
   318             self.capabilities = self.capabilities.copy()
   319             self.capabilities = self.capabilities.copy()
   322         super(chgcmdserver, self).cleanup()
   323         super(chgcmdserver, self).cleanup()
   323         # dispatch._runcatch() does not flush outputs if exception is not
   324         # dispatch._runcatch() does not flush outputs if exception is not
   324         # handled by dispatch._dispatch()
   325         # handled by dispatch._dispatch()
   325         self.ui.flush()
   326         self.ui.flush()
   326         self._restoreio()
   327         self._restoreio()
       
   328         self._ioattached = False
   327 
   329 
   328     def attachio(self):
   330     def attachio(self):
   329         """Attach to client's stdio passed via unix domain socket; all
   331         """Attach to client's stdio passed via unix domain socket; all
   330         channels except cresult will no longer be used
   332         channels except cresult will no longer be used
   331         """
   333         """
   335         clientfds = util.recvfds(self.clientsock.fileno())
   337         clientfds = util.recvfds(self.clientsock.fileno())
   336         _log('received fds: %r\n' % clientfds)
   338         _log('received fds: %r\n' % clientfds)
   337 
   339 
   338         ui = self.ui
   340         ui = self.ui
   339         ui.flush()
   341         ui.flush()
   340         first = self._saveio()
   342         self._saveio()
   341         for fd, (cn, fn, mode) in zip(clientfds, _iochannels):
   343         for fd, (cn, fn, mode) in zip(clientfds, _iochannels):
   342             assert fd > 0
   344             assert fd > 0
   343             fp = getattr(ui, fn)
   345             fp = getattr(ui, fn)
   344             os.dup2(fd, fp.fileno())
   346             os.dup2(fd, fp.fileno())
   345             os.close(fd)
   347             os.close(fd)
   346             if not first:
   348             if self._ioattached:
   347                 continue
   349                 continue
   348             # reset buffering mode when client is first attached. as we want
   350             # reset buffering mode when client is first attached. as we want
   349             # to see output immediately on pager, the mode stays unchanged
   351             # to see output immediately on pager, the mode stays unchanged
   350             # when client re-attached. ferr is unchanged because it should
   352             # when client re-attached. ferr is unchanged because it should
   351             # be unbuffered no matter if it is a tty or not.
   353             # be unbuffered no matter if it is a tty or not.
   360                     bufsize = -1  # system default
   362                     bufsize = -1  # system default
   361                 newfp = os.fdopen(fp.fileno(), mode, bufsize)
   363                 newfp = os.fdopen(fp.fileno(), mode, bufsize)
   362                 setattr(ui, fn, newfp)
   364                 setattr(ui, fn, newfp)
   363             setattr(self, cn, newfp)
   365             setattr(self, cn, newfp)
   364 
   366 
       
   367         self._ioattached = True
   365         self.cresult.write(struct.pack('>i', len(clientfds)))
   368         self.cresult.write(struct.pack('>i', len(clientfds)))
   366 
   369 
   367     def _saveio(self):
   370     def _saveio(self):
   368         if self._oldios:
   371         if self._oldios:
   369             return False
   372             return
   370         ui = self.ui
   373         ui = self.ui
   371         for cn, fn, _mode in _iochannels:
   374         for cn, fn, _mode in _iochannels:
   372             ch = getattr(self, cn)
   375             ch = getattr(self, cn)
   373             fp = getattr(ui, fn)
   376             fp = getattr(ui, fn)
   374             fd = os.dup(fp.fileno())
   377             fd = os.dup(fp.fileno())
   375             self._oldios.append((ch, fp, fd))
   378             self._oldios.append((ch, fp, fd))
   376         return True
       
   377 
   379 
   378     def _restoreio(self):
   380     def _restoreio(self):
   379         ui = self.ui
   381         ui = self.ui
   380         for (ch, fp, fd), (cn, fn, _mode) in zip(self._oldios, _iochannels):
   382         for (ch, fp, fd), (cn, fn, _mode) in zip(self._oldios, _iochannels):
   381             newfp = getattr(ui, fn)
   383             newfp = getattr(ui, fn)