Mercurial > hg
comparison mercurial/util.py @ 37118:5be286db5fb5
procutil: move process/executable management functions to new module
std* files, pipe helpers, and findexe()s are moved as well since they are
likely to be used with sub processes.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 24 Mar 2018 13:38:04 +0900 |
parents | e7b517809ebc |
children | 24ab3381bf15 |
comparison
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') |