浏览代码

Support file:// paths for repositories (#576).

Merge pull request #54 from diivi/feat/file-urls-support
Dan Helfman 2 年之前
父节点
当前提交
c83fae5e5b

+ 1 - 5
borgmatic/borg/export_tar.py

@@ -46,11 +46,7 @@ def export_tar_archive(
         + (('--dry-run',) if dry_run else ())
         + (('--tar-filter', tar_filter) if tar_filter else ())
         + (('--strip-components', str(strip_components)) if strip_components else ())
-        + flags.make_repository_archive_flags(
-            repository if ':' in repository else os.path.abspath(repository),
-            archive,
-            local_borg_version,
-        )
+        + flags.make_repository_archive_flags(repository, archive, local_borg_version,)
         + (destination_path,)
         + (tuple(paths) if paths else ())
     )

+ 1 - 5
borgmatic/borg/extract.py

@@ -106,11 +106,7 @@ def extract_archive(
         + (('--strip-components', str(strip_components)) if strip_components else ())
         + (('--progress',) if progress else ())
         + (('--stdout',) if extract_to_stdout else ())
-        + flags.make_repository_archive_flags(
-            repository if ':' in repository else os.path.abspath(repository),
-            archive,
-            local_borg_version,
-        )
+        + flags.make_repository_archive_flags(repository, archive, local_borg_version,)
         + (tuple(paths) if paths else ())
     )
 

+ 18 - 12
borgmatic/config/normalize.py

@@ -1,4 +1,5 @@
 import logging
+import os
 
 
 def normalize(config_filename, config):
@@ -68,20 +69,25 @@ def normalize(config_filename, config):
                         )
                     )
                 )
-            if ':' in repository and not repository.startswith('ssh://'):
-                rewritten_repository = (
-                    f"ssh://{repository.replace(':~', '/~').replace(':/', '/').replace(':', '/./')}"
-                )
-                logs.append(
-                    logging.makeLogRecord(
-                        dict(
-                            levelno=logging.WARNING,
-                            levelname='WARNING',
-                            msg=f'{config_filename}: Remote repository paths without ssh:// syntax are deprecated. Interpreting "{repository}" as "{rewritten_repository}"',
+            if ':' in repository:
+                if repository.startswith('file://'):
+                    config['location']['repositories'].append(
+                        os.path.abspath(repository.partition('file://')[-1])
+                    )
+                elif repository.startswith('ssh://'):
+                    config['location']['repositories'].append(repository)
+                else:
+                    rewritten_repository = f"ssh://{repository.replace(':~', '/~').replace(':/', '/').replace(':', '/./')}"
+                    logs.append(
+                        logging.makeLogRecord(
+                            dict(
+                                levelno=logging.WARNING,
+                                levelname='WARNING',
+                                msg=f'{config_filename}: Remote repository paths without ssh:// syntax are deprecated. Interpreting "{repository}" as "{rewritten_repository}"',
+                            )
                         )
                     )
-                )
-                config['location']['repositories'].append(rewritten_repository)
+                    config['location']['repositories'].append(rewritten_repository)
             else:
                 config['location']['repositories'].append(repository)
 

+ 7 - 4
borgmatic/config/validate.py

@@ -126,12 +126,15 @@ def normalize_repository_path(repository):
     '''
     Given a repository path, return the absolute path of it (for local repositories).
     '''
-    # A colon in the repository indicates it's a remote repository. Bail.
-    if ':' in repository:
+    # A colon in the repository could mean that it's either a file:// URL or a remote repository.
+    # If it's a remote repository, we don't want to normalize it. If it's a file:// URL, we do.
+    if ':' not in repository:
+        return os.path.abspath(repository)
+    elif repository.startswith('file://'):
+        return os.path.abspath(repository.partition('file://')[-1])
+    else:
         return repository
 
-    return os.path.abspath(repository)
-
 
 def repositories_match(first, second):
     '''

+ 5 - 0
tests/unit/config/test_normalize.py

@@ -87,6 +87,11 @@ from borgmatic.config import normalize as module
             {'location': {'repositories': ['ssh://foo@bar:1234/repo']}},
             False,
         ),
+        (
+            {'location': {'repositories': ['file:///repo']}},
+            {'location': {'repositories': ['/repo']}},
+            False,
+        ),
     ),
 )
 def test_normalize_applies_hard_coded_normalization_to_config(

+ 7 - 0
tests/unit/config/test_validate.py

@@ -83,6 +83,13 @@ def test_normalize_repository_path_passes_through_remote_repository():
     module.normalize_repository_path(repository) == repository
 
 
+def test_normalize_repository_path_passes_through_file_repository():
+    repository = 'file:///foo/bar/test.borg'
+    flexmock(module.os.path).should_receive('abspath').and_return('/foo/bar/test.borg')
+
+    module.normalize_repository_path(repository) == '/foo/bar/test.borg'
+
+
 def test_normalize_repository_path_passes_through_absolute_repository():
     repository = '/foo/bar/test.borg'
     flexmock(module.os.path).should_receive('abspath').and_return(repository)