mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-14 06:06:40 +00:00
Change the arbitrary URI support from implied to explicit
The move webapi function now takes a target_type argument which lets it know whether the target is a subdirectory name or URI. This is an improvement over the old system in which the move handler tried to guess whether the target was a name or a URI. Also fixed a little docs copypaste problem and tweaked some line wrapping.
This commit is contained in:
parent
b29d0920d3
commit
e58a01270b
@ -1281,16 +1281,21 @@ Renaming A Child
|
||||
Moving A Child
|
||||
----------------
|
||||
|
||||
``POST /uri/$DIRCAP/[SUBDIRS../]?t=rename&from_name=OLD&to_dir=TARGET[&to_name=NEW]``
|
||||
``POST /uri/$DIRCAP/[SUBDIRS../]?t=move&from_name=OLD&to_dir=TARGET``
|
||||
|
||||
This instructs the node to move a child of the given directory to a
|
||||
different directory, both of which must be mutable. The child can also be
|
||||
renamed in the process. The to_dir parameter can be either the name of a
|
||||
subdirectory of the dircap from which the child is being moved (multiple
|
||||
levels of descent are supported) or the writecap of an unrelated directory.
|
||||
different directory, both of which must be mutable. The child can also
|
||||
be renamed in the process. The to_dir parameter should contain the name
|
||||
of a subdirectory of the dircap from which the child is being moved
|
||||
(multiple levels of descent are supported), unless the file is to be
|
||||
moved to an unrelated directory. In the latter case, this can be
|
||||
specified by passing a target_type=uri argument and the target URI in
|
||||
to_dir=. If the target is the name of a subdirectory, this can be
|
||||
signified by passing target_type=name. A new name for the child can
|
||||
also be specified using the to_name= parameter.
|
||||
|
||||
This operation will replace any existing child of the new name, making it
|
||||
behave like the UNIX "``mv -f``" command. The original child is not
|
||||
This operation will replace any existing child of the new name, making
|
||||
it behave like the UNIX "``mv -f``" command. The original child is not
|
||||
unlinked until it is linked into the target directory.
|
||||
|
||||
Other Utilities
|
||||
|
@ -3247,7 +3247,6 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
|
||||
return d
|
||||
|
||||
def test_POST_move_file(self):
|
||||
""""""
|
||||
d = self.POST(self.public_url + "/foo", t="move",
|
||||
from_name="bar.txt", to_dir="sub")
|
||||
d.addCallback(lambda res:
|
||||
@ -3331,6 +3330,16 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
|
||||
d.addCallback(self.failUnlessIsBazDotTxt)
|
||||
return d
|
||||
|
||||
def test_POST_move_file_bad_target_type(self):
|
||||
d = self.POST(self.public_url + "/foo", t="move", target_type="*D",
|
||||
from_name="bar.txt", to_dir="sub")
|
||||
d.addBoth(self.shouldFail, error.Error,
|
||||
"test_POST_rename_file_slash_fail",
|
||||
"400 Bad Request",
|
||||
"invalid target_type parameter",
|
||||
)
|
||||
return d
|
||||
|
||||
def test_POST_move_file_multi_level(self):
|
||||
d = self.POST(self.public_url + "/foo/sub/level2?t=mkdir", "")
|
||||
d.addCallback(lambda res: self.POST(self.public_url + "/foo", t="move",
|
||||
@ -3344,7 +3353,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
|
||||
return d
|
||||
|
||||
def test_POST_move_file_to_uri(self):
|
||||
d = self.POST(self.public_url + "/foo", t="move",
|
||||
d = self.POST(self.public_url + "/foo", t="move", target_type="uri",
|
||||
from_name="bar.txt", to_dir=self._sub_uri)
|
||||
d.addCallback(lambda res:
|
||||
self.failIfNodeHasChild(self._foo_node, u"bar.txt"))
|
||||
@ -3379,7 +3388,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
|
||||
return d
|
||||
|
||||
def test_POST_move_file_to_bad_uri(self):
|
||||
d = self.POST(self.public_url + "/foo", t="move", from_name="bar.txt",
|
||||
d = self.POST(self.public_url + "/foo", t="move",
|
||||
from_name="bar.txt", target_type="uri",
|
||||
to_dir="URI:DIR2:mn5jlyjnrjeuydyswlzyui72i:rmneifcj6k6sycjljjhj3f6majsq2zqffydnnul5hfa4j577arma")
|
||||
d.addBoth(self.shouldFail, error.Error,
|
||||
"POST_move_file_to_bad_uri",
|
||||
|
@ -934,13 +934,6 @@ def is_literal_file_uri(s):
|
||||
s.startswith(ALLEGED_READONLY_PREFIX + 'URI:LIT:') or
|
||||
s.startswith(ALLEGED_IMMUTABLE_PREFIX + 'URI:LIT:'))
|
||||
|
||||
def is_writeable_directory_uri(s):
|
||||
if not isinstance(s, str):
|
||||
return False
|
||||
return (s.startswith('URI:DIR2:') or
|
||||
s.startswith(ALLEGED_READONLY_PREFIX + 'URI:DIR2:') or
|
||||
s.startswith(ALLEGED_IMMUTABLE_PREFIX + 'URI:DIR2:'))
|
||||
|
||||
def has_uri_prefix(s):
|
||||
if not isinstance(s, str):
|
||||
return False
|
||||
|
@ -13,7 +13,7 @@ from nevow.inevow import IRequest
|
||||
from foolscap.api import fireEventually
|
||||
|
||||
from allmydata.util import base32, time_format
|
||||
from allmydata.uri import from_string_dirnode, is_writeable_directory_uri
|
||||
from allmydata.uri import from_string_dirnode
|
||||
from allmydata.interfaces import IDirectoryNode, IFileNode, IFilesystemNode, \
|
||||
IImmutableFileNode, IMutableFileNode, ExistingChildError, \
|
||||
NoSuchChildError, EmptyPathnameComponentError, SDMF_VERSION, MDMF_VERSION
|
||||
@ -444,23 +444,30 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
|
||||
if not from_name or not to_dir:
|
||||
raise WebError("move requires from_name and to_dir")
|
||||
replace = boolean_of_arg(get_arg(req, "replace", "true"))
|
||||
target_type = get_arg(req, "target_type", "name")
|
||||
if not target_type in ["name", "uri"]:
|
||||
raise WebError("invalid target_type parameter",
|
||||
http.BAD_REQUEST)
|
||||
|
||||
# allow from_name to contain slashes, so they can fix names that
|
||||
# were accidentally created with them. But disallow them in to_name
|
||||
# (if it's specified), to discourage the practice.
|
||||
if to_name and "/" in to_name:
|
||||
raise WebError("to_name= may not contain a slash", http.BAD_REQUEST)
|
||||
raise WebError("to_name= may not contain a slash",
|
||||
http.BAD_REQUEST)
|
||||
|
||||
d = self.node.has_child(to_dir.split('/')[0])
|
||||
def get_target_node(isname):
|
||||
if isname or not is_writeable_directory_uri(str(to_dir)):
|
||||
d = defer.Deferred()
|
||||
def get_target_node(target_type):
|
||||
if target_type == "name":
|
||||
return self.node.get_child_at_path(to_dir)
|
||||
else:
|
||||
elif target_type == "uri":
|
||||
return self.client.create_node_from_uri(str(to_dir))
|
||||
d.addCallback(get_target_node)
|
||||
d.callback(target_type)
|
||||
def is_target_node_usable(target_node):
|
||||
if not IDirectoryNode.providedBy(target_node):
|
||||
raise WebError("to_dir is not a usable directory", http.GONE)
|
||||
raise WebError("to_dir is not a usable directory",
|
||||
http.GONE)
|
||||
return target_node
|
||||
d.addCallback(is_target_node_usable)
|
||||
d.addCallback(lambda new_parent: self.node.move_child_to(
|
||||
|
@ -17,12 +17,18 @@
|
||||
<input n:render="when_done" />
|
||||
|
||||
Move child:
|
||||
<input type="text" name="from_name" readonly="true" n:render="get_name" />
|
||||
<input type="text" name="from_name" readonly="true"
|
||||
n:render="get_name" /><br />
|
||||
to
|
||||
<input type="text" name="to_dir" /><br />
|
||||
<input checked="checked" type="radio" id="tt-name"
|
||||
value="name" name="target_type" />
|
||||
<label for="tt-name"> Subdirectory</label>
|
||||
<input type="radio" id="tt-uri" value="uri" name="target_type"/>
|
||||
<label for="tt-uri"> URI</label> <br /><br />
|
||||
New name?
|
||||
<input type="text" name="to_name" />
|
||||
<input type="submit" value="move" />
|
||||
<input type="submit" value="move" /><br />
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user