add --format= to 'tahoe put'/'mkdir', remove --mutable-type. Closes #1561
authorBrian Warner <warner@lothar.com>
Fri, 14 Oct 2011 03:15:00 +0000 (20:15 -0700)
committerBrian Warner <warner@lothar.com>
Fri, 14 Oct 2011 03:15:00 +0000 (20:15 -0700)
docs/frontends/CLI.rst
src/allmydata/scripts/cli.py
src/allmydata/scripts/tahoe_mkdir.py
src/allmydata/scripts/tahoe_put.py
src/allmydata/test/check_grid.py
src/allmydata/test/test_cli.py
src/allmydata/test/test_system.py

index 7aa2797966318a4ba2b3df768b158ca58898c1be..ed8ddf65debcf31d7c06c31aeb1d205b9e30b773 100644 (file)
@@ -261,9 +261,9 @@ Command Syntax Summary
 
 ``tahoe webopen [PATH]``
 
-``tahoe put [--mutable] [FROMLOCAL|-]``
+``tahoe put [--format=FORMAT] [FROMLOCAL|-]``
 
-``tahoe put [--mutable] FROMLOCAL|- TOPATH``
+``tahoe put [--format=FORMAT] FROMLOCAL|- TOPATH``
 
 ``tahoe put [FROMLOCAL|-] mutable-file-writecap``
 
@@ -394,15 +394,15 @@ Command Examples
  from the following path. When the source file is named "``-``", the contents
  are taken from stdin.
 
-``tahoe put file.txt --mutable``
+``tahoe put file.txt --format=SDMF``
 
- Create a new mutable file, fill it with the contents of ``file.txt``, and
- print the new write-cap to stdout.
+ Create a new (SDMF) mutable file, fill it with the contents of ``file.txt``,
and print the new write-cap to stdout.
 
 ``tahoe put file.txt MUTABLE-FILE-WRITECAP``
 
- Replace the contents of the given mutable file with the contents of ``file.txt``
- and prints the same write-cap to stdout.
+ Replace the contents of the given mutable file with the contents of
``file.txt`` and prints the same write-cap to stdout.
 
 ``tahoe cp file.txt tahoe:uploaded.txt``
 
index 970c8c409e80491261f94389f487daf05b98feff..950f6a79dff311f6fec5055a3bb61fcbc425e417 100644 (file)
@@ -51,17 +51,15 @@ class VDriveOptions(BaseOptions):
 
 class MakeDirectoryOptions(VDriveOptions):
     optParameters = [
-        ("mutable-type", None, None, "Create a mutable directory in the given format. "
-                                     "Valid formats are SDMF and MDMF, case-insensitive."),
+        ("format", None, None, "Create directory with the given format: SDMF and MDMF for mutable. (case-insensitive)"),
         ]
 
     def parseArgs(self, where=""):
         self.where = argv_to_unicode(where)
 
-        if self['mutable-type']:
-            if self['mutable-type'].lower() not in ("sdmf", "mdmf"):
-                raise usage.UsageError("%s is an invalid format" % self['mutable-type'])
-            self['mutable-type'] = self['mutable-type'].lower()
+        if self['format']:
+            if self['format'].upper() not in ("SDMF", "MDMF", "CHK"):
+                raise usage.UsageError("%s is an invalid format" % self['format'])
 
     def getSynopsis(self):
         return "Usage:  %s mkdir [options] [REMOTE_DIR]" % (self.command_name,)
@@ -172,11 +170,10 @@ Examples:
 
 class PutOptions(VDriveOptions):
     optFlags = [
-        ("mutable", "m", "Create a mutable file instead of an immutable one."),
+        ("mutable", "m", "Create a mutable file instead of an immutable one. (DEPRECATED, use --format=SDMF)"),
         ]
     optParameters = [
-        ("mutable-type", None, None, "Create a mutable file in the given format (implies --mutable). "
-                                     "Valid formats are SDMF and MDMF, case-insensitive."),
+        ("format", None, None, "Create file with the given format: SDMF and MDMF for mutable, CHK (default) for immutable. (case-insensitive)"),
         ]
 
     def parseArgs(self, arg1=None, arg2=None):
