]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blobdiff - src/allmydata/scripts/runner.py
CLI: put "[global-opts]" in all command synopses
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / scripts / runner.py
index 1da7059af6dc95d454246d0e3611d8920cd30048..085967079d7842102a2ca3151ab22af3455549a9 100644 (file)
@@ -1,16 +1,12 @@
 
-import sys
+import os, sys
 from cStringIO import StringIO
 
-import pkg_resources
-pkg_resources.require('twisted')
 from twisted.python import usage
 
-import allmydata
-pkg_resources.require(allmydata.__appname__)
-from allmydata.scripts.common import BaseOptions
-from allmydata.scripts import debug, create_node, startstop_node, cli, keygen, stats_gatherer
-from allmydata.util.encodingutil import quote_output, get_argv_encoding
+from allmydata.scripts.common import get_default_nodedir
+from allmydata.scripts import debug, create_node, startstop_node, cli, keygen, stats_gatherer, admin
+from allmydata.util.encodingutil import quote_output, get_io_encoding
 
 def GROUP(s):
     # Usage.parseOptions compares argv[1] against command[0], so it will
@@ -19,12 +15,30 @@ def GROUP(s):
     return [("\n" + s, None, None, None)]
 
 
-class Options(BaseOptions, usage.Options):
+_default_nodedir = get_default_nodedir()
+
+NODEDIR_HELP = ("Specify which Tahoe node directory should be used. The "
+                "directory should either contain a full Tahoe node, or a "
+                "file named node.url that points to some other Tahoe node. "
+                "It should also contain a file named '"
+                + os.path.join('private', 'aliases') +
+                "' which contains the mapping from alias name to root "
+                "dirnode URI.")
+if _default_nodedir:
+    NODEDIR_HELP += " [default for most commands: " + quote_output(_default_nodedir) + "]"
+
+class Options(usage.Options):
+    # unit tests can override these to point at StringIO instances
+    stdin = sys.stdin
+    stdout = sys.stdout
+    stderr = sys.stderr
+
     synopsis = "\nUsage:  tahoe <command> [command options]"
     subCommands = ( GROUP("Administration")
                     +   create_node.subCommands
                     +   keygen.subCommands
                     +   stats_gatherer.subCommands
+                    +   admin.subCommands
                     + GROUP("Controlling a node")
                     +   startstop_node.subCommands
                     + GROUP("Debugging")
@@ -33,13 +47,42 @@ class Options(BaseOptions, usage.Options):
                     +   cli.subCommands
                     )
 
+    optFlags = [
+        ["quiet", "q", "Operate silently."],
+        ["version", "V", "Display version numbers."],
+        ["version-and-path", None, "Display version numbers and paths to their locations."],
+    ]
+    optParameters = [
+        ["node-directory", "d", None, NODEDIR_HELP],
+    ]
+
+    def opt_version(self):
+        import allmydata
+        print >>self.stdout, allmydata.get_package_versions_string(debug=True)
+        self.no_command_needed = True
+
+    def opt_version_and_path(self):
+        import allmydata
+        print >>self.stdout, allmydata.get_package_versions_string(show_paths=True, debug=True)
+        self.no_command_needed = True
+
+    def getSynopsis(self):
+        return "\nUsage: tahoe [global-opts] <command> [command-options]"
+
     def getUsage(self, **kwargs):
         t = usage.Options.getUsage(self, **kwargs)
         return t + "\nPlease run 'tahoe <command> --help' for more details on each command.\n"
 
     def postOptions(self):
         if not hasattr(self, 'subOptions'):
-            raise usage.UsageError("must specify a command")
+            if not hasattr(self, 'no_command_needed'):
+                raise usage.UsageError("must specify a command")
+            sys.exit(0)
+
+
+create_dispatch = {}
+for module in (create_node, keygen, stats_gatherer):
+    create_dispatch.update(module.dispatch)
 
 def runner(argv,
            run_by_human=True,
@@ -70,7 +113,7 @@ def runner(argv,
             c = c.subOptions
         print >>stdout, str(c)
         try:
-            msg = e.args[0].decode(get_argv_encoding())
+            msg = e.args[0].decode(get_io_encoding())
         except Exception:
             msg = repr(e)
         print >>stdout, "%s:  %s\n" % (sys.argv[0], quote_output(msg, quotemarks=False))
@@ -86,21 +129,16 @@ def runner(argv,
     so.stderr = stderr
     so.stdin = stdin
 
-    rc = 0
-    if command in create_node.dispatch:
-        for basedir in so.basedirs:
-            f = create_node.dispatch[command]
-            rc = f(basedir, so, stdout, stderr) or rc
+    if command in create_dispatch:
+        rc = create_dispatch[command](so, stdout, stderr)
     elif command in startstop_node.dispatch:
         rc = startstop_node.dispatch[command](so, stdout, stderr)
     elif command in debug.dispatch:
         rc = debug.dispatch[command](so)
+    elif command in admin.dispatch:
+        rc = admin.dispatch[command](so)
     elif command in cli.dispatch:
         rc = cli.dispatch[command](so)
-    elif command in keygen.dispatch:
-        rc = keygen.dispatch[command](so, stdout, stderr)
-    elif command in stats_gatherer.dispatch:
-        rc = stats_gatherer.dispatch[command](so)
     elif command in ac_dispatch:
         rc = ac_dispatch[command](so, stdout, stderr)
     else:
@@ -110,9 +148,15 @@ def runner(argv,
 
 
 def run(install_node_control=True):
-    if sys.platform == "win32":
-        from allmydata.windows.fixups import initialize
-        initialize()
+    try:
+        if sys.platform == "win32":
+            from allmydata.windows.fixups import initialize
+            initialize()
+
+        rc = runner(sys.argv[1:], install_node_control=install_node_control)
+    except Exception:
+        import traceback
+        traceback.print_exc()
+        rc = 1
 
-    rc = runner(sys.argv[1:], install_node_control=install_node_control)
     sys.exit(rc)