972 |
972 |
973 def _isstdout(f): |
973 def _isstdout(f): |
974 fileno = getattr(f, 'fileno', None) |
974 fileno = getattr(f, 'fileno', None) |
975 return fileno and fileno() == sys.__stdout__.fileno() |
975 return fileno and fileno() == sys.__stdout__.fileno() |
976 |
976 |
977 def system(cmd, environ=None, cwd=None, onerr=None, errprefix=None, out=None): |
977 def shellenviron(environ=None): |
978 '''enhanced shell command execution. |
978 """return environ with optional override, useful for shelling out""" |
979 run with environment maybe modified, maybe in different dir. |
|
980 |
|
981 if command fails and onerr is None, return status, else raise onerr |
|
982 object as exception. |
|
983 |
|
984 if out is specified, it is assumed to be a file-like object that has a |
|
985 write() method. stdout and stderr will be redirected to out.''' |
|
986 if environ is None: |
|
987 environ = {} |
|
988 try: |
|
989 stdout.flush() |
|
990 except Exception: |
|
991 pass |
|
992 def py2shell(val): |
979 def py2shell(val): |
993 'convert python object into string that is useful to shell' |
980 'convert python object into string that is useful to shell' |
994 if val is None or val is False: |
981 if val is None or val is False: |
995 return '0' |
982 return '0' |
996 if val is True: |
983 if val is True: |
997 return '1' |
984 return '1' |
998 return str(val) |
985 return str(val) |
|
986 env = dict(encoding.environ) |
|
987 if environ: |
|
988 env.update((k, py2shell(v)) for k, v in environ.iteritems()) |
|
989 env['HG'] = hgexecutable() |
|
990 return env |
|
991 |
|
992 def system(cmd, environ=None, cwd=None, onerr=None, errprefix=None, out=None): |
|
993 '''enhanced shell command execution. |
|
994 run with environment maybe modified, maybe in different dir. |
|
995 |
|
996 if command fails and onerr is None, return status, else raise onerr |
|
997 object as exception. |
|
998 |
|
999 if out is specified, it is assumed to be a file-like object that has a |
|
1000 write() method. stdout and stderr will be redirected to out.''' |
|
1001 try: |
|
1002 stdout.flush() |
|
1003 except Exception: |
|
1004 pass |
999 origcmd = cmd |
1005 origcmd = cmd |
1000 cmd = quotecommand(cmd) |
1006 cmd = quotecommand(cmd) |
1001 if pycompat.sysplatform == 'plan9' and (sys.version_info[0] == 2 |
1007 if pycompat.sysplatform == 'plan9' and (sys.version_info[0] == 2 |
1002 and sys.version_info[1] < 7): |
1008 and sys.version_info[1] < 7): |
1003 # subprocess kludge to work around issues in half-baked Python |
1009 # subprocess kludge to work around issues in half-baked Python |
1004 # ports, notably bichued/python: |
1010 # ports, notably bichued/python: |
1005 if not cwd is None: |
1011 if not cwd is None: |
1006 os.chdir(cwd) |
1012 os.chdir(cwd) |
1007 rc = os.system(cmd) |
1013 rc = os.system(cmd) |
1008 else: |
1014 else: |
1009 env = dict(encoding.environ) |
1015 env = shellenviron(environ) |
1010 env.update((k, py2shell(v)) for k, v in environ.iteritems()) |
|
1011 env['HG'] = hgexecutable() |
|
1012 if out is None or _isstdout(out): |
1016 if out is None or _isstdout(out): |
1013 rc = subprocess.call(cmd, shell=True, close_fds=closefds, |
1017 rc = subprocess.call(cmd, shell=True, close_fds=closefds, |
1014 env=env, cwd=cwd) |
1018 env=env, cwd=cwd) |
1015 else: |
1019 else: |
1016 proc = subprocess.Popen(cmd, shell=True, close_fds=closefds, |
1020 proc = subprocess.Popen(cmd, shell=True, close_fds=closefds, |