mercurial/ui.py
changeset 40543 7bffbbe03e90
parent 40542 d8997c5ce2ff
child 40547 840cd57cde32
equal deleted inserted replaced
40542:d8997c5ce2ff 40543:7bffbbe03e90
   229         self._terminfoparams = {}
   229         self._terminfoparams = {}
   230         self._styles = {}
   230         self._styles = {}
   231         self._uninterruptible = False
   231         self._uninterruptible = False
   232 
   232 
   233         if src:
   233         if src:
   234             self.fout = src.fout
   234             self._fout = src._fout
   235             self.ferr = src.ferr
   235             self._ferr = src._ferr
   236             self.fin = src.fin
   236             self._fin = src._fin
   237             self._finoutredirected = src._finoutredirected
   237             self._finoutredirected = src._finoutredirected
   238             self.pageractive = src.pageractive
   238             self.pageractive = src.pageractive
   239             self._disablepager = src._disablepager
   239             self._disablepager = src._disablepager
   240             self._tweaked = src._tweaked
   240             self._tweaked = src._tweaked
   241 
   241 
   254             self.fixconfig()
   254             self.fixconfig()
   255 
   255 
   256             self.httppasswordmgrdb = src.httppasswordmgrdb
   256             self.httppasswordmgrdb = src.httppasswordmgrdb
   257             self._blockedtimes = src._blockedtimes
   257             self._blockedtimes = src._blockedtimes
   258         else:
   258         else:
   259             self.fout = procutil.stdout
   259             self._fout = procutil.stdout
   260             self.ferr = procutil.stderr
   260             self._ferr = procutil.stderr
   261             self.fin = procutil.stdin
   261             self._fin = procutil.stdin
   262             self._finoutredirected = False
   262             self._finoutredirected = False
   263             self.pageractive = False
   263             self.pageractive = False
   264             self._disablepager = False
   264             self._disablepager = False
   265             self._tweaked = False
   265             self._tweaked = False
   266 
   266 
   882 
   882 
   883     @util.propertycache
   883     @util.propertycache
   884     def paths(self):
   884     def paths(self):
   885         return paths(self)
   885         return paths(self)
   886 
   886 
       
   887     @property
       
   888     def fout(self):
       
   889         return self._fout
       
   890 
       
   891     @fout.setter
       
   892     def fout(self, f):
       
   893         self._fout = f
       
   894 
       
   895     @property
       
   896     def ferr(self):
       
   897         return self._ferr
       
   898 
       
   899     @ferr.setter
       
   900     def ferr(self, f):
       
   901         self._ferr = f
       
   902 
       
   903     @property
       
   904     def fin(self):
       
   905         return self._fin
       
   906 
       
   907     @fin.setter
       
   908     def fin(self, f):
       
   909         self._fin = f
       
   910 
   887     def pushbuffer(self, error=False, subproc=False, labeled=False):
   911     def pushbuffer(self, error=False, subproc=False, labeled=False):
   888         """install a buffer to capture standard output of the ui object
   912         """install a buffer to capture standard output of the ui object
   889 
   913 
   890         If error is True, the error output will be captured too.
   914         If error is True, the error output will be captured too.
   891 
   915 
   912             self._bufferapplylabels = None
   936             self._bufferapplylabels = None
   913 
   937 
   914         return "".join(self._buffers.pop())
   938         return "".join(self._buffers.pop())
   915 
   939 
   916     def _isbuffered(self, dest):
   940     def _isbuffered(self, dest):
   917         if dest is self.fout:
   941         if dest is self._fout:
   918             return bool(self._buffers)
   942             return bool(self._buffers)
   919         if dest is self.ferr:
   943         if dest is self._ferr:
   920             return bool(self._bufferstates and self._bufferstates[-1][0])
   944             return bool(self._bufferstates and self._bufferstates[-1][0])
   921         return False
   945         return False
   922 
   946 
   923     def canwritewithoutlabels(self):
   947     def canwritewithoutlabels(self):
   924         '''check if write skips the label'''
   948         '''check if write skips the label'''
   945 
   969 
   946         When labeling output for a specific command, a label of
   970         When labeling output for a specific command, a label of
   947         "cmdname.type" is recommended. For example, status issues
   971         "cmdname.type" is recommended. For example, status issues
   948         a label of "status.modified" for modified files.
   972         a label of "status.modified" for modified files.
   949         '''
   973         '''
   950         self._write(self.fout, *args, **opts)
   974         self._write(self._fout, *args, **opts)
   951 
   975 
   952     def write_err(self, *args, **opts):
   976     def write_err(self, *args, **opts):
   953         self._write(self.ferr, *args, **opts)
   977         self._write(self._ferr, *args, **opts)
   954 
   978 
   955     def _write(self, dest, *args, **opts):
   979     def _write(self, dest, *args, **opts):
   956         if self._isbuffered(dest):
   980         if self._isbuffered(dest):
   957             if self._bufferapplylabels:
   981             if self._bufferapplylabels:
   958                 label = opts.get(r'label', '')
   982                 label = opts.get(r'label', '')
   967         msg = b''.join(args)
   991         msg = b''.join(args)
   968 
   992 
   969         # opencode timeblockedsection because this is a critical path
   993         # opencode timeblockedsection because this is a critical path
   970         starttime = util.timer()
   994         starttime = util.timer()
   971         try:
   995         try:
   972             if dest is self.ferr and not getattr(self.fout, 'closed', False):
   996             if dest is self._ferr and not getattr(self._fout, 'closed', False):
   973                 self.fout.flush()
   997                 self._fout.flush()
   974             if self._colormode == 'win32':
   998             if self._colormode == 'win32':
   975                 # windows color printing is its own can of crab, defer to
   999                 # windows color printing is its own can of crab, defer to
   976                 # the color module and that is it.
  1000                 # the color module and that is it.
   977                 color.win32print(self, dest.write, msg, **opts)
  1001                 color.win32print(self, dest.write, msg, **opts)
   978             else:
  1002             else:
   980                     label = opts.get(r'label', '')
  1004                     label = opts.get(r'label', '')
   981                     msg = self.label(msg, label)
  1005                     msg = self.label(msg, label)
   982                 dest.write(msg)
  1006                 dest.write(msg)
   983             # stderr may be buffered under win32 when redirected to files,
  1007             # stderr may be buffered under win32 when redirected to files,
   984             # including stdout.
  1008             # including stdout.
   985             if dest is self.ferr and not getattr(self.ferr, 'closed', False):
  1009             if dest is self._ferr and not getattr(self._ferr, 'closed', False):
   986                 dest.flush()
  1010                 dest.flush()
   987         except IOError as err:
  1011         except IOError as err:
   988             if (dest is self.ferr
  1012             if (dest is self._ferr
   989                 and err.errno in (errno.EPIPE, errno.EIO, errno.EBADF)):
  1013                 and err.errno in (errno.EPIPE, errno.EIO, errno.EBADF)):
   990                 # no way to report the error, so ignore it
  1014                 # no way to report the error, so ignore it
   991                 return
  1015                 return
   992             raise error.StdioError(err)
  1016             raise error.StdioError(err)
   993         finally:
  1017         finally:
   997     def flush(self):
  1021     def flush(self):
   998         # opencode timeblockedsection because this is a critical path
  1022         # opencode timeblockedsection because this is a critical path
   999         starttime = util.timer()
  1023         starttime = util.timer()
  1000         try:
  1024         try:
  1001             try:
  1025             try:
  1002                 self.fout.flush()
  1026                 self._fout.flush()
  1003             except IOError as err:
  1027             except IOError as err:
  1004                 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
  1028                 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
  1005                     raise error.StdioError(err)
  1029                     raise error.StdioError(err)
  1006             finally:
  1030             finally:
  1007                 try:
  1031                 try:
  1008                     self.ferr.flush()
  1032                     self._ferr.flush()
  1009                 except IOError as err:
  1033                 except IOError as err:
  1010                     if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
  1034                     if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
  1011                         raise error.StdioError(err)
  1035                         raise error.StdioError(err)
  1012         finally:
  1036         finally:
  1013             self._blockedtimes['stdio_blocked'] += \
  1037             self._blockedtimes['stdio_blocked'] += \
  1253         '''
  1277         '''
  1254         i = self.configbool("ui", "interactive")
  1278         i = self.configbool("ui", "interactive")
  1255         if i is None:
  1279         if i is None:
  1256             # some environments replace stdin without implementing isatty
  1280             # some environments replace stdin without implementing isatty
  1257             # usually those are non-interactive
  1281             # usually those are non-interactive
  1258             return self._isatty(self.fin)
  1282             return self._isatty(self._fin)
  1259 
  1283 
  1260         return i
  1284         return i
  1261 
  1285 
  1262     def termwidth(self):
  1286     def termwidth(self):
  1263         '''how wide is the terminal in columns?
  1287         '''how wide is the terminal in columns?
  1291 
  1315 
  1292         i = self.configbool("ui", "formatted")
  1316         i = self.configbool("ui", "formatted")
  1293         if i is None:
  1317         if i is None:
  1294             # some environments replace stdout without implementing isatty
  1318             # some environments replace stdout without implementing isatty
  1295             # usually those are non-interactive
  1319             # usually those are non-interactive
  1296             return self._isatty(self.fout)
  1320             return self._isatty(self._fout)
  1297 
  1321 
  1298         return i
  1322         return i
  1299 
  1323 
  1300     def _readline(self):
  1324     def _readline(self):
  1301         # Replacing stdin/stdout temporarily is a hard problem on Python 3
  1325         # Replacing stdin/stdout temporarily is a hard problem on Python 3
  1302         # because they have to be text streams with *no buffering*. Instead,
  1326         # because they have to be text streams with *no buffering*. Instead,
  1303         # we use rawinput() only if call_readline() will be invoked by
  1327         # we use rawinput() only if call_readline() will be invoked by
  1304         # PyOS_Readline(), so no I/O will be made at Python layer.
  1328         # PyOS_Readline(), so no I/O will be made at Python layer.
  1305         usereadline = (self._isatty(self.fin) and self._isatty(self.fout)
  1329         usereadline = (self._isatty(self._fin) and self._isatty(self._fout)
  1306                        and procutil.isstdin(self.fin)
  1330                        and procutil.isstdin(self._fin)
  1307                        and procutil.isstdout(self.fout))
  1331                        and procutil.isstdout(self._fout))
  1308         if usereadline:
  1332         if usereadline:
  1309             try:
  1333             try:
  1310                 # magically add command line editing support, where
  1334                 # magically add command line editing support, where
  1311                 # available
  1335                 # available
  1312                 import readline
  1336                 import readline
  1324                 # When stdin is in binary mode on Windows, it can cause
  1348                 # When stdin is in binary mode on Windows, it can cause
  1325                 # raw_input() to emit an extra trailing carriage return
  1349                 # raw_input() to emit an extra trailing carriage return
  1326                 if pycompat.oslinesep == b'\r\n' and line.endswith(b'\r'):
  1350                 if pycompat.oslinesep == b'\r\n' and line.endswith(b'\r'):
  1327                     line = line[:-1]
  1351                     line = line[:-1]
  1328             else:
  1352             else:
  1329                 self.fout.write(b' ')
  1353                 self._fout.write(b' ')
  1330                 self.fout.flush()
  1354                 self._fout.flush()
  1331                 line = self.fin.readline()
  1355                 line = self._fin.readline()
  1332                 if not line:
  1356                 if not line:
  1333                     raise EOFError
  1357                     raise EOFError
  1334                 line = line.rstrip(pycompat.oslinesep)
  1358                 line = line.rstrip(pycompat.oslinesep)
  1335 
  1359 
  1336         return line
  1360         return line
  1341         """
  1365         """
  1342         if not self.interactive():
  1366         if not self.interactive():
  1343             self.write(msg, ' ', label='ui.prompt')
  1367             self.write(msg, ' ', label='ui.prompt')
  1344             self.write(default or '', "\n", label='ui.promptecho')
  1368             self.write(default or '', "\n", label='ui.promptecho')
  1345             return default
  1369             return default
  1346         self._writenobuf(self.fout, msg, label='ui.prompt')
  1370         self._writenobuf(self._fout, msg, label='ui.prompt')
  1347         self.flush()
  1371         self.flush()
  1348         try:
  1372         try:
  1349             r = self._readline()
  1373             r = self._readline()
  1350             if not r:
  1374             if not r:
  1351                 r = default
  1375                 r = default
  1409             self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
  1433             self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
  1410             # disable getpass() only if explicitly specified. it's still valid
  1434             # disable getpass() only if explicitly specified. it's still valid
  1411             # to interact with tty even if fin is not a tty.
  1435             # to interact with tty even if fin is not a tty.
  1412             with self.timeblockedsection('stdio'):
  1436             with self.timeblockedsection('stdio'):
  1413                 if self.configbool('ui', 'nontty'):
  1437                 if self.configbool('ui', 'nontty'):
  1414                     l = self.fin.readline()
  1438                     l = self._fin.readline()
  1415                     if not l:
  1439                     if not l:
  1416                         raise EOFError
  1440                         raise EOFError
  1417                     return l.rstrip('\n')
  1441                     return l.rstrip('\n')
  1418                 else:
  1442                 else:
  1419                     return getpass.getpass('')
  1443                     return getpass.getpass('')
  1535         if blockedtag is None:
  1559         if blockedtag is None:
  1536             # Long cmds tend to be because of an absolute path on cmd. Keep
  1560             # Long cmds tend to be because of an absolute path on cmd. Keep
  1537             # the tail end instead
  1561             # the tail end instead
  1538             cmdsuffix = cmd.translate(None, _keepalnum)[-85:]
  1562             cmdsuffix = cmd.translate(None, _keepalnum)[-85:]
  1539             blockedtag = 'unknown_system_' + cmdsuffix
  1563             blockedtag = 'unknown_system_' + cmdsuffix
  1540         out = self.fout
  1564         out = self._fout
  1541         if any(s[1] for s in self._bufferstates):
  1565         if any(s[1] for s in self._bufferstates):
  1542             out = self
  1566             out = self
  1543         with self.timeblockedsection(blockedtag):
  1567         with self.timeblockedsection(blockedtag):
  1544             rc = self._runsystem(cmd, environ=environ, cwd=cwd, out=out)
  1568             rc = self._runsystem(cmd, environ=environ, cwd=cwd, out=out)
  1545         if rc and onerr:
  1569         if rc and onerr:
  1680             if config is None or not self.configbool('devel', config):
  1704             if config is None or not self.configbool('devel', config):
  1681                 return
  1705                 return
  1682         msg = 'devel-warn: ' + msg
  1706         msg = 'devel-warn: ' + msg
  1683         stacklevel += 1 # get in develwarn
  1707         stacklevel += 1 # get in develwarn
  1684         if self.tracebackflag:
  1708         if self.tracebackflag:
  1685             util.debugstacktrace(msg, stacklevel, self.ferr, self.fout)
  1709             util.debugstacktrace(msg, stacklevel, self._ferr, self._fout)
  1686             self.log('develwarn', '%s at:\n%s' %
  1710             self.log('develwarn', '%s at:\n%s' %
  1687                      (msg, ''.join(util.getstackframes(stacklevel))))
  1711                      (msg, ''.join(util.getstackframes(stacklevel))))
  1688         else:
  1712         else:
  1689             curframe = inspect.currentframe()
  1713             curframe = inspect.currentframe()
  1690             calframe = inspect.getouterframes(curframe, 2)
  1714             calframe = inspect.getouterframes(curframe, 2)