[MERGE] Refactor loopback/paramiko/openssh/ssh connection opening

Andrew Bennetts andrew at canonical.com
Fri Aug 25 10:31:08 BST 2006


On Fri, Aug 25, 2006 at 03:54:39PM +1000, Martin Pool wrote:
[...]
> > +class LoopbackVendor(SSHVendor):
> > +    """SSH "vendor" that connects over a plain TCP socket, not SSH."""
> > +    
> > +    def connect_sftp(self, username, password, host, port):
> > +        sock = socket.socket()
> > +        try:
> > +            sock.connect((host, port))
> > +        except socket.error, e:
> > +            raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
> > +                                  % (host, port, e))
> > +        return SFTPClient(LoopbackSFTP(sock))
> > +
> 
> I realize this is just moved code but seeing it here made me realize -
> you probably want to try turning on TCP_NODELAY as we did in remote.py.
> It made a big difference to test suite runtime there and probably will
> here: just measure the walltime without and with.

Nearly three times slower at running tests matching '(?i)sftp', so let's not do
that here :)

> > +_ssh_vendors = {}
> > +
> > +def register_ssh_vendor(name, vendor_class):
> > +    """Register lazy-loaded SSH vendor class.""" 
> > +    _ssh_vendors[name] = vendor_class
> > +
> > +register_ssh_vendor('loopback', ssh.LoopbackVendor)
> > +register_ssh_vendor('paramiko', ssh.ParamikoVendor)
> > +register_ssh_vendor('none', ssh.ParamikoVendor)
> > +register_ssh_vendor('openssh', ssh.OpenSSHSubprocessVendor)
> > +register_ssh_vendor('ssh', ssh.SSHCorpSubprocessVendor)
> > +    
> 
> The registration and discovery of vendors should move to ssh.py too.

I was concerned about circular imports if I did that -- I guess that just means
register_ssh_vendor and _get_ssh_vendor should move to ssh.py, which actually
makes sense, so I'll do that.  Thanks.

> I wonder, would this be happier just having instances, since they're
> stateless?  Not a big deal.

Yeah, this was a bit of a coin toss for me.  I'll make them instances.

I've attached a bundle against the previous bundle.  I'll also push this up to
http://people.ubuntu.com/~andrew/bzr/sftp-refactoring

-Andrew.


-------------- next part --------------
# Bazaar revision bundle v0.8
#
# message:
#   Change register_ssh_vendor to take an instance rather than a class.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Fri 2006-08-25 19:28:52.361999989 +1000

=== modified file bzrlib/tests/test_sftp_transport.py // last-changed:andrew.be
... nnetts at canonical.com-20060825073108-ae0fcd0b05feb5eb
--- bzrlib/tests/test_sftp_transport.py
+++ bzrlib/tests/test_sftp_transport.py
@@ -297,9 +297,7 @@
         if not paramiko_loaded:
             raise TestSkipped('you must have paramiko to run this test')
         super(SSHVendorBadConnection, self).setUp()
-        import bzrlib.transport.sftp
-
-        self._transport_sftp = bzrlib.transport.sftp
+        import bzrlib.transport.ssh
 
         # open a random port, so we know nobody else is using it
         # but don't actually listen on the port.
@@ -307,14 +305,15 @@
         s.bind(('localhost', 0))
         self.bogus_url = 'sftp://%s:%s/' % s.getsockname()
 
-        orig_vendor = bzrlib.transport.sftp._ssh_vendor
+        orig_vendor = bzrlib.transport.ssh._ssh_vendor
         def reset():
-            bzrlib.transport.sftp._ssh_vendor = orig_vendor
+            bzrlib.transport.ssh._ssh_vendor = orig_vendor
             s.close()
         self.addCleanup(reset)
 
     def set_vendor(self, vendor):
-        self._transport_sftp._ssh_vendor = vendor
+        import bzrlib.transport.ssh
+        bzrlib.transport.ssh._ssh_vendor = vendor
 
     def test_bad_connection_paramiko(self):
         """Test that a real connection attempt raises the right error"""

=== modified file bzrlib/transport/sftp.py // last-changed:andrew.bennetts at cano
... nical.com-20060825073108-ae0fcd0b05feb5eb
--- bzrlib/transport/sftp.py
+++ bzrlib/transport/sftp.py
@@ -76,64 +76,6 @@
 _default_do_prefetch = (_paramiko_version >= (1, 5, 5))
 
 
