]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/scripts/cli.py
cli: tahoe stats/manifest: change --verbose to --raw, since I want -v for --verify...
[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, get_aliases
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 private/aliases which contains "
15          "the mapping from alias name to root dirnode URI."
16          ],
17         ["node-url", "u", None,
18          "URL of the tahoe node to use, a URL like \"http://127.0.0.1:8123\". "
19          "This overrides the URL found in the --node-directory ."],
20         ["dir-cap", None, None,
21          "Which dirnode URI should be used as the 'tahoe' alias."]
22         ]
23
24     def postOptions(self):
25         # compute a node-url from the existing options, put in self['node-url']
26         if self['node-directory']:
27             if sys.platform == 'win32' and self['node-directory'] == '~/.tahoe':
28                 from allmydata.windows import registry
29                 self['node-directory'] = registry.get_base_dir_path()
30             else:
31                 self['node-directory'] = os.path.expanduser(self['node-directory'])
32         if self['node-url']:
33             if (not isinstance(self['node-url'], basestring)
34                 or not NODEURL_RE.match(self['node-url'])):
35                 msg = ("--node-url is required to be a string and look like "
36                        "\"http://HOSTNAMEORADDR:PORT\", not: %r" %
37                        (self['node-url'],))
38                 raise usage.UsageError(msg)
39         else:
40             node_url_file = os.path.join(self['node-directory'], "node.url")
41             self['node-url'] = open(node_url_file, "r").read().strip()
42
43         aliases = get_aliases(self['node-directory'])
44         if self['dir-cap']:
45             aliases["tahoe"] = self['dir-cap']
46         self.aliases = aliases # maps alias name to dircap
47
48
49 class MakeDirectoryOptions(VDriveOptions):
50     def parseArgs(self, where=""):
51         self.where = where
52     longdesc = """Create a new directory, either unlinked or as a subdirectory."""
53
54 class AddAliasOptions(VDriveOptions):
55     def parseArgs(self, alias, cap):
56         self.alias = alias
57         self.cap = cap
58
59 class CreateAliasOptions(VDriveOptions):
60     def parseArgs(self, alias):
61         self.alias = alias
62
63 class ListAliasOptions(VDriveOptions):
64     pass
65
66 class ListOptions(VDriveOptions):
67     optFlags = [
68         ("long", "l", "Use long format: show file sizes, and timestamps"),
69         ("uri", "u", "Show file/directory URIs"),
70         ("readonly-uri", None, "Show readonly file/directory URIs"),
71         ("classify", "F", "Append '/' to directory names, and '*' to mutable"),
72         ("json", None, "Show the raw JSON output"),
73         ]
74     def parseArgs(self, where=""):
75         self.where = where
76
77     longdesc = """List the contents of some portion of the virtual drive."""
78
79 class GetOptions(VDriveOptions):
80     def parseArgs(self, arg1, arg2=None):
81         # tahoe get FOO |less            # write to stdout
82         # tahoe get tahoe:FOO |less      # same
83         # tahoe get FOO bar              # write to local file
84         # tahoe get tahoe:FOO bar        # same
85
86         self.from_file = arg1
87         self.to_file = arg2
88         if self.to_file == "-":
89             self.to_file = None
90
91     def getSynopsis(self):
92         return "%s get VDRIVE_FILE LOCAL_FILE" % (os.path.basename(sys.argv[0]),)
93
94     longdesc = """Retrieve a file from the virtual drive and write it to the
95     local filesystem. If LOCAL_FILE is omitted or '-', the contents of the file
96     will be written to stdout."""
97
98     def getUsage(self, width=None):
99         t = VDriveOptions.getUsage(self, width)
100         t += """
101 Examples:
102  % tahoe get FOO |less            # write to stdout
103  % tahoe get tahoe:FOO |less      # same
104  % tahoe get FOO bar              # write to local file
105  % tahoe get tahoe:FOO bar        # same
106 """
107         return t
108
109 class PutOptions(VDriveOptions):
110     optFlags = [
111         ("mutable", "m", "Create a mutable file instead of an immutable one."),
112         ]
113
114     def parseArgs(self, arg1=None, arg2=None):
115         # cat FILE > tahoe put           # create unlinked file from stdin
116         # cat FILE > tahoe put -         # same
117         # tahoe put bar                  # create unlinked file from local 'bar'
118         # cat FILE > tahoe put - FOO     # create tahoe:FOO from stdin
119         # tahoe put bar FOO              # copy local 'bar' to tahoe:FOO
120         # tahoe put bar tahoe:FOO        # same
121
122         if arg1 is not None and arg2 is not None:
123             self.from_file = arg1
124             self.to_file = arg2
125         elif arg1 is not None and arg2 is None:
126             self.from_file = arg1 # might be "-"
127             self.to_file = None
128         else:
129             self.from_file = None
130             self.to_file = None
131         if self.from_file == "-":
132             self.from_file = None
133
134     def getSynopsis(self):
135         return "%s put LOCAL_FILE VDRIVE_FILE" % (os.path.basename(sys.argv[0]),)
136
137     longdesc = """Put a file into the virtual drive (copying the file's
138     contents from the local filesystem). If VDRIVE_FILE is missing, upload
139     the file but do not link it into a directory: prints the new filecap to
140     stdout. If LOCAL_FILE is missing or '-', data will be copied from stdin.
141     VDRIVE_FILE is assumed to start with tahoe: unless otherwise specified."""
142
143     def getUsage(self, width=None):
144         t = VDriveOptions.getUsage(self, width)
145         t += """
146 Examples:
147  % cat FILE > tahoe put                # create unlinked file from stdin
148  % cat FILE > tahoe -                  # same
149  % tahoe put bar                       # create unlinked file from local 'bar'
150  % cat FILE > tahoe put - FOO          # create tahoe:FOO from stdin
151  % tahoe put bar FOO                   # copy local 'bar' to tahoe:FOO
152  % tahoe put bar tahoe:FOO             # same
153  % tahoe put bar MUTABLE-FILE-WRITECAP # modify the mutable file in-place
154 """
155         return t
156
157 class CpOptions(VDriveOptions):
158     optFlags = [
159         ("recursive", "r", "Copy source directory recursively."),
160         ("verbose", "v", "Be noisy about what is happening."),
161         ]
162     def parseArgs(self, *args):
163         if len(args) < 2:
164             raise usage.UsageError("cp requires at least two arguments")
165         self.sources = args[:-1]
166         self.destination = args[-1]
167
168 class RmOptions(VDriveOptions):
169     def parseArgs(self, where):
170         self.where = where
171
172     def getSynopsis(self):
173         return "%s rm VE_FILE" % (os.path.basename(sys.argv[0]),)
174
175 class MvOptions(VDriveOptions):
176     def parseArgs(self, frompath, topath):
177         self.from_file = frompath
178         self.to_file = topath
179
180     def getSynopsis(self):
181         return "%s mv FROM TO" % (os.path.basename(sys.argv[0]),)
182
183 class LnOptions(VDriveOptions):
184     def parseArgs(self, frompath, topath):
185         self.from_file = frompath
186         self.to_file = topath
187
188     def getSynopsis(self):
189         return "%s ln FROM TO" % (os.path.basename(sys.argv[0]),)
190
191 class WebopenOptions(VDriveOptions):
192     def parseArgs(self, where=''):
193         self.where = where
194
195     def getSynopsis(self):
196         return "%s webopen [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),)
197
198     longdesc = """Opens a webbrowser to the contents of some portion of the virtual drive."""
199
200 class ManifestOptions(VDriveOptions):
201     optFlags = [
202         ("storage-index", "s", "Only print storage index strings, not pathname+cap"),
203         ]
204     def parseArgs(self, where=''):
205         self.where = where
206
207     def getSynopsis(self):
208         return "%s manifest [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),)
209
210     longdesc = """Print a list of all files/directories reachable from the given starting point."""
211
212 class StatsOptions(VDriveOptions):
213     optFlags = [
214         ("raw", "r", "Display raw JSON data instead of parsed"),
215         ]
216     def parseArgs(self, where=''):
217         self.where = where
218
219     def getSynopsis(self):
220         return "%s stats [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),)
221
222     longdesc = """Print statistics about of all files/directories reachable from the given starting point."""
223
224 subCommands = [
225     ["mkdir", None, MakeDirectoryOptions, "Create a new directory"],
226     ["add-alias", None, AddAliasOptions, "Add a new alias cap"],
227     ["create-alias", None, CreateAliasOptions, "Create a new alias cap"],
228     ["list-aliases", None, ListAliasOptions, "List all alias caps"],
229     ["ls", None, ListOptions, "List a directory"],
230     ["get", None, GetOptions, "Retrieve a file from the virtual drive."],
231     ["put", None, PutOptions, "Upload a file into the virtual drive."],
232     ["cp", None, CpOptions, "Copy one or more files."],
233     ["rm", None, RmOptions, "Unlink a file or directory in the virtual drive."],
234     ["mv", None, MvOptions, "Move a file within the virtual drive."],
235     ["ln", None, LnOptions, "Make an additional link to an existing file."],
236     ["webopen", None, WebopenOptions, "Open a webbrowser to the root_dir"],
237     ["manifest", None, ManifestOptions, "List all files/dirs in a subtree"],
238     ["stats", None, StatsOptions, "Print statistics about all files/dirs in a subtree"],
239     ]
240
241 def mkdir(options):
242     from allmydata.scripts import tahoe_mkdir
243     rc = tahoe_mkdir.mkdir(options)
244     return rc
245
246 def add_alias(options):
247     from allmydata.scripts import tahoe_add_alias
248     rc = tahoe_add_alias.add_alias(options)
249     return rc
250
251 def create_alias(options):
252     from allmydata.scripts import tahoe_add_alias
253     rc = tahoe_add_alias.create_alias(options)
254     return rc
255
256 def list_aliases(options):
257     from allmydata.scripts import tahoe_add_alias
258     rc = tahoe_add_alias.list_aliases(options)
259     return rc
260
261 def list(options):
262     from allmydata.scripts import tahoe_ls
263     rc = tahoe_ls.list(options)
264     return rc
265
266 def get(options):
267     from allmydata.scripts import tahoe_get
268     rc = tahoe_get.get(options)
269     if rc == 0:
270         if options.to_file is None:
271             # be quiet, since the file being written to stdout should be
272             # proof enough that it worked, unless the user is unlucky
273             # enough to have picked an empty file
274             pass
275         else:
276             print >>options.stderr, "%s retrieved and written to %s" % \
277                   (options.from_file, options.to_file)
278     return rc
279
280 def put(options):
281     from allmydata.scripts import tahoe_put
282     rc = tahoe_put.put(options)
283     return rc
284
285 def cp(options):
286     from allmydata.scripts import tahoe_cp
287     rc = tahoe_cp.copy(options)
288     return rc
289
290 def rm(options):
291     from allmydata.scripts import tahoe_rm
292     rc = tahoe_rm.rm(options)
293     return rc
294
295 def mv(options):
296     from allmydata.scripts import tahoe_mv
297     rc = tahoe_mv.mv(options, mode="move")
298     return rc
299
300 def ln(options):
301     from allmydata.scripts import tahoe_mv
302     rc = tahoe_mv.mv(options, mode="link")
303     return rc
304
305 def webopen(options, opener=None):
306     from allmydata.scripts import tahoe_webopen
307     rc = tahoe_webopen.webopen(options, opener=opener)
308     return rc
309
310 def manifest(options):
311     from allmydata.scripts import tahoe_manifest
312     rc = tahoe_manifest.manifest(options)
313     return rc
314
315 def stats(options):
316     from allmydata.scripts import tahoe_manifest
317     rc = tahoe_manifest.stats(options)
318     return rc
319
320 dispatch = {
321     "mkdir": mkdir,
322     "add-alias": add_alias,
323     "create-alias": create_alias,
324     "list-aliases": list_aliases,
325     "ls": list,
326     "get": get,
327     "put": put,
328     "cp": cp,
329     "rm": rm,
330     "mv": mv,
331     "ln": ln,
332     "webopen": webopen,
333     "manifest": manifest,
334     "stats": stats,
335     }
336