##// END OF EJS Templates
py3: convert popen() command arguments in hgclient to str on Windows...
Matt Harbison -
r41020:6a372f94 default
parent child Browse files
Show More
@@ -1,142 +1,147
1 # A minimal client for Mercurial's command server
1 # A minimal client for Mercurial's command server
2
2
3 from __future__ import absolute_import, print_function
3 from __future__ import absolute_import, print_function
4
4
5 import io
5 import io
6 import os
6 import os
7 import re
7 import re
8 import signal
8 import signal
9 import socket
9 import socket
10 import struct
10 import struct
11 import subprocess
11 import subprocess
12 import sys
12 import sys
13 import time
13 import time
14
14
15 if sys.version_info[0] >= 3:
15 if sys.version_info[0] >= 3:
16 stdout = sys.stdout.buffer
16 stdout = sys.stdout.buffer
17 stderr = sys.stderr.buffer
17 stderr = sys.stderr.buffer
18 stringio = io.BytesIO
18 stringio = io.BytesIO
19 def bprint(*args):
19 def bprint(*args):
20 # remove b'' as well for ease of test migration
20 # remove b'' as well for ease of test migration
21 pargs = [re.sub(br'''\bb(['"])''', br'\1', b'%s' % a) for a in args]
21 pargs = [re.sub(br'''\bb(['"])''', br'\1', b'%s' % a) for a in args]
22 stdout.write(b' '.join(pargs) + b'\n')
22 stdout.write(b' '.join(pargs) + b'\n')
23 else:
23 else:
24 import cStringIO
24 import cStringIO
25 stdout = sys.stdout
25 stdout = sys.stdout
26 stderr = sys.stderr
26 stderr = sys.stderr
27 stringio = cStringIO.StringIO
27 stringio = cStringIO.StringIO
28 bprint = print
28 bprint = print
29
29
30 def connectpipe(path=None, extraargs=()):
30 def connectpipe(path=None, extraargs=()):
31 cmdline = [b'hg', b'serve', b'--cmdserver', b'pipe']
31 cmdline = [b'hg', b'serve', b'--cmdserver', b'pipe']
32 if path:
32 if path:
33 cmdline += [b'-R', path]
33 cmdline += [b'-R', path]
34 cmdline.extend(extraargs)
34 cmdline.extend(extraargs)
35
35
36 server = subprocess.Popen(cmdline, stdin=subprocess.PIPE,
36 def tonative(cmdline):
37 if os.name != r'nt':
38 return cmdline
39 return [arg.decode("utf-8") for arg in cmdline]
40
41 server = subprocess.Popen(tonative(cmdline), stdin=subprocess.PIPE,
37 stdout=subprocess.PIPE)
42 stdout=subprocess.PIPE)
38
43
39 return server
44 return server
40
45
41 class unixconnection(object):
46 class unixconnection(object):
42 def __init__(self, sockpath):
47 def __init__(self, sockpath):
43 self.sock = sock = socket.socket(socket.AF_UNIX)
48 self.sock = sock = socket.socket(socket.AF_UNIX)
44 sock.connect(sockpath)
49 sock.connect(sockpath)
45 self.stdin = sock.makefile('wb')
50 self.stdin = sock.makefile('wb')
46 self.stdout = sock.makefile('rb')
51 self.stdout = sock.makefile('rb')
47
52
48 def wait(self):
53 def wait(self):
49 self.stdin.close()
54 self.stdin.close()
50 self.stdout.close()
55 self.stdout.close()
51 self.sock.close()
56 self.sock.close()
52
57
53 class unixserver(object):
58 class unixserver(object):
54 def __init__(self, sockpath, logpath=None, repopath=None):
59 def __init__(self, sockpath, logpath=None, repopath=None):
55 self.sockpath = sockpath
60 self.sockpath = sockpath
56 cmdline = [b'hg', b'serve', b'--cmdserver', b'unix', b'-a', sockpath]
61 cmdline = [b'hg', b'serve', b'--cmdserver', b'unix', b'-a', sockpath]
57 if repopath:
62 if repopath:
58 cmdline += [b'-R', repopath]
63 cmdline += [b'-R', repopath]
59 if logpath:
64 if logpath:
60 stdout = open(logpath, 'a')
65 stdout = open(logpath, 'a')
61 stderr = subprocess.STDOUT
66 stderr = subprocess.STDOUT
62 else:
67 else:
63 stdout = stderr = None
68 stdout = stderr = None
64 self.server = subprocess.Popen(cmdline, stdout=stdout, stderr=stderr)
69 self.server = subprocess.Popen(cmdline, stdout=stdout, stderr=stderr)
65 # wait for listen()
70 # wait for listen()
66 while self.server.poll() is None:
71 while self.server.poll() is None:
67 if os.path.exists(sockpath):
72 if os.path.exists(sockpath):
68 break
73 break
69 time.sleep(0.1)
74 time.sleep(0.1)
70
75
71 def connect(self):
76 def connect(self):
72 return unixconnection(self.sockpath)
77 return unixconnection(self.sockpath)
73
78
74 def shutdown(self):
79 def shutdown(self):
75 os.kill(self.server.pid, signal.SIGTERM)
80 os.kill(self.server.pid, signal.SIGTERM)
76 self.server.wait()
81 self.server.wait()
77
82
78 def writeblock(server, data):
83 def writeblock(server, data):
79 server.stdin.write(struct.pack(b'>I', len(data)))
84 server.stdin.write(struct.pack(b'>I', len(data)))
80 server.stdin.write(data)
85 server.stdin.write(data)
81 server.stdin.flush()
86 server.stdin.flush()
82
87
83 def readchannel(server):
88 def readchannel(server):
84 data = server.stdout.read(5)
89 data = server.stdout.read(5)
85 if not data:
90 if not data:
86 raise EOFError
91 raise EOFError
87 channel, length = struct.unpack('>cI', data)
92 channel, length = struct.unpack('>cI', data)
88 if channel in b'IL':
93 if channel in b'IL':
89 return channel, length
94 return channel, length
90 else:
95 else:
91 return channel, server.stdout.read(length)
96 return channel, server.stdout.read(length)
92
97
93 def sep(text):
98 def sep(text):
94 return text.replace(b'\\', b'/')
99 return text.replace(b'\\', b'/')
95
100
96 def runcommand(server, args, output=stdout, error=stderr, input=None,
101 def runcommand(server, args, output=stdout, error=stderr, input=None,
97 outfilter=lambda x: x):
102 outfilter=lambda x: x):
98 bprint(b'*** runcommand', b' '.join(args))
103 bprint(b'*** runcommand', b' '.join(args))
99 stdout.flush()
104 stdout.flush()
100 server.stdin.write(b'runcommand\n')
105 server.stdin.write(b'runcommand\n')
101 writeblock(server, b'\0'.join(args))
106 writeblock(server, b'\0'.join(args))
102
107
103 if not input:
108 if not input:
104 input = stringio()
109 input = stringio()
105
110
106 while True:
111 while True:
107 ch, data = readchannel(server)
112 ch, data = readchannel(server)
108 if ch == b'o':
113 if ch == b'o':
109 output.write(outfilter(data))
114 output.write(outfilter(data))
110 output.flush()
115 output.flush()
111 elif ch == b'e':
116 elif ch == b'e':
112 error.write(data)
117 error.write(data)
113 error.flush()
118 error.flush()
114 elif ch == b'I':
119 elif ch == b'I':
115 writeblock(server, input.read(data))
120 writeblock(server, input.read(data))
116 elif ch == b'L':
121 elif ch == b'L':
117 writeblock(server, input.readline(data))
122 writeblock(server, input.readline(data))
118 elif ch == b'm':
123 elif ch == b'm':
119 bprint(b"message: %r" % data)
124 bprint(b"message: %r" % data)
120 elif ch == b'r':
125 elif ch == b'r':
121 ret, = struct.unpack('>i', data)
126 ret, = struct.unpack('>i', data)
122 if ret != 0:
127 if ret != 0:
123 bprint(b' [%d]' % ret)
128 bprint(b' [%d]' % ret)
124 return ret
129 return ret
125 else:
130 else:
126 bprint(b"unexpected channel %c: %r" % (ch, data))
131 bprint(b"unexpected channel %c: %r" % (ch, data))
127 if ch.isupper():
132 if ch.isupper():
128 return
133 return
129
134
130 def check(func, connect=connectpipe):
135 def check(func, connect=connectpipe):
131 stdout.flush()
136 stdout.flush()
132 server = connect()
137 server = connect()
133 try:
138 try:
134 return func(server)
139 return func(server)
135 finally:
140 finally:
136 server.stdin.close()
141 server.stdin.close()
137 server.wait()
142 server.wait()
138
143
139 def checkwith(connect=connectpipe, **kwargs):
144 def checkwith(connect=connectpipe, **kwargs):
140 def wrap(func):
145 def wrap(func):
141 return check(func, lambda: connect(**kwargs))
146 return check(func, lambda: connect(**kwargs))
142 return wrap
147 return wrap
General Comments 0
You need to be logged in to leave comments. Login now