From e99448cc7bc0e47918c798314349dd2991967d1d Mon Sep 17 00:00:00 2001 From: Manuel Riel Date: Thu, 31 Jan 2019 20:54:17 +0800 Subject: [PATCH] =?UTF-8?q?Add=20--rsh=20command=20line=20option=20to=20co?= =?UTF-8?q?mplement=20BORG=5FRSH=20env=20var.=20Fixes=20#=E2=80=A6=20(#429?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add --rsh command line option to complement BORG_RSH env var. Fixes #1701 (cherry picked from commit 9ab0a095abda3890e77c0fb5babe8b8fa3eacca1) --- docs/man/borg.1 | 1 + docs/usage_general.rst.inc | 3 ++- src/borg/archiver.py | 2 ++ src/borg/remote.py | 4 +++- src/borg/testsuite/repository.py | 31 ++++++++++++++++++++----------- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/docs/man/borg.1 b/docs/man/borg.1 index 5e89a2ebd..24dae7d1e 100644 --- a/docs/man/borg.1 +++ b/docs/man/borg.1 @@ -434,6 +434,7 @@ When set, use the given filename as \fI\%INI\fP\-style logging configuration. .B BORG_RSH When set, use this command instead of \fBssh\fP\&. This can be used to specify ssh options, such as a custom identity file \fBssh \-i /path/to/private/key\fP\&. See \fBman ssh\fP for other options. +Using the \fB\-\-rsh CMD\fP commandline option overrides the environment variable. .TP .B BORG_REMOTE_PATH When set, use the given path as borg executable on the remote (defaults to "borg" if unset). diff --git a/docs/usage_general.rst.inc b/docs/usage_general.rst.inc index 9ab1f5933..d2d7d5c27 100644 --- a/docs/usage_general.rst.inc +++ b/docs/usage_general.rst.inc @@ -204,7 +204,8 @@ General: When set, use the given filename as INI_-style logging configuration. BORG_RSH When set, use this command instead of ``ssh``. This can be used to specify ssh options, such as - a custom identity file ``ssh -i /path/to/private/key``. See ``man ssh`` for other options. + a custom identity file ``ssh -i /path/to/private/key``. See ``man ssh`` for other options. Using + the ``--rsh CMD`` commandline option overrides the environment variable. BORG_REMOTE_PATH When set, use the given path as borg executable on the remote (defaults to "borg" if unset). Using ``--remote-path PATH`` commandline option overrides the environment variable. diff --git a/src/borg/archiver.py b/src/borg/archiver.py index 838d28760..58ba05691 100644 --- a/src/borg/archiver.py +++ b/src/borg/archiver.py @@ -2664,6 +2664,8 @@ class Archiver: add_common_option('--debug-profile', metavar='FILE', dest='debug_profile', default=None, help='Write execution profile in Borg format into FILE. For local use a Python-' 'compatible file can be generated by suffixing FILE with ".pyprof".') + add_common_option('--rsh', metavar='RSH', dest='rsh', + help="Use this command to connect to the 'borg serve' process (default: 'ssh')") def define_exclude_and_patterns(add_option, *, tag_files=False, strip_components=False): add_option('-e', '--exclude', metavar='PATTERN', dest='patterns', diff --git a/src/borg/remote.py b/src/borg/remote.py index 54fdf574d..83f3e03f1 100644 --- a/src/borg/remote.py +++ b/src/borg/remote.py @@ -546,6 +546,7 @@ class RemoteRepository: self.unpacker = get_limited_unpacker('client') self.server_version = parse_version('1.0.8') # fallback version if server is too old to send version information self.p = None + self._args = args testing = location.host == '__testsuite__' # when testing, we invoke and talk to a borg process directly (no ssh). # when not testing, we invoke the system-installed ssh binary to talk to a remote borg. @@ -691,7 +692,8 @@ This problem will go away as soon as the server has been upgraded to 1.0.7+. def ssh_cmd(self, location): """return a ssh command line that can be prefixed to a borg command line""" - args = shlex.split(os.environ.get('BORG_RSH', 'ssh')) + rsh = self._args.rsh or os.environ.get('BORG_RSH', 'ssh') + args = shlex.split(rsh) if location.port: args += ['-p', str(location.port)] if location.user: diff --git a/src/borg/testsuite/repository.py b/src/borg/testsuite/repository.py index 49f2e1f10..c6b53df6a 100644 --- a/src/borg/testsuite/repository.py +++ b/src/borg/testsuite/repository.py @@ -798,6 +798,19 @@ class RemoteRepositoryTestCase(RepositoryTestCase): return RemoteRepository(Location('__testsuite__:' + os.path.join(self.tmppath, 'repository')), exclusive=True, create=create) + def _get_mock_args(self): + class MockArgs: + remote_path = 'borg' + umask = 0o077 + debug_topics = [] + rsh = None + + def __contains__(self, item): + # To behave like argparse.Namespace + return hasattr(self, item) + + return MockArgs() + def test_invalid_rpc(self): self.assert_raises(InvalidRPCMethod, lambda: self.repository.call('__init__', {})) @@ -856,6 +869,8 @@ class RemoteRepositoryTestCase(RepositoryTestCase): assert len(e.exception_full) > 0 def test_ssh_cmd(self): + args = self._get_mock_args() + self.repository._args = args assert self.repository.ssh_cmd(Location('example.com:foo')) == ['ssh', 'example.com'] assert self.repository.ssh_cmd(Location('ssh://example.com/foo')) == ['ssh', 'example.com'] assert self.repository.ssh_cmd(Location('ssh://user@example.com/foo')) == ['ssh', 'user@example.com'] @@ -864,17 +879,8 @@ class RemoteRepositoryTestCase(RepositoryTestCase): assert self.repository.ssh_cmd(Location('example.com:foo')) == ['ssh', '--foo', 'example.com'] def test_borg_cmd(self): - class MockArgs: - remote_path = 'borg' - umask = 0o077 - debug_topics = [] - - def __contains__(self, item): - # To behave like argparse.Namespace - return hasattr(self, item) - assert self.repository.borg_cmd(None, testing=True) == [sys.executable, '-m', 'borg.archiver', 'serve'] - args = MockArgs() + args = self._get_mock_args() # XXX without next line we get spurious test fails when using pytest-xdist, root cause unknown: logging.getLogger().setLevel(logging.INFO) # note: test logger is on info log level, so --info gets added automagically @@ -884,12 +890,15 @@ class RemoteRepositoryTestCase(RepositoryTestCase): args.debug_topics = ['something_client_side', 'repository_compaction'] assert self.repository.borg_cmd(args, testing=False) == ['borg-0.28.2', 'serve', '--umask=077', '--info', '--debug-topic=borg.debug.repository_compaction'] - args = MockArgs() + args = self._get_mock_args() args.storage_quota = 0 assert self.repository.borg_cmd(args, testing=False) == ['borg', 'serve', '--umask=077', '--info'] args.storage_quota = 314159265 assert self.repository.borg_cmd(args, testing=False) == ['borg', 'serve', '--umask=077', '--info', '--storage-quota=314159265'] + args.rsh = 'ssh -i foo' + self.repository._args = args + assert self.repository.ssh_cmd(Location('example.com:foo')) == ['ssh', '-i', 'foo', 'example.com'] class RemoteLegacyFree(RepositoryTestCaseBase):