source file: /home/buildslave/tahoe/edgy/build/src/allmydata/scripts/cli.py
file stats: 157 lines, 139 executed: 88.5% covered
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. subCommands = [
201. ["mkdir", None, MakeDirectoryOptions, "Create a new directory"],
202. ["add-alias", None, AddAliasOptions, "Add a new alias cap"],
203. ["create-alias", None, CreateAliasOptions, "Create a new alias cap"],
204. ["list-aliases", None, ListAliasOptions, "List all alias caps"],
205. ["ls", None, ListOptions, "List a directory"],
206. ["get", None, GetOptions, "Retrieve a file from the virtual drive."],
207. ["put", None, PutOptions, "Upload a file into the virtual drive."],
208. ["cp", None, CpOptions, "Copy one or more files."],
209. ["rm", None, RmOptions, "Unlink a file or directory in the virtual drive."],
210. ["mv", None, MvOptions, "Move a file within the virtual drive."],
211. ["ln", None, LnOptions, "Make an additional link to an existing file."],
212. ["webopen", None, WebopenOptions, "Open a webbrowser to the root_dir"],
213. ]
214.
215. def mkdir(options):
216. from allmydata.scripts import tahoe_mkdir
217. rc = tahoe_mkdir.mkdir(options)
218. return rc
219.
220. def add_alias(options):
221. from allmydata.scripts import tahoe_add_alias
222. rc = tahoe_add_alias.add_alias(options)
223. return rc
224.
225. def create_alias(options):
226. from allmydata.scripts import tahoe_add_alias
227. rc = tahoe_add_alias.create_alias(options)
228. return rc
229.
230. def list_aliases(options):
231. from allmydata.scripts import tahoe_add_alias
232. rc = tahoe_add_alias.list_aliases(options)
233. return rc
234.
235. def list(options):
236. from allmydata.scripts import tahoe_ls
237. rc = tahoe_ls.list(options)
238. return rc
239.
240. def get(options):
241. from allmydata.scripts import tahoe_get
242. rc = tahoe_get.get(options)
243. if rc == 0:
244. if options.to_file is None:
245. # be quiet, since the file being written to stdout should be
246. # proof enough that it worked, unless the user is unlucky
247. # enough to have picked an empty file
248. pass
249. else:
250. print >>options.stderr, "%s retrieved and written to %s" % \
251. (options.from_file, options.to_file)
252. return rc
253.
254. def put(options):
255. from allmydata.scripts import tahoe_put
256. rc = tahoe_put.put(options)
257. return rc
258.
259. def cp(options):
260. from allmydata.scripts import tahoe_cp
261. rc = tahoe_cp.copy(options)
262. return rc
263.
264. def rm(options):
265. from allmydata.scripts import tahoe_rm
266. rc = tahoe_rm.rm(options)
267. return rc
268.
269. def mv(options):
270. from allmydata.scripts import tahoe_mv
271. rc = tahoe_mv.mv(options, mode="move")
272. return rc
273.
274. def ln(options):
275. from allmydata.scripts import tahoe_mv
276. rc = tahoe_mv.mv(options, mode="link")
277. return rc
278.
279. def webopen(options, opener=None):
280. from allmydata.scripts import tahoe_webopen
281. rc = tahoe_webopen.webopen(options, opener=opener)
282. return rc
283.
284. dispatch = {
285. "mkdir": mkdir,
286. "add-alias": add_alias,
287. "create-alias": create_alias,
288. "list-aliases": list_aliases,
289. "ls": list,
290. "get": get,
291. "put": put,
292. "cp": cp,
293. "rm": rm,
294. "mv": mv,
295. "ln": ln,
296. "webopen": webopen,
297. }
298.