from allmydata.interfaces import IFilesystemNode, IDirectoryNode, IFileNode, \
IImmutableFileNode, IMutableFileNode, \
ExistingChildError, NoSuchChildError, ICheckable, IDeepCheckable, \
- MustBeDeepImmutableError, CapConstraintError
+ MustBeDeepImmutableError, CapConstraintError, ChildOfWrongTypeError
from allmydata.check_results import DeepCheckResults, \
DeepCheckAndRepairResults
from allmydata.monitor import Monitor
# the unpacked contents.
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.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):
children = self.node._unpack_contents(old_contents)
if self.name not in children:
self.old_child = None
return None
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]
new_contents = self.node._pack_contents(children)
return new_contents
self.set_node(name, node, metadata, overwrite))
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
fires (with the node just removed) when the operation finishes."""
assert isinstance(name, unicode)
if self.is_readonly():
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.addCallback(lambda res: deleter.old_child)
return d
class NoSuchChildError(Exception):
"""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):
"""I represent a filesystem node that is a container, with a
name-to-child mapping, holding the tahoe equivalent of a directory. All
I return a Deferred that fires (with the IFileNode of the uploaded
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
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
- name."""
+ string. If must_exist is True and I do not have a child by that 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):
"""I create and attach a directory at the given name. The new