]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/scripts/cli.py
cli: add test coverage
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / scripts / cli.py
1
2 import os.path, re, sys
3 from twisted.python import usage
4 from allmydata.scripts.common import BaseOptions
5
6 NODEURL_RE=re.compile("http://([^:]*)(:([1-9][0-9]*))?")
7
8 class VDriveOptions(BaseOptions, usage.Options):
9     optParameters = [
10         ["node-directory", "d", "~/.tahoe",
11          "Look here to find out which Tahoe node should be used for all "
12          "operations. The directory should either contain a full Tahoe node, "
13          "or a file named node.url which points to some other Tahoe node. "
14          "It should also contain a file named my_vdrive.uri which contains "
15          "the root dirnode URI that should be used, and a file named "
16          "global_root.uri which contains the public global root dirnode URI."
17          ],
18         ["node-url", "u", None,
19          "URL of the tahoe node to use, a URL like \"http://127.0.0.1:8123\". "
20          "This overrides the URL found in the --node-directory ."],
21         ["root-uri", "r", "private",
22          "Which dirnode URI should be used as a root directory. The string "
23          "'public' is special, and means we should use the public global root "
24          "as found in the global_root.uri file in the --node-directory . The "
25          "string 'private' is also special, and means we should use the "
26          "private vdrive as found in the my_vdrive.uri file in the "
27          "--node-directory ."],
28         ]
29
30     def postOptions(self):
31         # compute a node-url from the existing options, put in self['node-url']
32         if self['node-directory']:
33             self['node-directory'] = os.path.expanduser(self['node-directory'])
34         if self['node-url']:
35             if (not isinstance(self['node-url'], basestring)
36                 or not NODEURL_RE.match(self['node-url'])):
37                 msg = ("--node-url is required to be a string and look like "
38                        "\"http://HOSTNAMEORADDR:PORT\", not: %r" %
39                        (self['node-url'],))
40                 raise usage.UsageError(msg)
41         else:
42             node_url_file = os.path.join(self['node-directory'], "node.url")
43             self['node-url'] = open(node_url_file, "r").read().strip()
44
45         # also compute self['root-uri']
46         if self['root-uri'] == "private":
47             uri_file = os.path.join(self['node-directory'], "my_vdrive.uri")
48             self['root-uri'] = open(uri_file, "r").read().strip()
49         elif self['root-uri'] == "public":
50             uri_file = os.path.join(self['node-directory'], "global_root.uri")
51             self['root-uri'] = open(uri_file, "r").read().strip()
52         else:
53             from allmydata import uri
54             parsed = uri.from_string(self['root-uri'])
55             if not uri.IDirnodeURI.providedBy(parsed):
56                 raise usage.UsageError("--root-uri must be a dirnode URI, or "
57                                        "'public' or 'private'")
58
59
60 class ListOptions(VDriveOptions):
61     def parseArgs(self, vdrive_pathname=""):
62         self['vdrive_pathname'] = vdrive_pathname
63
64     longdesc = """List the contents of some portion of the virtual drive."""
65
66 class GetOptions(VDriveOptions):
67     def parseArgs(self, vdrive_filename, local_filename="-"):
68         self['vdrive_filename'] = vdrive_filename
69         self['local_filename'] = local_filename
70
71     def getSynopsis(self):
72         return "%s get VDRIVE_FILE LOCAL_FILE" % (os.path.basename(sys.argv[0]),)
73
74     longdesc = """Retrieve a file from the virtual drive and write it to the
75     local filesystem. If LOCAL_FILE is omitted or '-', the contents of the file
76     will be written to stdout."""
77
78 class PutOptions(VDriveOptions):
79     def parseArgs(self, local_filename, vdrive_filename):
80         self['local_filename'] = local_filename
81         self['vdrive_filename'] = vdrive_filename
82
83     def getSynopsis(self):
84         return "%s put LOCAL_FILE VDRIVE_FILE" % (os.path.basename(sys.argv[0]),)
85
86     longdesc = """Put a file into the virtual drive (copying the file's
87     contents from the local filesystem). LOCAL_FILE is required to be a
88     local file (it can't be stdin)."""
89
90 class RmOptions(VDriveOptions):
91     def parseArgs(self, vdrive_pathname):
92         self['vdrive_pathname'] = vdrive_pathname
93
94     def getSynopsis(self):
95         return "%s rm VE_FILE" % (os.path.basename(sys.argv[0]),)
96
97
98 subCommands = [
99     ["ls", None, ListOptions, "List a directory"],
100     ["get", None, GetOptions, "Retrieve a file from the virtual drive."],
101     ["put", None, PutOptions, "Upload a file into the virtual drive."],
102     ["rm", None, RmOptions, "Unlink a file or directory in the virtual drive."],
103     ]
104
105 def list(config, stdout, stderr):
106     from allmydata.scripts import tahoe_ls
107     rc = tahoe_ls.list(config['node-url'],
108                        config['root-uri'],
109                        config['vdrive_pathname'],
110                        stdout, stderr)
111     return rc
112
113 def get(config, stdout, stderr):
114     from allmydata.scripts import tahoe_get
115     vdrive_filename = config['vdrive_filename']
116     local_filename = config['local_filename']
117     rc = tahoe_get.get(config['node-url'],
118                        config['root-uri'],
119                        vdrive_filename,
120                        local_filename,
121                        stdout, stderr)
122     if rc == 0:
123         if local_filename is None or local_filename == "-":
124             # be quiet, since the file being written to stdout should be
125             # proof enough that it worked, unless the user is unlucky
126             # enough to have picked an empty file
127             pass
128         else:
129             print >>stderr, "%s retrieved and written to %s" % \
130                   (vdrive_filename, local_filename)
131     return rc
132
133 def put(config, stdout, stderr):
134     from allmydata.scripts import tahoe_put
135     vdrive_filename = config['vdrive_filename']
136     local_filename = config['local_filename']
137     if config['quiet']:
138         verbosity = 0
139     else:
140         verbosity = 2
141     rc = tahoe_put.put(config['node-url'],
142                        config['root-uri'],
143                        local_filename,
144                        vdrive_filename,
145                        verbosity,
146                        stdout, stderr)
147     return rc
148
149 def rm(config, stdout, stderr):
150     from allmydata.scripts import tahoe_rm
151     vdrive_pathname = config['vdrive_pathname']
152     if config['quiet']:
153         verbosity = 0
154     else:
155         verbosity = 2
156     rc = tahoe_rm.rm(config['node-url'],
157                      config['root-uri'],
158                      vdrive_pathname,
159                      verbosity,
160                      stdout, stderr)
161     return rc
162
163 dispatch = {
164     "ls": list,
165     "get": get,
166     "put": put,
167     "rm": rm,
168     }
169