mirror of https://github.com/borgbackup/borg.git
Merge pull request #6706 from ThomasWaldmann/revert-no-scp-in-master
Revert "Remove scp syntax for locations (#6697)"
This commit is contained in:
commit
b10d661185
|
@ -81,7 +81,7 @@ The options which are added to the key will perform the following:
|
|||
Due to the ``cd`` command we use, the server automatically changes the current
|
||||
working directory. Then client doesn't need to have knowledge of the absolute
|
||||
or relative remote repository path and can directly access the repositories at
|
||||
``ssh://<user>@<host>/./<repo>``.
|
||||
``<user>@<host>:<repo>``.
|
||||
|
||||
.. note:: The setup above ignores all client given commandline parameters
|
||||
which are normally appended to the `borg serve` command.
|
||||
|
@ -93,21 +93,21 @@ The client needs to initialize the `pictures` repository like this:
|
|||
|
||||
::
|
||||
|
||||
borg init ssh://backup@backup01.srv.local/./pictures
|
||||
borg init backup@backup01.srv.local:pictures
|
||||
|
||||
Or with the full path (should actually never be used, as only for demonstrational purposes).
|
||||
The server should automatically change the current working directory to the `<client fqdn>` folder.
|
||||
|
||||
::
|
||||
|
||||
borg init ssh://backup@backup01.srv.local/home/backup/repos/johndoe.clnt.local/pictures
|
||||
borg init backup@backup01.srv.local:/home/backup/repos/johndoe.clnt.local/pictures
|
||||
|
||||
When `johndoe.clnt.local` tries to access a not restricted path the following error is raised.
|
||||
John Doe tries to backup into the Web 01 path:
|
||||
|
||||
::
|
||||
|
||||
borg init ssh://backup@backup01.srv.local/home/backup/repos/web01.srv.local/pictures
|
||||
borg init backup@backup01.srv.local:/home/backup/repos/web01.srv.local/pictures
|
||||
|
||||
::
|
||||
|
||||
|
|
|
@ -405,7 +405,7 @@ Borg can initialize and access repositories on remote hosts if the
|
|||
host is accessible using SSH. This is fastest and easiest when Borg
|
||||
is installed on the remote host, in which case the following syntax is used::
|
||||
|
||||
$ borg init ssh://user@hostname/path/to/repo
|
||||
$ borg init user@hostname:/path/to/repo
|
||||
|
||||
Note: please see the usage chapter for a full documentation of repo URLs.
|
||||
|
||||
|
|
|
@ -14,16 +14,32 @@ Note: you may also prepend a ``file://`` to a filesystem path to get URL style.
|
|||
|
||||
**Remote repositories** accessed via ssh user@host:
|
||||
|
||||
``ssh://user@host:port/path/to/repo`` - remote repo, absolute path
|
||||
``user@host:/path/to/repo`` - remote repo, absolute path
|
||||
|
||||
``ssh://user@host:port/path/to/repo`` - same, alternative syntax, port can be given
|
||||
|
||||
|
||||
**Remote repositories with relative paths** can be given using this syntax:
|
||||
|
||||
``user@host:path/to/repo`` - path relative to current directory
|
||||
|
||||
``user@host:~/path/to/repo`` - path relative to user's home directory
|
||||
|
||||
``user@host:~other/path/to/repo`` - path relative to other's home directory
|
||||
|
||||
Note: giving ``user@host:/./path/to/repo`` or ``user@host:/~/path/to/repo`` or
|
||||
``user@host:/~other/path/to/repo`` is also supported, but not required here.
|
||||
|
||||
|
||||
**Remote repositories with relative paths, alternative syntax with port**:
|
||||
|
||||
``ssh://user@host:port/./path/to/repo`` - path relative to current directory
|
||||
|
||||
``ssh://user@host:port/~/path/to/repo`` - path relative to user's home directory
|
||||
|
||||
``ssh://user@host:port/~other/path/to/repo`` - path relative to other's home directory
|
||||
|
||||
|
||||
If you frequently need the same repo URL, it is a good idea to set the
|
||||
``BORG_REPO`` environment variable to set a default for the repo URL:
|
||||
|
||||
|
@ -36,31 +52,3 @@ to use the default - it will be read from BORG_REPO then.
|
|||
|
||||
Use ``::`` syntax to give the repo URL when syntax requires giving a positional
|
||||
argument for the repo (e.g. ``borg mount :: /mnt``).
|
||||
|
||||
Converting from scp-style repo URLs
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Borg does not support scp-style repo URLs any more.
|
||||
|
||||
Here is how you can convert to URL style:
|
||||
|
||||
::
|
||||
|
||||
user@host:path/to/repo # relative to cwd
|
||||
-->
|
||||
ssh://user@host:22/./path/to/repo # relative to cwd
|
||||
or (usually the cwd is the home dir after ssh login)
|
||||
ssh://user@host:22/~/path/to/repo # relative to home dir
|
||||
|
||||
user@host:/path/to/repo # absolute repo path
|
||||
-->
|
||||
ssh://user@host:22/path/to/repo # absolute repo path
|
||||
|
||||
Notes:
|
||||
|
||||
Port 22 is the default, so you can omit the ``:22`` if you like.
|
||||
|
||||
If you used some hack to use a non-standard port (which was not directly
|
||||
supported by the scp-style repo specification), you can now do it that way
|
||||
with the ``ssh:`` URL and remove the hack (usually in ssh configuration or
|
||||
given via ``--rsh`` borg option).
|
||||
|
|
|
@ -15,8 +15,8 @@ Examples
|
|||
|
||||
# Remote repository (accesses a remote borg via ssh)
|
||||
# repokey: stores the (encrypted) key into <REPO_DIR>/config
|
||||
$ borg init --encryption=repokey-aes-ocb ssh://user@hostname/./backup
|
||||
$ borg init --encryption=repokey-aes-ocb user@hostname:backup
|
||||
|
||||
# Remote repository (accesses a remote borg via ssh)
|
||||
# keyfile: stores the (encrypted) key into ~/.config/borg/keys/
|
||||
$ borg init --encryption=keyfile-aes-ocb ssh://user@hostname/./backup
|
||||
$ borg init --encryption=keyfile-aes-ocb user@hostname:backup
|
||||
|
|
|
@ -315,7 +315,7 @@ class Location:
|
|||
|
||||
# path must not contain :: (it ends at :: or string end), but may contain single colons.
|
||||
# to avoid ambiguities with other regexes, it must also not start with ":" nor with "//" nor with "ssh://".
|
||||
local_path_re = r"""
|
||||
scp_path_re = r"""
|
||||
(?!(:|//|ssh://)) # not starting with ":" or // or ssh://
|
||||
(?P<path>([^:]|(:(?!:)))+) # any chars, but no "::"
|
||||
"""
|
||||
|
@ -361,8 +361,13 @@ class Location:
|
|||
(?P<proto>file):// # file://
|
||||
""" + file_path_re + optional_archive_re, re.VERBOSE) # servername/path, path or path::archive
|
||||
|
||||
local_re = re.compile(
|
||||
local_path_re + optional_archive_re, re.VERBOSE) # local path with optional archive
|
||||
# note: scp_re is also used for local paths
|
||||
scp_re = re.compile(r"""
|
||||
(
|
||||
""" + optional_user_re + host_re + r""" # user@ (optional), host name or address
|
||||
: # : (required!)
|
||||
)? # user@host: part is optional
|
||||
""" + scp_path_re + optional_archive_re, re.VERBOSE) # path with optional archive
|
||||
|
||||
# get the repo from BORG_REPO env and the optional archive from param.
|
||||
# if the syntax requires giving REPOSITORY (see "borg mount"),
|
||||
|
@ -438,11 +443,13 @@ class Location:
|
|||
self.path = normpath_special(m.group('path'))
|
||||
self.archive = m.group('archive')
|
||||
return True
|
||||
m = self.local_re.match(text)
|
||||
m = self.scp_re.match(text)
|
||||
if m:
|
||||
self.user = m.group('user')
|
||||
self._host = m.group('host')
|
||||
self.path = normpath_special(m.group('path'))
|
||||
self.archive = m.group('archive')
|
||||
self.proto = 'file'
|
||||
self.proto = self._host and 'ssh' or 'file'
|
||||
return True
|
||||
return False
|
||||
|
||||
|
|
|
@ -4014,7 +4014,7 @@ class ManifestAuthenticationTest(ArchiverTestCaseBase):
|
|||
|
||||
|
||||
class RemoteArchiverTestCase(ArchiverTestCase):
|
||||
prefix = 'ssh://__testsuite__'
|
||||
prefix = '__testsuite__:'
|
||||
|
||||
def open_repository(self):
|
||||
return RemoteRepository(Location(self.repository_location))
|
||||
|
|
|
@ -113,6 +113,32 @@ class TestLocationWithoutEnv:
|
|||
"Location(proto='file', user=None, host=None, port=None, path='/some/path', archive=None)"
|
||||
assert Location('file:///some/path').to_key_filename() == keys_dir + 'some_path'
|
||||
|
||||
def test_scp(self, monkeypatch, keys_dir):
|
||||
monkeypatch.delenv('BORG_REPO', raising=False)
|
||||
assert repr(Location('user@host:/some/path::archive')) == \
|
||||
"Location(proto='ssh', user='user', host='host', port=None, path='/some/path', archive='archive')"
|
||||
assert repr(Location('user@host:/some/path')) == \
|
||||
"Location(proto='ssh', user='user', host='host', port=None, path='/some/path', archive=None)"
|
||||
assert repr(Location('user@[::]:/some/path::archive')) == \
|
||||
"Location(proto='ssh', user='user', host='::', port=None, path='/some/path', archive='archive')"
|
||||
assert repr(Location('user@[::]:/some/path')) == \
|
||||
"Location(proto='ssh', user='user', host='::', port=None, path='/some/path', archive=None)"
|
||||
assert repr(Location('user@[2001:db8::]:/some/path::archive')) == \
|
||||
"Location(proto='ssh', user='user', host='2001:db8::', port=None, path='/some/path', archive='archive')"
|
||||
assert repr(Location('user@[2001:db8::]:/some/path')) == \
|
||||
"Location(proto='ssh', user='user', host='2001:db8::', port=None, path='/some/path', archive=None)"
|
||||
assert repr(Location('user@[2001:db8::c0:ffee]:/some/path::archive')) == \
|
||||
"Location(proto='ssh', user='user', host='2001:db8::c0:ffee', port=None, path='/some/path', archive='archive')"
|
||||
assert repr(Location('user@[2001:db8::c0:ffee]:/some/path')) == \
|
||||
"Location(proto='ssh', user='user', host='2001:db8::c0:ffee', port=None, path='/some/path', archive=None)"
|
||||
assert repr(Location('user@[2001:db8::192.0.2.1]:/some/path::archive')) == \
|
||||
"Location(proto='ssh', user='user', host='2001:db8::192.0.2.1', port=None, path='/some/path', archive='archive')"
|
||||
assert repr(Location('user@[2001:db8::192.0.2.1]:/some/path')) == \
|
||||
"Location(proto='ssh', user='user', host='2001:db8::192.0.2.1', port=None, path='/some/path', archive=None)"
|
||||
assert Location('user@[2001:db8::192.0.2.1]:/some/path').to_key_filename() == keys_dir + '2001_db8__192_0_2_1__some_path'
|
||||
assert repr(Location('user@[2a02:0001:0002:0003:0004:0005:0006:0007]:/some/path')) == \
|
||||
"Location(proto='ssh', user='user', host='2a02:0001:0002:0003:0004:0005:0006:0007', port=None, path='/some/path', archive=None)"
|
||||
|
||||
def test_smb(self, monkeypatch, keys_dir):
|
||||
monkeypatch.delenv('BORG_REPO', raising=False)
|
||||
assert repr(Location('file:////server/share/path::archive')) == \
|
||||
|
@ -171,6 +197,8 @@ class TestLocationWithoutEnv:
|
|||
|
||||
def test_user_parsing(self):
|
||||
# see issue #1930
|
||||
assert repr(Location('host:path::2016-12-31@23:59:59')) == \
|
||||
"Location(proto='ssh', user=None, host='host', port=None, path='path', archive='2016-12-31@23:59:59')"
|
||||
assert repr(Location('ssh://host/path::2016-12-31@23:59:59')) == \
|
||||
"Location(proto='ssh', user=None, host='host', port=None, path='/path', archive='2016-12-31@23:59:59')"
|
||||
|
||||
|
@ -254,6 +282,15 @@ class TestLocationWithEnv:
|
|||
assert repr(Location()) == \
|
||||
"Location(proto='file', user=None, host=None, port=None, path='/some/path', archive=None)"
|
||||
|
||||
def test_scp(self, monkeypatch):
|
||||
monkeypatch.setenv('BORG_REPO', 'user@host:/some/path')
|
||||
assert repr(Location('::archive')) == \
|
||||
"Location(proto='ssh', user='user', host='host', port=None, path='/some/path', archive='archive')"
|
||||
assert repr(Location('::')) == \
|
||||
"Location(proto='ssh', user='user', host='host', port=None, path='/some/path', archive=None)"
|
||||
assert repr(Location()) == \
|
||||
"Location(proto='ssh', user='user', host='host', port=None, path='/some/path', archive=None)"
|
||||
|
||||
def test_folder(self, monkeypatch):
|
||||
monkeypatch.setenv('BORG_REPO', 'path')
|
||||
assert repr(Location('::archive')) == \
|
||||
|
|
|
@ -861,7 +861,7 @@ class RemoteRepositoryTestCase(RepositoryTestCase):
|
|||
repository = None # type: RemoteRepository
|
||||
|
||||
def open(self, create=False):
|
||||
return RemoteRepository(Location('ssh://__testsuite__' + os.path.join(self.tmppath, 'repository')),
|
||||
return RemoteRepository(Location('__testsuite__:' + os.path.join(self.tmppath, 'repository')),
|
||||
exclusive=True, create=create)
|
||||
|
||||
def _get_mock_args(self):
|
||||
|
@ -937,11 +937,12 @@ class RemoteRepositoryTestCase(RepositoryTestCase):
|
|||
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']
|
||||
assert self.repository.ssh_cmd(Location('ssh://user@example.com:1234/foo')) == ['ssh', '-p', '1234', 'user@example.com']
|
||||
os.environ['BORG_RSH'] = 'ssh --foo'
|
||||
assert self.repository.ssh_cmd(Location('ssh://example.com/foo')) == ['ssh', '--foo', 'example.com']
|
||||
assert self.repository.ssh_cmd(Location('example.com:foo')) == ['ssh', '--foo', 'example.com']
|
||||
|
||||
def test_borg_cmd(self):
|
||||
assert self.repository.borg_cmd(None, testing=True) == [sys.executable, '-m', 'borg.archiver', 'serve']
|
||||
|
@ -963,7 +964,7 @@ class RemoteRepositoryTestCase(RepositoryTestCase):
|
|||
'--storage-quota=314159265']
|
||||
args.rsh = 'ssh -i foo'
|
||||
self.repository._args = args
|
||||
assert self.repository.ssh_cmd(Location('ssh://example.com/foo')) == ['ssh', '-i', 'foo', 'example.com']
|
||||
assert self.repository.ssh_cmd(Location('example.com:foo')) == ['ssh', '-i', 'foo', 'example.com']
|
||||
|
||||
|
||||
class RemoteLegacyFree(RepositoryTestCaseBase):
|
||||
|
@ -971,7 +972,7 @@ class RemoteLegacyFree(RepositoryTestCaseBase):
|
|||
|
||||
def open(self, create=False):
|
||||
with patch.object(RemoteRepository, 'dictFormat', True):
|
||||
return RemoteRepository(Location('ssh://__testsuite__' + os.path.join(self.tmppath, 'repository')),
|
||||
return RemoteRepository(Location('__testsuite__:' + os.path.join(self.tmppath, 'repository')),
|
||||
exclusive=True, create=create)
|
||||
|
||||
def test_legacy_free(self):
|
||||
|
@ -994,7 +995,7 @@ class RemoteLegacyFree(RepositoryTestCaseBase):
|
|||
class RemoteRepositoryCheckTestCase(RepositoryCheckTestCase):
|
||||
|
||||
def open(self, create=False):
|
||||
return RemoteRepository(Location('ssh://__testsuite__' + os.path.join(self.tmppath, 'repository')),
|
||||
return RemoteRepository(Location('__testsuite__:' + os.path.join(self.tmppath, 'repository')),
|
||||
exclusive=True, create=create)
|
||||
|
||||
def test_crash_before_compact(self):
|
||||
|
|
Loading…
Reference in New Issue