##// END OF EJS Templates
cmdserver: include pid of server handling requests in hello message...
Yuya Nishihara -
r23036:19f5273c default
parent child Browse files
Show More
@@ -1,319 +1,321 b''
1 # commandserver.py - communicate with Mercurial's API over a pipe
1 # commandserver.py - communicate with Mercurial's API over a pipe
2 #
2 #
3 # Copyright Matt Mackall <mpm@selenic.com>
3 # Copyright Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from i18n import _
8 from i18n import _
9 import struct
9 import struct
10 import sys, os, errno, traceback, SocketServer
10 import sys, os, errno, traceback, SocketServer
11 import dispatch, encoding, util
11 import dispatch, encoding, util
12
12
13 logfile = None
13 logfile = None
14
14
15 def log(*args):
15 def log(*args):
16 if not logfile:
16 if not logfile:
17 return
17 return
18
18
19 for a in args:
19 for a in args:
20 logfile.write(str(a))
20 logfile.write(str(a))
21
21
22 logfile.flush()
22 logfile.flush()
23
23
24 class channeledoutput(object):
24 class channeledoutput(object):
25 """
25 """
26 Write data to out in the following format:
26 Write data to out in the following format:
27
27
28 data length (unsigned int),
28 data length (unsigned int),
29 data
29 data
30 """
30 """
31 def __init__(self, out, channel):
31 def __init__(self, out, channel):
32 self.out = out
32 self.out = out
33 self.channel = channel
33 self.channel = channel
34
34
35 def write(self, data):
35 def write(self, data):
36 if not data:
36 if not data:
37 return
37 return
38 self.out.write(struct.pack('>cI', self.channel, len(data)))
38 self.out.write(struct.pack('>cI', self.channel, len(data)))
39 self.out.write(data)
39 self.out.write(data)
40 self.out.flush()
40 self.out.flush()
41
41
42 def __getattr__(self, attr):
42 def __getattr__(self, attr):
43 if attr in ('isatty', 'fileno'):
43 if attr in ('isatty', 'fileno'):
44 raise AttributeError(attr)
44 raise AttributeError(attr)
45 return getattr(self.out, attr)
45 return getattr(self.out, attr)
46
46
47 class channeledinput(object):
47 class channeledinput(object):
48 """
48 """
49 Read data from in_.
49 Read data from in_.
50
50
51 Requests for input are written to out in the following format:
51 Requests for input are written to out in the following format:
52 channel identifier - 'I' for plain input, 'L' line based (1 byte)
52 channel identifier - 'I' for plain input, 'L' line based (1 byte)
53 how many bytes to send at most (unsigned int),
53 how many bytes to send at most (unsigned int),
54
54
55 The client replies with:
55 The client replies with:
56 data length (unsigned int), 0 meaning EOF
56 data length (unsigned int), 0 meaning EOF
57 data
57 data
58 """
58 """
59
59
60 maxchunksize = 4 * 1024
60 maxchunksize = 4 * 1024
61
61
62 def __init__(self, in_, out, channel):
62 def __init__(self, in_, out, channel):
63 self.in_ = in_
63 self.in_ = in_
64 self.out = out
64 self.out = out
65 self.channel = channel
65 self.channel = channel
66
66
67 def read(self, size=-1):
67 def read(self, size=-1):
68 if size < 0:
68 if size < 0:
69 # if we need to consume all the clients input, ask for 4k chunks
69 # if we need to consume all the clients input, ask for 4k chunks
70 # so the pipe doesn't fill up risking a deadlock
70 # so the pipe doesn't fill up risking a deadlock
71 size = self.maxchunksize
71 size = self.maxchunksize
72 s = self._read(size, self.channel)
72 s = self._read(size, self.channel)
73 buf = s
73 buf = s
74 while s:
74 while s:
75 s = self._read(size, self.channel)
75 s = self._read(size, self.channel)
76 buf += s
76 buf += s
77
77
78 return buf
78 return buf
79 else:
79 else:
80 return self._read(size, self.channel)
80 return self._read(size, self.channel)
81
81
82 def _read(self, size, channel):
82 def _read(self, size, channel):
83 if not size:
83 if not size:
84 return ''
84 return ''
85 assert size > 0
85 assert size > 0
86
86
87 # tell the client we need at most size bytes
87 # tell the client we need at most size bytes
88 self.out.write(struct.pack('>cI', channel, size))
88 self.out.write(struct.pack('>cI', channel, size))
89 self.out.flush()
89 self.out.flush()
90
90
91 length = self.in_.read(4)
91 length = self.in_.read(4)
92 length = struct.unpack('>I', length)[0]
92 length = struct.unpack('>I', length)[0]
93 if not length:
93 if not length:
94 return ''
94 return ''
95 else:
95 else:
96 return self.in_.read(length)
96 return self.in_.read(length)
97
97
98 def readline(self, size=-1):
98 def readline(self, size=-1):
99 if size < 0:
99 if size < 0:
100 size = self.maxchunksize
100 size = self.maxchunksize
101 s = self._read(size, 'L')
101 s = self._read(size, 'L')
102 buf = s
102 buf = s
103 # keep asking for more until there's either no more or
103 # keep asking for more until there's either no more or
104 # we got a full line
104 # we got a full line
105 while s and s[-1] != '\n':
105 while s and s[-1] != '\n':
106 s = self._read(size, 'L')
106 s = self._read(size, 'L')
107 buf += s
107 buf += s
108
108
109 return buf
109 return buf
110 else:
110 else:
111 return self._read(size, 'L')
111 return self._read(size, 'L')
112
112
113 def __iter__(self):
113 def __iter__(self):
114 return self
114 return self
115
115
116 def next(self):
116 def next(self):
117 l = self.readline()
117 l = self.readline()
118 if not l:
118 if not l:
119 raise StopIteration
119 raise StopIteration
120 return l
120 return l
121
121
122 def __getattr__(self, attr):
122 def __getattr__(self, attr):
123 if attr in ('isatty', 'fileno'):
123 if attr in ('isatty', 'fileno'):
124 raise AttributeError(attr)
124 raise AttributeError(attr)
125 return getattr(self.in_, attr)
125 return getattr(self.in_, attr)
126
126
127 class server(object):
127 class server(object):
128 """
128 """
129 Listens for commands on fin, runs them and writes the output on a channel
129 Listens for commands on fin, runs them and writes the output on a channel
130 based stream to fout.
130 based stream to fout.
131 """
131 """
132 def __init__(self, ui, repo, fin, fout):
132 def __init__(self, ui, repo, fin, fout):
133 self.cwd = os.getcwd()
133 self.cwd = os.getcwd()
134
134
135 logpath = ui.config("cmdserver", "log", None)
135 logpath = ui.config("cmdserver", "log", None)
136 if logpath:
136 if logpath:
137 global logfile
137 global logfile
138 if logpath == '-':
138 if logpath == '-':
139 # write log on a special 'd' (debug) channel
139 # write log on a special 'd' (debug) channel
140 logfile = channeledoutput(fout, 'd')
140 logfile = channeledoutput(fout, 'd')
141 else:
141 else:
142 logfile = open(logpath, 'a')
142 logfile = open(logpath, 'a')
143
143
144 if repo:
144 if repo:
145 # the ui here is really the repo ui so take its baseui so we don't
145 # the ui here is really the repo ui so take its baseui so we don't
146 # end up with its local configuration
146 # end up with its local configuration
147 self.ui = repo.baseui
147 self.ui = repo.baseui
148 self.repo = repo
148 self.repo = repo
149 self.repoui = repo.ui
149 self.repoui = repo.ui
150 else:
150 else:
151 self.ui = ui
151 self.ui = ui
152 self.repo = self.repoui = None
152 self.repo = self.repoui = None
153
153
154 self.cerr = channeledoutput(fout, 'e')
154 self.cerr = channeledoutput(fout, 'e')
155 self.cout = channeledoutput(fout, 'o')
155 self.cout = channeledoutput(fout, 'o')
156 self.cin = channeledinput(fin, fout, 'I')
156 self.cin = channeledinput(fin, fout, 'I')
157 self.cresult = channeledoutput(fout, 'r')
157 self.cresult = channeledoutput(fout, 'r')
158
158
159 self.client = fin
159 self.client = fin
160
160
161 def _read(self, size):
161 def _read(self, size):
162 if not size:
162 if not size:
163 return ''
163 return ''
164
164
165 data = self.client.read(size)
165 data = self.client.read(size)
166
166
167 # is the other end closed?
167 # is the other end closed?
168 if not data:
168 if not data:
169 raise EOFError
169 raise EOFError
170
170
171 return data
171 return data
172
172
173 def runcommand(self):
173 def runcommand(self):
174 """ reads a list of \0 terminated arguments, executes
174 """ reads a list of \0 terminated arguments, executes
175 and writes the return code to the result channel """
175 and writes the return code to the result channel """
176
176
177 length = struct.unpack('>I', self._read(4))[0]
177 length = struct.unpack('>I', self._read(4))[0]
178 if not length:
178 if not length:
179 args = []
179 args = []
180 else:
180 else:
181 args = self._read(length).split('\0')
181 args = self._read(length).split('\0')
182
182
183 # copy the uis so changes (e.g. --config or --verbose) don't
183 # copy the uis so changes (e.g. --config or --verbose) don't
184 # persist between requests
184 # persist between requests
185 copiedui = self.ui.copy()
185 copiedui = self.ui.copy()
186 uis = [copiedui]
186 uis = [copiedui]
187 if self.repo:
187 if self.repo:
188 self.repo.baseui = copiedui
188 self.repo.baseui = copiedui
189 # clone ui without using ui.copy because this is protected
189 # clone ui without using ui.copy because this is protected
190 repoui = self.repoui.__class__(self.repoui)
190 repoui = self.repoui.__class__(self.repoui)
191 repoui.copy = copiedui.copy # redo copy protection
191 repoui.copy = copiedui.copy # redo copy protection
192 uis.append(repoui)
192 uis.append(repoui)
193 self.repo.ui = self.repo.dirstate._ui = repoui
193 self.repo.ui = self.repo.dirstate._ui = repoui
194 self.repo.invalidateall()
194 self.repo.invalidateall()
195
195
196 for ui in uis:
196 for ui in uis:
197 # any kind of interaction must use server channels
197 # any kind of interaction must use server channels
198 ui.setconfig('ui', 'nontty', 'true', 'commandserver')
198 ui.setconfig('ui', 'nontty', 'true', 'commandserver')
199
199
200 req = dispatch.request(args[:], copiedui, self.repo, self.cin,
200 req = dispatch.request(args[:], copiedui, self.repo, self.cin,
201 self.cout, self.cerr)
201 self.cout, self.cerr)
202
202
203 ret = (dispatch.dispatch(req) or 0) & 255 # might return None
203 ret = (dispatch.dispatch(req) or 0) & 255 # might return None
204
204
205 # restore old cwd
205 # restore old cwd
206 if '--cwd' in args:
206 if '--cwd' in args:
207 os.chdir(self.cwd)
207 os.chdir(self.cwd)
208
208
209 self.cresult.write(struct.pack('>i', int(ret)))
209 self.cresult.write(struct.pack('>i', int(ret)))
210
210
211 def getencoding(self):
211 def getencoding(self):
212 """ writes the current encoding to the result channel """
212 """ writes the current encoding to the result channel """
213 self.cresult.write(encoding.encoding)
213 self.cresult.write(encoding.encoding)
214
214
215 def serveone(self):
215 def serveone(self):
216 cmd = self.client.readline()[:-1]
216 cmd = self.client.readline()[:-1]
217 if cmd:
217 if cmd:
218 handler = self.capabilities.get(cmd)
218 handler = self.capabilities.get(cmd)
219 if handler:
219 if handler:
220 handler(self)
220 handler(self)
221 else:
221 else:
222 # clients are expected to check what commands are supported by
222 # clients are expected to check what commands are supported by
223 # looking at the servers capabilities
223 # looking at the servers capabilities
224 raise util.Abort(_('unknown command %s') % cmd)
224 raise util.Abort(_('unknown command %s') % cmd)
225
225
226 return cmd != ''
226 return cmd != ''
227
227
228 capabilities = {'runcommand' : runcommand,
228 capabilities = {'runcommand' : runcommand,
229 'getencoding' : getencoding}
229 'getencoding' : getencoding}
230
230
231 def serve(self):
231 def serve(self):
232 hellomsg = 'capabilities: ' + ' '.join(sorted(self.capabilities))
232 hellomsg = 'capabilities: ' + ' '.join(sorted(self.capabilities))
233 hellomsg += '\n'
233 hellomsg += '\n'
234 hellomsg += 'encoding: ' + encoding.encoding
234 hellomsg += 'encoding: ' + encoding.encoding
235 hellomsg += '\n'
236 hellomsg += 'pid: %d' % os.getpid()
235
237
236 # write the hello msg in -one- chunk
238 # write the hello msg in -one- chunk
237 self.cout.write(hellomsg)
239 self.cout.write(hellomsg)
238
240
239 try:
241 try:
240 while self.serveone():
242 while self.serveone():
241 pass
243 pass
242 except EOFError:
244 except EOFError:
243 # we'll get here if the client disconnected while we were reading
245 # we'll get here if the client disconnected while we were reading
244 # its request
246 # its request
245 return 1
247 return 1
246
248
247 return 0
249 return 0
248
250
249 class pipeservice(object):
251 class pipeservice(object):
250 def __init__(self, ui, repo, opts):
252 def __init__(self, ui, repo, opts):
251 self.server = server(ui, repo, sys.stdin, sys.stdout)
253 self.server = server(ui, repo, sys.stdin, sys.stdout)
252
254
253 def init(self):
255 def init(self):
254 pass
256 pass
255
257
256 def run(self):
258 def run(self):
257 return self.server.serve()
259 return self.server.serve()
258
260
259 class _requesthandler(SocketServer.StreamRequestHandler):
261 class _requesthandler(SocketServer.StreamRequestHandler):
260 def handle(self):
262 def handle(self):
261 ui = self.server.ui
263 ui = self.server.ui
262 repo = self.server.repo
264 repo = self.server.repo
263 sv = server(ui, repo, self.rfile, self.wfile)
265 sv = server(ui, repo, self.rfile, self.wfile)
264 try:
266 try:
265 try:
267 try:
266 sv.serve()
268 sv.serve()
267 # handle exceptions that may be raised by command server. most of
269 # handle exceptions that may be raised by command server. most of
268 # known exceptions are caught by dispatch.
270 # known exceptions are caught by dispatch.
269 except util.Abort, inst:
271 except util.Abort, inst:
270 ui.warn(_('abort: %s\n') % inst)
272 ui.warn(_('abort: %s\n') % inst)
271 except IOError, inst:
273 except IOError, inst:
272 if inst.errno != errno.EPIPE:
274 if inst.errno != errno.EPIPE:
273 raise
275 raise
274 except KeyboardInterrupt:
276 except KeyboardInterrupt:
275 pass
277 pass
276 except: # re-raises
278 except: # re-raises
277 # also write traceback to error channel. otherwise client cannot
279 # also write traceback to error channel. otherwise client cannot
278 # see it because it is written to server's stderr by default.
280 # see it because it is written to server's stderr by default.
279 traceback.print_exc(file=sv.cerr)
281 traceback.print_exc(file=sv.cerr)
280 raise
282 raise
281
283
282 class unixservice(object):
284 class unixservice(object):
283 """
285 """
284 Listens on unix domain socket and forks server per connection
286 Listens on unix domain socket and forks server per connection
285 """
287 """
286 def __init__(self, ui, repo, opts):
288 def __init__(self, ui, repo, opts):
287 self.ui = ui
289 self.ui = ui
288 self.repo = repo
290 self.repo = repo
289 self.address = opts['address']
291 self.address = opts['address']
290 if not util.safehasattr(SocketServer, 'UnixStreamServer'):
292 if not util.safehasattr(SocketServer, 'UnixStreamServer'):
291 raise util.Abort(_('unsupported platform'))
293 raise util.Abort(_('unsupported platform'))
292 if not self.address:
294 if not self.address:
293 raise util.Abort(_('no socket path specified with --address'))
295 raise util.Abort(_('no socket path specified with --address'))
294
296
295 def init(self):
297 def init(self):
296 class cls(SocketServer.ForkingMixIn, SocketServer.UnixStreamServer):
298 class cls(SocketServer.ForkingMixIn, SocketServer.UnixStreamServer):
297 ui = self.ui
299 ui = self.ui
298 repo = self.repo
300 repo = self.repo
299 self.server = cls(self.address, _requesthandler)
301 self.server = cls(self.address, _requesthandler)
300 self.ui.status(_('listening at %s\n') % self.address)
302 self.ui.status(_('listening at %s\n') % self.address)
301 self.ui.flush() # avoid buffering of status message
303 self.ui.flush() # avoid buffering of status message
302
304
303 def run(self):
305 def run(self):
304 try:
306 try:
305 self.server.serve_forever()
307 self.server.serve_forever()
306 finally:
308 finally:
307 os.unlink(self.address)
309 os.unlink(self.address)
308
310
309 _servicemap = {
311 _servicemap = {
310 'pipe': pipeservice,
312 'pipe': pipeservice,
311 'unix': unixservice,
313 'unix': unixservice,
312 }
314 }
313
315
314 def createservice(ui, repo, opts):
316 def createservice(ui, repo, opts):
315 mode = opts['cmdserver']
317 mode = opts['cmdserver']
316 try:
318 try:
317 return _servicemap[mode](ui, repo, opts)
319 return _servicemap[mode](ui, repo, opts)
318 except KeyError:
320 except KeyError:
319 raise util.Abort(_('unknown mode %s') % mode)
321 raise util.Abort(_('unknown mode %s') % mode)
@@ -1,607 +1,607 b''
1 #if windows
1 #if windows
2 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH"
2 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH"
3 #else
3 #else
4 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH"
4 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH"
5 #endif
5 #endif
6 $ export PYTHONPATH
6 $ export PYTHONPATH
7
7
8 $ hg init repo
8 $ hg init repo
9 $ cd repo
9 $ cd repo
10
10
11 >>> from hgclient import readchannel, runcommand, check
11 >>> from hgclient import readchannel, runcommand, check
12 >>> @check
12 >>> @check
13 ... def hellomessage(server):
13 ... def hellomessage(server):
14 ... ch, data = readchannel(server)
14 ... ch, data = readchannel(server)
15 ... print '%c, %r' % (ch, data)
15 ... print '%c, %r' % (ch, data)
16 ... # run an arbitrary command to make sure the next thing the server
16 ... # run an arbitrary command to make sure the next thing the server
17 ... # sends isn't part of the hello message
17 ... # sends isn't part of the hello message
18 ... runcommand(server, ['id'])
18 ... runcommand(server, ['id'])
19 o, 'capabilities: getencoding runcommand\nencoding: *' (glob)
19 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
20 *** runcommand id
20 *** runcommand id
21 000000000000 tip
21 000000000000 tip
22
22
23 >>> from hgclient import check
23 >>> from hgclient import check
24 >>> @check
24 >>> @check
25 ... def unknowncommand(server):
25 ... def unknowncommand(server):
26 ... server.stdin.write('unknowncommand\n')
26 ... server.stdin.write('unknowncommand\n')
27 abort: unknown command unknowncommand
27 abort: unknown command unknowncommand
28
28
29 >>> from hgclient import readchannel, runcommand, check
29 >>> from hgclient import readchannel, runcommand, check
30 >>> @check
30 >>> @check
31 ... def checkruncommand(server):
31 ... def checkruncommand(server):
32 ... # hello block
32 ... # hello block
33 ... readchannel(server)
33 ... readchannel(server)
34 ...
34 ...
35 ... # no args
35 ... # no args
36 ... runcommand(server, [])
36 ... runcommand(server, [])
37 ...
37 ...
38 ... # global options
38 ... # global options
39 ... runcommand(server, ['id', '--quiet'])
39 ... runcommand(server, ['id', '--quiet'])
40 ...
40 ...
41 ... # make sure global options don't stick through requests
41 ... # make sure global options don't stick through requests
42 ... runcommand(server, ['id'])
42 ... runcommand(server, ['id'])
43 ...
43 ...
44 ... # --config
44 ... # --config
45 ... runcommand(server, ['id', '--config', 'ui.quiet=True'])
45 ... runcommand(server, ['id', '--config', 'ui.quiet=True'])
46 ...
46 ...
47 ... # make sure --config doesn't stick
47 ... # make sure --config doesn't stick
48 ... runcommand(server, ['id'])
48 ... runcommand(server, ['id'])
49 ...
49 ...
50 ... # negative return code should be masked
50 ... # negative return code should be masked
51 ... runcommand(server, ['id', '-runknown'])
51 ... runcommand(server, ['id', '-runknown'])
52 *** runcommand
52 *** runcommand
53 Mercurial Distributed SCM
53 Mercurial Distributed SCM
54
54
55 basic commands:
55 basic commands:
56
56
57 add add the specified files on the next commit
57 add add the specified files on the next commit
58 annotate show changeset information by line for each file
58 annotate show changeset information by line for each file
59 clone make a copy of an existing repository
59 clone make a copy of an existing repository
60 commit commit the specified files or all outstanding changes
60 commit commit the specified files or all outstanding changes
61 diff diff repository (or selected files)
61 diff diff repository (or selected files)
62 export dump the header and diffs for one or more changesets
62 export dump the header and diffs for one or more changesets
63 forget forget the specified files on the next commit
63 forget forget the specified files on the next commit
64 init create a new repository in the given directory
64 init create a new repository in the given directory
65 log show revision history of entire repository or files
65 log show revision history of entire repository or files
66 merge merge working directory with another revision
66 merge merge working directory with another revision
67 pull pull changes from the specified source
67 pull pull changes from the specified source
68 push push changes to the specified destination
68 push push changes to the specified destination
69 remove remove the specified files on the next commit
69 remove remove the specified files on the next commit
70 serve start stand-alone webserver
70 serve start stand-alone webserver
71 status show changed files in the working directory
71 status show changed files in the working directory
72 summary summarize working directory state
72 summary summarize working directory state
73 update update working directory (or switch revisions)
73 update update working directory (or switch revisions)
74
74
75 (use "hg help" for the full list of commands or "hg -v" for details)
75 (use "hg help" for the full list of commands or "hg -v" for details)
76 *** runcommand id --quiet
76 *** runcommand id --quiet
77 000000000000
77 000000000000
78 *** runcommand id
78 *** runcommand id
79 000000000000 tip
79 000000000000 tip
80 *** runcommand id --config ui.quiet=True
80 *** runcommand id --config ui.quiet=True
81 000000000000
81 000000000000
82 *** runcommand id
82 *** runcommand id
83 000000000000 tip
83 000000000000 tip
84 *** runcommand id -runknown
84 *** runcommand id -runknown
85 abort: unknown revision 'unknown'!
85 abort: unknown revision 'unknown'!
86 [255]
86 [255]
87
87
88 >>> from hgclient import readchannel, check
88 >>> from hgclient import readchannel, check
89 >>> @check
89 >>> @check
90 ... def inputeof(server):
90 ... def inputeof(server):
91 ... readchannel(server)
91 ... readchannel(server)
92 ... server.stdin.write('runcommand\n')
92 ... server.stdin.write('runcommand\n')
93 ... # close stdin while server is waiting for input
93 ... # close stdin while server is waiting for input
94 ... server.stdin.close()
94 ... server.stdin.close()
95 ...
95 ...
96 ... # server exits with 1 if the pipe closed while reading the command
96 ... # server exits with 1 if the pipe closed while reading the command
97 ... print 'server exit code =', server.wait()
97 ... print 'server exit code =', server.wait()
98 server exit code = 1
98 server exit code = 1
99
99
100 >>> import cStringIO
100 >>> import cStringIO
101 >>> from hgclient import readchannel, runcommand, check
101 >>> from hgclient import readchannel, runcommand, check
102 >>> @check
102 >>> @check
103 ... def serverinput(server):
103 ... def serverinput(server):
104 ... readchannel(server)
104 ... readchannel(server)
105 ...
105 ...
106 ... patch = """
106 ... patch = """
107 ... # HG changeset patch
107 ... # HG changeset patch
108 ... # User test
108 ... # User test
109 ... # Date 0 0
109 ... # Date 0 0
110 ... # Node ID c103a3dec114d882c98382d684d8af798d09d857
110 ... # Node ID c103a3dec114d882c98382d684d8af798d09d857
111 ... # Parent 0000000000000000000000000000000000000000
111 ... # Parent 0000000000000000000000000000000000000000
112 ... 1
112 ... 1
113 ...
113 ...
114 ... diff -r 000000000000 -r c103a3dec114 a
114 ... diff -r 000000000000 -r c103a3dec114 a
115 ... --- /dev/null Thu Jan 01 00:00:00 1970 +0000
115 ... --- /dev/null Thu Jan 01 00:00:00 1970 +0000
116 ... +++ b/a Thu Jan 01 00:00:00 1970 +0000
116 ... +++ b/a Thu Jan 01 00:00:00 1970 +0000
117 ... @@ -0,0 +1,1 @@
117 ... @@ -0,0 +1,1 @@
118 ... +1
118 ... +1
119 ... """
119 ... """
120 ...
120 ...
121 ... runcommand(server, ['import', '-'], input=cStringIO.StringIO(patch))
121 ... runcommand(server, ['import', '-'], input=cStringIO.StringIO(patch))
122 ... runcommand(server, ['log'])
122 ... runcommand(server, ['log'])
123 *** runcommand import -
123 *** runcommand import -
124 applying patch from stdin
124 applying patch from stdin
125 *** runcommand log
125 *** runcommand log
126 changeset: 0:eff892de26ec
126 changeset: 0:eff892de26ec
127 tag: tip
127 tag: tip
128 user: test
128 user: test
129 date: Thu Jan 01 00:00:00 1970 +0000
129 date: Thu Jan 01 00:00:00 1970 +0000
130 summary: 1
130 summary: 1
131
131
132
132
133 check that --cwd doesn't persist between requests:
133 check that --cwd doesn't persist between requests:
134
134
135 $ mkdir foo
135 $ mkdir foo
136 $ touch foo/bar
136 $ touch foo/bar
137 >>> from hgclient import readchannel, runcommand, check
137 >>> from hgclient import readchannel, runcommand, check
138 >>> @check
138 >>> @check
139 ... def cwd(server):
139 ... def cwd(server):
140 ... readchannel(server)
140 ... readchannel(server)
141 ... runcommand(server, ['--cwd', 'foo', 'st', 'bar'])
141 ... runcommand(server, ['--cwd', 'foo', 'st', 'bar'])
142 ... runcommand(server, ['st', 'foo/bar'])
142 ... runcommand(server, ['st', 'foo/bar'])
143 *** runcommand --cwd foo st bar
143 *** runcommand --cwd foo st bar
144 ? bar
144 ? bar
145 *** runcommand st foo/bar
145 *** runcommand st foo/bar
146 ? foo/bar
146 ? foo/bar
147
147
148 $ rm foo/bar
148 $ rm foo/bar
149
149
150
150
151 check that local configs for the cached repo aren't inherited when -R is used:
151 check that local configs for the cached repo aren't inherited when -R is used:
152
152
153 $ cat <<EOF >> .hg/hgrc
153 $ cat <<EOF >> .hg/hgrc
154 > [ui]
154 > [ui]
155 > foo = bar
155 > foo = bar
156 > EOF
156 > EOF
157
157
158 >>> from hgclient import readchannel, sep, runcommand, check
158 >>> from hgclient import readchannel, sep, runcommand, check
159 >>> @check
159 >>> @check
160 ... def localhgrc(server):
160 ... def localhgrc(server):
161 ... readchannel(server)
161 ... readchannel(server)
162 ...
162 ...
163 ... # the cached repo local hgrc contains ui.foo=bar, so showconfig should
163 ... # the cached repo local hgrc contains ui.foo=bar, so showconfig should
164 ... # show it
164 ... # show it
165 ... runcommand(server, ['showconfig'], outfilter=sep)
165 ... runcommand(server, ['showconfig'], outfilter=sep)
166 ...
166 ...
167 ... # but not for this repo
167 ... # but not for this repo
168 ... runcommand(server, ['init', 'foo'])
168 ... runcommand(server, ['init', 'foo'])
169 ... runcommand(server, ['-R', 'foo', 'showconfig', 'ui', 'defaults'])
169 ... runcommand(server, ['-R', 'foo', 'showconfig', 'ui', 'defaults'])
170 *** runcommand showconfig
170 *** runcommand showconfig
171 bundle.mainreporoot=$TESTTMP/repo
171 bundle.mainreporoot=$TESTTMP/repo
172 defaults.backout=-d "0 0"
172 defaults.backout=-d "0 0"
173 defaults.commit=-d "0 0"
173 defaults.commit=-d "0 0"
174 defaults.shelve=--date "0 0"
174 defaults.shelve=--date "0 0"
175 defaults.tag=-d "0 0"
175 defaults.tag=-d "0 0"
176 ui.slash=True
176 ui.slash=True
177 ui.interactive=False
177 ui.interactive=False
178 ui.mergemarkers=detailed
178 ui.mergemarkers=detailed
179 ui.foo=bar
179 ui.foo=bar
180 ui.nontty=true
180 ui.nontty=true
181 *** runcommand init foo
181 *** runcommand init foo
182 *** runcommand -R foo showconfig ui defaults
182 *** runcommand -R foo showconfig ui defaults
183 defaults.backout=-d "0 0"
183 defaults.backout=-d "0 0"
184 defaults.commit=-d "0 0"
184 defaults.commit=-d "0 0"
185 defaults.shelve=--date "0 0"
185 defaults.shelve=--date "0 0"
186 defaults.tag=-d "0 0"
186 defaults.tag=-d "0 0"
187 ui.slash=True
187 ui.slash=True
188 ui.interactive=False
188 ui.interactive=False
189 ui.mergemarkers=detailed
189 ui.mergemarkers=detailed
190 ui.nontty=true
190 ui.nontty=true
191
191
192 $ rm -R foo
192 $ rm -R foo
193
193
194 #if windows
194 #if windows
195 $ PYTHONPATH="$TESTTMP/repo;$PYTHONPATH"
195 $ PYTHONPATH="$TESTTMP/repo;$PYTHONPATH"
196 #else
196 #else
197 $ PYTHONPATH="$TESTTMP/repo:$PYTHONPATH"
197 $ PYTHONPATH="$TESTTMP/repo:$PYTHONPATH"
198 #endif
198 #endif
199
199
200 $ cat <<EOF > hook.py
200 $ cat <<EOF > hook.py
201 > import sys
201 > import sys
202 > def hook(**args):
202 > def hook(**args):
203 > print 'hook talking'
203 > print 'hook talking'
204 > print 'now try to read something: %r' % sys.stdin.read()
204 > print 'now try to read something: %r' % sys.stdin.read()
205 > EOF
205 > EOF
206
206
207 >>> import cStringIO
207 >>> import cStringIO
208 >>> from hgclient import readchannel, runcommand, check
208 >>> from hgclient import readchannel, runcommand, check
209 >>> @check
209 >>> @check
210 ... def hookoutput(server):
210 ... def hookoutput(server):
211 ... readchannel(server)
211 ... readchannel(server)
212 ... runcommand(server, ['--config',
212 ... runcommand(server, ['--config',
213 ... 'hooks.pre-identify=python:hook.hook',
213 ... 'hooks.pre-identify=python:hook.hook',
214 ... 'id'],
214 ... 'id'],
215 ... input=cStringIO.StringIO('some input'))
215 ... input=cStringIO.StringIO('some input'))
216 *** runcommand --config hooks.pre-identify=python:hook.hook id
216 *** runcommand --config hooks.pre-identify=python:hook.hook id
217 hook talking
217 hook talking
218 now try to read something: 'some input'
218 now try to read something: 'some input'
219 eff892de26ec tip
219 eff892de26ec tip
220
220
221 $ rm hook.py*
221 $ rm hook.py*
222
222
223 $ echo a >> a
223 $ echo a >> a
224 >>> import os
224 >>> import os
225 >>> from hgclient import readchannel, runcommand, check
225 >>> from hgclient import readchannel, runcommand, check
226 >>> @check
226 >>> @check
227 ... def outsidechanges(server):
227 ... def outsidechanges(server):
228 ... readchannel(server)
228 ... readchannel(server)
229 ... runcommand(server, ['status'])
229 ... runcommand(server, ['status'])
230 ... os.system('hg ci -Am2')
230 ... os.system('hg ci -Am2')
231 ... runcommand(server, ['tip'])
231 ... runcommand(server, ['tip'])
232 ... runcommand(server, ['status'])
232 ... runcommand(server, ['status'])
233 *** runcommand status
233 *** runcommand status
234 M a
234 M a
235 *** runcommand tip
235 *** runcommand tip
236 changeset: 1:d3a0a68be6de
236 changeset: 1:d3a0a68be6de
237 tag: tip
237 tag: tip
238 user: test
238 user: test
239 date: Thu Jan 01 00:00:00 1970 +0000
239 date: Thu Jan 01 00:00:00 1970 +0000
240 summary: 2
240 summary: 2
241
241
242 *** runcommand status
242 *** runcommand status
243
243
244 >>> import os
244 >>> import os
245 >>> from hgclient import readchannel, runcommand, check
245 >>> from hgclient import readchannel, runcommand, check
246 >>> @check
246 >>> @check
247 ... def bookmarks(server):
247 ... def bookmarks(server):
248 ... readchannel(server)
248 ... readchannel(server)
249 ... runcommand(server, ['bookmarks'])
249 ... runcommand(server, ['bookmarks'])
250 ...
250 ...
251 ... # changes .hg/bookmarks
251 ... # changes .hg/bookmarks
252 ... os.system('hg bookmark -i bm1')
252 ... os.system('hg bookmark -i bm1')
253 ... os.system('hg bookmark -i bm2')
253 ... os.system('hg bookmark -i bm2')
254 ... runcommand(server, ['bookmarks'])
254 ... runcommand(server, ['bookmarks'])
255 ...
255 ...
256 ... # changes .hg/bookmarks.current
256 ... # changes .hg/bookmarks.current
257 ... os.system('hg upd bm1 -q')
257 ... os.system('hg upd bm1 -q')
258 ... runcommand(server, ['bookmarks'])
258 ... runcommand(server, ['bookmarks'])
259 ...
259 ...
260 ... runcommand(server, ['bookmarks', 'bm3'])
260 ... runcommand(server, ['bookmarks', 'bm3'])
261 ... f = open('a', 'ab')
261 ... f = open('a', 'ab')
262 ... f.write('a\n')
262 ... f.write('a\n')
263 ... f.close()
263 ... f.close()
264 ... runcommand(server, ['commit', '-Amm'])
264 ... runcommand(server, ['commit', '-Amm'])
265 ... runcommand(server, ['bookmarks'])
265 ... runcommand(server, ['bookmarks'])
266 *** runcommand bookmarks
266 *** runcommand bookmarks
267 no bookmarks set
267 no bookmarks set
268 *** runcommand bookmarks
268 *** runcommand bookmarks
269 bm1 1:d3a0a68be6de
269 bm1 1:d3a0a68be6de
270 bm2 1:d3a0a68be6de
270 bm2 1:d3a0a68be6de
271 *** runcommand bookmarks
271 *** runcommand bookmarks
272 * bm1 1:d3a0a68be6de
272 * bm1 1:d3a0a68be6de
273 bm2 1:d3a0a68be6de
273 bm2 1:d3a0a68be6de
274 *** runcommand bookmarks bm3
274 *** runcommand bookmarks bm3
275 *** runcommand commit -Amm
275 *** runcommand commit -Amm
276 *** runcommand bookmarks
276 *** runcommand bookmarks
277 bm1 1:d3a0a68be6de
277 bm1 1:d3a0a68be6de
278 bm2 1:d3a0a68be6de
278 bm2 1:d3a0a68be6de
279 * bm3 2:aef17e88f5f0
279 * bm3 2:aef17e88f5f0
280
280
281 >>> import os
281 >>> import os
282 >>> from hgclient import readchannel, runcommand, check
282 >>> from hgclient import readchannel, runcommand, check
283 >>> @check
283 >>> @check
284 ... def tagscache(server):
284 ... def tagscache(server):
285 ... readchannel(server)
285 ... readchannel(server)
286 ... runcommand(server, ['id', '-t', '-r', '0'])
286 ... runcommand(server, ['id', '-t', '-r', '0'])
287 ... os.system('hg tag -r 0 foo')
287 ... os.system('hg tag -r 0 foo')
288 ... runcommand(server, ['id', '-t', '-r', '0'])
288 ... runcommand(server, ['id', '-t', '-r', '0'])
289 *** runcommand id -t -r 0
289 *** runcommand id -t -r 0
290
290
291 *** runcommand id -t -r 0
291 *** runcommand id -t -r 0
292 foo
292 foo
293
293
294 >>> import os
294 >>> import os
295 >>> from hgclient import readchannel, runcommand, check
295 >>> from hgclient import readchannel, runcommand, check
296 >>> @check
296 >>> @check
297 ... def setphase(server):
297 ... def setphase(server):
298 ... readchannel(server)
298 ... readchannel(server)
299 ... runcommand(server, ['phase', '-r', '.'])
299 ... runcommand(server, ['phase', '-r', '.'])
300 ... os.system('hg phase -r . -p')
300 ... os.system('hg phase -r . -p')
301 ... runcommand(server, ['phase', '-r', '.'])
301 ... runcommand(server, ['phase', '-r', '.'])
302 *** runcommand phase -r .
302 *** runcommand phase -r .
303 3: draft
303 3: draft
304 *** runcommand phase -r .
304 *** runcommand phase -r .
305 3: public
305 3: public
306
306
307 $ echo a >> a
307 $ echo a >> a
308 >>> from hgclient import readchannel, runcommand, check
308 >>> from hgclient import readchannel, runcommand, check
309 >>> @check
309 >>> @check
310 ... def rollback(server):
310 ... def rollback(server):
311 ... readchannel(server)
311 ... readchannel(server)
312 ... runcommand(server, ['phase', '-r', '.', '-p'])
312 ... runcommand(server, ['phase', '-r', '.', '-p'])
313 ... runcommand(server, ['commit', '-Am.'])
313 ... runcommand(server, ['commit', '-Am.'])
314 ... runcommand(server, ['rollback'])
314 ... runcommand(server, ['rollback'])
315 ... runcommand(server, ['phase', '-r', '.'])
315 ... runcommand(server, ['phase', '-r', '.'])
316 *** runcommand phase -r . -p
316 *** runcommand phase -r . -p
317 no phases changed
317 no phases changed
318 [1]
318 [1]
319 *** runcommand commit -Am.
319 *** runcommand commit -Am.
320 *** runcommand rollback
320 *** runcommand rollback
321 repository tip rolled back to revision 3 (undo commit)
321 repository tip rolled back to revision 3 (undo commit)
322 working directory now based on revision 3
322 working directory now based on revision 3
323 *** runcommand phase -r .
323 *** runcommand phase -r .
324 3: public
324 3: public
325
325
326 >>> import os
326 >>> import os
327 >>> from hgclient import readchannel, runcommand, check
327 >>> from hgclient import readchannel, runcommand, check
328 >>> @check
328 >>> @check
329 ... def branch(server):
329 ... def branch(server):
330 ... readchannel(server)
330 ... readchannel(server)
331 ... runcommand(server, ['branch'])
331 ... runcommand(server, ['branch'])
332 ... os.system('hg branch foo')
332 ... os.system('hg branch foo')
333 ... runcommand(server, ['branch'])
333 ... runcommand(server, ['branch'])
334 ... os.system('hg branch default')
334 ... os.system('hg branch default')
335 *** runcommand branch
335 *** runcommand branch
336 default
336 default
337 marked working directory as branch foo
337 marked working directory as branch foo
338 (branches are permanent and global, did you want a bookmark?)
338 (branches are permanent and global, did you want a bookmark?)
339 *** runcommand branch
339 *** runcommand branch
340 foo
340 foo
341 marked working directory as branch default
341 marked working directory as branch default
342 (branches are permanent and global, did you want a bookmark?)
342 (branches are permanent and global, did you want a bookmark?)
343
343
344 $ touch .hgignore
344 $ touch .hgignore
345 >>> import os
345 >>> import os
346 >>> from hgclient import readchannel, runcommand, check
346 >>> from hgclient import readchannel, runcommand, check
347 >>> @check
347 >>> @check
348 ... def hgignore(server):
348 ... def hgignore(server):
349 ... readchannel(server)
349 ... readchannel(server)
350 ... runcommand(server, ['commit', '-Am.'])
350 ... runcommand(server, ['commit', '-Am.'])
351 ... f = open('ignored-file', 'ab')
351 ... f = open('ignored-file', 'ab')
352 ... f.write('')
352 ... f.write('')
353 ... f.close()
353 ... f.close()
354 ... f = open('.hgignore', 'ab')
354 ... f = open('.hgignore', 'ab')
355 ... f.write('ignored-file')
355 ... f.write('ignored-file')
356 ... f.close()
356 ... f.close()
357 ... runcommand(server, ['status', '-i', '-u'])
357 ... runcommand(server, ['status', '-i', '-u'])
358 *** runcommand commit -Am.
358 *** runcommand commit -Am.
359 adding .hgignore
359 adding .hgignore
360 *** runcommand status -i -u
360 *** runcommand status -i -u
361 I ignored-file
361 I ignored-file
362
362
363 >>> import os
363 >>> import os
364 >>> from hgclient import readchannel, sep, runcommand, check
364 >>> from hgclient import readchannel, sep, runcommand, check
365 >>> @check
365 >>> @check
366 ... def phasecacheafterstrip(server):
366 ... def phasecacheafterstrip(server):
367 ... readchannel(server)
367 ... readchannel(server)
368 ...
368 ...
369 ... # create new head, 5:731265503d86
369 ... # create new head, 5:731265503d86
370 ... runcommand(server, ['update', '-C', '0'])
370 ... runcommand(server, ['update', '-C', '0'])
371 ... f = open('a', 'ab')
371 ... f = open('a', 'ab')
372 ... f.write('a\n')
372 ... f.write('a\n')
373 ... f.close()
373 ... f.close()
374 ... runcommand(server, ['commit', '-Am.', 'a'])
374 ... runcommand(server, ['commit', '-Am.', 'a'])
375 ... runcommand(server, ['log', '-Gq'])
375 ... runcommand(server, ['log', '-Gq'])
376 ...
376 ...
377 ... # make it public; draft marker moves to 4:7966c8e3734d
377 ... # make it public; draft marker moves to 4:7966c8e3734d
378 ... runcommand(server, ['phase', '-p', '.'])
378 ... runcommand(server, ['phase', '-p', '.'])
379 ... # load _phasecache.phaseroots
379 ... # load _phasecache.phaseroots
380 ... runcommand(server, ['phase', '.'], outfilter=sep)
380 ... runcommand(server, ['phase', '.'], outfilter=sep)
381 ...
381 ...
382 ... # strip 1::4 outside server
382 ... # strip 1::4 outside server
383 ... os.system('hg -q --config extensions.mq= strip 1')
383 ... os.system('hg -q --config extensions.mq= strip 1')
384 ...
384 ...
385 ... # shouldn't raise "7966c8e3734d: no node!"
385 ... # shouldn't raise "7966c8e3734d: no node!"
386 ... runcommand(server, ['branches'])
386 ... runcommand(server, ['branches'])
387 *** runcommand update -C 0
387 *** runcommand update -C 0
388 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
388 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
389 (leaving bookmark bm3)
389 (leaving bookmark bm3)
390 *** runcommand commit -Am. a
390 *** runcommand commit -Am. a
391 created new head
391 created new head
392 *** runcommand log -Gq
392 *** runcommand log -Gq
393 @ 5:731265503d86
393 @ 5:731265503d86
394 |
394 |
395 | o 4:7966c8e3734d
395 | o 4:7966c8e3734d
396 | |
396 | |
397 | o 3:b9b85890c400
397 | o 3:b9b85890c400
398 | |
398 | |
399 | o 2:aef17e88f5f0
399 | o 2:aef17e88f5f0
400 | |
400 | |
401 | o 1:d3a0a68be6de
401 | o 1:d3a0a68be6de
402 |/
402 |/
403 o 0:eff892de26ec
403 o 0:eff892de26ec
404
404
405 *** runcommand phase -p .
405 *** runcommand phase -p .
406 *** runcommand phase .
406 *** runcommand phase .
407 5: public
407 5: public
408 *** runcommand branches
408 *** runcommand branches
409 default 1:731265503d86
409 default 1:731265503d86
410
410
411 $ cat >> .hg/hgrc << EOF
411 $ cat >> .hg/hgrc << EOF
412 > [experimental]
412 > [experimental]
413 > evolution=createmarkers
413 > evolution=createmarkers
414 > EOF
414 > EOF
415
415
416 >>> import os
416 >>> import os
417 >>> from hgclient import readchannel, runcommand, check
417 >>> from hgclient import readchannel, runcommand, check
418 >>> @check
418 >>> @check
419 ... def obsolete(server):
419 ... def obsolete(server):
420 ... readchannel(server)
420 ... readchannel(server)
421 ...
421 ...
422 ... runcommand(server, ['up', 'null'])
422 ... runcommand(server, ['up', 'null'])
423 ... runcommand(server, ['phase', '-df', 'tip'])
423 ... runcommand(server, ['phase', '-df', 'tip'])
424 ... cmd = 'hg debugobsolete `hg log -r tip --template {node}`'
424 ... cmd = 'hg debugobsolete `hg log -r tip --template {node}`'
425 ... if os.name == 'nt':
425 ... if os.name == 'nt':
426 ... cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe
426 ... cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe
427 ... os.system(cmd)
427 ... os.system(cmd)
428 ... runcommand(server, ['log', '--hidden'])
428 ... runcommand(server, ['log', '--hidden'])
429 ... runcommand(server, ['log'])
429 ... runcommand(server, ['log'])
430 *** runcommand up null
430 *** runcommand up null
431 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
431 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
432 *** runcommand phase -df tip
432 *** runcommand phase -df tip
433 *** runcommand log --hidden
433 *** runcommand log --hidden
434 changeset: 1:731265503d86
434 changeset: 1:731265503d86
435 tag: tip
435 tag: tip
436 user: test
436 user: test
437 date: Thu Jan 01 00:00:00 1970 +0000
437 date: Thu Jan 01 00:00:00 1970 +0000
438 summary: .
438 summary: .
439
439
440 changeset: 0:eff892de26ec
440 changeset: 0:eff892de26ec
441 bookmark: bm1
441 bookmark: bm1
442 bookmark: bm2
442 bookmark: bm2
443 bookmark: bm3
443 bookmark: bm3
444 user: test
444 user: test
445 date: Thu Jan 01 00:00:00 1970 +0000
445 date: Thu Jan 01 00:00:00 1970 +0000
446 summary: 1
446 summary: 1
447
447
448 *** runcommand log
448 *** runcommand log
449 changeset: 0:eff892de26ec
449 changeset: 0:eff892de26ec
450 bookmark: bm1
450 bookmark: bm1
451 bookmark: bm2
451 bookmark: bm2
452 bookmark: bm3
452 bookmark: bm3
453 tag: tip
453 tag: tip
454 user: test
454 user: test
455 date: Thu Jan 01 00:00:00 1970 +0000
455 date: Thu Jan 01 00:00:00 1970 +0000
456 summary: 1
456 summary: 1
457
457
458
458
459 $ cat <<EOF >> .hg/hgrc
459 $ cat <<EOF >> .hg/hgrc
460 > [extensions]
460 > [extensions]
461 > mq =
461 > mq =
462 > EOF
462 > EOF
463
463
464 >>> import os
464 >>> import os
465 >>> from hgclient import readchannel, runcommand, check
465 >>> from hgclient import readchannel, runcommand, check
466 >>> @check
466 >>> @check
467 ... def mqoutsidechanges(server):
467 ... def mqoutsidechanges(server):
468 ... readchannel(server)
468 ... readchannel(server)
469 ...
469 ...
470 ... # load repo.mq
470 ... # load repo.mq
471 ... runcommand(server, ['qapplied'])
471 ... runcommand(server, ['qapplied'])
472 ... os.system('hg qnew 0.diff')
472 ... os.system('hg qnew 0.diff')
473 ... # repo.mq should be invalidated
473 ... # repo.mq should be invalidated
474 ... runcommand(server, ['qapplied'])
474 ... runcommand(server, ['qapplied'])
475 ...
475 ...
476 ... runcommand(server, ['qpop', '--all'])
476 ... runcommand(server, ['qpop', '--all'])
477 ... os.system('hg qqueue --create foo')
477 ... os.system('hg qqueue --create foo')
478 ... # repo.mq should be recreated to point to new queue
478 ... # repo.mq should be recreated to point to new queue
479 ... runcommand(server, ['qqueue', '--active'])
479 ... runcommand(server, ['qqueue', '--active'])
480 *** runcommand qapplied
480 *** runcommand qapplied
481 *** runcommand qapplied
481 *** runcommand qapplied
482 0.diff
482 0.diff
483 *** runcommand qpop --all
483 *** runcommand qpop --all
484 popping 0.diff
484 popping 0.diff
485 patch queue now empty
485 patch queue now empty
486 *** runcommand qqueue --active
486 *** runcommand qqueue --active
487 foo
487 foo
488
488
489 $ cat <<EOF > dbgui.py
489 $ cat <<EOF > dbgui.py
490 > from mercurial import cmdutil, commands
490 > from mercurial import cmdutil, commands
491 > cmdtable = {}
491 > cmdtable = {}
492 > command = cmdutil.command(cmdtable)
492 > command = cmdutil.command(cmdtable)
493 > @command("debuggetpass", norepo=True)
493 > @command("debuggetpass", norepo=True)
494 > def debuggetpass(ui):
494 > def debuggetpass(ui):
495 > ui.write("%s\\n" % ui.getpass())
495 > ui.write("%s\\n" % ui.getpass())
496 > @command("debugprompt", norepo=True)
496 > @command("debugprompt", norepo=True)
497 > def debugprompt(ui):
497 > def debugprompt(ui):
498 > ui.write("%s\\n" % ui.prompt("prompt:"))
498 > ui.write("%s\\n" % ui.prompt("prompt:"))
499 > EOF
499 > EOF
500 $ cat <<EOF >> .hg/hgrc
500 $ cat <<EOF >> .hg/hgrc
501 > [extensions]
501 > [extensions]
502 > dbgui = dbgui.py
502 > dbgui = dbgui.py
503 > EOF
503 > EOF
504
504
505 >>> import cStringIO
505 >>> import cStringIO
506 >>> from hgclient import readchannel, runcommand, check
506 >>> from hgclient import readchannel, runcommand, check
507 >>> @check
507 >>> @check
508 ... def getpass(server):
508 ... def getpass(server):
509 ... readchannel(server)
509 ... readchannel(server)
510 ... runcommand(server, ['debuggetpass', '--config',
510 ... runcommand(server, ['debuggetpass', '--config',
511 ... 'ui.interactive=True'],
511 ... 'ui.interactive=True'],
512 ... input=cStringIO.StringIO('1234\n'))
512 ... input=cStringIO.StringIO('1234\n'))
513 ... runcommand(server, ['debugprompt', '--config',
513 ... runcommand(server, ['debugprompt', '--config',
514 ... 'ui.interactive=True'],
514 ... 'ui.interactive=True'],
515 ... input=cStringIO.StringIO('5678\n'))
515 ... input=cStringIO.StringIO('5678\n'))
516 *** runcommand debuggetpass --config ui.interactive=True
516 *** runcommand debuggetpass --config ui.interactive=True
517 password: 1234
517 password: 1234
518 *** runcommand debugprompt --config ui.interactive=True
518 *** runcommand debugprompt --config ui.interactive=True
519 prompt: 5678
519 prompt: 5678
520
520
521
521
522 start without repository:
522 start without repository:
523
523
524 $ cd ..
524 $ cd ..
525
525
526 >>> from hgclient import readchannel, runcommand, check
526 >>> from hgclient import readchannel, runcommand, check
527 >>> @check
527 >>> @check
528 ... def hellomessage(server):
528 ... def hellomessage(server):
529 ... ch, data = readchannel(server)
529 ... ch, data = readchannel(server)
530 ... print '%c, %r' % (ch, data)
530 ... print '%c, %r' % (ch, data)
531 ... # run an arbitrary command to make sure the next thing the server
531 ... # run an arbitrary command to make sure the next thing the server
532 ... # sends isn't part of the hello message
532 ... # sends isn't part of the hello message
533 ... runcommand(server, ['id'])
533 ... runcommand(server, ['id'])
534 o, 'capabilities: getencoding runcommand\nencoding: *' (glob)
534 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
535 *** runcommand id
535 *** runcommand id
536 abort: there is no Mercurial repository here (.hg not found)
536 abort: there is no Mercurial repository here (.hg not found)
537 [255]
537 [255]
538
538
539 >>> from hgclient import readchannel, runcommand, check
539 >>> from hgclient import readchannel, runcommand, check
540 >>> @check
540 >>> @check
541 ... def startwithoutrepo(server):
541 ... def startwithoutrepo(server):
542 ... readchannel(server)
542 ... readchannel(server)
543 ... runcommand(server, ['init', 'repo2'])
543 ... runcommand(server, ['init', 'repo2'])
544 ... runcommand(server, ['id', '-R', 'repo2'])
544 ... runcommand(server, ['id', '-R', 'repo2'])
545 *** runcommand init repo2
545 *** runcommand init repo2
546 *** runcommand id -R repo2
546 *** runcommand id -R repo2
547 000000000000 tip
547 000000000000 tip
548
548
549
549
550 unix domain socket:
550 unix domain socket:
551
551
552 $ cd repo
552 $ cd repo
553 $ hg update -q
553 $ hg update -q
554
554
555 #if unix-socket
555 #if unix-socket
556
556
557 >>> import cStringIO
557 >>> import cStringIO
558 >>> from hgclient import unixserver, readchannel, runcommand, check
558 >>> from hgclient import unixserver, readchannel, runcommand, check
559 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
559 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
560 >>> def hellomessage(conn):
560 >>> def hellomessage(conn):
561 ... ch, data = readchannel(conn)
561 ... ch, data = readchannel(conn)
562 ... print '%c, %r' % (ch, data)
562 ... print '%c, %r' % (ch, data)
563 ... runcommand(conn, ['id'])
563 ... runcommand(conn, ['id'])
564 >>> check(hellomessage, server.connect)
564 >>> check(hellomessage, server.connect)
565 o, 'capabilities: getencoding runcommand\nencoding: *' (glob)
565 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
566 *** runcommand id
566 *** runcommand id
567 eff892de26ec tip bm1/bm2/bm3
567 eff892de26ec tip bm1/bm2/bm3
568 >>> def unknowncommand(conn):
568 >>> def unknowncommand(conn):
569 ... readchannel(conn)
569 ... readchannel(conn)
570 ... conn.stdin.write('unknowncommand\n')
570 ... conn.stdin.write('unknowncommand\n')
571 >>> check(unknowncommand, server.connect) # error sent to server.log
571 >>> check(unknowncommand, server.connect) # error sent to server.log
572 >>> def serverinput(conn):
572 >>> def serverinput(conn):
573 ... readchannel(conn)
573 ... readchannel(conn)
574 ... patch = """
574 ... patch = """
575 ... # HG changeset patch
575 ... # HG changeset patch
576 ... # User test
576 ... # User test
577 ... # Date 0 0
577 ... # Date 0 0
578 ... 2
578 ... 2
579 ...
579 ...
580 ... diff -r eff892de26ec -r 1ed24be7e7a0 a
580 ... diff -r eff892de26ec -r 1ed24be7e7a0 a
581 ... --- a/a
581 ... --- a/a
582 ... +++ b/a
582 ... +++ b/a
583 ... @@ -1,1 +1,2 @@
583 ... @@ -1,1 +1,2 @@
584 ... 1
584 ... 1
585 ... +2
585 ... +2
586 ... """
586 ... """
587 ... runcommand(conn, ['import', '-'], input=cStringIO.StringIO(patch))
587 ... runcommand(conn, ['import', '-'], input=cStringIO.StringIO(patch))
588 ... runcommand(conn, ['log', '-rtip', '-q'])
588 ... runcommand(conn, ['log', '-rtip', '-q'])
589 >>> check(serverinput, server.connect)
589 >>> check(serverinput, server.connect)
590 *** runcommand import -
590 *** runcommand import -
591 applying patch from stdin
591 applying patch from stdin
592 *** runcommand log -rtip -q
592 *** runcommand log -rtip -q
593 2:1ed24be7e7a0
593 2:1ed24be7e7a0
594 >>> server.shutdown()
594 >>> server.shutdown()
595
595
596 $ cat .hg/server.log
596 $ cat .hg/server.log
597 listening at .hg/server.sock
597 listening at .hg/server.sock
598 abort: unknown command unknowncommand
598 abort: unknown command unknowncommand
599 killed!
599 killed!
600
600
601 #else
601 #else
602
602
603 $ hg serve --cmdserver unix -a .hg/server.sock
603 $ hg serve --cmdserver unix -a .hg/server.sock
604 abort: unsupported platform
604 abort: unsupported platform
605 [255]
605 [255]
606
606
607 #endif
607 #endif
General Comments 0
You need to be logged in to leave comments. Login now