]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/scripts/runner.py
Magic Folder.
[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, \
9     admin, magic_folder_cli
10 from allmydata.util.encodingutil import quote_output, quote_local_unicode_path, get_io_encoding
11
12 def GROUP(s):
13     # Usage.parseOptions compares argv[1] against command[0], so it will
14     # effectively ignore any "subcommand" that starts with a newline. We use
15     # these to insert section headers into the --help output.
16     return [("\n(%s)" % s, None, None, None)]
17
18
19 _default_nodedir = get_default_nodedir()
20
21 NODEDIR_HELP = ("Specify which Tahoe node directory should be used. The "
22                 "directory should either contain a full Tahoe node, or a "
23                 "file named node.url that points to some other Tahoe node. "
24                 "It should also contain a file named '"
25                 + os.path.join('private', 'aliases') +
26                 "' which contains the mapping from alias name to root "
27                 "dirnode URI.")
28 if _default_nodedir:
29     NODEDIR_HELP += " [default for most commands: " + quote_local_unicode_path(_default_nodedir) + "]"
30
31 class Options(usage.Options):
32     # unit tests can override these to point at StringIO instances
33     stdin = sys.stdin
34     stdout = sys.stdout
35     stderr = sys.stderr
36
37     synopsis = "\nUsage:  tahoe <command> [command options]"
38     subCommands = ( GROUP("Administration")
39                     +   create_node.subCommands
40                     +   keygen.subCommands
41                     +   stats_gatherer.subCommands
42                     +   admin.subCommands
43                     + GROUP("Controlling a node")
44                     +   startstop_node.subCommands
45                     + GROUP("Debugging")
46                     +   debug.subCommands
47                     + GROUP("Using the filesystem")
48                     +   cli.subCommands
49                     +   magic_folder_cli.subCommands
50                     )
51
52     optFlags = [
53         ["quiet", "q", "Operate silently."],
54         ["version", "V", "Display version numbers."],
55         ["version-and-path", None, "Display version numbers and paths to their locations."],
56     ]
57     optParameters = [
58         ["node-directory", "d", None, NODEDIR_HELP],
59     ]
60
61     def opt_version(self):
62         import allmydata
63         print >>self.stdout, allmydata.get_package_versions_string(debug=True)
64         self.no_command_needed = True
65
66     def opt_version_and_path(self):
67         import allmydata
68         print >>self.stdout, allmydata.get_package_versions_string(show_paths=True, debug=True)
69         self.no_command_needed = True
70
71     def __str__(self):
72         return ("\nUsage: tahoe [global-options] <command> [command-options]\n"
73                 + self.getUsage())
74
75     synopsis = "\nUsage: tahoe [global-options]" # used only for subcommands
76
77     def getUsage(self, **kwargs):
78         t = usage.Options.getUsage(self, **kwargs)
79         t = t.replace("Options:", "\nGlobal options:", 1)
80         return t + "\nPlease run 'tahoe <command> --help' for more details on each command.\n"
81
82     def postOptions(self):
83         if not hasattr(self, 'subOptions'):
84             if not hasattr(self, 'no_command_needed'):
85                 raise usage.UsageError("must specify a command")
86             sys.exit(0)
87
88
89 create_dispatch = {}
90 for module in (create_node, keygen, stats_gatherer):
91     create_dispatch.update(module.dispatch)
92
93 def runner(argv,
94            run_by_human=True,
95            stdin=None, stdout=None, stderr=None,
96            install_node_control=True, additional_commands=None):
97
98     stdin  = stdin  or sys.stdin
99     stdout = stdout or sys.stdout
100     stderr = stderr or sys.stderr
101
102     config = Options()
103     if install_node_control:
104         config.subCommands.extend(startstop_node.subCommands)
105
106     ac_dispatch = {}
107     if additional_commands:
108         for ac in additional_commands:
109             config.subCommands.extend(ac.subCommands)
110             ac_dispatch.update(ac.dispatch)
111
112     try:
113         config.parseOptions(argv)
114     except usage.error, e:
115         if not run_by_human:
116             raise
117         c = config
118         while hasattr(c, 'subOptions'):
119             c = c.subOptions
120         print >>stdout, str(c)
121         try:
122             msg = e.args[0].decode(get_io_encoding())
123         except Exception:
124             msg = repr(e)
125         print >>stdout, "%s:  %s\n" % (sys.argv[0], quote_output(msg, quotemarks=False))
126         return 1
127
128     command = config.subCommand
129     so = config.subOptions
130
131     if config['quiet']:
132         stdout = StringIO()
133
134     so.stdout = stdout
135     so.stderr = stderr
136     so.stdin = stdin
137
138     if command in create_dispatch:
139         rc = create_dispatch[command](so, stdout, stderr)
140     elif command in startstop_node.dispatch:
141         rc = startstop_node.dispatch[command](so, stdout, stderr)
142     elif command in debug.dispatch:
143         rc = debug.dispatch[command](so)
144     elif command in admin.dispatch:
145         rc = admin.dispatch[command](so)
146     elif command in cli.dispatch:
147         rc = cli.dispatch[command](so)
148     elif command in magic_folder_cli.dispatch:
149         rc = magic_folder_cli.dispatch[command](so)
150     elif command in ac_dispatch:
151         rc = ac_dispatch[command](so, stdout, stderr)
152     else:
153         raise usage.UsageError()
154
155     return rc
156
157
158 def run(install_node_control=True):
159     try:
160         if sys.platform == "win32":
161             from allmydata.windows.fixups import initialize
162             initialize()
163
164         rc = runner(sys.argv[1:], install_node_control=install_node_control)
165     except Exception:
166         import traceback
167         traceback.print_exc()
168         rc = 1
169
170     sys.exit(rc)