annotate contrib/hgclient.py @ 33113:fc290a39590d

setup: replace runhg() with an hgcommand helper class Replace the runhg() function with an hgcommand helper class. hgcommand has as run() function similar to runhg(), but no longer requires the caller to pass in the exact path to python and the hg script, and the environment settings for invoking hg. For now this diff contains no behavior changes, but in the future this will make it easier for the hgcommand helper class to more intelligently figure out the proper way to invoke hg.
author Adam Simpkins <simpkins@fb.com>
date Tue, 27 Jun 2017 16:15:32 -0700
parents 3f45488d70df
children 73c2b9c9cd3c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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()