@@ -194,13 +191,9 @@ class PutOptions(VDriveOptions):
         if self.from_file == u"-":
             self.from_file = None
 
-        if self['mutable-type']:
-            if self['mutable-type'].lower() not in ("sdmf", "mdmf"):
-                raise usage.UsageError("%s is an invalid format" % self['mutable-type'])
-            self['mutable-type'] = self['mutable-type'].lower()
-
-        if self['mutable-type']:
-            self['mutable'] = True
+        if self['format']:
+            if self['format'].upper() not in ("SDMF", "MDMF", "CHK"):
+                raise usage.UsageError("%s is an invalid format" % self['format'])
 
     def getSynopsis(self):
         return "Usage:  %s put [options] LOCAL_FILE REMOTE_FILE" % (self.command_name,)
index cc0374bf7acd84312f8a58724c0a4277497a54e3..9820ada76fe92d17504192942ac17225ac898692 100644 (file)
@@ -22,8 +22,8 @@ def mkdir(options):
     if not where or not path:
         # create a new unlinked directory
         url = nodeurl + "uri?t=mkdir"
-        if options["mutable-type"]:
-            url += "&format=%s" % urllib.quote(options['mutable-type'])
+        if options["format"]:
+            url += "&format=%s" % urllib.quote(options['format'])
         resp = do_http("POST", url)
         rc = check_http_error(resp, stderr)
         if rc:
@@ -39,8 +39,8 @@ def mkdir(options):
     # path must be "/".join([s.encode("utf-8") for s in segments])
     url = nodeurl + "uri/%s/%s?t=mkdir" % (urllib.quote(rootcap),
                                            urllib.quote(path))
-    if options['mutable-type']:
-        url += "&format=%s" % urllib.quote(options['mutable-type'])
+    if options['format']:
+        url += "&format=%s" % urllib.quote(options['format'])
 
     resp = do_http("POST", url)
     check_http_error(resp, stderr)
index 3a3b39458e679ce1da010dcb7ff9d7eab6d9f90f..a85539efec87e0d96f4a839705a4261212848ac8 100644 (file)
@@ -18,7 +18,7 @@ def put(options):
     from_file = options.from_file
     to_file = options.to_file
     mutable = options['mutable']
-    mutable_type = options['mutable-type']
+    format = options['format']
     if options['quiet']:
         verbosity = 0
     else:
@@ -64,14 +64,13 @@ def put(options):
         # unlinked upload
         url = nodeurl + "uri"
 
-    file_format = None
+    queryargs = []
     if mutable:
-        file_format = "SDMF"
-    if mutable_type:
-        assert mutable
-        file_format = mutable_type.upper()
-    if file_format:
-        url += "?format=%s" % file_format
+        queryargs.append("mutable=true")
+    if format:
+        queryargs.append("format=%s" % format)
+    if queryargs:
+        url += "?" + "&".join(queryargs)
 
     if from_file:
         infileobj = open(os.path.expanduser(from_file), "rb")
index fbe8f5f131d618462fbf64409044f62e8140b516..a9d362bd99df671618305cbfb26f7e898f7823be 100644 (file)
@@ -30,8 +30,8 @@ To set up the client node, do the following:
   tahoe put -d DIR FILE testgrid:old.MD5SUM
   tahoe put -d DIR FILE testgrid:recent.MD5SUM
   tahoe put -d DIR FILE testgrid:recentdir/recent.MD5SUM
-  echo "" | tahoe put -d DIR --mutable testgrid:log
-  echo "" | tahoe put -d DIR --mutable testgrid:recentlog
+  echo "" | tahoe put -d DIR --format=SDMF testgrid:log
+  echo "" | tahoe put -d DIR --format=SDMF testgrid:recentlog
 
 This script will perform the following steps (the kind of compatibility that
 is being tested is in [brackets]):
