Skip to content

Commit

Permalink
Merge pull request #59 from ThomasWaldmann/fix-empty-base-dir
Browse files Browse the repository at this point in the history
backend.create: only reject non-empty storage, see #57
  • Loading branch information
ThomasWaldmann authored Sep 27, 2024
2 parents 7e36330 + d0151df commit b8a9a74
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 8 deletions.
13 changes: 9 additions & 4 deletions src/borgstore/backends/posixfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
import tempfile

from ._base import BackendBase, ItemInfo, validate_name
from .errors import BackendAlreadyExists, BackendDoesNotExist, BackendMustNotBeOpen, BackendMustBeOpen, ObjectNotFound
from .errors import BackendError, BackendAlreadyExists, BackendDoesNotExist, BackendMustNotBeOpen, BackendMustBeOpen
from .errors import ObjectNotFound
from ..constants import TMP_SUFFIX


Expand All @@ -37,9 +38,13 @@ def create(self):
if self.opened:
raise BackendMustNotBeOpen()
try:
self.base_path.mkdir()
except FileExistsError:
raise BackendAlreadyExists(f"posixfs storage base path already exists: {self.base_path}")
# we accept an already existing directory, but we do not create parent dirs:
self.base_path.mkdir(exist_ok=True, parents=False)
except FileNotFoundError:
raise BackendError(f"posixfs storage base path's parent directory does not exist: {self.base_path}")
contents = list(self.base_path.iterdir())
if contents:
raise BackendAlreadyExists(f"posixfs storage base path is not empty: {self.base_path}")

def destroy(self):
if self.opened:
Expand Down
16 changes: 12 additions & 4 deletions src/borgstore/backends/sftp.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
import paramiko

from ._base import BackendBase, ItemInfo, validate_name
from .errors import BackendMustBeOpen, BackendMustNotBeOpen, BackendDoesNotExist, BackendAlreadyExists, ObjectNotFound
from .errors import BackendError, BackendMustBeOpen, BackendMustNotBeOpen, BackendDoesNotExist, BackendAlreadyExists
from .errors import ObjectNotFound
from ..constants import TMP_SUFFIX


Expand Down Expand Up @@ -91,9 +92,16 @@ def create(self):
raise BackendMustNotBeOpen()
self._connect()
try:
self._mkdir(self.base_path, parents=False, exist_ok=False)
except (FileExistsError, IOError):
raise BackendAlreadyExists(f"sftp storage base path already exists: {self.base_path}")
try:
# we accept an already existing directory, but we do not create parent dirs:
self._mkdir(self.base_path, exist_ok=True, parents=False)
except FileNotFoundError:
raise BackendError(f"sftp storage base path's parent directory does not exist: {self.base_path}")
contents = list(self.client.listdir(self.base_path))
if contents:
raise BackendAlreadyExists(f"sftp storage base path is not empty: {self.base_path}")
except IOError as err:
raise BackendError(f"sftp storage I/O error: {err}")
finally:
self._disconnect()

Expand Down
3 changes: 3 additions & 0 deletions tests/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@ def test_load_partial(tested_backends, request):

def test_already_exists(tested_backends, request):
backend = get_backend_from_fixture(tested_backends, request)
with backend as _backend:
_backend.store("key", b"value") # make the backend "not empty"
# the backend must reject (re-)creation if there is already something at that place:
with pytest.raises(BackendAlreadyExists):
backend.create()

Expand Down

0 comments on commit b8a9a74

Please sign in to comment.