mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-06-23 01:08:53 +00:00
Add must_exist, must_be_directory, and must_be_file arguments to DirectoryNode.delete. This will be used to fixes a minor condition in the SFTP frontend.
This commit is contained in:
@ -11,7 +11,7 @@ from allmydata.unknown import UnknownNode, strip_prefix_for_ro
|
|||||||
from allmydata.interfaces import IFilesystemNode, IDirectoryNode, IFileNode, \
|
from allmydata.interfaces import IFilesystemNode, IDirectoryNode, IFileNode, \
|
||||||
IImmutableFileNode, IMutableFileNode, \
|
IImmutableFileNode, IMutableFileNode, \
|
||||||
ExistingChildError, NoSuchChildError, ICheckable, IDeepCheckable, \
|
ExistingChildError, NoSuchChildError, ICheckable, IDeepCheckable, \
|
||||||
MustBeDeepImmutableError, CapConstraintError
|
MustBeDeepImmutableError, CapConstraintError, ChildOfWrongTypeError
|
||||||
from allmydata.check_results import DeepCheckResults, \
|
from allmydata.check_results import DeepCheckResults, \
|
||||||
DeepCheckAndRepairResults
|
DeepCheckAndRepairResults
|
||||||
from allmydata.monitor import Monitor
|
from allmydata.monitor import Monitor
|
||||||
@ -81,10 +81,13 @@ def update_metadata(metadata, new_metadata, now):
|
|||||||
# the unpacked contents.
|
# the unpacked contents.
|
||||||
|
|
||||||
class Deleter:
|
class Deleter:
|
||||||
def __init__(self, node, name, must_exist=True):
|
def __init__(self, node, name, must_exist=True, must_be_directory=False, must_be_file=False):
|
||||||
self.node = node
|
self.node = node
|
||||||
self.name = name
|
self.name = name
|
||||||
self.must_exist = True
|
self.must_exist = must_exist
|
||||||
|
self.must_be_directory = must_be_directory
|
||||||
|
self.must_be_file = must_be_file
|
||||||
|
|
||||||
def modify(self, old_contents, servermap, first_time):
|
def modify(self, old_contents, servermap, first_time):
|
||||||
children = self.node._unpack_contents(old_contents)
|
children = self.node._unpack_contents(old_contents)
|
||||||
if self.name not in children:
|
if self.name not in children:
|
||||||
@ -93,6 +96,13 @@ class Deleter:
|
|||||||
self.old_child = None
|
self.old_child = None
|
||||||
return None
|
return None
|
||||||
self.old_child, metadata = children[self.name]
|
self.old_child, metadata = children[self.name]
|
||||||
|
|
||||||
|
# Unknown children can be removed regardless of must_be_directory or must_be_file.
|
||||||
|
if self.must_be_directory and IFileNode.providedBy(self.old_child):
|
||||||
|
raise ChildOfWrongTypeError("delete required a directory, not a file")
|
||||||
|
if self.must_be_file and IDirectoryNode.providedBy(self.old_child):
|
||||||
|
raise ChildOfWrongTypeError("delete required a file, not a directory")
|
||||||
|
|
||||||
del children[self.name]
|
del children[self.name]
|
||||||
new_contents = self.node._pack_contents(children)
|
new_contents = self.node._pack_contents(children)
|
||||||
return new_contents
|
return new_contents
|
||||||
@ -568,13 +578,14 @@ class DirectoryNode:
|
|||||||
self.set_node(name, node, metadata, overwrite))
|
self.set_node(name, node, metadata, overwrite))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def delete(self, name):
|
def delete(self, name, must_exist=True, must_be_directory=False, must_be_file=False):
|
||||||
"""I remove the child at the specific name. I return a Deferred that
|
"""I remove the child at the specific name. I return a Deferred that
|
||||||
fires (with the node just removed) when the operation finishes."""
|
fires (with the node just removed) when the operation finishes."""
|
||||||
assert isinstance(name, unicode)
|
assert isinstance(name, unicode)
|
||||||
if self.is_readonly():
|
if self.is_readonly():
|
||||||
return defer.fail(NotWriteableError())
|
return defer.fail(NotWriteableError())
|
||||||
deleter = Deleter(self, name)
|
deleter = Deleter(self, name, must_exist=must_exist,
|
||||||
|
must_be_directory=must_be_directory, must_be_file=must_be_file)
|
||||||
d = self._node.modify(deleter.modify)
|
d = self._node.modify(deleter.modify)
|
||||||
d.addCallback(lambda res: deleter.old_child)
|
d.addCallback(lambda res: deleter.old_child)
|
||||||
return d
|
return d
|
||||||
|
@ -828,6 +828,9 @@ class ExistingChildError(Exception):
|
|||||||
class NoSuchChildError(Exception):
|
class NoSuchChildError(Exception):
|
||||||
"""A directory node was asked to fetch a child which does not exist."""
|
"""A directory node was asked to fetch a child which does not exist."""
|
||||||
|
|
||||||
|
class ChildOfWrongTypeError(Exception):
|
||||||
|
"""An operation was attempted on a child of the wrong type (file or directory)."""
|
||||||
|
|
||||||
class IDirectoryNode(IFilesystemNode):
|
class IDirectoryNode(IFilesystemNode):
|
||||||
"""I represent a filesystem node that is a container, with a
|
"""I represent a filesystem node that is a container, with a
|
||||||
name-to-child mapping, holding the tahoe equivalent of a directory. All
|
name-to-child mapping, holding the tahoe equivalent of a directory. All
|
||||||
@ -974,11 +977,13 @@ class IDirectoryNode(IFilesystemNode):
|
|||||||
I return a Deferred that fires (with the IFileNode of the uploaded
|
I return a Deferred that fires (with the IFileNode of the uploaded
|
||||||
file) when the operation completes."""
|
file) when the operation completes."""
|
||||||
|
|
||||||
def delete(name):
|
def delete(name, must_exist=True, must_be_directory=False, must_be_file=False):
|
||||||
"""I remove the child at the specific name. I return a Deferred that
|
"""I remove the child at the specific name. I return a Deferred that
|
||||||
fires when the operation finishes. The child name must be a unicode
|
fires when the operation finishes. The child name must be a unicode
|
||||||
string. I raise NoSuchChildError if I do not have a child by that
|
string. If must_exist is True and I do not have a child by that name,
|
||||||
name."""
|
I raise NoSuchChildError. If must_be_directory is True and the child
|
||||||
|
is a file, or if must_be_file is True and the child is a directory,
|
||||||
|
I raise ChildOfWrongTypeError."""
|
||||||
|
|
||||||
def create_subdirectory(name, initial_children={}, overwrite=True):
|
def create_subdirectory(name, initial_children={}, overwrite=True):
|
||||||
"""I create and attach a directory at the given name. The new
|
"""I create and attach a directory at the given name. The new
|
||||||
|
Reference in New Issue
Block a user