@@ -189,7 +189,7 @@ class GridTester:
         self.cli("put", "-", "testgrid:"+fn, stdin=data, ignore_stderr=True)
 
     def put_mutable(self, fn, data):
-        self.cli("put", "--mutable", "-", "testgrid:"+fn,
+        self.cli("put", "--format=SDMF", "-", "testgrid:"+fn,
                  stdin=data, ignore_stderr=True)
 
     def update(self, fn):
index f9acbc0630a9c0eb61f8a0b1071d6968523181c2..464e2b568c1c1ab17ab38fbff544ed4a4a100fda 100644 (file)
@@ -1160,67 +1160,79 @@ class Put(GridTestMixin, CLITestMixin, unittest.TestCase):
         self.failUnlessIn("URI:SSK-RO", json)
         self.failUnlessIn("URI:SSK-Verifier", json)
 
-    def test_mutable_type(self):
-        self.basedir = "cli/Put/mutable_type"
+    def _check_chk_json(self, (rc, json, err)):
+        self.failUnlessEqual(rc, 0)
+        self.failUnlessEqual(err, "")
+        self.failUnlessIn('"format": "CHK"', json)
+        # We also want to see the appropriate CHK caps.
+        self.failUnlessIn("URI:CHK", json)
+        self.failUnlessIn("URI:CHK-Verifier", json)
+
+    def test_format(self):
+        self.basedir = "cli/Put/format"
         self.set_up_grid()
-        data = "data" * 100000
+        data = "data" * 40000 # 160kB total, two segments
         fn1 = os.path.join(self.basedir, "data")
         fileutil.write(fn1, data)
         d = self.do_cli("create-alias", "tahoe")
 
-        def _put_and_ls(ign, mutable_type, filename):
-            d2 = self.do_cli("put", "--mutable", "--mutable-type="+mutable_type,
-                             fn1, filename)
-            def _dont_fail((rc, out, err)):
-                self.failUnlessEqual(rc, 0)
-            d2.addCallback(_dont_fail)
-            d2.addCallback(lambda ign: self.do_cli("ls", "--json", filename))
+        def _put_and_ls(ign, cmdargs, expected, filename=None):
+            if filename:
+                args = ["put"] + cmdargs + [fn1, filename]
+            else:
+                # unlinked
+                args = ["put"] + cmdargs + [fn1]
+            d2 = self.do_cli(*args)
+            def _list((rc, out, err)):
+                self.failUnlessEqual(rc, 0) # don't allow failure
+                if filename:
+                    return self.do_cli("ls", "--json", filename)
+                else:
+                    cap = out.strip()
+                    return self.do_cli("ls", "--json", cap)
+            d2.addCallback(_list)
             return d2
 
-        d.addCallback(_put_and_ls, "mdmf", "tahoe:uploaded.txt")
-        d.addCallback(self._check_mdmf_json)
-        d.addCallback(_put_and_ls, "MDMF", "tahoe:uploaded2.txt")
-        d.addCallback(self._check_mdmf_json)
-        d.addCallback(_put_and_ls, "sdmf", "tahoe:uploaded3.txt")
+        # 'tahoe put' to a directory
+        d.addCallback(_put_and_ls, ["--mutable"], "SDMF", "tahoe:s1.txt")
+        d.addCallback(self._check_sdmf_json) # backwards-compatibility
+        d.addCallback(_put_and_ls, ["--format=SDMF"], "SDMF", "tahoe:s2.txt")
         d.addCallback(self._check_sdmf_json)
-        d.addCallback(_put_and_ls, "SDMF", "tahoe:uploaded4.txt")
+        d.addCallback(_put_and_ls, ["--format=sdmf"], "SDMF", "tahoe:s3.txt")
+        d.addCallback(self._check_sdmf_json)
+        d.addCallback(_put_and_ls, ["--mutable", "--format=SDMF"], "SDMF", "tahoe:s4.txt")
         d.addCallback(self._check_sdmf_json)
-        return d
 
-    def test_mutable_type_unlinked(self):
-        self.basedir = "cli/Put/mutable_type_unlinked"
-        self.set_up_grid()
-        data = "data" * 100000
-        fn1 = os.path.join(self.basedir, "data")
-        fileutil.write(fn1, data)
-        d = self.do_cli("put", "--mutable", "--mutable-type=mdmf", fn1)
-        d.addCallback(lambda (rc, cap, err):
-            self.do_cli("ls", "--json", cap))
+        d.addCallback(_put_and_ls, ["--format=MDMF"], "MDMF", "tahoe:m1.txt")
         d.addCallback(self._check_mdmf_json)
-        d.addCallback(lambda ignored:
-            self.do_cli("put", "--mutable", "--mutable-type=sdmf", fn1))
-        d.addCallback(lambda (rc, cap, err):
-            self.do_cli("ls", "--json", cap))
+        d.addCallback(_put_and_ls, ["--mutable", "--format=MDMF"], "MDMF", "tahoe:m2.txt")
+        d.addCallback(self._check_mdmf_json)
+
+        d.addCallback(_put_and_ls, ["--format=CHK"], "CHK", "tahoe:c1.txt")
+        d.addCallback(self._check_chk_json)
+        d.addCallback(_put_and_ls, [], "CHK", "tahoe:c1.txt")
+        d.addCallback(self._check_chk_json)
+
+        # 'tahoe put' unlinked
+        d.addCallback(_put_and_ls, ["--mutable"], "SDMF")
+        d.addCallback(self._check_sdmf_json) # backwards-compatibility
+        d.addCallback(_put_and_ls, ["--format=SDMF"], "SDMF")
+        d.addCallback(self._check_sdmf_json)
+        d.addCallback(_put_and_ls, ["--format=sdmf"], "SDMF")
+        d.addCallback(self._check_sdmf_json)
+        d.addCallback(_put_and_ls, ["--mutable", "--format=SDMF"], "SDMF")
         d.addCallback(self._check_sdmf_json)
-        return d
 
-    def test_mutable_type_implies_mutable(self):
-        self.basedir = "cli/Put/mutable_type_implies_mutable"
-        self.set_up_grid()
-        data = "data" * 100000
-        fn1 = os.path.join(self.basedir, "data")
-        fileutil.write(fn1, data)
-        d = self.do_cli("put", "--mutable-type=mdmf", fn1)
-        d.addCallback(lambda (rc, cap, err):
-            self.do_cli("ls", "--json", cap))
-        # This will fail if an immutable file is created instead of a
-        # mutable file.
+        d.addCallback(_put_and_ls, ["--format=MDMF"], "MDMF")
         d.addCallback(self._check_mdmf_json)
-        d.addCallback(lambda ignored:
-            self.do_cli("put", "--mutable-type=sdmf", fn1))
-        d.addCallback(lambda (rc, cap, err):
-            self.do_cli("ls", "--json", cap))
-        d.addCallback(self._check_sdmf_json)
+        d.addCallback(_put_and_ls, ["--mutable", "--format=MDMF"], "MDMF")
+        d.addCallback(self._check_mdmf_json)
+
+        d.addCallback(_put_and_ls, ["--format=CHK"], "CHK")
+        d.addCallback(self._check_chk_json)
+        d.addCallback(_put_and_ls, [], "CHK")
+        d.addCallback(self._check_chk_json)
+
         return d
 
     def test_put_to_mdmf_cap(self):
@@ -1229,7 +1241,7 @@ class Put(GridTestMixin, CLITestMixin, unittest.TestCase):
         data = "data" * 100000
         fn1 = os.path.join(self.basedir, "data")
         fileutil.write(fn1, data)
-        d = self.do_cli("put", "--mutable", "--mutable-type=mdmf", fn1)
+        d = self.do_cli("put", "--format=MDMF", fn1)
         def _got_cap((rc, out, err)):
             self.failUnlessEqual(rc, 0)
             self.cap = out.strip()
@@ -1275,7 +1287,7 @@ class Put(GridTestMixin, CLITestMixin, unittest.TestCase):
         data = "data" * 100000
         fn1 = os.path.join(self.basedir, "data")
         fileutil.write(fn1, data)
-        d = self.do_cli("put", "--mutable", "--mutable-type=sdmf", fn1)
+        d = self.do_cli("put", "--format=SDMF", fn1)
         def _got_cap((rc, out, err)):
             self.failUnlessEqual(rc, 0)
             self.cap = out.strip()
@@ -1303,7 +1315,7 @@ class Put(GridTestMixin, CLITestMixin, unittest.TestCase):
         o = cli.PutOptions()
         self.failUnlessRaises(usage.UsageError,
                               o.parseOptions,
-                              ["--mutable", "--mutable-type=ldmf"])
+                              ["--format=LDMF"])
 
     def test_put_with_nonexistent_alias(self):
         # when invoked with an alias that doesn't exist, 'tahoe put'
