Merge pull request #462 from Unrud/durabledirs
Durable creation of directories and make sure that the root colleciton exists.
This commit is contained in:
commit
4549d1b2db
@ -261,6 +261,8 @@ class BaseCollection:
|
||||
|
||||
The ``path`` is relative.
|
||||
|
||||
The root collection "/" must always exist.
|
||||
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@ -425,6 +427,19 @@ class Collection(BaseCollection):
|
||||
return file_name
|
||||
raise FileExistsError(errno.EEXIST, "No usable file name found")
|
||||
|
||||
@classmethod
|
||||
def _makedirs_synced(cls, filesystem_path, exist_ok=False):
|
||||
if os.path.isdir(filesystem_path) and exist_ok:
|
||||
return
|
||||
parent_filesystem_path = os.path.dirname(filesystem_path)
|
||||
# Prevent infinite loop
|
||||
if filesystem_path != parent_filesystem_path:
|
||||
# Create parent dirs recursively
|
||||
cls._makedirs_synced(parent_filesystem_path, exist_ok=True)
|
||||
# Possible race!
|
||||
os.makedirs(filesystem_path, exist_ok=exist_ok)
|
||||
sync_directory(parent_filesystem_path)
|
||||
|
||||
@classmethod
|
||||
def discover(cls, path, depth="0"):
|
||||
if path is None:
|
||||
@ -437,14 +452,16 @@ class Collection(BaseCollection):
|
||||
if not attributes[0]:
|
||||
attributes.pop()
|
||||
|
||||
# Try to guess if the path leads to a collection or an item
|
||||
folder = cls._get_collection_root_folder()
|
||||
# Create the root collection
|
||||
cls._makedirs_synced(folder, exist_ok=True)
|
||||
try:
|
||||
filesystem_path = path_to_filesystem(folder, sane_path)
|
||||
except ValueError:
|
||||
# Path is unsafe
|
||||
return
|
||||
|
||||
# Check if the path exists and if it leads to a collection or an item
|
||||
if not os.path.isdir(filesystem_path):
|
||||
if attributes and os.path.isfile(filesystem_path):
|
||||
href = attributes.pop()
|
||||
@ -495,11 +512,11 @@ class Collection(BaseCollection):
|
||||
if not props.get("tag") and collection:
|
||||
props["tag"] = collection[0].name
|
||||
if not props:
|
||||
os.makedirs(filesystem_path, exist_ok=True)
|
||||
cls._makedirs_synced(filesystem_path, exist_ok=True)
|
||||
return cls(sane_path, principal=principal)
|
||||
|
||||
parent_dir = os.path.dirname(filesystem_path)
|
||||
os.makedirs(parent_dir, exist_ok=True)
|
||||
cls._makedirs_synced(parent_dir, exist_ok=True)
|
||||
|
||||
# Create a temporary directory with an unsafe name
|
||||
with TemporaryDirectory(
|
||||
@ -718,8 +735,7 @@ class Collection(BaseCollection):
|
||||
if not cls._lock_file:
|
||||
folder = os.path.expanduser(
|
||||
cls.configuration.get("storage", "filesystem_folder"))
|
||||
if not os.path.exists(folder):
|
||||
os.makedirs(folder, exist_ok=True)
|
||||
cls._makedirs_synced(folder, exist_ok=True)
|
||||
lock_path = os.path.join(folder, ".Radicale.lock")
|
||||
cls._lock_file = open(lock_path, "w+")
|
||||
# Set access rights to a necessary minimum to prevent locking
|
||||
|
Loading…
Reference in New Issue
Block a user