mirror of
https://github.com/borgbackup/borg.git
synced 2026-04-15 21:59:58 -04:00
add rest store support
This commit is contained in:
parent
93dfcf4565
commit
a2ea1e9883
5 changed files with 56 additions and 26 deletions
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
|
|
@ -281,13 +281,13 @@ jobs:
|
|||
- name: Install borgbackup
|
||||
run: |
|
||||
if [[ "$TOXENV" == *"llfuse"* ]]; then
|
||||
pip install -ve ".[llfuse,cockpit,s3,sftp]"
|
||||
pip install -ve ".[llfuse,cockpit,s3,sftp,rest,rclone]"
|
||||
elif [[ "$TOXENV" == *"pyfuse3"* ]]; then
|
||||
pip install -ve ".[pyfuse3,cockpit,s3,sftp]"
|
||||
pip install -ve ".[pyfuse3,cockpit,s3,sftp,rest,rclone]"
|
||||
elif [[ "$TOXENV" == *"mfusepy"* ]]; then
|
||||
pip install -ve ".[mfusepy,cockpit,s3,sftp]"
|
||||
pip install -ve ".[mfusepy,cockpit,s3,sftp,rest,rclone]"
|
||||
else
|
||||
pip install -ve ".[cockpit,s3,sftp]"
|
||||
pip install -ve ".[cockpit,s3,sftp,rest,rclone]"
|
||||
fi
|
||||
|
||||
- name: Build Borg fat binaries (${{ matrix.binary }})
|
||||
|
|
@ -461,7 +461,7 @@ jobs:
|
|||
pip -V
|
||||
python -m pip install --upgrade pip wheel
|
||||
pip install -r requirements.d/development.lock.txt
|
||||
pip install -e ".[mfusepy,cockpit,s3,sftp]"
|
||||
pip install -e ".[mfusepy,cockpit,s3,sftp,rest,rclone]"
|
||||
tox -e py311-mfusepy
|
||||
|
||||
if [[ "${{ matrix.do_binaries }}" == "true" && "${{ startsWith(github.ref, 'refs/tags/') }}" == "true" ]]; then
|
||||
|
|
@ -657,7 +657,7 @@ jobs:
|
|||
run: |
|
||||
# build borg.exe
|
||||
. env/bin/activate
|
||||
pip install -e ".[cockpit,s3,sftp]"
|
||||
pip install -e ".[cockpit,s3,sftp,rest,rclone]"
|
||||
mkdir -p dist/binary
|
||||
pyinstaller -y --clean --distpath=dist/binary scripts/borg.exe.spec
|
||||
# build sdist and wheel in dist/...
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ license = "BSD-3-Clause"
|
|||
license-files = ["LICENSE", "AUTHORS"]
|
||||
dependencies = [
|
||||
"borghash ~= 0.1.0",
|
||||
"borgstore ~= 0.3.0",
|
||||
"borgstore ~= 0.4.0",
|
||||
"msgpack >=1.0.3, <=1.1.2",
|
||||
"packaging",
|
||||
"platformdirs >=3.0.0, <5.0.0; sys_platform == 'darwin'", # for macOS: breaking changes in 3.0.0.
|
||||
|
|
@ -51,8 +51,10 @@ mfusepy = ["mfusepy >= 3.1.0, <4.0.0"] # fuse 2+3, high-level
|
|||
# a pypi release of borgbackup can't contain a dependency on github!
|
||||
# mfusepym = ["mfusepy @ git+https://github.com/mxmlnkn/mfusepy.git@master"]
|
||||
nofuse = []
|
||||
s3 = ["borgstore[s3] ~= 0.3.0"]
|
||||
sftp = ["borgstore[sftp] ~= 0.3.0"]
|
||||
s3 = ["borgstore[s3] ~= 0.4.0"]
|
||||
sftp = ["borgstore[sftp] ~= 0.4.0"]
|
||||
rclone = ["borgstore[rclone] ~= 0.4.0"]
|
||||
rest = ["borgstore[rest] ~= 0.4.0"]
|
||||
cockpit = ["textual>=6.8.0"] # might also work with older versions, untested
|
||||
|
||||
[project.urls]
|
||||
|
|
@ -189,71 +191,71 @@ pass_env = ["*"] # needed by tox4, so env vars are visible for building borg
|
|||
|
||||
[tool.tox.env.py310-llfuse]
|
||||
set_env = {BORG_FUSE_IMPL = "llfuse"}
|
||||
extras = ["llfuse", "sftp", "s3"]
|
||||
extras = ["llfuse", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py310-pyfuse3]
|
||||
set_env = {BORG_FUSE_IMPL = "pyfuse3"}
|
||||
extras = ["pyfuse3", "sftp", "s3"]
|
||||
extras = ["pyfuse3", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py310-mfusepy]
|
||||
set_env = {BORG_FUSE_IMPL = "mfusepy"}
|
||||
extras = ["mfusepy", "sftp", "s3"]
|
||||
extras = ["mfusepy", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py311-none]
|
||||
|
||||
[tool.tox.env.py311-llfuse]
|
||||
set_env = {BORG_FUSE_IMPL = "llfuse"}
|
||||
extras = ["llfuse", "sftp", "s3"]
|
||||
extras = ["llfuse", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py311-pyfuse3]
|
||||
set_env = {BORG_FUSE_IMPL = "pyfuse3"}
|
||||
extras = ["pyfuse3", "sftp", "s3"]
|
||||
extras = ["pyfuse3", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py311-mfusepy]
|
||||
set_env = {BORG_FUSE_IMPL = "mfusepy"}
|
||||
extras = ["mfusepy", "sftp", "s3"]
|
||||
extras = ["mfusepy", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py312-none]
|
||||
|
||||
[tool.tox.env.py312-llfuse]
|
||||
set_env = {BORG_FUSE_IMPL = "llfuse"}
|
||||
extras = ["llfuse", "sftp", "s3"]
|
||||
extras = ["llfuse", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py312-pyfuse3]
|
||||
set_env = {BORG_FUSE_IMPL = "pyfuse3"}
|
||||
extras = ["pyfuse3", "sftp", "s3"]
|
||||
extras = ["pyfuse3", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py312-mfusepy]
|
||||
set_env = {BORG_FUSE_IMPL = "mfusepy"}
|
||||
extras = ["mfusepy", "sftp", "s3"]
|
||||
extras = ["mfusepy", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py313-none]
|
||||
|
||||
[tool.tox.env.py313-llfuse]
|
||||
set_env = {BORG_FUSE_IMPL = "llfuse"}
|
||||
extras = ["llfuse", "sftp", "s3"]
|
||||
extras = ["llfuse", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py313-pyfuse3]
|
||||
set_env = {BORG_FUSE_IMPL = "pyfuse3"}
|
||||
extras = ["pyfuse3", "sftp", "s3"]
|
||||
extras = ["pyfuse3", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py313-mfusepy]
|
||||
set_env = {BORG_FUSE_IMPL = "mfusepy"}
|
||||
extras = ["mfusepy", "sftp", "s3"]
|
||||
extras = ["mfusepy", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py314-none]
|
||||
|
||||
[tool.tox.env.py314-llfuse]
|
||||
set_env = {BORG_FUSE_IMPL = "llfuse"}
|
||||
extras = ["llfuse", "sftp", "s3"]
|
||||
extras = ["llfuse", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py314-pyfuse3]
|
||||
set_env = {BORG_FUSE_IMPL = "pyfuse3"}
|
||||
extras = ["pyfuse3", "sftp", "s3"]
|
||||
extras = ["pyfuse3", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.py314-mfusepy]
|
||||
set_env = {BORG_FUSE_IMPL = "mfusepy"}
|
||||
extras = ["mfusepy", "sftp", "s3"]
|
||||
extras = ["mfusepy", "sftp", "s3", "rest", "rclone"]
|
||||
|
||||
[tool.tox.env.ruff]
|
||||
skip_install = true
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ def get_repository(location, *, create, exclusive, lock_wait, lock, args, v1_or_
|
|||
)
|
||||
|
||||
elif (
|
||||
location.proto in ("sftp", "file", "rclone", "s3", "b2") and not v1_or_v2
|
||||
location.proto in ("sftp", "file", "http", "https", "rclone", "s3", "b2") and not v1_or_v2
|
||||
): # stuff directly supported by borgstore
|
||||
repository = Repository(location, create=create, exclusive=exclusive, lock_wait=lock_wait, lock=lock)
|
||||
|
||||
|
|
|
|||
|
|
@ -552,6 +552,17 @@ class Location:
|
|||
re.VERBOSE,
|
||||
)
|
||||
|
||||
# BorgStore REST server
|
||||
# (http|https)://user:pass@host:port/
|
||||
http_re = re.compile(
|
||||
r"(?P<proto>http|https)://"
|
||||
+ r"((?P<user>[^:@]+):(?P<pass>[^@]+)@)?"
|
||||
+ host_re
|
||||
+ optional_port_re
|
||||
+ r"(?P<path>/)",
|
||||
re.VERBOSE,
|
||||
)
|
||||
|
||||
# (s3|b2):[(profile|(access_key_id:access_key_secret))@][scheme://hostname[:port]]/bucket/path
|
||||
s3_re = re.compile(
|
||||
r"""
|
||||
|
|
@ -620,6 +631,15 @@ class Location:
|
|||
self.port = m.group("port") and int(m.group("port")) or None
|
||||
self.path = os.path.normpath(m.group("path"))
|
||||
return True
|
||||
m = self.http_re.match(text)
|
||||
if m:
|
||||
self.proto = m.group("proto")
|
||||
self.user = m.group("user")
|
||||
self._pass = True if m.group("pass") else False
|
||||
self._host = m.group("host")
|
||||
self.port = m.group("port") and int(m.group("port")) or None
|
||||
self.path = m.group("path")
|
||||
return True
|
||||
m = self.rclone_re.match(text)
|
||||
if m:
|
||||
self.proto = m.group("proto")
|
||||
|
|
@ -683,7 +703,7 @@ class Location:
|
|||
return self.path
|
||||
if self.proto == "rclone":
|
||||
return f"{self.proto}:{self.path}"
|
||||
if self.proto in ("sftp", "ssh", "s3", "b2"):
|
||||
if self.proto in ("sftp", "ssh", "s3", "b2", "http", "https"):
|
||||
return (
|
||||
f"{self.proto}://"
|
||||
f"{(self.user + '@') if self.user else ''}"
|
||||
|
|
|
|||
|
|
@ -194,6 +194,14 @@ class TestLocationWithoutEnv:
|
|||
)
|
||||
assert Location("sftp://user@host:1234//abs/path").to_key_filename() == keys_dir + "host___abs_path"
|
||||
|
||||
def test_http(self, monkeypatch, keys_dir):
|
||||
monkeypatch.delenv("BORG_REPO", raising=False)
|
||||
assert (
|
||||
repr(Location("http://user:pass@host:1234/"))
|
||||
== "Location(proto='http', user='user', pass='REDACTED', host='host', port=1234, path='/')"
|
||||
)
|
||||
assert Location("http://user:pass@host:1234/").to_key_filename() == keys_dir + "host__"
|
||||
|
||||
def test_socket(self, monkeypatch, keys_dir):
|
||||
monkeypatch.delenv("BORG_REPO", raising=False)
|
||||
url = "socket:///c:/repo/path" if is_win32 else "socket:///repo/path"
|
||||
|
|
|
|||
Loading…
Reference in a new issue