From 9214dbda50ff9d10ec638ceb1ba77aaa0e22331d Mon Sep 17 00:00:00 2001 From: david-sarah Date: Thu, 27 May 2010 12:45:29 -0700 Subject: [PATCH] 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. --- src/allmydata/dirnode.py | 21 ++++++++++++++++----- src/allmydata/interfaces.py | 11 ++++++++--- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/allmydata/dirnode.py b/src/allmydata/dirnode.py index 8a485f41..bfc151a3 100644 --- a/src/allmydata/dirnode.py +++ b/src/allmydata/dirnode.py @@ -11,7 +11,7 @@ from allmydata.unknown import UnknownNode, strip_prefix_for_ro 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 @@ -81,10 +81,13 @@ def update_metadata(metadata, new_metadata, now): # 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: @@ -93,6 +96,13 @@ class Deleter: 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 @@ -568,13 +578,14 @@ class DirectoryNode: 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 diff --git a/src/allmydata/interfaces.py b/src/allmydata/interfaces.py index 948fac03..98c3dbb1 100644 --- a/src/allmydata/interfaces.py +++ b/src/allmydata/interfaces.py @@ -828,6 +828,9 @@ class ExistingChildError(Exception): 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 @@ -974,11 +977,13 @@ class IDirectoryNode(IFilesystemNode): 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 -- 2.45.2