]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
cli: implement 'mv'. Closes #162.
authorBrian Warner <warner@allmydata.com>
Fri, 12 Oct 2007 03:31:48 +0000 (20:31 -0700)
committerBrian Warner <warner@allmydata.com>
Fri, 12 Oct 2007 03:31:48 +0000 (20:31 -0700)
src/allmydata/scripts/cli.py
src/allmydata/scripts/tahoe_mv.py [new file with mode: 0644]
src/allmydata/test/test_system.py

index 99e2fa479c5b06962edc8fcab9957e770480b98f..a0a674c7e0f64de010a907fe0e53d1bcb26d05ff 100644 (file)
@@ -94,12 +94,21 @@ class RmOptions(VDriveOptions):
     def getSynopsis(self):
         return "%s rm VE_FILE" % (os.path.basename(sys.argv[0]),)
 
+class MvOptions(VDriveOptions):
+    def parseArgs(self, frompath, topath):
+        self['from'] = frompath
+        self['to'] = topath
+
+    def getSynopsis(self):
+        return "%s mv FROM TO" % (os.path.basename(sys.argv[0]),)
+
 
 subCommands = [
     ["ls", None, ListOptions, "List a directory"],
     ["get", None, GetOptions, "Retrieve a file from the virtual drive."],
     ["put", None, PutOptions, "Upload a file into the virtual drive."],
     ["rm", None, RmOptions, "Unlink a file or directory in the virtual drive."],
+    ["mv", None, MvOptions, "Move a file within the virtual drive."],
     ]
 
 def list(config, stdout, stderr):
@@ -160,10 +169,22 @@ def rm(config, stdout, stderr):
                      stdout, stderr)
     return rc
 
+def mv(config, stdout, stderr):
+    from allmydata.scripts import tahoe_mv
+    frompath = config['from']
+    topath = config['to']
+    rc = tahoe_mv.mv(config['node-url'],
+                     config['root-uri'],
+                     frompath,
+                     topath,
+                     stdout, stderr)
+    return rc
+
 dispatch = {
     "ls": list,
     "get": get,
     "put": put,
     "rm": rm,
+    "mv": mv,
     }
 
diff --git a/src/allmydata/scripts/tahoe_mv.py b/src/allmydata/scripts/tahoe_mv.py
new file mode 100644 (file)
index 0000000..4020c6e
--- /dev/null
@@ -0,0 +1,69 @@
+#! /usr/bin/python
+
+import re
+import urllib, httplib
+import urlparse
+import simplejson
+
+# copied from twisted/web/client.py
+def _parse(url, defaultPort=None):
+    url = url.strip()
+    parsed = urlparse.urlparse(url)
+    scheme = parsed[0]
+    path = urlparse.urlunparse(('','')+parsed[2:])
+    if defaultPort is None:
+        if scheme == 'https':
+            defaultPort = 443
+        else:
+            defaultPort = 80
+    host, port = parsed[1], defaultPort
+    if ':' in host:
+        host, port = host.split(':')
+        port = int(port)
+    if path == "":
+        path = "/"
+    return scheme, host, port, path
+
+def do_http(method, url, body=""):
+    scheme, host, port, path = _parse(url)
+    if scheme == "http":
+        c = httplib.HTTPConnection(host, port)
+    elif scheme == "https":
+        c = httplib.HTTPSConnection(host, port)
+    else:
+        raise ValueError("unknown scheme '%s', need http or https" % scheme)
+    c.putrequest(method, path)
+    import allmydata
+    c.putheader("User-Agent", "tahoe_mv/%s" % allmydata.__version__)
+    c.putheader("Content-Length", str(len(body)))
+    c.endheaders()
+    c.send(body)
+    return c.getresponse()
+
+def mv(nodeurl, root_uri, frompath, topath, stdout, stderr):
+    if nodeurl[-1] != "/":
+        nodeurl += "/"
+    url = nodeurl + "uri/%s/" % urllib.quote(root_uri.replace("/","!"))
+    data = urllib.urlopen(url + frompath + "?t=json").read()
+
+    nodetype, attrs = simplejson.loads(data)
+    uri = attrs.get("rw_uri") or attrs["ro_uri"]
+
+    put_url = url + topath + "?t=uri"
+    resp = do_http("PUT", put_url, uri)
+    status = resp.status
+    if not re.search(r'^2\d\d$', str(status)):
+        print >>stderr, "error, got %s %s" % (resp.status, resp.reason)
+        print >>stderr, resp.read()
+
+    # now remove the original
+    resp = do_http("DELETE", url + frompath)
+    if not re.search(r'^2\d\d$', str(status)):
+        print >>stderr, "error, got %s %s" % (resp.status, resp.reason)
+        print >>stderr, resp.read()
+
+    print >>stdout, "OK"
+    return
+
+
+
index 649dc04f0defd056fa2a73f32a8383a13855fe0e..6b4c28d8889a397f8d0be3be7db45833ca86b834 100644 (file)
@@ -741,8 +741,30 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase):
             self.failUnlessEqual(err, "")
         d.addCallback(_check_get)
 
+        def _mv(res):
+            argv = ["mv"] + nodeargs + ["test_put/upload.txt",
+                                        "test_put/moved.txt"]
+            return self._run_cli(argv)
+        d.addCallback(_mv)
+        def _check_mv((out,err)):
+            self.failUnless("OK" in out)
+            self.failUnlessEqual(err, "")
+            vdrive0 = self.clients[0].getServiceNamed("vdrive")
+            d = defer.maybeDeferred(vdrive0.get_node_at_path,
+                                    "~/test_put/upload.txt")
+            d.addBoth(self.shouldFail, KeyError, "test_cli._check_rm",
+                      "unable to find child named 'upload.txt'")
+            d.addCallback(lambda res:
+                          vdrive0.get_node_at_path("~/test_put/moved.txt"))
+            d.addCallback(lambda filenode: filenode.download_to_data())
+            def _check_mv2(res):
+                self.failUnless("I will not write" in res)
+            d.addCallback(_check_mv2)
+            return d
+        d.addCallback(_check_mv)
+
         def _rm(res):
-            argv = ["rm"] + nodeargs + ["test_put/upload.txt"]
+            argv = ["rm"] + nodeargs + ["test_put/moved.txt"]
             return self._run_cli(argv)
         d.addCallback(_rm)
         def _check_rm((out,err)):
@@ -750,9 +772,9 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase):
             self.failUnlessEqual(err, "")
             vdrive0 = self.clients[0].getServiceNamed("vdrive")
             d = defer.maybeDeferred(vdrive0.get_node_at_path,
-                                    "~/test_put/upload.txt")
+                                    "~/test_put/moved.txt")
             d.addBoth(self.shouldFail, KeyError, "test_cli._check_rm",
-                      "unable to find child named 'upload.txt'")
+                      "unable to find child named 'moved.txt'")
             return d
         d.addCallback(_check_rm)
         return d