[PATCH] sshrepo: add support for paramiko transport engine
Steve Borho
steve at borho.org
Thu Apr 1 00:47:11 CDT 2010
# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1270100782 18000
# Node ID 692bd14317b35db4e856d222269d3c23320fced6
# Parent fa7a14277cefdfda5b331fa9f9cddbfab8dd8eca
sshrepo: add support for paramiko transport engine
This is incomplete, looking for comment and/or aid. It could at least use some
cleanup and improved error handling. I'm not at all sure readerr() won't get
stuck if there's actual stderr output. But this at least passes simple sniff
tests.
To use, install paramiko and pycrypto Python modules, then set ui.ssh to
paramiko.
diff -r fa7a14277cef -r 692bd14317b3 mercurial/sshrepo.py
--- a/mercurial/sshrepo.py Thu Apr 01 00:15:29 2010 +0200
+++ b/mercurial/sshrepo.py Thu Apr 01 00:46:22 2010 -0500
@@ -22,6 +22,7 @@
class sshrepository(repo.repository):
def __init__(self, ui, path, create=0):
+ self._pclient = None
self._url = path
self.ui = ui
@@ -40,16 +41,42 @@
args = util.sshargs(sshcmd, self.host, self.user, self.port)
if create:
- cmd = '%s %s "%s init %s"'
- cmd = cmd % (sshcmd, args, remotecmd, self.path)
-
- ui.note(_('running %s\n') % cmd)
- res = util.system(cmd)
+ if sshcmd == 'paramiko':
+ cmd = '%s init %s'
+ cmd = cmd % (remotecmd, self.path)
+ ui.note(_('running %s\n') % cmd)
+ client = self.pconnect()
+ client.exec_command(cmd)
+ client.close()
+ res = 0
+ else:
+ cmd = '%s %s "%s init %s"'
+ cmd = cmd % (sshcmd, args, remotecmd, self.path)
+ ui.note(_('running %s\n') % cmd)
+ res = util.system(cmd)
if res != 0:
self.abort(error.RepoError(_("could not create remote repo")))
self.validate_repo(ui, sshcmd, args, remotecmd)
+ def pconnect(self):
+ import demandimport
+ demandimport.disable()
+ try:
+ # http://www.lag.net/paramiko/docs/
+ from paramiko import SSHClient, AutoAddPolicy
+ except ImportError:
+ self.abort(error.Abort(_("paramiko not found")))
+ demandimport.enable()
+ client = SSHClient()
+ client.load_system_host_keys()
+ client.connect(self.host, int(self.port or '22'), self.user)
+ client.get_transport().use_compression(True)
+ # client.get_transport().set_keepalive(True)
+ # client.set_missing_host_key_policy(AutoAddPolicy())
+ # client.SecurityOptions.*
+ return client
+
def url(self):
return self._url
@@ -57,12 +84,18 @@
# cleanup up previous run
self.cleanup()
- cmd = '%s %s "%s -R %s serve --stdio"'
- cmd = cmd % (sshcmd, args, remotecmd, self.path)
-
- cmd = util.quotecommand(cmd)
- ui.note(_('running %s\n') % cmd)
- self.pipeo, self.pipei, self.pipee = util.popen3(cmd)
+ if sshcmd == 'paramiko':
+ cmd = '%s -R %s serve --stdio'
+ cmd = cmd % (remotecmd, self.path)
+ client = self.pconnect()
+ self.pipeo, self.pipei, self.pipee = client.exec_command(cmd)
+ self._pclient = client
+ else:
+ cmd = '%s %s "%s -R %s serve --stdio"'
+ cmd = cmd % (sshcmd, args, remotecmd, self.path)
+ cmd = util.quotecommand(cmd)
+ ui.note(_('running %s\n') % cmd)
+ self.pipeo, self.pipei, self.pipee = util.popen3(cmd)
# skip any noise generated by remote shell
self.do_cmd("hello")
@@ -89,9 +122,13 @@
def readerr(self):
while 1:
- size = util.fstat(self.pipee).st_size
- if size == 0:
- break
+ if self._pclient:
+ if not self.pipee.channel.recv_stderr_ready():
+ break
+ else:
+ size = util.fstat(self.pipee).st_size
+ if size == 0:
+ break
l = self.pipee.readline()
if not l:
break
@@ -103,6 +140,8 @@
def cleanup(self):
try:
+ if self._pclient:
+ self._pclient.close()
self.pipeo.close()
self.pipei.close()
# read the error descriptor until EOF
More information about the Mercurial-devel
mailing list