author | Yuya Nishihara <yuya@tcha.org> |
Thu, 04 Jan 2018 15:20:46 +0900 | |
changeset 35689 | 5fe6f946f111 |
parent 28836 | 3f45488d70df |
child 40314 | 73c2b9c9cd3c |
permissions | -rw-r--r-- |
22566
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
1 |
# A minimal client for Mercurial's command server |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
2 |
|
28355
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
3 |
from __future__ import absolute_import, print_function |
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
4 |
import os |
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
5 |
import signal |
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
6 |
import socket |
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
7 |
import struct |
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
8 |
import subprocess |
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
9 |
import sys |
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
10 |
import time |
22566
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
11 |
|
28836
3f45488d70df
test-commandserver: handle cStringIO.StringIO/io.StringIO divergence
timeless <timeless@mozdev.org>
parents:
28355
diff
changeset
|
12 |
try: |
3f45488d70df
test-commandserver: handle cStringIO.StringIO/io.StringIO divergence
timeless <timeless@mozdev.org>
parents:
28355
diff
changeset
|
13 |
import cStringIO as io |
3f45488d70df
test-commandserver: handle cStringIO.StringIO/io.StringIO divergence
timeless <timeless@mozdev.org>
parents:
28355
diff
changeset
|
14 |
stringio = io.StringIO |
3f45488d70df
test-commandserver: handle cStringIO.StringIO/io.StringIO divergence
timeless <timeless@mozdev.org>
parents:
28355
diff
changeset
|
15 |
except ImportError: |
3f45488d70df
test-commandserver: handle cStringIO.StringIO/io.StringIO divergence
timeless <timeless@mozdev.org>
parents:
28355
diff
changeset
|
16 |
import io |
3f45488d70df
test-commandserver: handle cStringIO.StringIO/io.StringIO divergence
timeless <timeless@mozdev.org>
parents:
28355
diff
changeset
|
17 |
stringio = io.StringIO |
3f45488d70df
test-commandserver: handle cStringIO.StringIO/io.StringIO divergence
timeless <timeless@mozdev.org>
parents:
28355
diff
changeset
|
18 |
|
22992
892b2b8c1b50
test-commandserver: allow check() to make connection in different way
Yuya Nishihara <yuya@tcha.org>
parents:
22991
diff
changeset
|
19 |
def connectpipe(path=None): |
22566
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
20 |
cmdline = ['hg', 'serve', '--cmdserver', 'pipe'] |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
21 |
if path: |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
22 |
cmdline += ['-R', path] |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
23 |
|
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
24 |
server = subprocess.Popen(cmdline, stdin=subprocess.PIPE, |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
25 |
stdout=subprocess.PIPE) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
26 |
|
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
27 |
return server |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
28 |
|
22993
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
29 |
class unixconnection(object): |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
30 |
def __init__(self, sockpath): |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
31 |
self.sock = sock = socket.socket(socket.AF_UNIX) |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
32 |
sock.connect(sockpath) |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
33 |
self.stdin = sock.makefile('wb') |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
34 |
self.stdout = sock.makefile('rb') |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
35 |
|
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
36 |
def wait(self): |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
37 |
self.stdin.close() |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
38 |
self.stdout.close() |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
39 |
self.sock.close() |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
40 |
|
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
41 |
class unixserver(object): |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
42 |
def __init__(self, sockpath, logpath=None, repopath=None): |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
43 |
self.sockpath = sockpath |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
44 |
cmdline = ['hg', 'serve', '--cmdserver', 'unix', '-a', sockpath] |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
45 |
if repopath: |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
46 |
cmdline += ['-R', repopath] |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
47 |
if logpath: |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
48 |
stdout = open(logpath, 'a') |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
49 |
stderr = subprocess.STDOUT |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
50 |
else: |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
51 |
stdout = stderr = None |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
52 |
self.server = subprocess.Popen(cmdline, stdout=stdout, stderr=stderr) |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
53 |
# wait for listen() |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
54 |
while self.server.poll() is None: |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
55 |
if os.path.exists(sockpath): |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
56 |
break |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
57 |
time.sleep(0.1) |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
58 |
|
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
59 |
def connect(self): |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
60 |
return unixconnection(self.sockpath) |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
61 |
|
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
62 |
def shutdown(self): |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
63 |
os.kill(self.server.pid, signal.SIGTERM) |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
64 |
self.server.wait() |
24c5fd2894f8
test-commandserver: add connector for unix domain socket server
Yuya Nishihara <yuya@tcha.org>
parents:
22992
diff
changeset
|
65 |
|
22566
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
66 |
def writeblock(server, data): |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
67 |
server.stdin.write(struct.pack('>I', len(data))) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
68 |
server.stdin.write(data) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
69 |
server.stdin.flush() |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
70 |
|
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
71 |
def readchannel(server): |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
72 |
data = server.stdout.read(5) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
73 |
if not data: |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
74 |
raise EOFError |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
75 |
channel, length = struct.unpack('>cI', data) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
76 |
if channel in 'IL': |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
77 |
return channel, length |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
78 |
else: |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
79 |
return channel, server.stdout.read(length) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
80 |
|
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
81 |
def sep(text): |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
82 |
return text.replace('\\', '/') |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
83 |
|
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
84 |
def runcommand(server, args, output=sys.stdout, error=sys.stderr, input=None, |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
85 |
outfilter=lambda x: x): |
28355
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
86 |
print('*** runcommand', ' '.join(args)) |
22566
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
87 |
sys.stdout.flush() |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
88 |
server.stdin.write('runcommand\n') |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
89 |
writeblock(server, '\0'.join(args)) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
90 |
|
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
91 |
if not input: |
28836
3f45488d70df
test-commandserver: handle cStringIO.StringIO/io.StringIO divergence
timeless <timeless@mozdev.org>
parents:
28355
diff
changeset
|
92 |
input = stringio() |
22566
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
93 |
|
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
94 |
while True: |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
95 |
ch, data = readchannel(server) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
96 |
if ch == 'o': |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
97 |
output.write(outfilter(data)) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
98 |
output.flush() |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
99 |
elif ch == 'e': |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
100 |
error.write(data) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
101 |
error.flush() |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
102 |
elif ch == 'I': |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
103 |
writeblock(server, input.read(data)) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
104 |
elif ch == 'L': |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
105 |
writeblock(server, input.readline(data)) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
106 |
elif ch == 'r': |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
107 |
ret, = struct.unpack('>i', data) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
108 |
if ret != 0: |
28355
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
109 |
print(' [%d]' % ret) |
22566
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
110 |
return ret |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
111 |
else: |
28355
897a4bbd578b
hgclient: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents:
22993
diff
changeset
|
112 |
print("unexpected channel %c: %r" % (ch, data)) |
22566
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
113 |
if ch.isupper(): |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
114 |
return |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
115 |
|
22992
892b2b8c1b50
test-commandserver: allow check() to make connection in different way
Yuya Nishihara <yuya@tcha.org>
parents:
22991
diff
changeset
|
116 |
def check(func, connect=connectpipe): |
22566
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
117 |
sys.stdout.flush() |
22991
a94594f5d52f
test-commandserver: remove unused repopath argument from check()
Yuya Nishihara <yuya@tcha.org>
parents:
22572
diff
changeset
|
118 |
server = connect() |
22566
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
119 |
try: |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
120 |
return func(server) |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
121 |
finally: |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
122 |
server.stdin.close() |
480b7fefbb08
test-commandserver: split helper functions to new hgclient module
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
123 |
server.wait() |