]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/scripts/runner.py
4767e59e067138d1ae6436249c980ae8c452b3f1
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / scripts / runner.py
1
2 import os, sys
3 from cStringIO import StringIO
4
5 from twisted.python import usage
6
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
10
11 def GROUP(s):
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)]
16
17
18 _default_nodedir = get_default_nodedir()
19
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 "
26                 "dirnode URI.")
27 if _default_nodedir:
28     NODEDIR_HELP += " [default for most commands: " + quote_local_unicode_path(_default_nodedir) + "]"
29
30 class Options(usage.Options):
31     # unit tests can override these to point at StringIO instances
32     stdin = sys.stdin
33     stdout = sys.stdout
34     stderr = sys.stderr
35
36     synopsis = "\nUsage:  tahoe <command> [command options]"
37     subCommands = ( GROUP("Administration")
38                     +   create_node.subCommands
39                     +   keygen.subCommands
40                     +   stats_gatherer.subCommands
41                     +   admin.subCommands
42                     + GROUP("Controlling a node")
43                     +   startstop_node.subCommands
44                     + GROUP("Debugging")
45                     +   debug.subCommands
46                     + GROUP("Using the filesystem")
47                     +   cli.subCommands
48                     )
49
50     optFlags = [
51         ["quiet", "q", "Operate silently."],
52         ["version", "V", "Display version numbers."],
53         ["version-and-path", None, "Display version numbers and paths to their locations."],
54     ]
55     optParameters = [
56         ["node-directory", "d", None, NODEDIR_HELP],
57     ]
58
59     def opt_version(self):
60         import allmydata
61         print >>self.stdout, allmydata.get_package_versions_string(debug=True)
62         self.no_command_needed = True
63
64     def opt_version_and_path(self):
65         import allmydata
66         print >>self.stdout, allmydata.get_package_versions_string(show_paths=True, debug=True)
67         self.no_command_needed = True
68
69     def __str__(self):
70         return ("\nUsage: tahoe [global-options] <command> [command-options]\n"
71                 + self.getUsage())
72
73     synopsis = "\nUsage: tahoe [global-opts]" # used only for subcommands
74
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"
79
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")
84             sys.exit(0)
85
86
87 create_dispatch = {}
88 for module in (create_node, keygen, stats_gatherer):
89     create_dispatch.update(module.dispatch)
90
91 def runner(argv,
92            run_by_human=True,
93            stdin=None, stdout=None, stderr=None,
94            install_node_control=True, additional_commands=None):
95
96     stdin  = stdin  or sys.stdin
97     stdout = stdout or sys.stdout
98     stderr = stderr or sys.stderr
99
100     config = Options()
101     if install_node_control:
102         config.subCommands.extend(startstop_node.subCommands)
103
104     ac_dispatch = {}
105     if additional_commands:
106         for ac in additional_commands:
107             config.subCommands.extend(ac.subCommands)
108             ac_dispatch.update(ac.dispatch)
109
110     try:
111         config.parseOptions(argv)
112     except usage.error, e:
113         if not run_by_human:
114             raise
115         c = config
116         while hasattr(c, 'subOptions'):
117             c = c.subOptions
118         print >>stdout, str(c)
119         try:
120             msg = e.args[0].decode(get_io_encoding())
121         except Exception:
122             msg = repr(e)
123         print >>stdout, "%s:  %s\n" % (sys.argv[0], quote_output(msg, quotemarks=False))
124         return 1
125
126     command = config.subCommand
127     so = config.subOptions
128
129     if config['quiet']:
130         stdout = StringIO()
131
132     so.stdout = stdout
133     so.stderr = stderr
134     so.stdin = stdin
135
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)
148     else:
149         raise usage.UsageError()
150
151     return rc
152
153
154 def run(install_node_control=True):
155     try:
156         if sys.platform == "win32":
157             from allmydata.windows.fixups import initialize
158             initialize()
159
160         rc = runner(sys.argv[1:], install_node_control=install_node_control)
161     except Exception:
162         import traceback
163         traceback.print_exc()
164         rc = 1
165
166     sys.exit(rc)