##// END OF EJS Templates
sshpeer: use the doublepipe object for the server to client channel...
Pierre-Yves David -
r25422:8dc5ee5b default
parent child Browse files
Show More
@@ -1,326 +1,327
1 # sshpeer.py - ssh repository proxy class for mercurial
1 # sshpeer.py - ssh repository proxy class for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 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 import re
8 import re
9 from i18n import _
9 from i18n import _
10 import util, error, wireproto
10 import util, error, wireproto
11
11
12 class remotelock(object):
12 class remotelock(object):
13 def __init__(self, repo):
13 def __init__(self, repo):
14 self.repo = repo
14 self.repo = repo
15 def release(self):
15 def release(self):
16 self.repo.unlock()
16 self.repo.unlock()
17 self.repo = None
17 self.repo = None
18 def __del__(self):
18 def __del__(self):
19 if self.repo:
19 if self.repo:
20 self.release()
20 self.release()
21
21
22 def _serverquote(s):
22 def _serverquote(s):
23 if not s:
23 if not s:
24 return s
24 return s
25 '''quote a string for the remote shell ... which we assume is sh'''
25 '''quote a string for the remote shell ... which we assume is sh'''
26 if re.match('[a-zA-Z0-9@%_+=:,./-]*$', s):
26 if re.match('[a-zA-Z0-9@%_+=:,./-]*$', s):
27 return s
27 return s
28 return "'%s'" % s.replace("'", "'\\''")
28 return "'%s'" % s.replace("'", "'\\''")
29
29
30 def _forwardoutput(ui, pipe):
30 def _forwardoutput(ui, pipe):
31 """display all data currently available on pipe as remote output.
31 """display all data currently available on pipe as remote output.
32
32
33 This is non blocking."""
33 This is non blocking."""
34 s = util.readpipe(pipe)
34 s = util.readpipe(pipe)
35 if s:
35 if s:
36 for l in s.splitlines():
36 for l in s.splitlines():
37 ui.status(_("remote: "), l, '\n')
37 ui.status(_("remote: "), l, '\n')
38
38
39 class doublepipe(object):
39 class doublepipe(object):
40 """Operate a side-channel pipe in addition of a main one
40 """Operate a side-channel pipe in addition of a main one
41
41
42 The side-channel pipe contains server output to be forwarded to the user
42 The side-channel pipe contains server output to be forwarded to the user
43 input. The double pipe will behave as the "main" pipe, but will ensure the
43 input. The double pipe will behave as the "main" pipe, but will ensure the
44 content of the "side" pipe is properly processed while we wait for blocking
44 content of the "side" pipe is properly processed while we wait for blocking
45 call on the "main" pipe.
45 call on the "main" pipe.
46
46
47 If large amounts of data are read from "main", the forward will cease after
47 If large amounts of data are read from "main", the forward will cease after
48 the first bytes start to appear. This simplifies the implementation
48 the first bytes start to appear. This simplifies the implementation
49 without affecting actual output of sshpeer too much as we rarely issue
49 without affecting actual output of sshpeer too much as we rarely issue
50 large read for data not yet emitted by the server.
50 large read for data not yet emitted by the server.
51
51
52 The main pipe is expected to be a 'bufferedinputpipe' from the util module
52 The main pipe is expected to be a 'bufferedinputpipe' from the util module
53 that handle all the os specific bites. This class lives in this module
53 that handle all the os specific bites. This class lives in this module
54 because it focus on behavior specifig to the ssh protocol."""
54 because it focus on behavior specifig to the ssh protocol."""
55
55
56 def __init__(self, ui, main, side):
56 def __init__(self, ui, main, side):
57 self._ui = ui
57 self._ui = ui
58 self._main = main
58 self._main = main
59 self._side = side
59 self._side = side
60
60
61 def _wait(self):
61 def _wait(self):
62 """wait until some data are available on main or side
62 """wait until some data are available on main or side
63
63
64 return a pair of boolean (ismainready, issideready)
64 return a pair of boolean (ismainready, issideready)
65
65
66 (This will only wait for data if the setup is supported by `util.poll`)
66 (This will only wait for data if the setup is supported by `util.poll`)
67 """
67 """
68 if self._main.hasbuffer:
68 if self._main.hasbuffer:
69 return (True, True) # main has data, assume side is worth poking at.
69 return (True, True) # main has data, assume side is worth poking at.
70 fds = [self._main.fileno(), self._side.fileno()]
70 fds = [self._main.fileno(), self._side.fileno()]
71 try:
71 try:
72 act = util.poll(fds)
72 act = util.poll(fds)
73 except NotImplementedError:
73 except NotImplementedError:
74 # non supported yet case, assume all have data.
74 # non supported yet case, assume all have data.
75 act = fds
75 act = fds
76 return (self._main.fileno() in act, self._side.fileno() in act)
76 return (self._main.fileno() in act, self._side.fileno() in act)
77
77
78 def read(self, size):
78 def read(self, size):
79 return self._call('read', size)
79 return self._call('read', size)
80
80
81 def readline(self):
81 def readline(self):
82 return self._call('readline')
82 return self._call('readline')
83
83
84 def _call(self, methname, size=None):
84 def _call(self, methname, size=None):
85 """call <methname> on "main", forward output of "side" while blocking
85 """call <methname> on "main", forward output of "side" while blocking
86 """
86 """
87 if size == 0 or self._main.closed:
87 if size == 0 or self._main.closed:
88 _forwardoutput(self._ui, self._side)
88 _forwardoutput(self._ui, self._side)
89 return ''
89 return ''
90 while True:
90 while True:
91 mainready, sideready = self._wait()
91 mainready, sideready = self._wait()
92 if sideready:
92 if sideready:
93 _forwardoutput(self._ui, self._side)
93 _forwardoutput(self._ui, self._side)
94 if mainready:
94 if mainready:
95 meth = getattr(self._main, methname)
95 meth = getattr(self._main, methname)
96 if size is None:
96 if size is None:
97 return meth()
97 return meth()
98 else:
98 else:
99 return meth(size)
99 return meth(size)
100
100
101 def close(self):
101 def close(self):
102 return self._main.close()
102 return self._main.close()
103
103
104 class sshpeer(wireproto.wirepeer):
104 class sshpeer(wireproto.wirepeer):
105 def __init__(self, ui, path, create=False):
105 def __init__(self, ui, path, create=False):
106 self._url = path
106 self._url = path
107 self.ui = ui
107 self.ui = ui
108 self.pipeo = self.pipei = self.pipee = None
108 self.pipeo = self.pipei = self.pipee = None
109
109
110 u = util.url(path, parsequery=False, parsefragment=False)
110 u = util.url(path, parsequery=False, parsefragment=False)
111 if u.scheme != 'ssh' or not u.host or u.path is None:
111 if u.scheme != 'ssh' or not u.host or u.path is None:
112 self._abort(error.RepoError(_("couldn't parse location %s") % path))
112 self._abort(error.RepoError(_("couldn't parse location %s") % path))
113
113
114 self.user = u.user
114 self.user = u.user
115 if u.passwd is not None:
115 if u.passwd is not None:
116 self._abort(error.RepoError(_("password in URL not supported")))
116 self._abort(error.RepoError(_("password in URL not supported")))
117 self.host = u.host
117 self.host = u.host
118 self.port = u.port
118 self.port = u.port
119 self.path = u.path or "."
119 self.path = u.path or "."
120
120
121 sshcmd = self.ui.config("ui", "ssh", "ssh")
121 sshcmd = self.ui.config("ui", "ssh", "ssh")
122 remotecmd = self.ui.config("ui", "remotecmd", "hg")
122 remotecmd = self.ui.config("ui", "remotecmd", "hg")
123
123
124 args = util.sshargs(sshcmd,
124 args = util.sshargs(sshcmd,
125 _serverquote(self.host),
125 _serverquote(self.host),
126 _serverquote(self.user),
126 _serverquote(self.user),
127 _serverquote(self.port))
127 _serverquote(self.port))
128
128
129 if create:
129 if create:
130 cmd = '%s %s %s' % (sshcmd, args,
130 cmd = '%s %s %s' % (sshcmd, args,
131 util.shellquote("%s init %s" %
131 util.shellquote("%s init %s" %
132 (_serverquote(remotecmd), _serverquote(self.path))))
132 (_serverquote(remotecmd), _serverquote(self.path))))
133 ui.debug('running %s\n' % cmd)
133 ui.debug('running %s\n' % cmd)
134 res = ui.system(cmd)
134 res = ui.system(cmd)
135 if res != 0:
135 if res != 0:
136 self._abort(error.RepoError(_("could not create remote repo")))
136 self._abort(error.RepoError(_("could not create remote repo")))
137
137
138 self._validaterepo(sshcmd, args, remotecmd)
138 self._validaterepo(sshcmd, args, remotecmd)
139
139
140 def url(self):
140 def url(self):
141 return self._url
141 return self._url
142
142
143 def _validaterepo(self, sshcmd, args, remotecmd):
143 def _validaterepo(self, sshcmd, args, remotecmd):
144 # cleanup up previous run
144 # cleanup up previous run
145 self.cleanup()
145 self.cleanup()
146
146
147 cmd = '%s %s %s' % (sshcmd, args,
147 cmd = '%s %s %s' % (sshcmd, args,
148 util.shellquote("%s -R %s serve --stdio" %
148 util.shellquote("%s -R %s serve --stdio" %
149 (_serverquote(remotecmd), _serverquote(self.path))))
149 (_serverquote(remotecmd), _serverquote(self.path))))
150 self.ui.debug('running %s\n' % cmd)
150 self.ui.debug('running %s\n' % cmd)
151 cmd = util.quotecommand(cmd)
151 cmd = util.quotecommand(cmd)
152
152
153 # while self.subprocess isn't used, having it allows the subprocess to
153 # while self.subprocess isn't used, having it allows the subprocess to
154 # to clean up correctly later
154 # to clean up correctly later
155 #
155 #
156 # no buffer allow the use of 'select'
156 # no buffer allow the use of 'select'
157 # feel free to remove buffering and select usage when we ultimately
157 # feel free to remove buffering and select usage when we ultimately
158 # move to threading.
158 # move to threading.
159 sub = util.popen4(cmd, bufsize=0)
159 sub = util.popen4(cmd, bufsize=0)
160 self.pipeo, self.pipei, self.pipee, self.subprocess = sub
160 self.pipeo, self.pipei, self.pipee, self.subprocess = sub
161
161
162 self.pipei = util.bufferedinputpipe(self.pipei)
162 self.pipei = util.bufferedinputpipe(self.pipei)
163 self.pipei = doublepipe(self.ui, self.pipei, self.pipee)
163
164
164 # skip any noise generated by remote shell
165 # skip any noise generated by remote shell
165 self._callstream("hello")
166 self._callstream("hello")
166 r = self._callstream("between", pairs=("%s-%s" % ("0"*40, "0"*40)))
167 r = self._callstream("between", pairs=("%s-%s" % ("0"*40, "0"*40)))
167 lines = ["", "dummy"]
168 lines = ["", "dummy"]
168 max_noise = 500
169 max_noise = 500
169 while lines[-1] and max_noise:
170 while lines[-1] and max_noise:
170 l = r.readline()
171 l = r.readline()
171 self.readerr()
172 self.readerr()
172 if lines[-1] == "1\n" and l == "\n":
173 if lines[-1] == "1\n" and l == "\n":
173 break
174 break
174 if l:
175 if l:
175 self.ui.debug("remote: ", l)
176 self.ui.debug("remote: ", l)
176 lines.append(l)
177 lines.append(l)
177 max_noise -= 1
178 max_noise -= 1
178 else:
179 else:
179 self._abort(error.RepoError(_('no suitable response from '
180 self._abort(error.RepoError(_('no suitable response from '
180 'remote hg')))
181 'remote hg')))
181
182
182 self._caps = set()
183 self._caps = set()
183 for l in reversed(lines):
184 for l in reversed(lines):
184 if l.startswith("capabilities:"):
185 if l.startswith("capabilities:"):
185 self._caps.update(l[:-1].split(":")[1].split())
186 self._caps.update(l[:-1].split(":")[1].split())
186 break
187 break
187
188
188 def _capabilities(self):
189 def _capabilities(self):
189 return self._caps
190 return self._caps
190
191
191 def readerr(self):
192 def readerr(self):
192 _forwardoutput(self.ui, self.pipee)
193 _forwardoutput(self.ui, self.pipee)
193
194
194 def _abort(self, exception):
195 def _abort(self, exception):
195 self.cleanup()
196 self.cleanup()
196 raise exception
197 raise exception
197
198
198 def cleanup(self):
199 def cleanup(self):
199 if self.pipeo is None:
200 if self.pipeo is None:
200 return
201 return
201 self.pipeo.close()
202 self.pipeo.close()
202 self.pipei.close()
203 self.pipei.close()
203 try:
204 try:
204 # read the error descriptor until EOF
205 # read the error descriptor until EOF
205 for l in self.pipee:
206 for l in self.pipee:
206 self.ui.status(_("remote: "), l)
207 self.ui.status(_("remote: "), l)
207 except (IOError, ValueError):
208 except (IOError, ValueError):
208 pass
209 pass
209 self.pipee.close()
210 self.pipee.close()
210
211
211 __del__ = cleanup
212 __del__ = cleanup
212
213
213 def _callstream(self, cmd, **args):
214 def _callstream(self, cmd, **args):
214 self.ui.debug("sending %s command\n" % cmd)
215 self.ui.debug("sending %s command\n" % cmd)
215 self.pipeo.write("%s\n" % cmd)
216 self.pipeo.write("%s\n" % cmd)
216 _func, names = wireproto.commands[cmd]
217 _func, names = wireproto.commands[cmd]
217 keys = names.split()
218 keys = names.split()
218 wireargs = {}
219 wireargs = {}
219 for k in keys:
220 for k in keys:
220 if k == '*':
221 if k == '*':
221 wireargs['*'] = args
222 wireargs['*'] = args
222 break
223 break
223 else:
224 else:
224 wireargs[k] = args[k]
225 wireargs[k] = args[k]
225 del args[k]
226 del args[k]
226 for k, v in sorted(wireargs.iteritems()):
227 for k, v in sorted(wireargs.iteritems()):
227 self.pipeo.write("%s %d\n" % (k, len(v)))
228 self.pipeo.write("%s %d\n" % (k, len(v)))
228 if isinstance(v, dict):
229 if isinstance(v, dict):
229 for dk, dv in v.iteritems():
230 for dk, dv in v.iteritems():
230 self.pipeo.write("%s %d\n" % (dk, len(dv)))
231 self.pipeo.write("%s %d\n" % (dk, len(dv)))
231 self.pipeo.write(dv)
232 self.pipeo.write(dv)
232 else:
233 else:
233 self.pipeo.write(v)
234 self.pipeo.write(v)
234 self.pipeo.flush()
235 self.pipeo.flush()
235
236
236 return self.pipei
237 return self.pipei
237
238
238 def _callcompressable(self, cmd, **args):
239 def _callcompressable(self, cmd, **args):
239 return self._callstream(cmd, **args)
240 return self._callstream(cmd, **args)
240
241
241 def _call(self, cmd, **args):
242 def _call(self, cmd, **args):
242 self._callstream(cmd, **args)
243 self._callstream(cmd, **args)
243 return self._recv()
244 return self._recv()
244
245
245 def _callpush(self, cmd, fp, **args):
246 def _callpush(self, cmd, fp, **args):
246 r = self._call(cmd, **args)
247 r = self._call(cmd, **args)
247 if r:
248 if r:
248 return '', r
249 return '', r
249 while True:
250 while True:
250 d = fp.read(4096)
251 d = fp.read(4096)
251 if not d:
252 if not d:
252 break
253 break
253 self._send(d)
254 self._send(d)
254 self._send("", flush=True)
255 self._send("", flush=True)
255 r = self._recv()
256 r = self._recv()
256 if r:
257 if r:
257 return '', r
258 return '', r
258 return self._recv(), ''
259 return self._recv(), ''
259
260
260 def _calltwowaystream(self, cmd, fp, **args):
261 def _calltwowaystream(self, cmd, fp, **args):
261 r = self._call(cmd, **args)
262 r = self._call(cmd, **args)
262 if r:
263 if r:
263 # XXX needs to be made better
264 # XXX needs to be made better
264 raise util.Abort('unexpected remote reply: %s' % r)
265 raise util.Abort('unexpected remote reply: %s' % r)
265 while True:
266 while True:
266 d = fp.read(4096)
267 d = fp.read(4096)
267 if not d:
268 if not d:
268 break
269 break
269 self._send(d)
270 self._send(d)
270 self._send("", flush=True)
271 self._send("", flush=True)
271 return self.pipei
272 return self.pipei
272
273
273 def _recv(self):
274 def _recv(self):
274 l = self.pipei.readline()
275 l = self.pipei.readline()
275 if l == '\n':
276 if l == '\n':
276 self.readerr()
277 self.readerr()
277 msg = _('check previous remote output')
278 msg = _('check previous remote output')
278 self._abort(error.OutOfBandError(hint=msg))
279 self._abort(error.OutOfBandError(hint=msg))
279 self.readerr()
280 self.readerr()
280 try:
281 try:
281 l = int(l)
282 l = int(l)
282 except ValueError:
283 except ValueError:
283 self._abort(error.ResponseError(_("unexpected response:"), l))
284 self._abort(error.ResponseError(_("unexpected response:"), l))
284 return self.pipei.read(l)
285 return self.pipei.read(l)
285
286
286 def _send(self, data, flush=False):
287 def _send(self, data, flush=False):
287 self.pipeo.write("%d\n" % len(data))
288 self.pipeo.write("%d\n" % len(data))
288 if data:
289 if data:
289 self.pipeo.write(data)
290 self.pipeo.write(data)
290 if flush:
291 if flush:
291 self.pipeo.flush()
292 self.pipeo.flush()
292 self.readerr()
293 self.readerr()
293
294
294 def lock(self):
295 def lock(self):
295 self._call("lock")
296 self._call("lock")
296 return remotelock(self)
297 return remotelock(self)
297
298
298 def unlock(self):
299 def unlock(self):
299 self._call("unlock")
300 self._call("unlock")
300
301
301 def addchangegroup(self, cg, source, url, lock=None):
302 def addchangegroup(self, cg, source, url, lock=None):
302 '''Send a changegroup to the remote server. Return an integer
303 '''Send a changegroup to the remote server. Return an integer
303 similar to unbundle(). DEPRECATED, since it requires locking the
304 similar to unbundle(). DEPRECATED, since it requires locking the
304 remote.'''
305 remote.'''
305 d = self._call("addchangegroup")
306 d = self._call("addchangegroup")
306 if d:
307 if d:
307 self._abort(error.RepoError(_("push refused: %s") % d))
308 self._abort(error.RepoError(_("push refused: %s") % d))
308 while True:
309 while True:
309 d = cg.read(4096)
310 d = cg.read(4096)
310 if not d:
311 if not d:
311 break
312 break
312 self.pipeo.write(d)
313 self.pipeo.write(d)
313 self.readerr()
314 self.readerr()
314
315
315 self.pipeo.flush()
316 self.pipeo.flush()
316
317
317 self.readerr()
318 self.readerr()
318 r = self._recv()
319 r = self._recv()
319 if not r:
320 if not r:
320 return 1
321 return 1
321 try:
322 try:
322 return int(r)
323 return int(r)
323 except ValueError:
324 except ValueError:
324 self._abort(error.ResponseError(_("unexpected response:"), r))
325 self._abort(error.ResponseError(_("unexpected response:"), r))
325
326
326 instance = sshpeer
327 instance = sshpeer
@@ -1,503 +1,503
1
1
2 This test tries to exercise the ssh functionality with a dummy script
2 This test tries to exercise the ssh functionality with a dummy script
3
3
4 creating 'remote' repo
4 creating 'remote' repo
5
5
6 $ hg init remote
6 $ hg init remote
7 $ cd remote
7 $ cd remote
8 $ echo this > foo
8 $ echo this > foo
9 $ echo this > fooO
9 $ echo this > fooO
10 $ hg ci -A -m "init" foo fooO
10 $ hg ci -A -m "init" foo fooO
11
11
12 insert a closed branch (issue4428)
12 insert a closed branch (issue4428)
13
13
14 $ hg up null
14 $ hg up null
15 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
15 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
16 $ hg branch closed
16 $ hg branch closed
17 marked working directory as branch closed
17 marked working directory as branch closed
18 (branches are permanent and global, did you want a bookmark?)
18 (branches are permanent and global, did you want a bookmark?)
19 $ hg ci -mc0
19 $ hg ci -mc0
20 $ hg ci --close-branch -mc1
20 $ hg ci --close-branch -mc1
21 $ hg up -q default
21 $ hg up -q default
22
22
23 configure for serving
23 configure for serving
24
24
25 $ cat <<EOF > .hg/hgrc
25 $ cat <<EOF > .hg/hgrc
26 > [server]
26 > [server]
27 > uncompressed = True
27 > uncompressed = True
28 >
28 >
29 > [hooks]
29 > [hooks]
30 > changegroup = python "$TESTDIR/printenv.py" changegroup-in-remote 0 ../dummylog
30 > changegroup = python "$TESTDIR/printenv.py" changegroup-in-remote 0 ../dummylog
31 > EOF
31 > EOF
32 $ cd ..
32 $ cd ..
33
33
34 repo not found error
34 repo not found error
35
35
36 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local
36 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local
37 remote: abort: there is no Mercurial repository here (.hg not found)!
37 remote: abort: there is no Mercurial repository here (.hg not found)!
38 abort: no suitable response from remote hg!
38 abort: no suitable response from remote hg!
39 [255]
39 [255]
40
40
41 non-existent absolute path
41 non-existent absolute path
42
42
43 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local
43 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local
44 remote: abort: there is no Mercurial repository here (.hg not found)!
44 remote: abort: there is no Mercurial repository here (.hg not found)!
45 abort: no suitable response from remote hg!
45 abort: no suitable response from remote hg!
46 [255]
46 [255]
47
47
48 clone remote via stream
48 clone remote via stream
49
49
50 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream
50 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream
51 streaming all changes
51 streaming all changes
52 4 files to transfer, 615 bytes of data
52 4 files to transfer, 615 bytes of data
53 transferred 615 bytes in * seconds (*) (glob)
53 transferred 615 bytes in * seconds (*) (glob)
54 searching for changes
54 searching for changes
55 no changes found
55 no changes found
56 updating to branch default
56 updating to branch default
57 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
57 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 $ cd local-stream
58 $ cd local-stream
59 $ hg verify
59 $ hg verify
60 checking changesets
60 checking changesets
61 checking manifests
61 checking manifests
62 crosschecking files in changesets and manifests
62 crosschecking files in changesets and manifests
63 checking files
63 checking files
64 2 files, 3 changesets, 2 total revisions
64 2 files, 3 changesets, 2 total revisions
65 $ hg branches
65 $ hg branches
66 default 0:1160648e36ce
66 default 0:1160648e36ce
67 $ cd ..
67 $ cd ..
68
68
69 clone bookmarks via stream
69 clone bookmarks via stream
70
70
71 $ hg -R local-stream book mybook
71 $ hg -R local-stream book mybook
72 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2
72 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2
73 streaming all changes
73 streaming all changes
74 4 files to transfer, 615 bytes of data
74 4 files to transfer, 615 bytes of data
75 transferred 615 bytes in * seconds (*) (glob)
75 transferred 615 bytes in * seconds (*) (glob)
76 searching for changes
76 searching for changes
77 no changes found
77 no changes found
78 updating to branch default
78 updating to branch default
79 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
79 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
80 $ cd stream2
80 $ cd stream2
81 $ hg book
81 $ hg book
82 mybook 0:1160648e36ce
82 mybook 0:1160648e36ce
83 $ cd ..
83 $ cd ..
84 $ rm -rf local-stream stream2
84 $ rm -rf local-stream stream2
85
85
86 clone remote via pull
86 clone remote via pull
87
87
88 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local
88 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local
89 requesting all changes
89 requesting all changes
90 adding changesets
90 adding changesets
91 adding manifests
91 adding manifests
92 adding file changes
92 adding file changes
93 added 3 changesets with 2 changes to 2 files
93 added 3 changesets with 2 changes to 2 files
94 updating to branch default
94 updating to branch default
95 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
95 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
96
96
97 verify
97 verify
98
98
99 $ cd local
99 $ cd local
100 $ hg verify
100 $ hg verify
101 checking changesets
101 checking changesets
102 checking manifests
102 checking manifests
103 crosschecking files in changesets and manifests
103 crosschecking files in changesets and manifests
104 checking files
104 checking files
105 2 files, 3 changesets, 2 total revisions
105 2 files, 3 changesets, 2 total revisions
106 $ echo '[hooks]' >> .hg/hgrc
106 $ echo '[hooks]' >> .hg/hgrc
107 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup-in-local 0 ../dummylog" >> .hg/hgrc
107 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup-in-local 0 ../dummylog" >> .hg/hgrc
108
108
109 empty default pull
109 empty default pull
110
110
111 $ hg paths
111 $ hg paths
112 default = ssh://user@dummy/remote
112 default = ssh://user@dummy/remote
113 $ hg pull -e "python \"$TESTDIR/dummyssh\""
113 $ hg pull -e "python \"$TESTDIR/dummyssh\""
114 pulling from ssh://user@dummy/remote
114 pulling from ssh://user@dummy/remote
115 searching for changes
115 searching for changes
116 no changes found
116 no changes found
117
117
118 pull from wrong ssh URL
118 pull from wrong ssh URL
119
119
120 $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist
120 $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist
121 pulling from ssh://user@dummy/doesnotexist
121 pulling from ssh://user@dummy/doesnotexist
122 remote: abort: there is no Mercurial repository here (.hg not found)!
122 remote: abort: there is no Mercurial repository here (.hg not found)!
123 abort: no suitable response from remote hg!
123 abort: no suitable response from remote hg!
124 [255]
124 [255]
125
125
126 local change
126 local change
127
127
128 $ echo bleah > foo
128 $ echo bleah > foo
129 $ hg ci -m "add"
129 $ hg ci -m "add"
130
130
131 updating rc
131 updating rc
132
132
133 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
133 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
134 $ echo "[ui]" >> .hg/hgrc
134 $ echo "[ui]" >> .hg/hgrc
135 $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc
135 $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc
136
136
137 find outgoing
137 find outgoing
138
138
139 $ hg out ssh://user@dummy/remote
139 $ hg out ssh://user@dummy/remote
140 comparing with ssh://user@dummy/remote
140 comparing with ssh://user@dummy/remote
141 searching for changes
141 searching for changes
142 changeset: 3:a28a9d1a809c
142 changeset: 3:a28a9d1a809c
143 tag: tip
143 tag: tip
144 parent: 0:1160648e36ce
144 parent: 0:1160648e36ce
145 user: test
145 user: test
146 date: Thu Jan 01 00:00:00 1970 +0000
146 date: Thu Jan 01 00:00:00 1970 +0000
147 summary: add
147 summary: add
148
148
149
149
150 find incoming on the remote side
150 find incoming on the remote side
151
151
152 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local
152 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local
153 comparing with ssh://user@dummy/local
153 comparing with ssh://user@dummy/local
154 searching for changes
154 searching for changes
155 changeset: 3:a28a9d1a809c
155 changeset: 3:a28a9d1a809c
156 tag: tip
156 tag: tip
157 parent: 0:1160648e36ce
157 parent: 0:1160648e36ce
158 user: test
158 user: test
159 date: Thu Jan 01 00:00:00 1970 +0000
159 date: Thu Jan 01 00:00:00 1970 +0000
160 summary: add
160 summary: add
161
161
162
162
163 find incoming on the remote side (using absolute path)
163 find incoming on the remote side (using absolute path)
164
164
165 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`"
165 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`"
166 comparing with ssh://user@dummy/$TESTTMP/local
166 comparing with ssh://user@dummy/$TESTTMP/local
167 searching for changes
167 searching for changes
168 changeset: 3:a28a9d1a809c
168 changeset: 3:a28a9d1a809c
169 tag: tip
169 tag: tip
170 parent: 0:1160648e36ce
170 parent: 0:1160648e36ce
171 user: test
171 user: test
172 date: Thu Jan 01 00:00:00 1970 +0000
172 date: Thu Jan 01 00:00:00 1970 +0000
173 summary: add
173 summary: add
174
174
175
175
176 push
176 push
177
177
178 $ hg push
178 $ hg push
179 pushing to ssh://user@dummy/remote
179 pushing to ssh://user@dummy/remote
180 searching for changes
180 searching for changes
181 remote: adding changesets
181 remote: adding changesets
182 remote: adding manifests
182 remote: adding manifests
183 remote: adding file changes
183 remote: adding file changes
184 remote: added 1 changesets with 1 changes to 1 files
184 remote: added 1 changesets with 1 changes to 1 files
185 $ cd ../remote
185 $ cd ../remote
186
186
187 check remote tip
187 check remote tip
188
188
189 $ hg tip
189 $ hg tip
190 changeset: 3:a28a9d1a809c
190 changeset: 3:a28a9d1a809c
191 tag: tip
191 tag: tip
192 parent: 0:1160648e36ce
192 parent: 0:1160648e36ce
193 user: test
193 user: test
194 date: Thu Jan 01 00:00:00 1970 +0000
194 date: Thu Jan 01 00:00:00 1970 +0000
195 summary: add
195 summary: add
196
196
197 $ hg verify
197 $ hg verify
198 checking changesets
198 checking changesets
199 checking manifests
199 checking manifests
200 crosschecking files in changesets and manifests
200 crosschecking files in changesets and manifests
201 checking files
201 checking files
202 2 files, 4 changesets, 3 total revisions
202 2 files, 4 changesets, 3 total revisions
203 $ hg cat -r tip foo
203 $ hg cat -r tip foo
204 bleah
204 bleah
205 $ echo z > z
205 $ echo z > z
206 $ hg ci -A -m z z
206 $ hg ci -A -m z z
207 created new head
207 created new head
208
208
209 test pushkeys and bookmarks
209 test pushkeys and bookmarks
210
210
211 $ cd ../local
211 $ cd ../local
212 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces
212 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces
213 bookmarks
213 bookmarks
214 namespaces
214 namespaces
215 phases
215 phases
216 $ hg book foo -r 0
216 $ hg book foo -r 0
217 $ hg out -B
217 $ hg out -B
218 comparing with ssh://user@dummy/remote
218 comparing with ssh://user@dummy/remote
219 searching for changed bookmarks
219 searching for changed bookmarks
220 foo 1160648e36ce
220 foo 1160648e36ce
221 $ hg push -B foo
221 $ hg push -B foo
222 pushing to ssh://user@dummy/remote
222 pushing to ssh://user@dummy/remote
223 searching for changes
223 searching for changes
224 no changes found
224 no changes found
225 exporting bookmark foo
225 exporting bookmark foo
226 [1]
226 [1]
227 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks
227 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks
228 foo 1160648e36cec0054048a7edc4110c6f84fde594
228 foo 1160648e36cec0054048a7edc4110c6f84fde594
229 $ hg book -f foo
229 $ hg book -f foo
230 $ hg push --traceback
230 $ hg push --traceback
231 pushing to ssh://user@dummy/remote
231 pushing to ssh://user@dummy/remote
232 searching for changes
232 searching for changes
233 no changes found
233 no changes found
234 updating bookmark foo
234 updating bookmark foo
235 [1]
235 [1]
236 $ hg book -d foo
236 $ hg book -d foo
237 $ hg in -B
237 $ hg in -B
238 comparing with ssh://user@dummy/remote
238 comparing with ssh://user@dummy/remote
239 searching for changed bookmarks
239 searching for changed bookmarks
240 foo a28a9d1a809c
240 foo a28a9d1a809c
241 $ hg book -f -r 0 foo
241 $ hg book -f -r 0 foo
242 $ hg pull -B foo
242 $ hg pull -B foo
243 pulling from ssh://user@dummy/remote
243 pulling from ssh://user@dummy/remote
244 no changes found
244 no changes found
245 updating bookmark foo
245 updating bookmark foo
246 $ hg book -d foo
246 $ hg book -d foo
247 $ hg push -B foo
247 $ hg push -B foo
248 pushing to ssh://user@dummy/remote
248 pushing to ssh://user@dummy/remote
249 searching for changes
249 searching for changes
250 no changes found
250 no changes found
251 deleting remote bookmark foo
251 deleting remote bookmark foo
252 [1]
252 [1]
253
253
254 a bad, evil hook that prints to stdout
254 a bad, evil hook that prints to stdout
255
255
256 $ cat <<EOF > $TESTTMP/badhook
256 $ cat <<EOF > $TESTTMP/badhook
257 > import sys
257 > import sys
258 > sys.stdout.write("KABOOM\n")
258 > sys.stdout.write("KABOOM\n")
259 > EOF
259 > EOF
260
260
261 $ echo '[hooks]' >> ../remote/.hg/hgrc
261 $ echo '[hooks]' >> ../remote/.hg/hgrc
262 $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc
262 $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc
263 $ echo r > r
263 $ echo r > r
264 $ hg ci -A -m z r
264 $ hg ci -A -m z r
265
265
266 push should succeed even though it has an unexpected response
266 push should succeed even though it has an unexpected response
267
267
268 $ hg push
268 $ hg push
269 pushing to ssh://user@dummy/remote
269 pushing to ssh://user@dummy/remote
270 searching for changes
270 searching for changes
271 remote has heads on branch 'default' that are not known locally: 6c0482d977a3
271 remote has heads on branch 'default' that are not known locally: 6c0482d977a3
272 remote: adding changesets
272 remote: adding changesets
273 remote: adding manifests
273 remote: adding manifests
274 remote: adding file changes
274 remote: adding file changes
275 remote: added 1 changesets with 1 changes to 1 files
275 remote: added 1 changesets with 1 changes to 1 files
276 remote: KABOOM
276 remote: KABOOM
277 $ hg -R ../remote heads
277 $ hg -R ../remote heads
278 changeset: 5:1383141674ec
278 changeset: 5:1383141674ec
279 tag: tip
279 tag: tip
280 parent: 3:a28a9d1a809c
280 parent: 3:a28a9d1a809c
281 user: test
281 user: test
282 date: Thu Jan 01 00:00:00 1970 +0000
282 date: Thu Jan 01 00:00:00 1970 +0000
283 summary: z
283 summary: z
284
284
285 changeset: 4:6c0482d977a3
285 changeset: 4:6c0482d977a3
286 parent: 0:1160648e36ce
286 parent: 0:1160648e36ce
287 user: test
287 user: test
288 date: Thu Jan 01 00:00:00 1970 +0000
288 date: Thu Jan 01 00:00:00 1970 +0000
289 summary: z
289 summary: z
290
290
291
291
292 clone bookmarks
292 clone bookmarks
293
293
294 $ hg -R ../remote bookmark test
294 $ hg -R ../remote bookmark test
295 $ hg -R ../remote bookmarks
295 $ hg -R ../remote bookmarks
296 * test 4:6c0482d977a3
296 * test 4:6c0482d977a3
297 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks
297 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks
298 requesting all changes
298 requesting all changes
299 adding changesets
299 adding changesets
300 adding manifests
300 adding manifests
301 adding file changes
301 adding file changes
302 added 6 changesets with 5 changes to 4 files (+1 heads)
302 added 6 changesets with 5 changes to 4 files (+1 heads)
303 updating to branch default
303 updating to branch default
304 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
304 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
305 $ hg -R local-bookmarks bookmarks
305 $ hg -R local-bookmarks bookmarks
306 test 4:6c0482d977a3
306 test 4:6c0482d977a3
307
307
308 passwords in ssh urls are not supported
308 passwords in ssh urls are not supported
309 (we use a glob here because different Python versions give different
309 (we use a glob here because different Python versions give different
310 results here)
310 results here)
311
311
312 $ hg push ssh://user:erroneouspwd@dummy/remote
312 $ hg push ssh://user:erroneouspwd@dummy/remote
313 pushing to ssh://user:*@dummy/remote (glob)
313 pushing to ssh://user:*@dummy/remote (glob)
314 abort: password in URL not supported!
314 abort: password in URL not supported!
315 [255]
315 [255]
316
316
317 $ cd ..
317 $ cd ..
318
318
319 hide outer repo
319 hide outer repo
320 $ hg init
320 $ hg init
321
321
322 Test remote paths with spaces (issue2983):
322 Test remote paths with spaces (issue2983):
323
323
324 $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
324 $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
325 $ touch "$TESTTMP/a repo/test"
325 $ touch "$TESTTMP/a repo/test"
326 $ hg -R 'a repo' commit -A -m "test"
326 $ hg -R 'a repo' commit -A -m "test"
327 adding test
327 adding test
328 $ hg -R 'a repo' tag tag
328 $ hg -R 'a repo' tag tag
329 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
329 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
330 73649e48688a
330 73649e48688a
331
331
332 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO"
332 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO"
333 abort: unknown revision 'noNoNO'!
333 abort: unknown revision 'noNoNO'!
334 [255]
334 [255]
335
335
336 Test (non-)escaping of remote paths with spaces when cloning (issue3145):
336 Test (non-)escaping of remote paths with spaces when cloning (issue3145):
337
337
338 $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
338 $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
339 destination directory: a repo
339 destination directory: a repo
340 abort: destination 'a repo' is not empty
340 abort: destination 'a repo' is not empty
341 [255]
341 [255]
342
342
343 Test hg-ssh using a helper script that will restore PYTHONPATH (which might
343 Test hg-ssh using a helper script that will restore PYTHONPATH (which might
344 have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right
344 have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right
345 parameters:
345 parameters:
346
346
347 $ cat > ssh.sh << EOF
347 $ cat > ssh.sh << EOF
348 > userhost="\$1"
348 > userhost="\$1"
349 > SSH_ORIGINAL_COMMAND="\$2"
349 > SSH_ORIGINAL_COMMAND="\$2"
350 > export SSH_ORIGINAL_COMMAND
350 > export SSH_ORIGINAL_COMMAND
351 > PYTHONPATH="$PYTHONPATH"
351 > PYTHONPATH="$PYTHONPATH"
352 > export PYTHONPATH
352 > export PYTHONPATH
353 > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo"
353 > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo"
354 > EOF
354 > EOF
355
355
356 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo"
356 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo"
357 73649e48688a
357 73649e48688a
358
358
359 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo"
359 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo"
360 remote: Illegal repository "$TESTTMP/a'repo" (glob)
360 remote: Illegal repository "$TESTTMP/a'repo" (glob)
361 abort: no suitable response from remote hg!
361 abort: no suitable response from remote hg!
362 [255]
362 [255]
363
363
364 $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
364 $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
365 remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
365 remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
366 abort: no suitable response from remote hg!
366 abort: no suitable response from remote hg!
367 [255]
367 [255]
368
368
369 $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh"
369 $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh"
370 Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
370 Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
371 [255]
371 [255]
372
372
373 Test hg-ssh in read-only mode:
373 Test hg-ssh in read-only mode:
374
374
375 $ cat > ssh.sh << EOF
375 $ cat > ssh.sh << EOF
376 > userhost="\$1"
376 > userhost="\$1"
377 > SSH_ORIGINAL_COMMAND="\$2"
377 > SSH_ORIGINAL_COMMAND="\$2"
378 > export SSH_ORIGINAL_COMMAND
378 > export SSH_ORIGINAL_COMMAND
379 > PYTHONPATH="$PYTHONPATH"
379 > PYTHONPATH="$PYTHONPATH"
380 > export PYTHONPATH
380 > export PYTHONPATH
381 > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote"
381 > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote"
382 > EOF
382 > EOF
383
383
384 $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local
384 $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local
385 requesting all changes
385 requesting all changes
386 adding changesets
386 adding changesets
387 adding manifests
387 adding manifests
388 adding file changes
388 adding file changes
389 added 6 changesets with 5 changes to 4 files (+1 heads)
389 added 6 changesets with 5 changes to 4 files (+1 heads)
390 updating to branch default
390 updating to branch default
391 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
392
392
393 $ cd read-only-local
393 $ cd read-only-local
394 $ echo "baz" > bar
394 $ echo "baz" > bar
395 $ hg ci -A -m "unpushable commit" bar
395 $ hg ci -A -m "unpushable commit" bar
396 $ hg push --ssh "sh ../ssh.sh"
396 $ hg push --ssh "sh ../ssh.sh"
397 pushing to ssh://user@dummy/*/remote (glob)
397 pushing to ssh://user@dummy/*/remote (glob)
398 searching for changes
398 searching for changes
399 remote: Permission denied
399 abort: pretxnopen.hg-ssh hook failed
400 abort: pretxnopen.hg-ssh hook failed
400 remote: Permission denied
401 [255]
401 [255]
402
402
403 $ cd ..
403 $ cd ..
404
404
405 stderr from remote commands should be printed before stdout from local code (issue4336)
405 stderr from remote commands should be printed before stdout from local code (issue4336)
406
406
407 $ hg clone remote stderr-ordering
407 $ hg clone remote stderr-ordering
408 updating to branch default
408 updating to branch default
409 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
409 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 $ cd stderr-ordering
410 $ cd stderr-ordering
411 $ cat >> localwrite.py << EOF
411 $ cat >> localwrite.py << EOF
412 > from mercurial import exchange, extensions
412 > from mercurial import exchange, extensions
413 >
413 >
414 > def wrappedpush(orig, repo, *args, **kwargs):
414 > def wrappedpush(orig, repo, *args, **kwargs):
415 > res = orig(repo, *args, **kwargs)
415 > res = orig(repo, *args, **kwargs)
416 > repo.ui.write('local stdout\n')
416 > repo.ui.write('local stdout\n')
417 > return res
417 > return res
418 >
418 >
419 > def extsetup(ui):
419 > def extsetup(ui):
420 > extensions.wrapfunction(exchange, 'push', wrappedpush)
420 > extensions.wrapfunction(exchange, 'push', wrappedpush)
421 > EOF
421 > EOF
422
422
423 $ cat >> .hg/hgrc << EOF
423 $ cat >> .hg/hgrc << EOF
424 > [paths]
424 > [paths]
425 > default-push = ssh://user@dummy/remote
425 > default-push = ssh://user@dummy/remote
426 > [ui]
426 > [ui]
427 > ssh = python "$TESTDIR/dummyssh"
427 > ssh = python "$TESTDIR/dummyssh"
428 > [extensions]
428 > [extensions]
429 > localwrite = localwrite.py
429 > localwrite = localwrite.py
430 > EOF
430 > EOF
431
431
432 $ echo localwrite > foo
432 $ echo localwrite > foo
433 $ hg commit -m 'testing localwrite'
433 $ hg commit -m 'testing localwrite'
434 $ hg push
434 $ hg push
435 pushing to ssh://user@dummy/remote
435 pushing to ssh://user@dummy/remote
436 searching for changes
436 searching for changes
437 remote: adding changesets
437 remote: adding changesets
438 remote: adding manifests
438 remote: adding manifests
439 remote: adding file changes
439 remote: adding file changes
440 remote: added 1 changesets with 1 changes to 1 files
440 remote: added 1 changesets with 1 changes to 1 files
441 remote: KABOOM
441 remote: KABOOM
442 local stdout
442 local stdout
443
443
444 debug output
444 debug output
445
445
446 $ hg pull --debug ssh://user@dummy/remote
446 $ hg pull --debug ssh://user@dummy/remote
447 pulling from ssh://user@dummy/remote
447 pulling from ssh://user@dummy/remote
448 running python "*/dummyssh" user@dummy 'hg -R remote serve --stdio' (glob)
448 running python "*/dummyssh" user@dummy 'hg -R remote serve --stdio' (glob)
449 sending hello command
449 sending hello command
450 sending between command
450 sending between command
451 remote: 286
451 remote: 286
452 remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
452 remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
453 remote: 1
453 remote: 1
454 query 1; heads
454 query 1; heads
455 sending batch command
455 sending batch command
456 searching for changes
456 searching for changes
457 all remote heads known locally
457 all remote heads known locally
458 no changes found
458 no changes found
459 sending getbundle command
459 sending getbundle command
460 bundle2-input-bundle: with-transaction
460 bundle2-input-bundle: with-transaction
461 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
461 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
462 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
462 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
463 bundle2-input-part: total payload size 45
463 bundle2-input-part: total payload size 45
464 bundle2-input-bundle: 1 parts total
464 bundle2-input-bundle: 1 parts total
465 checking for updated bookmarks
465 checking for updated bookmarks
466 preparing listkeys for "phases"
466 preparing listkeys for "phases"
467 sending listkeys command
467 sending listkeys command
468 received listkey for "phases": 15 bytes
468 received listkey for "phases": 15 bytes
469
469
470 $ cd ..
470 $ cd ..
471
471
472 $ cat dummylog
472 $ cat dummylog
473 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
473 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
474 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
474 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
475 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
475 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
476 Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio
476 Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio
477 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
477 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
478 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
478 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
479 Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio
479 Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio
480 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
480 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
481 Got arguments 1:user@dummy 2:hg -R local serve --stdio
481 Got arguments 1:user@dummy 2:hg -R local serve --stdio
482 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
482 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
483 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
483 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
484 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
484 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
485 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
485 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
486 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
486 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
487 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
487 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
488 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
488 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
489 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
489 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
490 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
490 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
491 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
491 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
492 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
492 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
493 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
493 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
494 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
494 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
495 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
495 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
496 Got arguments 1:user@dummy 2:hg init 'a repo'
496 Got arguments 1:user@dummy 2:hg init 'a repo'
497 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
497 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
498 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
498 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
499 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
499 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
500 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
500 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
501 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
501 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
502 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
502 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
503 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
503 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
General Comments 0
You need to be logged in to leave comments. Login now