3 from cStringIO import StringIO
5 from twisted.python import usage
7 from allmydata.scripts.common import get_default_nodedir
8 from allmydata.scripts import debug, create_node, startstop_node, cli, keygen, stats_gatherer, admin
9 from allmydata.util.encodingutil import quote_output, quote_local_unicode_path, get_io_encoding
12 # Usage.parseOptions compares argv[1] against command[0], so it will
13 # effectively ignore any "subcommand" that starts with a newline. We use
14 # these to insert section headers into the --help output.
15 return [("\n(%s)" % s, None, None, None)]
18 _default_nodedir = get_default_nodedir()
20 NODEDIR_HELP = ("Specify which Tahoe node directory should be used. The "
21 "directory should either contain a full Tahoe node, or a "
22 "file named node.url that points to some other Tahoe node. "
23 "It should also contain a file named '"
24 + os.path.join('private', 'aliases') +
25 "' which contains the mapping from alias name to root "
28 NODEDIR_HELP += " [default for most commands: " + quote_local_unicode_path(_default_nodedir) + "]"
30 class Options(usage.Options):
31 # unit tests can override these to point at StringIO instances
36 synopsis = "\nUsage: tahoe <command> [command options]"
37 subCommands = ( GROUP("Administration")
38 + create_node.subCommands
40 + stats_gatherer.subCommands
42 + GROUP("Controlling a node")
43 + startstop_node.subCommands
46 + GROUP("Using the filesystem")
51 ["quiet", "q", "Operate silently."],
52 ["version", "V", "Display version numbers."],
53 ["version-and-path", None, "Display version numbers and paths to their locations."],
56 ["node-directory", "d", None, NODEDIR_HELP],
59 def opt_version(self):
61 print >>self.stdout, allmydata.get_package_versions_string(debug=True)
62 self.no_command_needed = True
64 def opt_version_and_path(self):
66 print >>self.stdout, allmydata.get_package_versions_string(show_paths=True, debug=True)
67 self.no_command_needed = True
70 return ("\nUsage: tahoe [global-options] <command> [command-options]\n"
73 synopsis = "\nUsage: tahoe [global-options]" # used only for subcommands
75 def getUsage(self, **kwargs):
76 t = usage.Options.getUsage(self, **kwargs)
77 t = t.replace("Options:", "\nGlobal options:", 1)
78 return t + "\nPlease run 'tahoe <command> --help' for more details on each command.\n"
80 def postOptions(self):
81 if not hasattr(self, 'subOptions'):
82 if not hasattr(self, 'no_command_needed'):
83 raise usage.UsageError("must specify a command")
88 for module in (create_node, keygen, stats_gatherer):
89 create_dispatch.update(module.dispatch)
93 stdin=None, stdout=None, stderr=None,
94 install_node_control=True, additional_commands=None):
96 stdin = stdin or sys.stdin
97 stdout = stdout or sys.stdout
98 stderr = stderr or sys.stderr
101 if install_node_control:
102 config.subCommands.extend(startstop_node.subCommands)
105 if additional_commands:
106 for ac in additional_commands:
107 config.subCommands.extend(ac.subCommands)
108 ac_dispatch.update(ac.dispatch)
111 config.parseOptions(argv)
112 except usage.error, e:
116 while hasattr(c, 'subOptions'):
118 print >>stdout, str(c)
120 msg = e.args[0].decode(get_io_encoding())
123 print >>stdout, "%s: %s\n" % (sys.argv[0], quote_output(msg, quotemarks=False))
126 command = config.subCommand
127 so = config.subOptions
136 if command in create_dispatch:
137 rc = create_dispatch[command](so, stdout, stderr)
138 elif command in startstop_node.dispatch:
139 rc = startstop_node.dispatch[command](so, stdout, stderr)
140 elif command in debug.dispatch:
141 rc = debug.dispatch[command](so)
142 elif command in admin.dispatch:
143 rc = admin.dispatch[command](so)
144 elif command in cli.dispatch:
145 rc = cli.dispatch[command](so)
146 elif command in ac_dispatch:
147 rc = ac_dispatch[command](so, stdout, stderr)
149 raise usage.UsageError()
154 def run(install_node_control=True):
156 if sys.platform == "win32":
157 from allmydata.windows.fixups import initialize
160 rc = runner(sys.argv[1:], install_node_control=install_node_control)
163 traceback.print_exc()