-_ssh_vendors = {}
-
-def register_ssh_vendor(name, vendor_class):
-    """Register lazy-loaded SSH vendor class.""" 
-    _ssh_vendors[name] = vendor_class
-
-register_ssh_vendor('loopback', ssh.LoopbackVendor)
-register_ssh_vendor('paramiko', ssh.ParamikoVendor)
-register_ssh_vendor('none', ssh.ParamikoVendor)
-register_ssh_vendor('openssh', ssh.OpenSSHSubprocessVendor)
-register_ssh_vendor('ssh', ssh.SSHCorpSubprocessVendor)
-    
-_ssh_vendor = None
-def _get_ssh_vendor():
-    """Find out what version of SSH is on the system."""
-    global _ssh_vendor
-    if _ssh_vendor is not None:
-        return _ssh_vendor
-
-    if 'BZR_SSH' in os.environ:
-        vendor_name = os.environ['BZR_SSH']
-        try:
-            klass = _ssh_vendors[vendor_name]
-        except KeyError:
-            raise UnknownSSH(vendor_name)
-        else:
-            _ssh_vendor = klass()
-        return _ssh_vendor
-
-    try:
-        p = subprocess.Popen(['ssh', '-V'],
-                             stdin=subprocess.PIPE,
-                             stdout=subprocess.PIPE,
-                             stderr=subprocess.PIPE,
-                             **ssh.os_specific_subprocess_params())
-        returncode = p.returncode
-        stdout, stderr = p.communicate()
-    except OSError:
-        returncode = -1
-        stdout = stderr = ''
-    if 'OpenSSH' in stderr:
-        mutter('ssh implementation is OpenSSH')
-        _ssh_vendor = ssh.OpenSSHSubprocessVendor()
-    elif 'SSH Secure Shell' in stderr:
-        mutter('ssh implementation is SSH Corp.')
-        _ssh_vendor = ssh.SSHCorpSubprocessVendor()
-
-    if _ssh_vendor is not None:
-        return _ssh_vendor
-
-    # XXX: 20051123 jamesh
-    # A check for putty's plink or lsh would go here.
-
-    mutter('falling back to paramiko implementation')
-    _ssh_vendor = ssh.ParamikoVendor()
-    return _ssh_vendor
-
-
 def clear_connection_cache():
     """Remove all hosts from the SFTP connection cache.
 
@@ -906,9 +848,8 @@
         event.wait(5.0)
     
     def setUp(self):
-        global _ssh_vendor
-        self._original_vendor = _ssh_vendor
-        _ssh_vendor = self._vendor
+        self._original_vendor = ssh._ssh_vendor
+        ssh._ssh_vendor = self._vendor
         if sys.platform == 'win32':
             # Win32 needs to use the UNICODE api
             self._homedir = getcwd()
@@ -926,9 +867,8 @@
 
     def tearDown(self):
         """See bzrlib.transport.Server.tearDown."""
-        global _ssh_vendor
         self._listener.stop()
-        _ssh_vendor = self._original_vendor
+        ssh._ssh_vendor = self._original_vendor
 
     def get_bogus_url(self):
         """See bzrlib.transport.Server.get_bogus_url."""
@@ -956,6 +896,10 @@
         self._vendor = ssh.LoopbackVendor()
 
     def _run_server(self, sock):
+        # Re-import these as locals, so that they're still accessible during
+        # interpreter shutdown (when all module globals get set to None, leading
+        # to confusing errors like "'NoneType' object has no attribute 'error'".
+        import socket, errno
         class FakeChannel(object):
             def get_transport(self):
                 return self
@@ -1031,7 +975,7 @@
     return sftp
 
 def _sftp_connect_uncached(host, port, username, password):
-    vendor = _get_ssh_vendor()
+    vendor = ssh._get_ssh_vendor()
     sftp = vendor.connect_sftp(username, password, host, port)
     return sftp
 

=== modified file bzrlib/transport/ssh.py
--- bzrlib/transport/ssh.py
+++ bzrlib/transport/ssh.py
@@ -54,6 +54,57 @@
 # connect to an agent if we are on win32 and using Paramiko older than 1.6
 _use_ssh_agent = (sys.platform != 'win32' or _paramiko_version >= (1, 6, 0))
 
+_ssh_vendors = {}
+
+def register_ssh_vendor(name, vendor):
+    """Register SSH vendor."""
+    _ssh_vendors[name] = vendor
+
+    
+_ssh_vendor = None
+def _get_ssh_vendor():
+    """Find out what version of SSH is on the system."""
+    global _ssh_vendor
+    if _ssh_vendor is not None:
+        return _ssh_vendor
+
+    if 'BZR_SSH' in os.environ:
+        vendor_name = os.environ['BZR_SSH']
+        try:
+            _ssh_vendor = _ssh_vendors[vendor_name]
+        except KeyError:
+            raise UnknownSSH(vendor_name)
+        return _ssh_vendor
+
+    try:
+        p = subprocess.Popen(['ssh', '-V'],
+                             stdin=subprocess.PIPE,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE,
+                             **os_specific_subprocess_params())
+        returncode = p.returncode
+        stdout, stderr = p.communicate()
+    except OSError:
+        returncode = -1
+        stdout = stderr = ''
+    if 'OpenSSH' in stderr:
+        mutter('ssh implementation is OpenSSH')
+        _ssh_vendor = OpenSSHSubprocessVendor()
+    elif 'SSH Secure Shell' in stderr:
+        mutter('ssh implementation is SSH Corp.')
+        _ssh_vendor = SSHCorpSubprocessVendor()
+
+    if _ssh_vendor is not None:
+        return _ssh_vendor
+
+    # XXX: 20051123 jamesh
+    # A check for putty's plink or lsh would go here.
+
+    mutter('falling back to paramiko implementation')
+    _ssh_vendor = ssh.ParamikoVendor()
+    return _ssh_vendor
+
+
 
 def _ignore_sigint():
     # TODO: This should possibly ignore SIGHUP as well, but bzr currently
@@ -118,6 +169,8 @@
                                   % (host, port, e))
         return SFTPClient(LoopbackSFTP(sock))
 
+register_ssh_vendor('loopback', LoopbackVendor())
+
 
 class ParamikoVendor(SSHVendor):
     """Vendor that uses paramiko."""
@@ -168,6 +221,8 @@
                                   (host, port), e)
         return sftp
 
+register_ssh_vendor('paramiko', ParamikoVendor())
+
 
 class SubprocessVendor(SSHVendor):
     """Abstract base class for vendors that use pipes to a subprocess."""
@@ -202,6 +257,8 @@
         """
         raise NotImplementedError(self._get_vendor_specific_argv)
 
