diff --git a/src/borgstore/backends/posixfs.py b/src/borgstore/backends/posixfs.py index d61f931..a39a964 100644 --- a/src/borgstore/backends/posixfs.py +++ b/src/borgstore/backends/posixfs.py @@ -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 @@ -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: diff --git a/src/borgstore/backends/sftp.py b/src/borgstore/backends/sftp.py index 5f3404f..8c1ead6 100644 --- a/src/borgstore/backends/sftp.py +++ b/src/borgstore/backends/sftp.py @@ -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 @@ -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() diff --git a/tests/test_backends.py b/tests/test_backends.py index c37a45d..09d469c 100644 --- a/tests/test_backends.py +++ b/tests/test_backends.py @@ -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()