فهرست منبع

Revert "Remove scp syntax for locations (#6697)"

This reverts commit 1b4b84dfd8f1ec2a3aa156fb9cc2714ef6263143.
Thomas Waldmann 3 سال پیش
والد
کامیت
61299d23db

+ 4 - 4
docs/deployment/central-backup-server.rst

@@ -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
 
 ::
 

+ 1 - 1
docs/quickstart.rst

@@ -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.
 

+ 17 - 29
docs/usage/general/repository-urls.rst.inc

@@ -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).

+ 2 - 2
docs/usage/init.rst

@@ -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

+ 12 - 5
src/borg/helpers/parseformat.py

@@ -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
 

+ 1 - 1
src/borg/testsuite/archiver.py

@@ -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))

+ 37 - 0
src/borg/testsuite/helpers.py

@@ -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')) == \

+ 6 - 5
src/borg/testsuite/repository.py

@@ -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):