+register_ssh_vendor('none', ParamikoVendor())
+
 
 class OpenSSHSubprocessVendor(SubprocessVendor):
     """SSH vendor that uses the 'ssh' executable from OpenSSH."""
@@ -227,6 +284,8 @@
             args.extend([host] + command)
         return args
 
+register_ssh_vendor('openssh', OpenSSHSubprocessVendor())
+
 
 class SSHCorpSubprocessVendor(SubprocessVendor):
     """SSH vendor that uses the 'ssh' executable from SSH Corporation."""
@@ -249,6 +308,8 @@
             args.extend([host] + command)
         return args
     
+register_ssh_vendor('ssh', SSHCorpSubprocessVendor())
+
 
 def _paramiko_auth(username, password, host, paramiko_transport):
     # paramiko requires a username, but it might be none if nothing was supplied

# revision id: andrew.bennetts at canonical.com-20060825092852-067a5aa6991e7805
# sha1: daa3f438e7e67d5efc7ce09eacc0e0adadad3555
# inventory sha1: 47f0c6469e6c26f6f204357d2abbb9664b31ce82
# parent ids:
#   andrew.bennetts at canonical.com-20060825073108-ae0fcd0b05feb5eb
# base id: andrew.bennetts at canonical.com-20060825050539-08009a757f120d12
# properties:
#   branch-nick: sftp refactoring 2

# message:
#   Move register_ssh_vendor, _ssh_vendor and _get_ssh_vendor into ssh.py
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Fri 2006-08-25 17:31:08.887000084 +1000