@@ -3308,7 +3320,7 @@ class Mkdir(GridTestMixin, CLITestMixin, unittest.TestCase):
             self.failUnlessIn(st, out)
             return out
         def _mkdir(ign, mutable_type, uri_prefix, dirname):
-            d2 = self.do_cli("mkdir", "--mutable-type="+mutable_type, dirname)
+            d2 = self.do_cli("mkdir", "--format="+mutable_type, dirname)
             d2.addCallback(_check, uri_prefix)
             def _stash_filecap(cap):
                 u = uri.from_string(cap)
@@ -3330,7 +3342,7 @@ class Mkdir(GridTestMixin, CLITestMixin, unittest.TestCase):
     def test_mkdir_mutable_type_unlinked(self):
         self.basedir = os.path.dirname(self.mktemp())
         self.set_up_grid()
-        d = self.do_cli("mkdir", "--mutable-type=sdmf")
+        d = self.do_cli("mkdir", "--format=SDMF")
         def _check((rc, out, err), st):
             self.failUnlessReallyEqual(rc, 0)
             self.failUnlessReallyEqual(err, "")
@@ -3349,7 +3361,7 @@ class Mkdir(GridTestMixin, CLITestMixin, unittest.TestCase):
         d.addCallback(lambda res: self.do_cli("ls", "--json",
                                               self._filecap))
         d.addCallback(_check, '"format": "SDMF"')
