command-line: add "rm", and tidy-up variable names, and make it so "allmydata-tahoe spam" prints a usage message instead of returning silently

This commit is contained in:
Zooko O'Whielacronx 2007-08-17 13:23:16 -07:00
parent e554962ac3
commit a12ef1ae82
7 changed files with 125 additions and 24 deletions

View File

@ -104,10 +104,11 @@ available there, with download links, and forms to upload new files.
USAGE - command-line interface
Run "allmydata-tahoe ls [VIRTUAL DIRECTORY NAME]" to list the contents
of a virtual directory. Run "allmydata-tahoe get [VIRTUAL FILE NAME]
[LOCAL FILE NAME]" to download a file. Run "allmydata-tahoe put
[LOCAL FILE NAME] [VIRTUAL FILE NAME]" to upload a file.
Run "allmydata-tahoe ls [VIRTUAL PATH NAME]" to list the contents of a
virtual directory. Run "allmydata-tahoe get [VIRTUAL FILE NAME] [LOCAL FILE
NAME]" to download a file. Run "allmydata-tahoe put [LOCAL FILE NAME]
[VIRTUAL FILE NAME]" to upload a file. Run "allmydata-tahoe rm [VIRTUAL PATH
NAME]" to unlink a file or directory in the virtual drive.
USAGE - other

View File