=== modified file bzrlib/tests/test_sftp_transport.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3NmdHBfdHJhbnNwb3J0LnB5CisrKyBienJsaWIvdGVzdHMv
dGVzdF9zZnRwX3RyYW5zcG9ydC5weQpAQCAtMjk3LDkgKzI5Nyw3IEBACiAgICAgICAgIGlmIG5v
dCBwYXJhbWlrb19sb2FkZWQ6CiAgICAgICAgICAgICByYWlzZSBUZXN0U2tpcHBlZCgneW91IG11
c3QgaGF2ZSBwYXJhbWlrbyB0byBydW4gdGhpcyB0ZXN0JykKICAgICAgICAgc3VwZXIoU1NIVmVu
ZG9yQmFkQ29ubmVjdGlvbiwgc2VsZikuc2V0VXAoKQotICAgICAgICBpbXBvcnQgYnpybGliLnRy
YW5zcG9ydC5zZnRwCi0KLSAgICAgICAgc2VsZi5fdHJhbnNwb3J0X3NmdHAgPSBienJsaWIudHJh
bnNwb3J0LnNmdHAKKyAgICAgICAgaW1wb3J0IGJ6cmxpYi50cmFuc3BvcnQuc3NoCiAKICAgICAg
ICAgIyBvcGVuIGEgcmFuZG9tIHBvcnQsIHNvIHdlIGtub3cgbm9ib2R5IGVsc2UgaXMgdXNpbmcg
aXQKICAgICAgICAgIyBidXQgZG9uJ3QgYWN0dWFsbHkgbGlzdGVuIG9uIHRoZSBwb3J0LgpAQCAt
MzA3LDE0ICszMDUsMTUgQEAKICAgICAgICAgcy5iaW5kKCgnbG9jYWxob3N0JywgMCkpCiAgICAg
ICAgIHNlbGYuYm9ndXNfdXJsID0gJ3NmdHA6Ly8lczolcy8nICUgcy5nZXRzb2NrbmFtZSgpCiAK
LSAgICAgICAgb3JpZ192ZW5kb3IgPSBienJsaWIudHJhbnNwb3J0LnNmdHAuX3NzaF92ZW5kb3IK
KyAgICAgICAgb3JpZ192ZW5kb3IgPSBienJsaWIudHJhbnNwb3J0LnNzaC5fc3NoX3ZlbmRvcgog
ICAgICAgICBkZWYgcmVzZXQoKToKLSAgICAgICAgICAgIGJ6cmxpYi50cmFuc3BvcnQuc2Z0cC5f
c3NoX3ZlbmRvciA9IG9yaWdfdmVuZG9yCisgICAgICAgICAgICBienJsaWIudHJhbnNwb3J0LnNz
aC5fc3NoX3ZlbmRvciA9IG9yaWdfdmVuZG9yCiAgICAgICAgICAgICBzLmNsb3NlKCkKICAgICAg
ICAgc2VsZi5hZGRDbGVhbnVwKHJlc2V0KQogCiAgICAgZGVmIHNldF92ZW5kb3Ioc2VsZiwgdmVu
ZG9yKToKLSAgICAgICAgc2VsZi5fdHJhbnNwb3J0X3NmdHAuX3NzaF92ZW5kb3IgPSB2ZW5kb3IK
KyAgICAgICAgaW1wb3J0IGJ6cmxpYi50cmFuc3BvcnQuc3NoCisgICAgICAgIGJ6cmxpYi50cmFu
c3BvcnQuc3NoLl9zc2hfdmVuZG9yID0gdmVuZG9yCiAKICAgICBkZWYgdGVzdF9iYWRfY29ubmVj
dGlvbl9wYXJhbWlrbyhzZWxmKToKICAgICAgICAgIiIiVGVzdCB0aGF0IGEgcmVhbCBjb25uZWN0
aW9uIGF0dGVtcHQgcmFpc2VzIHRoZSByaWdodCBlcnJvciIiIgoK

