]> arthur.barton.de Git - bup.git/commitdiff
client: Extract 'bup server' connection code into its own module.
authorAvery Pennarun <apenwarr@gmail.com>
Sun, 21 Mar 2010 03:03:53 +0000 (23:03 -0400)
committerAvery Pennarun <apenwarr@gmail.com>
Sun, 21 Mar 2010 05:50:37 +0000 (01:50 -0400)
The screwball function we use to let us run 'bup xxx' on a remote server
after correctly setting the PATH variable is about to become useful for more
than just 'bup server'.

lib/bup/client.py
lib/bup/ssh.py [new file with mode: 0644]
t/tclient.py

index cb8e9a439d7650658bd60b83d8e450fe6c7a73a4..8a83e38e40a3fef958bbadf07f8687a7abfc4120 100644 (file)
@@ -1,7 +1,6 @@
 import re, struct, errno, select
-from bup import git
+from bup import git, ssh
 from bup.helpers import *
-from subprocess import Popen, PIPE
 
 
 class ClientError(Exception):
@@ -10,54 +9,27 @@ class ClientError(Exception):
 
 class Client:
     def __init__(self, remote, create=False):
-        self._busy = None
-        self.p = None
-        self.conn = None
+        self._busy = self.conn = self.p = None
         rs = remote.split(':', 1)
-        main_exe = os.environ.get('BUP_MAIN_EXE') or sys.argv[0]
-        nicedir = os.path.split(os.path.abspath(main_exe))[0]
-        nicedir = re.sub(r':', "_", nicedir)
         if len(rs) == 1:
-            (host, dir) = ('NONE', remote)
-            def fixenv():
-                os.environ['PATH'] = ':'.join([nicedir,
-                                               os.environ.get('PATH', '')])
-            argv = ['bup', 'server']
+            (host, dir) = (None, remote)
         else:
             (host, dir) = rs
-            fixenv = None
-            # WARNING: shell quoting security holes are possible here, so we
-            # have to be super careful.  We have to use 'sh -c' because
-            # csh-derived shells can't handle PATH= notation.  We can't
-            # set PATH in advance, because ssh probably replaces it.  We
-            # can't exec *safely* using argv, because *both* ssh and 'sh -c'
-            # allow shellquoting.  So we end up having to double-shellquote
-            # stuff here.
-            escapedir = re.sub(r'([^\w/])', r'\\\\\\\1', nicedir)
-            cmd = r"""
-                       sh -c PATH=%s:'$PATH bup server'
-                   """ % escapedir
-            argv = ['ssh', host, '--', cmd.strip()]
-            #log('argv is: %r\n' % argv)
-        def setup():
-            if fixenv:
-                fixenv()
-            os.setsid()
         (self.host, self.dir) = (host, dir)
         self.cachedir = git.repo('index-cache/%s'
                                  % re.sub(r'[^@\w]', '_', 
                                           "%s:%s" % (host, dir)))
         try:
-            self.p = p = Popen(argv, stdin=PIPE, stdout=PIPE, preexec_fn=setup)
+            self.p = ssh.connect(host, 'server')
         except OSError, e:
             raise ClientError, 'exec %r: %s' % (argv[0], e), sys.exc_info()[2]
-        self.conn = conn = Conn(p.stdout, p.stdin)
+        self.conn = Conn(self.p.stdout, self.p.stdin)
         if dir:
             dir = re.sub(r'[\r\n]', ' ', dir)
             if create:
-                conn.write('init-dir %s\n' % dir)
+                self.conn.write('init-dir %s\n' % dir)
             else:
-                conn.write('set-dir %s\n' % dir)
+                self.conn.write('set-dir %s\n' % dir)
             self.check_ok()
         self.sync_indexes_del()
 
diff --git a/lib/bup/ssh.py b/lib/bup/ssh.py
new file mode 100644 (file)
index 0000000..cefa543
--- /dev/null
@@ -0,0 +1,35 @@
+import os, re, subprocess
+from bup import helpers
+
+def connect(rhost, subcmd):
+    assert(not re.search(r'[^\w-]', subcmd))
+    main_exe = os.environ.get('BUP_MAIN_EXE') or sys.argv[0]
+    nicedir = os.path.split(os.path.abspath(main_exe))[0]
+    nicedir = re.sub(r':', "_", nicedir)
+    if rhost == '-':
+        rhost = None
+    if not rhost:
+        argv = ['bup', subcmd]
+    else:
+        # WARNING: shell quoting security holes are possible here, so we
+        # have to be super careful.  We have to use 'sh -c' because
+        # csh-derived shells can't handle PATH= notation.  We can't
+        # set PATH in advance, because ssh probably replaces it.  We
+        # can't exec *safely* using argv, because *both* ssh and 'sh -c'
+        # allow shellquoting.  So we end up having to double-shellquote
+        # stuff here.
+        escapedir = re.sub(r'([^\w/])', r'\\\\\\\1', nicedir)
+        force_tty = helpers.atoi(os.environ.get('BUP_FORCE_TTY'))
+        cmd = r"""
+                   sh -c PATH=%s:'$PATH BUP_FORCE_TTY=%s bup %s'
+               """ % (escapedir, force_tty, subcmd)
+        argv = ['ssh', rhost, '--', cmd.strip()]
+        #helpers.log('argv is: %r\n' % argv)
+    def setup():
+        # runs in the child process
+        if not rhost:
+            os.environ['PATH'] = ':'.join([nicedir,
+                                           os.environ.get('PATH', '')])
+        os.setsid()
+    return subprocess.Popen(argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                            preexec_fn=setup)
index 9a6a8885dab893c7f6f3515444051b1954a54ec9..895e05241d3e9f35d891bad104802caf0de45f83 100644 (file)
@@ -15,6 +15,7 @@ s2 = randbytes(10000)
 def test_server_split_with_indexes():
     os.environ['BUP_MAIN_EXE'] = './bup'
     os.environ['BUP_DIR'] = bupdir = 'buptest_tclient.tmp'
+    subprocess.call(['rm', '-rf', bupdir])
     git.init_repo(bupdir)
     lw = git.PackWriter()
     c = client.Client(bupdir, create=True)