-        d.addCallback(lambda res: self.do_cli("mkdir", "--mutable-type=mdmf"))
+        d.addCallback(lambda res: self.do_cli("mkdir", "--format=MDMF"))
         d.addCallback(_check, "URI:DIR2-MDMF")
         d.addCallback(_stash_dircap)
         d.addCallback(lambda res: self.do_cli("ls", "--json",
@@ -3361,7 +3373,7 @@ class Mkdir(GridTestMixin, CLITestMixin, unittest.TestCase):
         o = cli.MakeDirectoryOptions()
         self.failUnlessRaises(usage.UsageError,
                               o.parseOptions,
-                              ["--mutable", "--mutable-type=ldmf"])
+                              ["--format=LDMF"])
 
     def test_mkdir_unicode(self):
         self.basedir = os.path.dirname(self.mktemp())
index 639968ddeeceee0fb4d9b587634dad3cd8316b9c..ccf3cad474f991b129cf2520beaddf6e20a601f0 100644 (file)
@@ -1518,7 +1518,7 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase):
         d.addCallback(run, "put", files[1], "subdir/tahoe-file1")
         #  tahoe put bar tahoe:FOO
         d.addCallback(run, "put", files[2], "tahoe:file2")
-        d.addCallback(run, "put", "--mutable", files[3], "tahoe:file3")
+        d.addCallback(run, "put", "--format=SDMF", files[3], "tahoe:file3")
         def _check_put_mutable((out,err)):
             self._mutable_file3_uri = out.strip()
         d.addCallback(_check_put_mutable)