Repository: borgbackup/borgstore

Issue:
file:// urls and relative paths
See: https://github.com/borgbackup/borg/issues/8372

Discussion:

Patch:
diff --git a/src/borgstore/backends/posixfs.py b/src/borgstore/backends/posixfs.py
index a39a964..8c5cfa5 100644
--- a/src/borgstore/backends/posixfs.py
+++ b/src/borgstore/backends/posixfs.py
@@ -17,11 +17,17 @@ from ..constants import TMP_SUFFIX
 
 def get_file_backend(url):
     # file:///absolute/path
-    # or
-    # file://relative/path (temporary hack, might change in future)
+    # notes:
+    # - we only support **local** fs **absolute** paths.
+    # - there is no such thing as a "relative path" local fs file: url
+    # - the general url syntax is proto://host/path
+    # - // introduces the host part. it is empty here, meaning localhost / local fs.
+    # - the third slash is NOT optional, it is the start of an absolute path as well
+    #   as the separator between the host and the path part.
+    # - the caller is responsible to give an absolute path.
     file_regex = r"""
-        file://
-        (?P<path>(.*))
+        file://  # only empty host part is supported
+        (?P<path>(/.*))  # path must be an absolute path
     """
     m = re.match(file_regex, url, re.VERBOSE)
     if m:
@@ -30,7 +36,9 @@ def get_file_backend(url):
 
 class PosixFS(BackendBase):
     def __init__(self, path, *, do_fsync=False):
-        self.base_path = Path(path).absolute()
+        self.base_path = Path(path)
+        if not self.base_path.is_absolute():
+            raise BackendError("path must be an absolute path")
         self.opened = False
         self.do_fsync = do_fsync  # False = 26x faster, see #10
 


Test patch:
diff --git a/tests/test_backends.py b/tests/test_backends.py
index b75dc8a..99b8bd3 100644
--- a/tests/test_backends.py
+++ b/tests/test_backends.py
@@ -125,11 +125,7 @@ def get_backend_from_fixture(tested_backends, request):
 
 
 @pytest.mark.parametrize(
-    "url,path",
-    [
-        ("file:///absolute/path", "/absolute/path"),  # first 2 slashes are to introduce host (empty here)
-        ("file://relative/path", "relative/path"),  # TODO: fix this, see #23
-    ],
+    "url,path", [("file:///absolute/path", "/absolute/path")]  # first 2 slashes are to introduce host (empty here)
 )
 def test_file_url(url, path):
     backend = get_file_backend(url)
@@ -137,6 +133,28 @@ def test_file_url(url, path):
     assert backend.base_path == Path(path).absolute()
 
 
+@pytest.mark.parametrize(
+    "url",
+    [
+        # file://hostname/path is the generic pattern for file urls.
+        # posixfs does not support non-local fs file urls (with a non-empty hostname part).
+        # also, there is no such thing as a relative path local fs file url, #23:
+        # - "relative" would be the hostname here, not a part of a relative path,
+        #   but we do not support non-empty hostnames (== remote fs) in posixfs.
+        # - "path" would be a network fs share name here, not a part of a relative path,
+        #   this is also not supported in posixfs.
+        "file://relative/path",  # invalid "relative path" URL
+        "file://hostname/share",  # unsupported remote fs URL
+    ],
+)
+def test_invalid_or_remote_file_url(url):
+    backend = get_file_backend(url)
+    # the url is not recognized by the posixfs backend.
+    # this behaviour keeps the option open that we could have another backend that
+    # can deal with non-local fs file urls.
+    assert backend is None
+
+
 @pytest.mark.skipif(not sftp_is_available, reason="SFTP is not available")
 @pytest.mark.parametrize(
     "url,username,hostname,port,path",