Merge pull request #469 from Unrud/atomicput
Atomic replacement of whole collection by PUT
This commit is contained in:
commit
94ac2c5c8a
@ -574,9 +574,6 @@ class Application:
|
|||||||
tag = tags.get(content_type)
|
tag = tags.get(content_type)
|
||||||
|
|
||||||
if write_whole_collection:
|
if write_whole_collection:
|
||||||
if item:
|
|
||||||
# Delete old collection
|
|
||||||
item.delete()
|
|
||||||
new_item = self.Collection.create_collection(
|
new_item = self.Collection.create_collection(
|
||||||
path, items, {"tag": tag})
|
path, items, {"tag": tag})
|
||||||
else:
|
else:
|
||||||
|
@ -294,6 +294,10 @@ class BaseCollection:
|
|||||||
def create_collection(cls, href, collection=None, props=None):
|
def create_collection(cls, href, collection=None, props=None):
|
||||||
"""Create a collection.
|
"""Create a collection.
|
||||||
|
|
||||||
|
If the collection already exists and neither ``collection`` nor
|
||||||
|
``props`` are set, this method shouldn't do anything. Otherwise the
|
||||||
|
existing collection must be replaced.
|
||||||
|
|
||||||
``collection`` is a list of vobject components.
|
``collection`` is a list of vobject components.
|
||||||
|
|
||||||
``props`` are metadata values for the collection.
|
``props`` are metadata values for the collection.
|
||||||
@ -551,6 +555,11 @@ class Collection(BaseCollection):
|
|||||||
for card in collection:
|
for card in collection:
|
||||||
self.upload(self._find_available_file_name(), card)
|
self.upload(self._find_available_file_name(), card)
|
||||||
|
|
||||||
|
# This operation is not atomic on the filesystem level but it's
|
||||||
|
# very unlikely that one rename operations succeeds while the
|
||||||
|
# other fails or that only one gets written to disk.
|
||||||
|
if os.path.exists(filesystem_path):
|
||||||
|
os.rename(filesystem_path, os.path.join(tmp_dir, "delete"))
|
||||||
os.rename(tmp_filesystem_path, filesystem_path)
|
os.rename(tmp_filesystem_path, filesystem_path)
|
||||||
sync_directory(parent_dir)
|
sync_directory(parent_dir)
|
||||||
|
|
||||||
|
@ -119,6 +119,21 @@ class BaseRequests:
|
|||||||
assert "DTSTART;TZID=Europe/Paris:20140901T180000" in answer
|
assert "DTSTART;TZID=Europe/Paris:20140901T180000" in answer
|
||||||
assert "DTEND;TZID=Europe/Paris:20140901T210000" in answer
|
assert "DTEND;TZID=Europe/Paris:20140901T210000" in answer
|
||||||
|
|
||||||
|
def test_put_whole_collection(self):
|
||||||
|
"""Create and overwrite a whole collection."""
|
||||||
|
event = get_file_content("event1.ics")
|
||||||
|
status, headers, answer = self.request("PUT", "/calendar.ics/", event)
|
||||||
|
assert status == 201
|
||||||
|
status, headers, answer = self.request(
|
||||||
|
"PUT", "/calendar.ics/event1.ics", event)
|
||||||
|
assert status == 201
|
||||||
|
# Overwrite
|
||||||
|
status, headers, answer = self.request("PUT", "/calendar.ics/", event)
|
||||||
|
assert status == 201
|
||||||
|
status, headers, answer = self.request(
|
||||||
|
"GET", "/calendar.ics/event1.ics")
|
||||||
|
assert status == 404
|
||||||
|
|
||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
"""Delete an event."""
|
"""Delete an event."""
|
||||||
self.request("MKCOL", "/calendar.ics/")
|
self.request("MKCOL", "/calendar.ics/")
|
||||||
|
Loading…
Reference in New Issue
Block a user