=== modified file bzrlib/transport/sftp.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvc2Z0cC5weQorKysgYnpybGliL3RyYW5zcG9ydC9zZnRwLnB5
CkBAIC03Niw2NCArNzYsNiBAQAogX2RlZmF1bHRfZG9fcHJlZmV0Y2ggPSAoX3BhcmFtaWtvX3Zl
cnNpb24gPj0gKDEsIDUsIDUpKQogCiAKLV9zc2hfdmVuZG9ycyA9IHt9Ci0KLWRlZiByZWdpc3Rl
cl9zc2hfdmVuZG9yKG5hbWUsIHZlbmRvcl9jbGFzcyk6Ci0gICAgIiIiUmVnaXN0ZXIgbGF6eS1s
b2FkZWQgU1NIIHZlbmRvciBjbGFzcy4iIiIgCi0gICAgX3NzaF92ZW5kb3JzW25hbWVdID0gdmVu
ZG9yX2NsYXNzCi0KLXJlZ2lzdGVyX3NzaF92ZW5kb3IoJ2xvb3BiYWNrJywgc3NoLkxvb3BiYWNr
VmVuZG9yKQotcmVnaXN0ZXJfc3NoX3ZlbmRvcigncGFyYW1pa28nLCBzc2guUGFyYW1pa29WZW5k
b3IpCi1yZWdpc3Rlcl9zc2hfdmVuZG9yKCdub25lJywgc3NoLlBhcmFtaWtvVmVuZG9yKQotcmVn
aXN0ZXJfc3NoX3ZlbmRvcignb3BlbnNzaCcsIHNzaC5PcGVuU1NIU3VicHJvY2Vzc1ZlbmRvcikK
LXJlZ2lzdGVyX3NzaF92ZW5kb3IoJ3NzaCcsIHNzaC5TU0hDb3JwU3VicHJvY2Vzc1ZlbmRvcikK
LSAgICAKLV9zc2hfdmVuZG9yID0gTm9uZQotZGVmIF9nZXRfc3NoX3ZlbmRvcigpOgotICAgICIi
IkZpbmQgb3V0IHdoYXQgdmVyc2lvbiBvZiBTU0ggaXMgb24gdGhlIHN5c3RlbS4iIiIKLSAgICBn
bG9iYWwgX3NzaF92ZW5kb3IKLSAgICBpZiBfc3NoX3ZlbmRvciBpcyBub3QgTm9uZToKLSAgICAg
ICAgcmV0dXJuIF9zc2hfdmVuZG9yCi0KLSAgICBpZiAnQlpSX1NTSCcgaW4gb3MuZW52aXJvbjoK
LSAgICAgICAgdmVuZG9yX25hbWUgPSBvcy5lbnZpcm9uWydCWlJfU1NIJ10KLSAgICAgICAgdHJ5
OgotICAgICAgICAgICAga2xhc3MgPSBfc3NoX3ZlbmRvcnNbdmVuZG9yX25hbWVdCi0gICAgICAg
IGV4Y2VwdCBLZXlFcnJvcjoKLSAgICAgICAgICAgIHJhaXNlIFVua25vd25TU0godmVuZG9yX25h
bWUpCi0gICAgICAgIGVsc2U6Ci0gICAgICAgICAgICBfc3NoX3ZlbmRvciA9IGtsYXNzKCkKLSAg
ICAgICAgcmV0dXJuIF9zc2hfdmVuZG9yCi0KLSAgICB0cnk6Ci0gICAgICAgIHAgPSBzdWJwcm9j
ZXNzLlBvcGVuKFsnc3NoJywgJy1WJ10sCi0gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0
ZGluPXN1YnByb2Nlc3MuUElQRSwKLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Rkb3V0
PXN1YnByb2Nlc3MuUElQRSwKLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RkZXJyPXN1
YnByb2Nlc3MuUElQRSwKLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipzc2gub3Nfc3Bl
Y2lmaWNfc3VicHJvY2Vzc19wYXJhbXMoKSkKLSAgICAgICAgcmV0dXJuY29kZSA9IHAucmV0dXJu
Y29kZQotICAgICAgICBzdGRvdXQsIHN0ZGVyciA9IHAuY29tbXVuaWNhdGUoKQotICAgIGV4Y2Vw
dCBPU0Vycm9yOgotICAgICAgICByZXR1cm5jb2RlID0gLTEKLSAgICAgICAgc3Rkb3V0ID0gc3Rk
ZXJyID0gJycKLSAgICBpZiAnT3BlblNTSCcgaW4gc3RkZXJyOgotICAgICAgICBtdXR0ZXIoJ3Nz
aCBpbXBsZW1lbnRhdGlvbiBpcyBPcGVuU1NIJykKLSAgICAgICAgX3NzaF92ZW5kb3IgPSBzc2gu
T3BlblNTSFN1YnByb2Nlc3NWZW5kb3IoKQotICAgIGVsaWYgJ1NTSCBTZWN1cmUgU2hlbGwnIGlu
IHN0ZGVycjoKLSAgICAgICAgbXV0dGVyKCdzc2ggaW1wbGVtZW50YXRpb24gaXMgU1NIIENvcnAu
JykKLSAgICAgICAgX3NzaF92ZW5kb3IgPSBzc2guU1NIQ29ycFN1YnByb2Nlc3NWZW5kb3IoKQot
Ci0gICAgaWYgX3NzaF92ZW5kb3IgaXMgbm90IE5vbmU6Ci0gICAgICAgIHJldHVybiBfc3NoX3Zl
bmRvcgotCi0gICAgIyBYWFg6IDIwMDUxMTIzIGphbWVzaAotICAgICMgQSBjaGVjayBmb3IgcHV0
dHkncyBwbGluayBvciBsc2ggd291bGQgZ28gaGVyZS4KLQotICAgIG11dHRlcignZmFsbGluZyBi
YWNrIHRvIHBhcmFtaWtvIGltcGxlbWVudGF0aW9uJykKLSAgICBfc3NoX3ZlbmRvciA9IHNzaC5Q
YXJhbWlrb1ZlbmRvcigpCi0gICAgcmV0dXJuIF9zc2hfdmVuZG9yCi0KLQogZGVmIGNsZWFyX2Nv
bm5lY3Rpb25fY2FjaGUoKToKICAgICAiIiJSZW1vdmUgYWxsIGhvc3RzIGZyb20gdGhlIFNGVFAg
Y29ubmVjdGlvbiBjYWNoZS4KIApAQCAtOTA2LDkgKzg0OCw4IEBACiAgICAgICAgIGV2ZW50Lndh
aXQoNS4wKQogICAgIAogICAgIGRlZiBzZXRVcChzZWxmKToKLSAgICAgICAgZ2xvYmFsIF9zc2hf
dmVuZG9yCi0gICAgICAgIHNlbGYuX29yaWdpbmFsX3ZlbmRvciA9IF9zc2hfdmVuZG9yCi0gICAg
ICAgIF9zc2hfdmVuZG9yID0gc2VsZi5fdmVuZG9yCisgICAgICAgIHNlbGYuX29yaWdpbmFsX3Zl
bmRvciA9IHNzaC5fc3NoX3ZlbmRvcgorICAgICAgICBzc2guX3NzaF92ZW5kb3IgPSBzZWxmLl92
ZW5kb3IKICAgICAgICAgaWYgc3lzLnBsYXRmb3JtID09ICd3aW4zMic6CiAgICAgICAgICAgICAj
IFdpbjMyIG5lZWRzIHRvIHVzZSB0aGUgVU5JQ09ERSBhcGkKICAgICAgICAgICAgIHNlbGYuX2hv
bWVkaXIgPSBnZXRjd2QoKQpAQCAtOTI2LDkgKzg2Nyw4IEBACiAKICAgICBkZWYgdGVhckRvd24o
c2VsZik6CiAgICAgICAgICIiIlNlZSBienJsaWIudHJhbnNwb3J0LlNlcnZlci50ZWFyRG93bi4i
IiIKLSAgICAgICAgZ2xvYmFsIF9zc2hfdmVuZG9yCiAgICAgICAgIHNlbGYuX2xpc3RlbmVyLnN0
b3AoKQotICAgICAgICBfc3NoX3ZlbmRvciA9IHNlbGYuX29yaWdpbmFsX3ZlbmRvcgorICAgICAg
ICBzc2guX3NzaF92ZW5kb3IgPSBzZWxmLl9vcmlnaW5hbF92ZW5kb3IKIAogICAgIGRlZiBnZXRf
Ym9ndXNfdXJsKHNlbGYpOgogICAgICAgICAiIiJTZWUgYnpybGliLnRyYW5zcG9ydC5TZXJ2ZXIu
Z2V0X2JvZ3VzX3VybC4iIiIKQEAgLTk1Niw2ICs4OTYsMTAgQEAKICAgICAgICAgc2VsZi5fdmVu
ZG9yID0gc3NoLkxvb3BiYWNrVmVuZG9yKCkKIAogICAgIGRlZiBfcnVuX3NlcnZlcihzZWxmLCBz
b2NrKToKKyAgICAgICAgIyBSZS1pbXBvcnQgdGhlc2UgYXMgbG9jYWxzLCBzbyB0aGF0IHRoZXkn
cmUgc3RpbGwgYWNjZXNzaWJsZSBkdXJpbmcKKyAgICAgICAgIyBpbnRlcnByZXRlciBzaHV0ZG93
biAod2hlbiBhbGwgbW9kdWxlIGdsb2JhbHMgZ2V0IHNldCB0byBOb25lLCBsZWFkaW5nCisgICAg
ICAgICMgdG8gY29uZnVzaW5nIGVycm9ycyBsaWtlICInTm9uZVR5cGUnIG9iamVjdCBoYXMgbm8g
YXR0cmlidXRlICdlcnJvciciLgorICAgICAgICBpbXBvcnQgc29ja2V0LCBlcnJubwogICAgICAg
ICBjbGFzcyBGYWtlQ2hhbm5lbChvYmplY3QpOgogICAgICAgICAgICAgZGVmIGdldF90cmFuc3Bv
cnQoc2VsZik6CiAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYKQEAgLTEwMzEsNyArOTc1LDcg
QEAKICAgICByZXR1cm4gc2Z0cAogCiBkZWYgX3NmdHBfY29ubmVjdF91bmNhY2hlZChob3N0LCBw
b3J0LCB1c2VybmFtZSwgcGFzc3dvcmQpOgotICAgIHZlbmRvciA9IF9nZXRfc3NoX3ZlbmRvcigp
CisgICAgdmVuZG9yID0gc3NoLl9nZXRfc3NoX3ZlbmRvcigpCiAgICAgc2Z0cCA9IHZlbmRvci5j
b25uZWN0X3NmdHAodXNlcm5hbWUsIHBhc3N3b3JkLCBob3N0LCBwb3J0KQogICAgIHJldHVybiBz
ZnRwCiAKCg==

