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) |