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