=== modified file bzrlib/transport/ssh.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvc3NoLnB5CisrKyBienJsaWIvdHJhbnNwb3J0L3NzaC5weQpA
QCAtNTQsNiArNTQsNTkgQEAKICMgY29ubmVjdCB0byBhbiBhZ2VudCBpZiB3ZSBhcmUgb24gd2lu
MzIgYW5kIHVzaW5nIFBhcmFtaWtvIG9sZGVyIHRoYW4gMS42CiBfdXNlX3NzaF9hZ2VudCA9IChz
eXMucGxhdGZvcm0gIT0gJ3dpbjMyJyBvciBfcGFyYW1pa29fdmVyc2lvbiA+PSAoMSwgNiwgMCkp
CiAKK19zc2hfdmVuZG9ycyA9IHt9CisKK2RlZiByZWdpc3Rlcl9zc2hfdmVuZG9yKG5hbWUsIHZl
bmRvcl9jbGFzcyk6CisgICAgIiIiUmVnaXN0ZXIgbGF6eS1sb2FkZWQgU1NIIHZlbmRvciBjbGFz
cy4iIiIgCisgICAgX3NzaF92ZW5kb3JzW25hbWVdID0gdmVuZG9yX2NsYXNzCisKKyAgICAKK19z
c2hfdmVuZG9yID0gTm9uZQorZGVmIF9nZXRfc3NoX3ZlbmRvcigpOgorICAgICIiIkZpbmQgb3V0
IHdoYXQgdmVyc2lvbiBvZiBTU0ggaXMgb24gdGhlIHN5c3RlbS4iIiIKKyAgICBnbG9iYWwgX3Nz
aF92ZW5kb3IKKyAgICBpZiBfc3NoX3ZlbmRvciBpcyBub3QgTm9uZToKKyAgICAgICAgcmV0dXJu
IF9zc2hfdmVuZG9yCisKKyAgICBpZiAnQlpSX1NTSCcgaW4gb3MuZW52aXJvbjoKKyAgICAgICAg
dmVuZG9yX25hbWUgPSBvcy5lbnZpcm9uWydCWlJfU1NIJ10KKyAgICAgICAgdHJ5OgorICAgICAg
ICAgICAga2xhc3MgPSBfc3NoX3ZlbmRvcnNbdmVuZG9yX25hbWVdCisgICAgICAgIGV4Y2VwdCBL
ZXlFcnJvcjoKKyAgICAgICAgICAgIHJhaXNlIFVua25vd25TU0godmVuZG9yX25hbWUpCisgICAg
ICAgIGVsc2U6CisgICAgICAgICAgICBfc3NoX3ZlbmRvciA9IGtsYXNzKCkKKyAgICAgICAgcmV0
dXJuIF9zc2hfdmVuZG9yCisKKyAgICB0cnk6CisgICAgICAgIHAgPSBzdWJwcm9jZXNzLlBvcGVu
KFsnc3NoJywgJy1WJ10sCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZGluPXN1YnBy
b2Nlc3MuUElQRSwKKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Rkb3V0PXN1YnByb2Nl
c3MuUElQRSwKKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RkZXJyPXN1YnByb2Nlc3Mu
UElQRSwKKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipvc19zcGVjaWZpY19zdWJwcm9j
ZXNzX3BhcmFtcygpKQorICAgICAgICByZXR1cm5jb2RlID0gcC5yZXR1cm5jb2RlCisgICAgICAg
IHN0ZG91dCwgc3RkZXJyID0gcC5jb21tdW5pY2F0ZSgpCisgICAgZXhjZXB0IE9TRXJyb3I6Cisg
ICAgICAgIHJldHVybmNvZGUgPSAtMQorICAgICAgICBzdGRvdXQgPSBzdGRlcnIgPSAnJworICAg
IGlmICdPcGVuU1NIJyBpbiBzdGRlcnI6CisgICAgICAgIG11dHRlcignc3NoIGltcGxlbWVudGF0
aW9uIGlzIE9wZW5TU0gnKQorICAgICAgICBfc3NoX3ZlbmRvciA9IE9wZW5TU0hTdWJwcm9jZXNz
VmVuZG9yKCkKKyAgICBlbGlmICdTU0ggU2VjdXJlIFNoZWxsJyBpbiBzdGRlcnI6CisgICAgICAg
IG11dHRlcignc3NoIGltcGxlbWVudGF0aW9uIGlzIFNTSCBDb3JwLicpCisgICAgICAgIF9zc2hf
dmVuZG9yID0gU1NIQ29ycFN1YnByb2Nlc3NWZW5kb3IoKQorCisgICAgaWYgX3NzaF92ZW5kb3Ig
aXMgbm90IE5vbmU6CisgICAgICAgIHJldHVybiBfc3NoX3ZlbmRvcgorCisgICAgIyBYWFg6IDIw
MDUxMTIzIGphbWVzaAorICAgICMgQSBjaGVjayBmb3IgcHV0dHkncyBwbGluayBvciBsc2ggd291
bGQgZ28gaGVyZS4KKworICAgIG11dHRlcignZmFsbGluZyBiYWNrIHRvIHBhcmFtaWtvIGltcGxl
bWVudGF0aW9uJykKKyAgICBfc3NoX3ZlbmRvciA9IHNzaC5QYXJhbWlrb1ZlbmRvcigpCisgICAg
cmV0dXJuIF9zc2hfdmVuZG9yCisKKwogCiBkZWYgX2lnbm9yZV9zaWdpbnQoKToKICAgICAjIFRP
RE86IFRoaXMgc2hvdWxkIHBvc3NpYmx5IGlnbm9yZSBTSUdIVVAgYXMgd2VsbCwgYnV0IGJ6ciBj
dXJyZW50bHkKQEAgLTExOCw2ICsxNzEsOCBAQAogICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICUgKGhvc3QsIHBvcnQsIGUpKQogICAgICAgICByZXR1cm4gU0ZUUENsaWVudChMb29w
YmFja1NGVFAoc29jaykpCiAKK3JlZ2lzdGVyX3NzaF92ZW5kb3IoJ2xvb3BiYWNrJywgTG9vcGJh
Y2tWZW5kb3IpCisKIAogY2xhc3MgUGFyYW1pa29WZW5kb3IoU1NIVmVuZG9yKToKICAgICAiIiJW
ZW5kb3IgdGhhdCB1c2VzIHBhcmFtaWtvLiIiIgpAQCAtMTY4LDYgKzIyMyw4IEBACiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgKGhvc3QsIHBvcnQpLCBlKQogICAgICAgICByZXR1
cm4gc2Z0cAogCityZWdpc3Rlcl9zc2hfdmVuZG9yKCdwYXJhbWlrbycsIFBhcmFtaWtvVmVuZG9y
KQorCiAKIGNsYXNzIFN1YnByb2Nlc3NWZW5kb3IoU1NIVmVuZG9yKToKICAgICAiIiJBYnN0cmFj
dCBiYXNlIGNsYXNzIGZvciB2ZW5kb3JzIHRoYXQgdXNlIHBpcGVzIHRvIGEgc3VicHJvY2Vzcy4i
IiIKQEAgLTIwMiw2ICsyNTksOCBAQAogICAgICAgICAiIiIKICAgICAgICAgcmFpc2UgTm90SW1w
bGVtZW50ZWRFcnJvcihzZWxmLl9nZXRfdmVuZG9yX3NwZWNpZmljX2FyZ3YpCiAKK3JlZ2lzdGVy
X3NzaF92ZW5kb3IoJ25vbmUnLCBQYXJhbWlrb1ZlbmRvcikKKwogCiBjbGFzcyBPcGVuU1NIU3Vi
cHJvY2Vzc1ZlbmRvcihTdWJwcm9jZXNzVmVuZG9yKToKICAgICAiIiJTU0ggdmVuZG9yIHRoYXQg
dXNlcyB0aGUgJ3NzaCcgZXhlY3V0YWJsZSBmcm9tIE9wZW5TU0guIiIiCkBAIC0yMjcsNiArMjg2
LDggQEAKICAgICAgICAgICAgIGFyZ3MuZXh0ZW5kKFtob3N0XSArIGNvbW1hbmQpCiAgICAgICAg
IHJldHVybiBhcmdzCiAKK3JlZ2lzdGVyX3NzaF92ZW5kb3IoJ29wZW5zc2gnLCBPcGVuU1NIU3Vi
cHJvY2Vzc1ZlbmRvcikKKwogCiBjbGFzcyBTU0hDb3JwU3VicHJvY2Vzc1ZlbmRvcihTdWJwcm9j
ZXNzVmVuZG9yKToKICAgICAiIiJTU0ggdmVuZG9yIHRoYXQgdXNlcyB0aGUgJ3NzaCcgZXhlY3V0
YWJsZSBmcm9tIFNTSCBDb3Jwb3JhdGlvbi4iIiIKQEAgLTI0OSw2ICszMTAsOCBAQAogICAgICAg
ICAgICAgYXJncy5leHRlbmQoW2hvc3RdICsgY29tbWFuZCkKICAgICAgICAgcmV0dXJuIGFyZ3MK
ICAgICAKK3JlZ2lzdGVyX3NzaF92ZW5kb3IoJ3NzaCcsIFNTSENvcnBTdWJwcm9jZXNzVmVuZG9y
KQorCiAKIGRlZiBfcGFyYW1pa29fYXV0aCh1c2VybmFtZSwgcGFzc3dvcmQsIGhvc3QsIHBhcmFt
aWtvX3RyYW5zcG9ydCk6CiAgICAgIyBwYXJhbWlrbyByZXF1aXJlcyBhIHVzZXJuYW1lLCBidXQg
aXQgbWlnaHQgYmUgbm9uZSBpZiBub3RoaW5nIHdhcyBzdXBwbGllZAoK

# revision id: andrew.bennetts at canonical.com-20060825073108-ae0fcd0b05feb5eb
# sha1: 342a3b3f5d3692f78ac6fc3b977db173be3caabe
# inventory sha1: ffe400da58eb28394129cfbfe2d47adaacefbfd9
# parent ids:
#   andrew.bennetts at canonical.com-20060825050539-08009a757f120d12
# properties:
#   branch-nick: sftp refactoring 2



More information about the bazaar mailing list