Skip to content
19 changes: 12 additions & 7 deletions src/borgstore/backends/rclone.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,24 @@ def get_rclone_backend(url):
rclone:remote:
rclone:remote:path
"""

if not url.startswith("rclone:"):
return None

try:
# Check rclone is on the path
info = json.loads(subprocess.check_output([RCLONE, "rc", "--loopback", "core/version"]))
except Exception:
raise BackendDoesNotExist("rclone binary not found on the path or not working properly")
if info["decomposed"] < [1, 57, 0]:
raise BackendDoesNotExist(f"rclone version must be at least v1.57.0 - found {info['version']}")

rclone_regex = r"""
rclone:
(?P<path>(.*))
"""
m = re.match(rclone_regex, url, re.VERBOSE)
if m:
# Check rclone is on the path
try:
info = json.loads(subprocess.check_output([RCLONE, "rc", "--loopback", "core/version"]))
except Exception:
raise BackendDoesNotExist("rclone binary not found on the path or not working properly")
if info["decomposed"] < [1, 57, 0]:
raise BackendDoesNotExist(f"rclone version must be at least v1.57.0 - found {info['version']}")
return Rclone(path=m["path"])


Expand Down
6 changes: 5 additions & 1 deletion src/borgstore/backends/s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ def get_s3_backend(url: str):
Supports URLs of the form:
(s3|b2):[profile|(access_key_id:access_key_secret)@][schema://hostname[:port]]/bucket/path
"""
if boto3 is None:

if not url.startswith(("s3:", "b2:")):
return None

if boto3 is None:
raise BackendDoesNotExist("The S3 backend requires dependencies. Install them with: 'pip install borgstore[s3]'")

# (s3|b2):[profile|(access_key_id:access_key_secret)@][schema://hostname[:port]]/bucket/path
s3_regex = r"""
(?P<s3type>(s3|b2)):
Expand Down
15 changes: 11 additions & 4 deletions src/borgstore/backends/sftp.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@

def get_sftp_backend(url):
"""Get SFTP backend from URL."""

if not url.startswith("sftp:"):
return None

if paramiko is None:
raise BackendDoesNotExist("The SFTP backend requires dependencies. Install them with: 'pip install borgstore[sftp]'")


# sftp://username@hostname:22/path
# Notes:
# - username and port are optional
Expand All @@ -34,10 +42,9 @@ def get_sftp_backend(url):
(?P<hostname>([^:/]+))(?::(?P<port>\d+))?/ # slash as separator, not part of the path
(?P<path>(.+)) # path may or may not start with a slash, must not be empty
"""
if paramiko is not None:
m = re.match(sftp_regex, url, re.VERBOSE)
if m:
return Sftp(username=m["username"], hostname=m["hostname"], port=int(m["port"] or "0"), path=m["path"])
m = re.match(sftp_regex, url, re.VERBOSE)
if m:
return Sftp(username=m["username"], hostname=m["hostname"], port=int(m["port"] or "0"), path=m["path"])


class Sftp(BackendBase):
Expand Down
Loading