129 except (IOError, ValueError): |
129 except (IOError, ValueError): |
130 pass |
130 pass |
131 |
131 |
132 pipee.close() |
132 pipee.close() |
133 |
133 |
|
134 def _makeconnection(ui, sshcmd, args, remotecmd, path, sshenv=None): |
|
135 """Create an SSH connection to a server. |
|
136 |
|
137 Returns a tuple of (process, stdin, stdout, stderr) for the |
|
138 spawned process. |
|
139 """ |
|
140 cmd = '%s %s %s' % ( |
|
141 sshcmd, |
|
142 args, |
|
143 util.shellquote('%s -R %s serve --stdio' % ( |
|
144 _serverquote(remotecmd), _serverquote(path)))) |
|
145 |
|
146 ui.debug('running %s\n' % cmd) |
|
147 cmd = util.quotecommand(cmd) |
|
148 |
|
149 # no buffer allow the use of 'select' |
|
150 # feel free to remove buffering and select usage when we ultimately |
|
151 # move to threading. |
|
152 stdin, stdout, stderr, proc = util.popen4(cmd, bufsize=0, env=sshenv) |
|
153 |
|
154 stdout = doublepipe(ui, util.bufferedinputpipe(stdout), stderr) |
|
155 stdin = doublepipe(ui, stdin, stderr) |
|
156 |
|
157 return proc, stdin, stdout, stderr |
|
158 |
134 class sshpeer(wireproto.wirepeer): |
159 class sshpeer(wireproto.wirepeer): |
135 def __init__(self, ui, path, create=False, sshstate=None): |
160 def __init__(self, ui, path, create=False, sshstate=None): |
136 self._url = path |
161 self._url = path |
137 self._ui = ui |
162 self._ui = ui |
138 self._pipeo = self._pipei = self._pipee = None |
163 # self._subprocess is unused. Keeping a handle on the process |
139 |
164 # holds a reference and prevents it from being garbage collected. |
140 u = util.url(path, parsequery=False, parsefragment=False) |
165 self._subprocess, self._pipei, self._pipeo, self._pipee = sshstate |
141 self._path = u.path or '.' |
166 |
142 |
167 self._validaterepo() |
143 self._validaterepo(*sshstate) |
|
144 |
168 |
145 # Begin of _basepeer interface. |
169 # Begin of _basepeer interface. |
146 |
170 |
147 @util.propertycache |
171 @util.propertycache |
148 def ui(self): |
172 def ui(self): |
170 def capabilities(self): |
194 def capabilities(self): |
171 return self._caps |
195 return self._caps |
172 |
196 |
173 # End of _basewirecommands interface. |
197 # End of _basewirecommands interface. |
174 |
198 |
175 def _validaterepo(self, sshcmd, args, remotecmd, sshenv=None): |
199 def _validaterepo(self): |
176 assert self._pipei is None |
|
177 |
|
178 cmd = '%s %s %s' % (sshcmd, args, |
|
179 util.shellquote("%s -R %s serve --stdio" % |
|
180 (_serverquote(remotecmd), _serverquote(self._path)))) |
|
181 self.ui.debug('running %s\n' % cmd) |
|
182 cmd = util.quotecommand(cmd) |
|
183 |
|
184 # while self._subprocess isn't used, having it allows the subprocess to |
|
185 # to clean up correctly later |
|
186 # |
|
187 # no buffer allow the use of 'select' |
|
188 # feel free to remove buffering and select usage when we ultimately |
|
189 # move to threading. |
|
190 sub = util.popen4(cmd, bufsize=0, env=sshenv) |
|
191 self._pipeo, self._pipei, self._pipee, self._subprocess = sub |
|
192 |
|
193 self._pipei = util.bufferedinputpipe(self._pipei) |
|
194 self._pipei = doublepipe(self.ui, self._pipei, self._pipee) |
|
195 self._pipeo = doublepipe(self.ui, self._pipeo, self._pipee) |
|
196 |
|
197 def badresponse(): |
200 def badresponse(): |
198 msg = _("no suitable response from remote hg") |
201 msg = _("no suitable response from remote hg") |
199 hint = self.ui.config("ui", "ssherrorhint") |
202 hint = self.ui.config("ui", "ssherrorhint") |
200 self._abort(error.RepoError(msg, hint=hint)) |
203 self._abort(error.RepoError(msg, hint=hint)) |
201 |
204 |
378 ui.debug('running %s\n' % cmd) |
381 ui.debug('running %s\n' % cmd) |
379 res = ui.system(cmd, blockedtag='sshpeer', environ=sshenv) |
382 res = ui.system(cmd, blockedtag='sshpeer', environ=sshenv) |
380 if res != 0: |
383 if res != 0: |
381 raise error.RepoError(_('could not create remote repo')) |
384 raise error.RepoError(_('could not create remote repo')) |
382 |
385 |
383 sshstate = (sshcmd, args, remotecmd, sshenv) |
386 proc, stdin, stdout, stderr = _makeconnection(ui, sshcmd, args, remotecmd, |
|
387 remotepath, sshenv) |
|
388 |
|
389 sshstate = (proc, stdout, stdin, stderr) |
384 |
390 |
385 return sshpeer(ui, path, create=create, sshstate=sshstate) |
391 return sshpeer(ui, path, create=create, sshstate=sshstate) |