mercurial/util.py
changeset 37118 5be286db5fb5
parent 37117 e7b517809ebc
child 37121 24ab3381bf15
equal deleted inserted replaced
37117:e7b517809ebc 37118:5be286db5fb5
    20 import collections
    20 import collections
    21 import contextlib
    21 import contextlib
    22 import errno
    22 import errno
    23 import gc
    23 import gc
    24 import hashlib
    24 import hashlib
    25 import imp
       
    26 import io
       
    27 import itertools
    25 import itertools
    28 import mmap
    26 import mmap
    29 import os
    27 import os
    30 import platform as pyplatform
    28 import platform as pyplatform
    31 import re as remod
    29 import re as remod
    32 import shutil
    30 import shutil
    33 import signal
       
    34 import socket
    31 import socket
    35 import stat
    32 import stat
    36 import subprocess
       
    37 import sys
    33 import sys
    38 import tempfile
    34 import tempfile
    39 import time
    35 import time
    40 import traceback
    36 import traceback
    41 import warnings
    37 import warnings
    50     pycompat,
    46     pycompat,
    51     urllibcompat,
    47     urllibcompat,
    52 )
    48 )
    53 from .utils import (
    49 from .utils import (
    54     dateutil,
    50     dateutil,
       
    51     procutil,
    55     stringutil,
    52     stringutil,
    56 )
    53 )
    57 
    54 
    58 base85 = policy.importmod(r'base85')
    55 base85 = policy.importmod(r'base85')
    59 osutil = policy.importmod(r'osutil')
    56 osutil = policy.importmod(r'osutil')
    67 httplib = pycompat.httplib
    64 httplib = pycompat.httplib
    68 pickle = pycompat.pickle
    65 pickle = pycompat.pickle
    69 queue = pycompat.queue
    66 queue = pycompat.queue
    70 safehasattr = pycompat.safehasattr
    67 safehasattr = pycompat.safehasattr
    71 socketserver = pycompat.socketserver
    68 socketserver = pycompat.socketserver
    72 stderr = pycompat.stderr
       
    73 stdin = pycompat.stdin
       
    74 stdout = pycompat.stdout
       
    75 bytesio = pycompat.bytesio
    69 bytesio = pycompat.bytesio
    76 # TODO deprecate stringio name, as it is a lie on Python 3.
    70 # TODO deprecate stringio name, as it is a lie on Python 3.
    77 stringio = bytesio
    71 stringio = bytesio
    78 xmlrpclib = pycompat.xmlrpclib
    72 xmlrpclib = pycompat.xmlrpclib
    79 
    73 
    82 urlreq = urllibcompat.urlreq
    76 urlreq = urllibcompat.urlreq
    83 
    77 
    84 # workaround for win32mbcs
    78 # workaround for win32mbcs
    85 _filenamebytestr = pycompat.bytestr
    79 _filenamebytestr = pycompat.bytestr
    86 
    80 
    87 def isatty(fp):
       
    88     try:
       
    89         return fp.isatty()
       
    90     except AttributeError:
       
    91         return False
       
    92 
       
    93 # glibc determines buffering on first write to stdout - if we replace a TTY
       
    94 # destined stdout with a pipe destined stdout (e.g. pager), we want line
       
    95 # buffering
       
    96 if isatty(stdout):
       
    97     stdout = os.fdopen(stdout.fileno(), r'wb', 1)
       
    98 
       
    99 if pycompat.iswindows:
    81 if pycompat.iswindows:
   100     from . import windows as platform
    82     from . import windows as platform
   101     stdout = platform.winstdout(stdout)
       
   102 else:
    83 else:
   103     from . import posix as platform
    84     from . import posix as platform
   104 
    85 
   105 _ = i18n._
    86 _ = i18n._
   106 
    87 
   108 cachestat = platform.cachestat
    89 cachestat = platform.cachestat
   109 checkexec = platform.checkexec
    90 checkexec = platform.checkexec
   110 checklink = platform.checklink
    91 checklink = platform.checklink
   111 copymode = platform.copymode
    92 copymode = platform.copymode
   112 expandglobs = platform.expandglobs
    93 expandglobs = platform.expandglobs
   113 explainexit = platform.explainexit
       
   114 findexe = platform.findexe
       
   115 getfsmountpoint = platform.getfsmountpoint
    94 getfsmountpoint = platform.getfsmountpoint
   116 getfstype = platform.getfstype
    95 getfstype = platform.getfstype
   117 _gethgcmd = platform.gethgcmd
       
   118 getuser = platform.getuser
       
   119 getpid = os.getpid
       
   120 groupmembers = platform.groupmembers
    96 groupmembers = platform.groupmembers
   121 groupname = platform.groupname
    97 groupname = platform.groupname
   122 hidewindow = platform.hidewindow
       
   123 isexec = platform.isexec
    98 isexec = platform.isexec
   124 isowner = platform.isowner
    99 isowner = platform.isowner
   125 listdir = osutil.listdir
   100 listdir = osutil.listdir
   126 localpath = platform.localpath
   101 localpath = platform.localpath
   127 lookupreg = platform.lookupreg
   102 lookupreg = platform.lookupreg
   134 openhardlinks = platform.openhardlinks
   109 openhardlinks = platform.openhardlinks
   135 oslink = platform.oslink
   110 oslink = platform.oslink
   136 parsepatchoutput = platform.parsepatchoutput
   111 parsepatchoutput = platform.parsepatchoutput
   137 pconvert = platform.pconvert
   112 pconvert = platform.pconvert
   138 poll = platform.poll
   113 poll = platform.poll
   139 popen = platform.popen
       
   140 posixfile = platform.posixfile
   114 posixfile = platform.posixfile
   141 quotecommand = platform.quotecommand
       
   142 readpipe = platform.readpipe
       
   143 rename = platform.rename
   115 rename = platform.rename
   144 removedirs = platform.removedirs
   116 removedirs = platform.removedirs
   145 samedevice = platform.samedevice
   117 samedevice = platform.samedevice
   146 samefile = platform.samefile
   118 samefile = platform.samefile
   147 samestat = platform.samestat
   119 samestat = platform.samestat
   148 setbinary = platform.setbinary
       
   149 setflags = platform.setflags
   120 setflags = platform.setflags
   150 setsignalhandler = platform.setsignalhandler
       
   151 shellquote = platform.shellquote
       
   152 shellsplit = platform.shellsplit
       
   153 spawndetached = platform.spawndetached
       
   154 split = platform.split
   121 split = platform.split
   155 sshargs = platform.sshargs
       
   156 statfiles = getattr(osutil, 'statfiles', platform.statfiles)
   122 statfiles = getattr(osutil, 'statfiles', platform.statfiles)
   157 statisexec = platform.statisexec
   123 statisexec = platform.statisexec
   158 statislink = platform.statislink
   124 statislink = platform.statislink
   159 testpid = platform.testpid
       
   160 umask = platform.umask
   125 umask = platform.umask
   161 unlink = platform.unlink
   126 unlink = platform.unlink
   162 username = platform.username
   127 username = platform.username
   163 
   128 
   164 try:
   129 try:
   165     recvfds = osutil.recvfds
   130     recvfds = osutil.recvfds
   166 except AttributeError:
       
   167     pass
       
   168 try:
       
   169     setprocname = osutil.setprocname
       
   170 except AttributeError:
       
   171     pass
       
   172 try:
       
   173     unblocksignal = osutil.unblocksignal
       
   174 except AttributeError:
   131 except AttributeError:
   175     pass
   132     pass
   176 
   133 
   177 # Python compatibility
   134 # Python compatibility
   178 
   135 
   344     def buffer(sliceable, offset=0, length=None):
   301     def buffer(sliceable, offset=0, length=None):
   345         if length is not None:
   302         if length is not None:
   346             return memoryview(sliceable)[offset:offset + length]
   303             return memoryview(sliceable)[offset:offset + length]
   347         return memoryview(sliceable)[offset:]
   304         return memoryview(sliceable)[offset:]
   348 
   305 
   349 closefds = pycompat.isposix
       
   350 
       
   351 _chunksize = 4096
   306 _chunksize = 4096
   352 
   307 
   353 class bufferedinputpipe(object):
   308 class bufferedinputpipe(object):
   354     """a manually buffered input pipe
   309     """a manually buffered input pipe
   355 
   310 
   461         # Empty files cannot be mmapped, but mmapread should still work.  Check
   416         # Empty files cannot be mmapped, but mmapread should still work.  Check
   462         # if the file is empty, and if so, return an empty buffer.
   417         # if the file is empty, and if so, return an empty buffer.
   463         if os.fstat(fd).st_size == 0:
   418         if os.fstat(fd).st_size == 0:
   464             return ''
   419             return ''
   465         raise
   420         raise
   466 
       
   467 def popen2(cmd, env=None, newlines=False):
       
   468     # Setting bufsize to -1 lets the system decide the buffer size.
       
   469     # The default for bufsize is 0, meaning unbuffered. This leads to
       
   470     # poor performance on Mac OS X: http://bugs.python.org/issue4194
       
   471     p = subprocess.Popen(cmd, shell=True, bufsize=-1,
       
   472                          close_fds=closefds,
       
   473                          stdin=subprocess.PIPE, stdout=subprocess.PIPE,
       
   474                          universal_newlines=newlines,
       
   475                          env=env)
       
   476     return p.stdin, p.stdout
       
   477 
       
   478 def popen3(cmd, env=None, newlines=False):
       
   479     stdin, stdout, stderr, p = popen4(cmd, env, newlines)
       
   480     return stdin, stdout, stderr
       
   481 
       
   482 def popen4(cmd, env=None, newlines=False, bufsize=-1):
       
   483     p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
       
   484                          close_fds=closefds,
       
   485                          stdin=subprocess.PIPE, stdout=subprocess.PIPE,
       
   486                          stderr=subprocess.PIPE,
       
   487                          universal_newlines=newlines,
       
   488                          env=env)
       
   489     return p.stdin, p.stdout, p.stderr, p
       
   490 
   421 
   491 class fileobjectproxy(object):
   422 class fileobjectproxy(object):
   492     """A proxy around file objects that tells a watcher when events occur.
   423     """A proxy around file objects that tells a watcher when events occur.
   493 
   424 
   494     This type is intended to only be used for testing purposes. Think hard
   425     This type is intended to only be used for testing purposes. Think hard
  1498 def clearcachedproperty(obj, prop):
  1429 def clearcachedproperty(obj, prop):
  1499     '''clear a cached property value, if one has been set'''
  1430     '''clear a cached property value, if one has been set'''
  1500     if prop in obj.__dict__:
  1431     if prop in obj.__dict__:
  1501         del obj.__dict__[prop]
  1432         del obj.__dict__[prop]
  1502 
  1433 
  1503 def pipefilter(s, cmd):
       
  1504     '''filter string S through command CMD, returning its output'''
       
  1505     p = subprocess.Popen(cmd, shell=True, close_fds=closefds,
       
  1506                          stdin=subprocess.PIPE, stdout=subprocess.PIPE)
       
  1507     pout, perr = p.communicate(s)
       
  1508     return pout
       
  1509 
       
  1510 def tempfilter(s, cmd):
       
  1511     '''filter string S through a pair of temporary files with CMD.
       
  1512     CMD is used as a template to create the real command to be run,
       
  1513     with the strings INFILE and OUTFILE replaced by the real names of
       
  1514     the temporary files generated.'''
       
  1515     inname, outname = None, None
       
  1516     try:
       
  1517         infd, inname = tempfile.mkstemp(prefix='hg-filter-in-')
       
  1518         fp = os.fdopen(infd, r'wb')
       
  1519         fp.write(s)
       
  1520         fp.close()
       
  1521         outfd, outname = tempfile.mkstemp(prefix='hg-filter-out-')
       
  1522         os.close(outfd)
       
  1523         cmd = cmd.replace('INFILE', inname)
       
  1524         cmd = cmd.replace('OUTFILE', outname)
       
  1525         code = os.system(cmd)
       
  1526         if pycompat.sysplatform == 'OpenVMS' and code & 1:
       
  1527             code = 0
       
  1528         if code:
       
  1529             raise error.Abort(_("command '%s' failed: %s") %
       
  1530                               (cmd, explainexit(code)))
       
  1531         with open(outname, 'rb') as fp:
       
  1532             return fp.read()
       
  1533     finally:
       
  1534         try:
       
  1535             if inname:
       
  1536                 os.unlink(inname)
       
  1537         except OSError:
       
  1538             pass
       
  1539         try:
       
  1540             if outname:
       
  1541                 os.unlink(outname)
       
  1542         except OSError:
       
  1543             pass
       
  1544 
       
  1545 _filtertable = {
       
  1546     'tempfile:': tempfilter,
       
  1547     'pipe:': pipefilter,
       
  1548 }
       
  1549 
       
  1550 def filter(s, cmd):
       
  1551     "filter a string through a command that transforms its input to its output"
       
  1552     for name, fn in _filtertable.iteritems():
       
  1553         if cmd.startswith(name):
       
  1554             return fn(s, cmd[len(name):].lstrip())
       
  1555     return pipefilter(s, cmd)
       
  1556 
       
  1557 def increasingchunks(source, min=1024, max=65536):
  1434 def increasingchunks(source, min=1024, max=65536):
  1558     '''return no less than min bytes per chunk while data remains,
  1435     '''return no less than min bytes per chunk while data remains,
  1559     doubling min after each chunk until it reaches max'''
  1436     doubling min after each chunk until it reaches max'''
  1560     def log2(x):
  1437     def log2(x):
  1561         if not x:
  1438         if not x:
  1642         a.pop()
  1519         a.pop()
  1643         b.pop()
  1520         b.pop()
  1644     b.reverse()
  1521     b.reverse()
  1645     return pycompat.ossep.join((['..'] * len(a)) + b) or '.'
  1522     return pycompat.ossep.join((['..'] * len(a)) + b) or '.'
  1646 
  1523 
  1647 def mainfrozen():
       
  1648     """return True if we are a frozen executable.
       
  1649 
       
  1650     The code supports py2exe (most common, Windows only) and tools/freeze
       
  1651     (portable, not much used).
       
  1652     """
       
  1653     return (safehasattr(sys, "frozen") or # new py2exe
       
  1654             safehasattr(sys, "importers") or # old py2exe
       
  1655             imp.is_frozen(u"__main__")) # tools/freeze
       
  1656 
       
  1657 # the location of data files matching the source code
  1524 # the location of data files matching the source code
  1658 if mainfrozen() and getattr(sys, 'frozen', None) != 'macosx_app':
  1525 if procutil.mainfrozen() and getattr(sys, 'frozen', None) != 'macosx_app':
  1659     # executable version (py2exe) doesn't support __file__
  1526     # executable version (py2exe) doesn't support __file__
  1660     datapath = os.path.dirname(pycompat.sysexecutable)
  1527     datapath = os.path.dirname(pycompat.sysexecutable)
  1661 else:
  1528 else:
  1662     datapath = os.path.dirname(pycompat.fsencode(__file__))
  1529     datapath = os.path.dirname(pycompat.fsencode(__file__))
  1663 
  1530 
  1664 i18n.setdatapath(datapath)
  1531 i18n.setdatapath(datapath)
  1665 
       
  1666 _hgexecutable = None
       
  1667 
       
  1668 def hgexecutable():
       
  1669     """return location of the 'hg' executable.
       
  1670 
       
  1671     Defaults to $HG or 'hg' in the search path.
       
  1672     """
       
  1673     if _hgexecutable is None:
       
  1674         hg = encoding.environ.get('HG')
       
  1675         mainmod = sys.modules[r'__main__']
       
  1676         if hg:
       
  1677             _sethgexecutable(hg)
       
  1678         elif mainfrozen():
       
  1679             if getattr(sys, 'frozen', None) == 'macosx_app':
       
  1680                 # Env variable set by py2app
       
  1681                 _sethgexecutable(encoding.environ['EXECUTABLEPATH'])
       
  1682             else:
       
  1683                 _sethgexecutable(pycompat.sysexecutable)
       
  1684         elif (os.path.basename(
       
  1685             pycompat.fsencode(getattr(mainmod, '__file__', ''))) == 'hg'):
       
  1686             _sethgexecutable(pycompat.fsencode(mainmod.__file__))
       
  1687         else:
       
  1688             exe = findexe('hg') or os.path.basename(sys.argv[0])
       
  1689             _sethgexecutable(exe)
       
  1690     return _hgexecutable
       
  1691 
       
  1692 def _sethgexecutable(path):
       
  1693     """set location of the 'hg' executable"""
       
  1694     global _hgexecutable
       
  1695     _hgexecutable = path
       
  1696 
       
  1697 def _testfileno(f, stdf):
       
  1698     fileno = getattr(f, 'fileno', None)
       
  1699     try:
       
  1700         return fileno and fileno() == stdf.fileno()
       
  1701     except io.UnsupportedOperation:
       
  1702         return False # fileno() raised UnsupportedOperation
       
  1703 
       
  1704 def isstdin(f):
       
  1705     return _testfileno(f, sys.__stdin__)
       
  1706 
       
  1707 def isstdout(f):
       
  1708     return _testfileno(f, sys.__stdout__)
       
  1709 
       
  1710 def shellenviron(environ=None):
       
  1711     """return environ with optional override, useful for shelling out"""
       
  1712     def py2shell(val):
       
  1713         'convert python object into string that is useful to shell'
       
  1714         if val is None or val is False:
       
  1715             return '0'
       
  1716         if val is True:
       
  1717             return '1'
       
  1718         return pycompat.bytestr(val)
       
  1719     env = dict(encoding.environ)
       
  1720     if environ:
       
  1721         env.update((k, py2shell(v)) for k, v in environ.iteritems())
       
  1722     env['HG'] = hgexecutable()
       
  1723     return env
       
  1724 
       
  1725 def system(cmd, environ=None, cwd=None, out=None):
       
  1726     '''enhanced shell command execution.
       
  1727     run with environment maybe modified, maybe in different dir.
       
  1728 
       
  1729     if out is specified, it is assumed to be a file-like object that has a
       
  1730     write() method. stdout and stderr will be redirected to out.'''
       
  1731     try:
       
  1732         stdout.flush()
       
  1733     except Exception:
       
  1734         pass
       
  1735     cmd = quotecommand(cmd)
       
  1736     env = shellenviron(environ)
       
  1737     if out is None or isstdout(out):
       
  1738         rc = subprocess.call(cmd, shell=True, close_fds=closefds,
       
  1739                              env=env, cwd=cwd)
       
  1740     else:
       
  1741         proc = subprocess.Popen(cmd, shell=True, close_fds=closefds,
       
  1742                                 env=env, cwd=cwd, stdout=subprocess.PIPE,
       
  1743                                 stderr=subprocess.STDOUT)
       
  1744         for line in iter(proc.stdout.readline, ''):
       
  1745             out.write(line)
       
  1746         proc.wait()
       
  1747         rc = proc.returncode
       
  1748     if pycompat.sysplatform == 'OpenVMS' and rc & 1:
       
  1749         rc = 0
       
  1750     return rc
       
  1751 
  1532 
  1752 def checksignature(func):
  1533 def checksignature(func):
  1753     '''wrap a function with code to check for calling errors'''
  1534     '''wrap a function with code to check for calling errors'''
  1754     def check(*args, **kwargs):
  1535     def check(*args, **kwargs):
  1755         try:
  1536         try:
  2130     Note that this function does not use os.altsep because this is
  1911     Note that this function does not use os.altsep because this is
  2131     an alternative of simple "xxx.split(os.sep)".
  1912     an alternative of simple "xxx.split(os.sep)".
  2132     It is recommended to use os.path.normpath() before using this
  1913     It is recommended to use os.path.normpath() before using this
  2133     function if need.'''
  1914     function if need.'''
  2134     return path.split(pycompat.ossep)
  1915     return path.split(pycompat.ossep)
  2135 
       
  2136 def gui():
       
  2137     '''Are we running in a GUI?'''
       
  2138     if pycompat.isdarwin:
       
  2139         if 'SSH_CONNECTION' in encoding.environ:
       
  2140             # handle SSH access to a box where the user is logged in
       
  2141             return False
       
  2142         elif getattr(osutil, 'isgui', None):
       
  2143             # check if a CoreGraphics session is available
       
  2144             return osutil.isgui()
       
  2145         else:
       
  2146             # pure build; use a safe default
       
  2147             return True
       
  2148     else:
       
  2149         return pycompat.iswindows or encoding.environ.get("DISPLAY")
       
  2150 
  1916 
  2151 def mktempcopy(name, emptyok=False, createmode=None):
  1917 def mktempcopy(name, emptyok=False, createmode=None):
  2152     """Create a temporary file with the same contents from name
  1918     """Create a temporary file with the same contents from name
  2153 
  1919 
  2154     The permission bits are copied from the original file.
  1920     The permission bits are copied from the original file.
  2714             yield line
  2480             yield line
  2715 
  2481 
  2716 def expandpath(path):
  2482 def expandpath(path):
  2717     return os.path.expanduser(os.path.expandvars(path))
  2483     return os.path.expanduser(os.path.expandvars(path))
  2718 
  2484 
  2719 def hgcmd():
       
  2720     """Return the command used to execute current hg
       
  2721 
       
  2722     This is different from hgexecutable() because on Windows we want
       
  2723     to avoid things opening new shell windows like batch files, so we
       
  2724     get either the python call or current executable.
       
  2725     """
       
  2726     if mainfrozen():
       
  2727         if getattr(sys, 'frozen', None) == 'macosx_app':
       
  2728             # Env variable set by py2app
       
  2729             return [encoding.environ['EXECUTABLEPATH']]
       
  2730         else:
       
  2731             return [pycompat.sysexecutable]
       
  2732     return _gethgcmd()
       
  2733 
       
  2734 def rundetached(args, condfn):
       
  2735     """Execute the argument list in a detached process.
       
  2736 
       
  2737     condfn is a callable which is called repeatedly and should return
       
  2738     True once the child process is known to have started successfully.
       
  2739     At this point, the child process PID is returned. If the child
       
  2740     process fails to start or finishes before condfn() evaluates to
       
  2741     True, return -1.
       
  2742     """
       
  2743     # Windows case is easier because the child process is either
       
  2744     # successfully starting and validating the condition or exiting
       
  2745     # on failure. We just poll on its PID. On Unix, if the child
       
  2746     # process fails to start, it will be left in a zombie state until
       
  2747     # the parent wait on it, which we cannot do since we expect a long
       
  2748     # running process on success. Instead we listen for SIGCHLD telling
       
  2749     # us our child process terminated.
       
  2750     terminated = set()
       
  2751     def handler(signum, frame):
       
  2752         terminated.add(os.wait())
       
  2753     prevhandler = None
       
  2754     SIGCHLD = getattr(signal, 'SIGCHLD', None)
       
  2755     if SIGCHLD is not None:
       
  2756         prevhandler = signal.signal(SIGCHLD, handler)
       
  2757     try:
       
  2758         pid = spawndetached(args)
       
  2759         while not condfn():
       
  2760             if ((pid in terminated or not testpid(pid))
       
  2761                 and not condfn()):
       
  2762                 return -1
       
  2763             time.sleep(0.1)
       
  2764         return pid
       
  2765     finally:
       
  2766         if prevhandler is not None:
       
  2767             signal.signal(signal.SIGCHLD, prevhandler)
       
  2768 
       
  2769 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
  2485 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
  2770     """Return the result of interpolating items in the mapping into string s.
  2486     """Return the result of interpolating items in the mapping into string s.
  2771 
  2487 
  2772     prefix is a single character string, or a two character string with
  2488     prefix is a single character string, or a two character string with
  2773     a backslash as the first character if the prefix needs to be escaped in
  2489     a backslash as the first character if the prefix needs to be escaped in
  3255                 yield (fnmax, fnln, func)
  2971                 yield (fnmax, fnln, func)
  3256             else:
  2972             else:
  3257                 yield line % (fnmax, fnln, func)
  2973                 yield line % (fnmax, fnln, func)
  3258 
  2974 
  3259 def debugstacktrace(msg='stacktrace', skip=0,
  2975 def debugstacktrace(msg='stacktrace', skip=0,
  3260                     f=stderr, otherf=stdout, depth=0):
  2976                     f=procutil.stderr, otherf=procutil.stdout, depth=0):
  3261     '''Writes a message to f (stderr) with a nicely formatted stacktrace.
  2977     '''Writes a message to f (stderr) with a nicely formatted stacktrace.
  3262     Skips the 'skip' entries closest to the call, then show 'depth' entries.
  2978     Skips the 'skip' entries closest to the call, then show 'depth' entries.
  3263     By default it will flush stdout first.
  2979     By default it will flush stdout first.
  3264     It can be used everywhere and intentionally does not require an ui object.
  2980     It can be used everywhere and intentionally does not require an ui object.
  3265     Not be used in production code but very convenient while developing.
  2981     Not be used in production code but very convenient while developing.
  4074 parsetimezone = _deprecatedfunc(dateutil.parsetimezone, '4.6')
  3790 parsetimezone = _deprecatedfunc(dateutil.parsetimezone, '4.6')
  4075 strdate = _deprecatedfunc(dateutil.strdate, '4.6')
  3791 strdate = _deprecatedfunc(dateutil.strdate, '4.6')
  4076 parsedate = _deprecatedfunc(dateutil.parsedate, '4.6')
  3792 parsedate = _deprecatedfunc(dateutil.parsedate, '4.6')
  4077 matchdate = _deprecatedfunc(dateutil.matchdate, '4.6')
  3793 matchdate = _deprecatedfunc(dateutil.matchdate, '4.6')
  4078 
  3794 
       
  3795 stderr = procutil.stderr
       
  3796 stdin = procutil.stdin
       
  3797 stdout = procutil.stdout
       
  3798 explainexit = procutil.explainexit
       
  3799 findexe = procutil.findexe
       
  3800 getuser = procutil.getuser
       
  3801 getpid = procutil.getpid
       
  3802 hidewindow = procutil.hidewindow
       
  3803 popen = procutil.popen
       
  3804 quotecommand = procutil.quotecommand
       
  3805 readpipe = procutil.readpipe
       
  3806 setbinary = procutil.setbinary
       
  3807 setsignalhandler = procutil.setsignalhandler
       
  3808 shellquote = procutil.shellquote
       
  3809 shellsplit = procutil.shellsplit
       
  3810 spawndetached = procutil.spawndetached
       
  3811 sshargs = procutil.sshargs
       
  3812 testpid = procutil.testpid
       
  3813 try:
       
  3814     setprocname = procutil.setprocname
       
  3815 except AttributeError:
       
  3816     pass
       
  3817 try:
       
  3818     unblocksignal = procutil.unblocksignal
       
  3819 except AttributeError:
       
  3820     pass
       
  3821 closefds = procutil.closefds
       
  3822 isatty = procutil.isatty
       
  3823 popen2 = procutil.popen2
       
  3824 popen3 = procutil.popen3
       
  3825 popen4 = procutil.popen4
       
  3826 pipefilter = procutil.pipefilter
       
  3827 tempfilter = procutil.tempfilter
       
  3828 filter = procutil.filter
       
  3829 mainfrozen = procutil.mainfrozen
       
  3830 hgexecutable = procutil.hgexecutable
       
  3831 isstdin = procutil.isstdin
       
  3832 isstdout = procutil.isstdout
       
  3833 shellenviron = procutil.shellenviron
       
  3834 system = procutil.system
       
  3835 gui = procutil.gui
       
  3836 hgcmd = procutil.hgcmd
       
  3837 rundetached = procutil.rundetached
       
  3838 
  4079 escapedata = _deprecatedfunc(stringutil.escapedata, '4.6')
  3839 escapedata = _deprecatedfunc(stringutil.escapedata, '4.6')
  4080 binary = _deprecatedfunc(stringutil.binary, '4.6')
  3840 binary = _deprecatedfunc(stringutil.binary, '4.6')
  4081 stringmatcher = _deprecatedfunc(stringutil.stringmatcher, '4.6')
  3841 stringmatcher = _deprecatedfunc(stringutil.stringmatcher, '4.6')
  4082 shortuser = _deprecatedfunc(stringutil.shortuser, '4.6')
  3842 shortuser = _deprecatedfunc(stringutil.shortuser, '4.6')
  4083 emailuser = _deprecatedfunc(stringutil.emailuser, '4.6')
  3843 emailuser = _deprecatedfunc(stringutil.emailuser, '4.6')