@ -19,8 +19,8 @@ class VDriveOptions(BaseOptions, usage.Options):
raise usage.UsageError("--node-url is required to be a string and look like \"http://HOSTNAMEORADDR:PORT\", not: %r" % (self['node-url'],))
class ListOptions(VDriveOptions):
def parseArgs(self, vdrive_filename=""):
self['vdrive_filename'] = vdrive_filename
def parseArgs(self, vdrive_pathname=""):
self['vdrive_pathname'] = vdrive_pathname
longdesc = """List the contents of some portion of the virtual drive."""
@ -38,8 +38,8 @@ class GetOptions(VDriveOptions):
class PutOptions(VDriveOptions):
def parseArgs(self, local_filename, vdrive_filename):
self['vdrive_filename'] = vdrive_filename
self['local_filename'] = local_filename
self['vdrive_filename'] = vdrive_filename
def getSynopsis(self):
return "%s put LOCAL_FILEVDRI VE_FILE" % (os.path.basename(sys.argv[0]),)
@ -48,19 +48,26 @@ class PutOptions(VDriveOptions):
contents from the local filesystem). If LOCAL_FILE is omitted or '-', the
contents of the file will be read from stdin."""
class RmOptions(VDriveOptions):
def parseArgs(self, vdrive_pathname):
self['vdrive_pathname'] = vdrive_pathname
def getSynopsis(self):
return "%s rm VE_FILE" % (os.path.basename(sys.argv[0]),)
subCommands = [
["ls", None, ListOptions, "List a directory"],
["get", None, GetOptions, "Retrieve a file from the virtual drive."],
["put", None, PutOptions, "Upload a file into the virtual drive."],
["rm", None, RmOptions, "Unlink a file or directory in the virtual drive."],
]
def list(config, stdout, stderr):
from allmydata.scripts import tahoe_ls
rc = tahoe_ls.list(config['node-url'],
config['vdrive'],
config['vdrive_filename'])
config['vdrive_pathname'])
return rc
def get(config, stdout, stderr):
@ -92,8 +99,21 @@ def put(config, stdout, stderr):
verbosity = 2
rc = tahoe_put.put(config['node-url'],
config['vdrive'],
vdrive_filename,
local_filename,
vdrive_filename,
verbosity)
return rc
def rm(config, stdout, stderr):
from allmydata.scripts import tahoe_rm
vdrive_pathname = config['vdrive_pathname']
if config['quiet']:
verbosity = 0
else:
verbosity = 2
rc = tahoe_rm.rm(config['node-url'],
config['vdrive'],
vdrive_pathname,
verbosity)
return rc
@ -101,5 +121,6 @@ dispatch = {
"ls": list,
"get": get,
"put": put,
"rm": rm,
}

View File

@ -49,6 +49,8 @@ def runner(argv, run_by_human=True, stdout=sys.stdout, stderr=sys.stderr):
rc = debug.dispatch[command](so, stdout, stderr)
elif command in cli.dispatch:
rc = cli.dispatch[command](so, stdout, stderr)
else:
raise usage.UsageError()
return rc

View File

@ -2,12 +2,12 @@
import sys, urllib
def get(nodeurl, vdrive, vdrive_file, local_file):
def get(nodeurl, vdrive, vdrive_fname, local_file):
if nodeurl[-1] != "/":
nodeurl += "/"
url = nodeurl + "vdrive/" + vdrive + "/"
if vdrive_file:
url += vdrive_file
if vdrive_fname:
url += vdrive_fname
if local_file is None or local_file == "-":
outf = sys.stdout
@ -36,12 +36,12 @@ def main():
if not isinstance(options.nodeurl, basestring) or not NODEURL_RE.match(options.nodeurl):
raise ValueError("--node-url is required to be a string and look like \"http://HOSTNAMEORADDR:PORT\", not: %r" % (options.nodeurl,))
vdrive_file = args[0]
vdrive_fname = args[0]
local_file = None
if len(args) > 1:
local_file = args[1]
get(options.nodeurl, options.vdrive, vdrive_file, local_file)
get(options.nodeurl, options.vdrive, vdrive_fname, local_file)
if __name__ == '__main__':
main()

View File

@ -3,12 +3,12 @@
import urllib
import simplejson
def list(nodeurl, vdrive, vdrive_file):
def list(nodeurl, vdrive, vdrive_pathname):
if nodeurl[-1] != "/":
nodeurl += "/"
url = nodeurl + "vdrive/" + vdrive + "/"
if vdrive_file:
url += vdrive_file
if vdrive_pathname:
url += vdrive_pathname
url += "?t=json"
data = urllib.urlopen(url).read()
@ -40,11 +40,11 @@ def main():
if not isinstance(options.nodeurl, basestring) or not NODEURL_RE.match(options.nodeurl):
raise ValueError("--node-url is required to be a string and look like \"http://HOSTNAMEORADDR:PORT\", not: %r" % (options.nodeurl,))
vdrive_file = ""
vdrive_pathname = ""
if args:
vdrive_file = args[0]
vdrive_pathname = args[0]
list(options.nodeurl, options.vdrive, vdrive_file)
list(options.nodeurl, options.vdrive, vdrive_pathname)
if __name__ == '__main__':
main()

View File

@ -4,7 +4,7 @@ import re, socket, sys
NODEURL_RE=re.compile("http://([^:]*)(:([1-9][0-9]*))?")
def put(nodeurl, vdrive, vdrive_fname, local_fname, verbosity):
def put(nodeurl, vdrive, local_fname, vdrive_fname, verbosity):
"""
@param verbosity: 0, 1, or 2, meaning quiet, verbose, or very verbose
@ -85,11 +85,11 @@ def main():
raise ValueError("--node-url is required to be a string and look like \"http://HOSTNAMEORADDR:PORT\", not: %r" % (options.nodeurl,))
local_file = args[0]
vdrive_file = None
vdrive_fname = None
if len(args) > 1:
vdrive_file = args[1]
vdrive_fname = args[1]
return put(options.nodeurl, options.vdrive, vdrive_file, local_file)
return put(options.nodeurl, options.vdrive, vdrive_fname, local_file)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,77 @@
#!/usr/bin/env python
import re, socket, sys
NODEURL_RE=re.compile("http://([^:]*)(:([1-9][0-9]*))?")
def rm(nodeurl, vdrive, vdrive_pathname, verbosity):
"""
@param verbosity: 0, 1, or 2, meaning quiet, verbose, or very verbose
@return: a Deferred which eventually fires with the exit code
"""
mo = NODEURL_RE.match(nodeurl)
host = mo.group(1)
port = int(mo.group(3))
url = "/vdrive/" + vdrive + "/"
if vdrive_pathname:
url += vdrive_pathname
so = socket.socket()
so.connect((host, port,))
CHUNKSIZE=2**16
data = "DELETE %s HTTP/1.1\r\nConnection: close\r\nHostname: %s\r\n\r\n" % (url, host,)
sent = so.send(data)
respbuf = []
data = so.recv(CHUNKSIZE)
while data:
respbuf.append(data)
data = so.recv(CHUNKSIZE)
so.shutdown(socket.SHUT_WR)
data = so.recv(CHUNKSIZE)
while data:
respbuf.append(data)
data = so.recv(CHUNKSIZE)
respstr = ''.join(respbuf)
headerend = respstr.find('\r\n\r\n')
if headerend == -1:
headerend = len(respstr)
header = respstr[:headerend]
RESP_RE=re.compile("^HTTP/[0-9]\.[0-9] ([0-9]*) *([A-Za-z_ ]*)") # This regex is soooo ad hoc... --Zooko 2007-08-16
mo = RESP_RE.match(header)
if mo:
code = int(mo.group(1))
word = mo.group(2)
if code == 200:
print "%s %s" % (code, word,)
return 0
print respstr[headerend:]
return 1
def main():
import optparse, re
parser = optparse.OptionParser()
parser.add_option("-d", "--vdrive", dest="vdrive", default="global")
parser.add_option("-u", "--node-url", dest="nodeurl")
(options, args) = parser.parse_args()
NODEURL_RE=re.compile("http://([^:]*)(:([1-9][0-9]*))?")
if not isinstance(options.nodeurl, basestring) or not NODEURL_RE.match(options.nodeurl):
raise ValueError("--node-url is required to be a string and look like \"http://HOSTNAMEORADDR:PORT\", not: %r" % (options.nodeurl,))
vdrive_pathname = args[0]
return put(options.nodeurl, options.vdrive, vdrive_pathname, local_file)
if __name__ == '__main__':
main()