mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-18 10:46:24 +00:00
cli: improve formatting of all commands
Also: * do some light refactoring of create-client/node * make it clear that these commands' --basedir options do the same as the global --node-directory option * use "global-options" instead of "global-opts"
This commit is contained in:
parent
01619844de
commit
8f41713fe9
@ -3,8 +3,6 @@ from twisted.python import usage
|
||||
from allmydata.scripts.common import BaseOptions
|
||||
|
||||
class GenerateKeypairOptions(BaseOptions):
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] admin generate-keypair"
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = BaseOptions.getUsage(self, width)
|
||||
@ -26,7 +24,7 @@ class DerivePubkeyOptions(BaseOptions):
|
||||
self.privkey = privkey
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] admin derive-pubkey PRIVKEY"
|
||||
return "Usage: tahoe [global-options] admin derive-pubkey PRIVKEY"
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = BaseOptions.getUsage(self, width)
|
||||
@ -57,7 +55,7 @@ class AdminCommand(BaseOptions):
|
||||
if not hasattr(self, 'subOptions'):
|
||||
raise usage.UsageError("must specify a subcommand")
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] admin SUBCOMMAND"
|
||||
return "Usage: tahoe [global-options] admin SUBCOMMAND"
|
||||
def getUsage(self, width=None):
|
||||
t = BaseOptions.getUsage(self, width)
|
||||
t += """
|
||||
|
@ -57,10 +57,8 @@ class MakeDirectoryOptions(FilesystemOptions):
|
||||
if self['format'].upper() not in ("SDMF", "MDMF"):
|
||||
raise usage.UsageError("%s is an invalid format" % self['format'])
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] mkdir [options] [REMOTE_DIR]" % (self.command_name,)
|
||||
|
||||
longdesc = """Create a new directory, either unlinked or as a subdirectory."""
|
||||
synopsis = "[options] [REMOTE_DIR]"
|
||||
description = """Create a new directory, either unlinked or as a subdirectory."""
|
||||
|
||||
class AddAliasOptions(FilesystemOptions):
|
||||
def parseArgs(self, alias, cap):
|
||||
@ -69,10 +67,8 @@ class AddAliasOptions(FilesystemOptions):
|
||||
self.alias = self.alias[:-1]
|
||||
self.cap = cap
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] add-alias [options] ALIAS[:] DIRCAP" % (self.command_name,)
|
||||
|
||||
longdesc = """Add a new alias for an existing directory."""
|
||||
synopsis = "[options] ALIAS[:] DIRCAP"
|
||||
description = """Add a new alias for an existing directory."""
|
||||
|
||||
class CreateAliasOptions(FilesystemOptions):
|
||||
def parseArgs(self, alias):
|
||||
@ -80,16 +76,12 @@ class CreateAliasOptions(FilesystemOptions):
|
||||
if self.alias.endswith(u':'):
|
||||
self.alias = self.alias[:-1]
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] create-alias [options] ALIAS[:]" % (self.command_name,)
|
||||
|
||||
longdesc = """Create a new directory and add an alias for it."""
|
||||
synopsis = "[options] ALIAS[:]"
|
||||
description = """Create a new directory and add an alias for it."""
|
||||
|
||||
class ListAliasesOptions(FilesystemOptions):
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] list-aliases [options]" % (self.command_name,)
|
||||
|
||||
longdesc = """Display a table of all configured aliases."""
|
||||
synopsis = "[options]"
|
||||
description = """Display a table of all configured aliases."""
|
||||
|
||||
class ListOptions(FilesystemOptions):
|
||||
optFlags = [
|
||||
@ -102,10 +94,9 @@ class ListOptions(FilesystemOptions):
|
||||
def parseArgs(self, where=""):
|
||||
self.where = argv_to_unicode(where)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] ls [options] [PATH]" % (self.command_name,)
|
||||
synopsis = "[options] [PATH]"
|
||||
|
||||
longdesc = """
|
||||
description = """
|
||||
List the contents of some portion of the grid.
|
||||
|
||||
If PATH is omitted, "tahoe:" is assumed.
|
||||
@ -113,7 +104,7 @@ class ListOptions(FilesystemOptions):
|
||||
When the -l or --long option is used, each line is shown in the
|
||||
following format:
|
||||
|
||||
drwx <size> <date/time> <name in this directory>
|
||||
drwx <size> <date/time> <name in this directory>
|
||||
|
||||
where each of the letters on the left may be replaced by '-'.
|
||||
If 'd' is present, it indicates that the object is a directory.
|
||||
@ -146,24 +137,20 @@ class GetOptions(FilesystemOptions):
|
||||
self.from_file = argv_to_unicode(arg1)
|
||||
self.to_file = None if arg2 is None else argv_to_abspath(arg2)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] get [options] REMOTE_FILE LOCAL_FILE" % (self.command_name,)
|
||||
synopsis = "[options] REMOTE_FILE LOCAL_FILE"
|
||||
|
||||
longdesc = """
|
||||
description = """
|
||||
Retrieve a file from the grid and write it to the local filesystem. If
|
||||
LOCAL_FILE is omitted or '-', the contents of the file will be written to
|
||||
stdout."""
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = FilesystemOptions.getUsage(self, width)
|
||||
t += """
|
||||
Examples:
|
||||
% tahoe get FOO |less # write to stdout
|
||||
% tahoe get tahoe:FOO |less # same
|
||||
% tahoe get FOO bar # write to local file
|
||||
% tahoe get tahoe:FOO bar # same
|
||||
"""
|
||||
return t
|
||||
description_unwrapped = """
|
||||
Examples:
|
||||
% tahoe get FOO |less # write to stdout
|
||||
% tahoe get tahoe:FOO |less # same
|
||||
% tahoe get FOO bar # write to local file
|
||||
% tahoe get tahoe:FOO bar # same
|
||||
"""
|
||||
|
||||
class PutOptions(FilesystemOptions):
|
||||
optFlags = [
|
||||
@ -186,33 +173,30 @@ class PutOptions(FilesystemOptions):
|
||||
if self['format'].upper() not in ("SDMF", "MDMF", "CHK"):
|
||||
raise usage.UsageError("%s is an invalid format" % self['format'])
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] put [options] LOCAL_FILE REMOTE_FILE" % (self.command_name,)
|
||||
synopsis = "[options] LOCAL_FILE REMOTE_FILE"
|
||||
|
||||
longdesc = """
|
||||
description = """
|
||||
Put a file into the grid, copying its contents from the local filesystem.
|
||||
If REMOTE_FILE is missing, upload the file but do not link it into a
|
||||
directory; also print the new filecap to stdout. If LOCAL_FILE is missing
|
||||
or '-', data will be copied from stdin. REMOTE_FILE is assumed to start
|
||||
with tahoe: unless otherwise specified.
|
||||
|
||||
If the destination file already exists and is mutable, it will be modified
|
||||
in-place, whether or not --mutable is specified. (--mutable only affects
|
||||
creation of new files.)"""
|
||||
If the destination file already exists and is mutable, it will be
|
||||
modified in-place, whether or not --mutable is specified. (--mutable only
|
||||
affects creation of new files.)
|
||||
"""
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = FilesystemOptions.getUsage(self, width)
|
||||
t += """
|
||||
Examples:
|
||||
% cat FILE | tahoe put # create unlinked file from stdin
|
||||
% cat FILE | tahoe put - # same
|
||||
% tahoe put bar # create unlinked file from local 'bar'
|
||||
% cat FILE | tahoe put - FOO # create tahoe:FOO from stdin
|
||||
% tahoe put bar FOO # copy local 'bar' to tahoe:FOO
|
||||
% tahoe put bar tahoe:FOO # same
|
||||
% tahoe put bar MUTABLE-FILE-WRITECAP # modify the mutable file in-place
|
||||
"""
|
||||
return t
|
||||
description_unwrapped = """
|
||||
Examples:
|
||||
% cat FILE | tahoe put # create unlinked file from stdin
|
||||
% cat FILE | tahoe put - # same
|
||||
% tahoe put bar # create unlinked file from local 'bar'
|
||||
% cat FILE | tahoe put - FOO # create tahoe:FOO from stdin
|
||||
% tahoe put bar FOO # copy local 'bar' to tahoe:FOO
|
||||
% tahoe put bar tahoe:FOO # same
|
||||
% tahoe put bar MUTABLE-FILE-WRITECAP # modify the mutable file in-place
|
||||
"""
|
||||
|
||||
class CpOptions(FilesystemOptions):
|
||||
optFlags = [
|
||||
@ -229,10 +213,9 @@ class CpOptions(FilesystemOptions):
|
||||
self.sources = map(argv_to_unicode, args[:-1])
|
||||
self.destination = argv_to_unicode(args[-1])
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] cp [options] FROM.. TO" % (self.command_name,)
|
||||
synopsis = "[options] FROM.. TO"
|
||||
|
||||
longdesc = """
|
||||
description = """
|
||||
Use 'tahoe cp' to copy files between a local filesystem and a Tahoe grid.
|
||||
Any FROM/TO arguments that begin with an alias indicate Tahoe-side
|
||||
files or non-file arguments. Directories will be copied recursively.
|
||||
@ -240,15 +223,15 @@ class CpOptions(FilesystemOptions):
|
||||
you have previously set up an alias 'home' with 'tahoe create-alias home',
|
||||
here are some examples:
|
||||
|
||||
tahoe cp ~/foo.txt home: # creates tahoe-side home:foo.txt
|
||||
tahoe cp ~/foo.txt home: # creates tahoe-side home:foo.txt
|
||||
|
||||
tahoe cp ~/foo.txt /tmp/bar.txt home: # copies two files to home:
|
||||
tahoe cp ~/foo.txt /tmp/bar.txt home: # copies two files to home:
|
||||
|
||||
tahoe cp ~/Pictures home:stuff/my-pictures # copies directory recursively
|
||||
tahoe cp ~/Pictures home:stuff/my-pictures # copies directory recursively
|
||||
|
||||
You can also use a dircap as either FROM or TO target:
|
||||
|
||||
tahoe cp URI:DIR2-RO:ixqhc4kdbjxc7o65xjnveoewym:5x6lwoxghrd5rxhwunzavft2qygfkt27oj3fbxlq4c6p45z5uneq/blog.html ./ # copy Zooko's wiki page to a local file
|
||||
tahoe cp URI:DIR2-RO:ixqhc4kdbjxc7o65xjnveoewym:5x6lwoxghrd5rxhwunzavft2qygfkt27oj3fbxlq4c6p45z5uneq/blog.html ./ # copy Zooko's wiki page to a local file
|
||||
|
||||
This command still has some limitations: symlinks and special files
|
||||
(device nodes, named pipes) are not handled very well. Arguments should
|
||||
@ -266,22 +249,21 @@ class UnlinkOptions(FilesystemOptions):
|
||||
def parseArgs(self, where):
|
||||
self.where = argv_to_unicode(where)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] unlink [options] REMOTE_FILE" % (self.command_name,)
|
||||
synopsis = "[options] REMOTE_FILE"
|
||||
description = "Remove a named file from its parent directory."
|
||||
|
||||
class RmOptions(UnlinkOptions):
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] rm [options] REMOTE_FILE" % (self.command_name,)
|
||||
synopsis = "[options] REMOTE_FILE"
|
||||
description = "Remove a named file from its parent directory."
|
||||
|
||||
class MvOptions(FilesystemOptions):
|
||||
def parseArgs(self, frompath, topath):
|
||||
self.from_file = argv_to_unicode(frompath)
|
||||
self.to_file = argv_to_unicode(topath)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] mv [options] FROM TO" % (self.command_name,)
|
||||
synopsis = "[options] FROM TO"
|
||||
|
||||
longdesc = """
|
||||
description = """
|
||||
Use 'tahoe mv' to move files that are already on the grid elsewhere on
|
||||
the grid, e.g., 'tahoe mv alias:some_file alias:new_file'.
|
||||
|
||||
@ -298,10 +280,9 @@ class LnOptions(FilesystemOptions):
|
||||
self.from_file = argv_to_unicode(frompath)
|
||||
self.to_file = argv_to_unicode(topath)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] ln [options] FROM_LINK TO_LINK" % (self.command_name,)
|
||||
synopsis = "[options] FROM_LINK TO_LINK"
|
||||
|
||||
longdesc = """
|
||||
description = """
|
||||
Use 'tahoe ln' to duplicate a link (directory entry) already on the grid
|
||||
to elsewhere on the grid. For example 'tahoe ln alias:some_file
|
||||
alias:new_file'. causes 'alias:new_file' to point to the same object that
|
||||
@ -345,8 +326,7 @@ class BackupOptions(FilesystemOptions):
|
||||
self.from_dir = argv_to_abspath(localdir)
|
||||
self.to_dir = argv_to_unicode(topath)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] backup [options] FROM ALIAS:TO" % (self.command_name,)
|
||||
synopsis = "[options] FROM ALIAS:TO"
|
||||
|
||||
def opt_exclude(self, pattern):
|
||||
"""Ignore files matching a glob pattern. You may give multiple
|
||||
@ -388,7 +368,7 @@ class BackupOptions(FilesystemOptions):
|
||||
else:
|
||||
yield filename
|
||||
|
||||
longdesc = """
|
||||
description = """
|
||||
Add a versioned backup of the local FROM directory to a timestamped
|
||||
subdirectory of the TO/Archives directory on the grid, sharing as many
|
||||
files and directories as possible with earlier backups. Create TO/Latest
|
||||
@ -403,10 +383,10 @@ class WebopenOptions(FilesystemOptions):
|
||||
def parseArgs(self, where=''):
|
||||
self.where = argv_to_unicode(where)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] webopen [options] [ALIAS:PATH]" % (self.command_name,)
|
||||
synopsis = "[options] [ALIAS:PATH]"
|
||||
|
||||
longdesc = """Open a web browser to the contents of some file or
|
||||
description = """
|
||||
Open a web browser to the contents of some file or
|
||||
directory on the grid. When run without arguments, open the Welcome
|
||||
page."""
|
||||
|
||||
@ -420,11 +400,10 @@ class ManifestOptions(FilesystemOptions):
|
||||
def parseArgs(self, where=''):
|
||||
self.where = argv_to_unicode(where)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] manifest [options] [ALIAS:PATH]" % (self.command_name,)
|
||||
|
||||
longdesc = """Print a list of all files and directories reachable from
|
||||
the given starting point."""
|
||||
synopsis = "[options] [ALIAS:PATH]"
|
||||
description = """
|
||||
Print a list of all files and directories reachable from the given
|
||||
starting point."""
|
||||
|
||||
class StatsOptions(FilesystemOptions):
|
||||
optFlags = [
|
||||
@ -433,11 +412,10 @@ class StatsOptions(FilesystemOptions):
|
||||
def parseArgs(self, where=''):
|
||||
self.where = argv_to_unicode(where)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] stats [options] [ALIAS:PATH]" % (self.command_name,)
|
||||
|
||||
longdesc = """Print statistics about of all files and directories
|
||||
reachable from the given starting point."""
|
||||
synopsis = "[options] [ALIAS:PATH]"
|
||||
description = """
|
||||
Print statistics about of all files and directories reachable from the
|
||||
given starting point."""
|
||||
|
||||
class CheckOptions(FilesystemOptions):
|
||||
optFlags = [
|
||||
@ -449,10 +427,8 @@ class CheckOptions(FilesystemOptions):
|
||||
def parseArgs(self, *locations):
|
||||
self.locations = map(argv_to_unicode, locations)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] check [options] [ALIAS:PATH]" % (self.command_name,)
|
||||
|
||||
longdesc = """
|
||||
synopsis = "[options] [ALIAS:PATH]"
|
||||
description = """
|
||||
Check a single file or directory: count how many shares are available and
|
||||
verify their hashes. Optionally repair the file if any problems were
|
||||
found."""
|
||||
@ -468,10 +444,8 @@ class DeepCheckOptions(FilesystemOptions):
|
||||
def parseArgs(self, *locations):
|
||||
self.locations = map(argv_to_unicode, locations)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] deep-check [options] [ALIAS:PATH]" % (self.command_name,)
|
||||
|
||||
longdesc = """
|
||||
synopsis = "[options] [ALIAS:PATH]"
|
||||
description = """
|
||||
Check all files and directories reachable from the given starting point
|
||||
(which must be a directory), like 'tahoe check' but for multiple files.
|
||||
Optionally repair any problems found."""
|
||||
|
@ -93,7 +93,7 @@ class NoDefaultBasedirOptions(BasedirOptions):
|
||||
BasedirOptions.parseArgs(self, basedir)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] %s [options] NODEDIR" % (self.command_name, self.subcommand_name)
|
||||
return "Usage: %s [global-options] %s [options] NODEDIR" % (self.command_name, self.subcommand_name)
|
||||
|
||||
|
||||
DEFAULT_ALIAS = u"tahoe"
|
||||
|
@ -1,11 +1,12 @@
|
||||
|
||||
import os, sys
|
||||
from allmydata.scripts.common import BasedirOptions, NoDefaultBasedirOptions
|
||||
from allmydata.scripts.default_nodedir import _default_nodedir
|
||||
from allmydata.util.assertutil import precondition
|
||||
from allmydata.util.encodingutil import listdir_unicode, argv_to_unicode, quote_output
|
||||
from allmydata.util.encodingutil import listdir_unicode, argv_to_unicode, quote_output, quote_local_unicode_path
|
||||
import allmydata
|
||||
|
||||
class CreateClientOptions(BasedirOptions):
|
||||
class _CreateBaseOptions(BasedirOptions):
|
||||
optParameters = [
|
||||
# we provide 'create-node'-time options for the most common
|
||||
# configuration knobs. The rest can be controlled by editing
|
||||
@ -14,28 +15,30 @@ class CreateClientOptions(BasedirOptions):
|
||||
("introducer", "i", None, "Specify the introducer FURL to use."),
|
||||
("webport", "p", "tcp:3456:interface=127.0.0.1",
|
||||
"Specify which TCP port to run the HTTP interface on. Use 'none' to disable."),
|
||||
("basedir", "C", None, "Specify which Tahoe base directory should be used. This has the same effect as the global --node-directory option. [default: %s]"
|
||||
% quote_local_unicode_path(_default_nodedir)),
|
||||
|
||||
]
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] create-client [options] [NODEDIR]" % (self.command_name,)
|
||||
|
||||
# This is overridden in order to ensure we get a "Wrong number of arguments."
|
||||
# error when more than one argument is given.
|
||||
# This is overridden in order to ensure we get a "Wrong number of
|
||||
# arguments." error when more than one argument is given.
|
||||
def parseArgs(self, basedir=None):
|
||||
BasedirOptions.parseArgs(self, basedir)
|
||||
|
||||
class CreateClientOptions(_CreateBaseOptions):
|
||||
synopsis = "[options] [NODEDIR]"
|
||||
description = "Create a client-only Tahoe-LAFS node (no storage server)."
|
||||
|
||||
class CreateNodeOptions(CreateClientOptions):
|
||||
optFlags = [
|
||||
("no-storage", None, "Do not offer storage service to other nodes."),
|
||||
]
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] create-node [options] [NODEDIR]" % (self.command_name,)
|
||||
|
||||
synopsis = "[options] [NODEDIR]"
|
||||
description = "Create a full Tahoe-LAFS node (client+server)."
|
||||
|
||||
class CreateIntroducerOptions(NoDefaultBasedirOptions):
|
||||
subcommand_name = "create-introducer"
|
||||
description = "Create a Tahoe-LAFS introducer."
|
||||
|
||||
|
||||
client_tac = """
|
||||
|
@ -11,25 +11,21 @@ from allmydata.scripts.common import BaseOptions
|
||||
|
||||
class DumpOptions(BaseOptions):
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] debug dump-share SHARE_FILENAME"
|
||||
return "Usage: tahoe [global-options] debug dump-share SHARE_FILENAME"
|
||||
|
||||
optFlags = [
|
||||
["offsets", None, "Display a table of section offsets."],
|
||||
["leases-only", None, "Dump leases but not CHK contents."],
|
||||
]
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = BaseOptions.getUsage(self, width)
|
||||
t += """
|
||||
description = """
|
||||
Print lots of information about the given share, by parsing the share's
|
||||
contents. This includes share type, lease information, encoding parameters,
|
||||
hash-tree roots, public keys, and segment sizes. This command also emits a
|
||||
verify-cap for the file that uses the share.
|
||||
|
||||
tahoe debug dump-share testgrid/node-3/storage/shares/4v/4vozh77tsrw7mdhnj7qvp5ky74/0
|
||||
|
||||
"""
|
||||
return t
|
||||
|
||||
def parseArgs(self, filename):
|
||||
from allmydata.util.encodingutil import argv_to_abspath
|
||||
@ -408,7 +404,7 @@ def dump_MDMF_share(m, length, options):
|
||||
|
||||
class DumpCapOptions(BaseOptions):
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] debug dump-cap [options] FILECAP"
|
||||
return "Usage: tahoe [global-options] debug dump-cap [options] FILECAP"
|
||||
optParameters = [
|
||||
["nodeid", "n",
|
||||
None, "Specify the storage server nodeid (ASCII), to construct WE and secrets."],
|
||||
@ -420,9 +416,7 @@ class DumpCapOptions(BaseOptions):
|
||||
def parseArgs(self, cap):
|
||||
self.cap = cap
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = BaseOptions.getUsage(self, width)
|
||||
t += """
|
||||
description = """
|
||||
Print information about the given cap-string (aka: URI, file-cap, dir-cap,
|
||||
read-cap, write-cap). The URI string is parsed and unpacked. This prints the
|
||||
type of the cap, its storage index, and any derived keys.
|
||||
@ -437,7 +431,6 @@ If additional information is provided (storage server nodeid and/or client
|
||||
base secret), this command will compute the shared secrets used for the
|
||||
write-enabler and for lease-renewal.
|
||||
"""
|
||||
return t
|
||||
|
||||
|
||||
def dump_cap(options):
|
||||
@ -610,16 +603,14 @@ def dump_uri_instance(u, nodeid, secret, out, show_header=True):
|
||||
|
||||
class FindSharesOptions(BaseOptions):
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] debug find-shares STORAGE_INDEX NODEDIRS.."
|
||||
return "Usage: tahoe [global-options] debug find-shares STORAGE_INDEX NODEDIRS.."
|
||||
|
||||
def parseArgs(self, storage_index_s, *nodedirs):
|
||||
from allmydata.util.encodingutil import argv_to_abspath
|
||||
self.si_s = storage_index_s
|
||||
self.nodedirs = map(argv_to_abspath, nodedirs)
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = BaseOptions.getUsage(self, width)
|
||||
t += """
|
||||
description = """
|
||||
Locate all shares for the given storage index. This command looks through one
|
||||
or more node directories to find the shares. It returns a list of filenames,
|
||||
one per line, for each share file found.
|
||||
@ -630,7 +621,6 @@ It may be useful during testing, when running a test grid in which all the
|
||||
nodes are on a local disk. The share files thus located can be counted,
|
||||
examined (with dump-share), or corrupted/deleted to test checker/repairer.
|
||||
"""
|
||||
return t
|
||||
|
||||
def find_shares(options):
|
||||
"""Given a storage index and a list of node directories, emit a list of
|
||||
@ -659,9 +649,6 @@ def find_shares(options):
|
||||
|
||||
|
||||
class CatalogSharesOptions(BaseOptions):
|
||||
"""
|
||||
|
||||
"""
|
||||
def parseArgs(self, *nodedirs):
|
||||
from allmydata.util.encodingutil import argv_to_abspath
|
||||
self.nodedirs = map(argv_to_abspath, nodedirs)
|
||||
@ -669,11 +656,9 @@ class CatalogSharesOptions(BaseOptions):
|
||||
raise usage.UsageError("must specify at least one node directory")
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] debug catalog-shares NODEDIRS.."
|
||||
return "Usage: tahoe [global-options] debug catalog-shares NODEDIRS.."
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = BaseOptions.getUsage(self, width)
|
||||
t += """
|
||||
description = """
|
||||
Locate all shares in the given node directories, and emit a one-line summary
|
||||
of each share. Run it like this:
|
||||
|
||||
@ -691,7 +676,6 @@ you see shares with the same SI but different parameters/filesize/UEB_hash,
|
||||
then something is wrong. The misc/find-share/anomalies.py script may be
|
||||
useful for purpose.
|
||||
"""
|
||||
return t
|
||||
|
||||
def call(c, *args, **kwargs):
|
||||
# take advantage of the fact that ImmediateReadBucketProxy returns
|
||||
@ -882,15 +866,13 @@ def catalog_shares_one_abbrevdir(si_s, si_dir, now, out, err):
|
||||
|
||||
class CorruptShareOptions(BaseOptions):
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] debug corrupt-share SHARE_FILENAME"
|
||||
return "Usage: tahoe [global-options] debug corrupt-share SHARE_FILENAME"
|
||||
|
||||
optParameters = [
|
||||
["offset", "o", "block-random", "Specify which bit to flip."],
|
||||
]
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = BaseOptions.getUsage(self, width)
|
||||
t += """
|
||||
description = """
|
||||
Corrupt the given share by flipping a bit. This will cause a
|
||||
verifying/downloading client to log an integrity-check failure incident, and
|
||||
downloads will proceed with a different share.
|
||||
@ -902,7 +884,6 @@ to flip a single random bit of the block data.
|
||||
|
||||
Obviously, this command should not be used in normal operation.
|
||||
"""
|
||||
return t
|
||||
def parseArgs(self, filename):
|
||||
self['filename'] = filename
|
||||
|
||||
@ -962,7 +943,7 @@ def corrupt_share(options):
|
||||
|
||||
class ReplOptions(BaseOptions):
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] debug repl"
|
||||
return "Usage: tahoe [global-options] debug repl"
|
||||
|
||||
def repl(options):
|
||||
import code
|
||||
@ -973,7 +954,7 @@ DEFAULT_TESTSUITE = 'allmydata'
|
||||
|
||||
class TrialOptions(twisted_trial.Options):
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] debug trial [options] [[file|package|module|TestCase|testmethod]...]"
|
||||
return "Usage: tahoe [global-options] debug trial [options] [[file|package|module|TestCase|testmethod]...]"
|
||||
|
||||
def parseOptions(self, all_subargs, *a, **kw):
|
||||
self.trial_args = list(all_subargs)
|
||||
@ -985,13 +966,10 @@ class TrialOptions(twisted_trial.Options):
|
||||
if not nonoption_args:
|
||||
self.trial_args.append(DEFAULT_TESTSUITE)
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = twisted_trial.Options.getUsage(self, width)
|
||||
t += """
|
||||
The 'tahoe debug trial' command uses the correct imports for this instance of
|
||||
Tahoe-LAFS. The default test suite is '%s'.
|
||||
""" % (DEFAULT_TESTSUITE,)
|
||||
return t
|
||||
longdesc = twisted_trial.Options.longdesc + "\n\n" + (
|
||||
"The 'tahoe debug trial' command uses the correct imports for this "
|
||||
"instance of Tahoe-LAFS. The default test suite is '%s'."
|
||||
% DEFAULT_TESTSUITE)
|
||||
|
||||
def trial(config):
|
||||
sys.argv = ['trial'] + config.trial_args
|
||||
@ -1014,9 +992,9 @@ def fixOptionsClass( (subcmd, shortcut, OptionsClass, desc) ):
|
||||
t = OptionsClass.getSynopsis(self)
|
||||
i = t.find("Usage: flogtool ")
|
||||
if i >= 0:
|
||||
return "Usage: tahoe [global-opts] debug flogtool " + t[i+len("Usage: flogtool "):]
|
||||
return "Usage: tahoe [global-options] debug flogtool " + t[i+len("Usage: flogtool "):]
|
||||
else:
|
||||
return "Usage: tahoe [global-opts] debug flogtool %s [options]" % (subcmd,)
|
||||
return "Usage: tahoe [global-options] debug flogtool %s [options]" % (subcmd,)
|
||||
return (subcmd, shortcut, FixedOptionsClass, desc)
|
||||
|
||||
class FlogtoolOptions(foolscap_cli.Options):
|
||||
@ -1025,7 +1003,7 @@ class FlogtoolOptions(foolscap_cli.Options):
|
||||
self.subCommands = map(fixOptionsClass, self.subCommands)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe [global-opts] debug flogtool (%s) [command options]" % ("|".join([x[0] for x in self.subCommands]))
|
||||
return "Usage: tahoe [global-options] debug flogtool COMMAND [flogtool-options]"
|
||||
|
||||
def parseOptions(self, all_subargs, *a, **kw):
|
||||
self.flogtool_args = list(all_subargs)
|
||||
@ -1037,7 +1015,7 @@ class FlogtoolOptions(foolscap_cli.Options):
|
||||
The 'tahoe debug flogtool' command uses the correct imports for this instance
|
||||
of Tahoe-LAFS.
|
||||
|
||||
Please run 'tahoe debug flogtool SUBCOMMAND --help' for more details on each
|
||||
Please run 'tahoe debug flogtool COMMAND --help' for more details on each
|
||||
subcommand.
|
||||
"""
|
||||
return t
|
||||
@ -1066,20 +1044,11 @@ class DebugCommand(BaseOptions):
|
||||
def postOptions(self):
|
||||
if not hasattr(self, 'subOptions'):
|
||||
raise usage.UsageError("must specify a subcommand")
|
||||
def getSynopsis(self):
|
||||
return ""
|
||||
synopsis = "COMMAND"
|
||||
|
||||
def getUsage(self, width=None):
|
||||
#t = BaseOptions.getUsage(self, width)
|
||||
t = """Usage: tahoe debug SUBCOMMAND
|
||||
Subcommands:
|
||||
tahoe debug dump-share Unpack and display the contents of a share.
|
||||
tahoe debug dump-cap Unpack a read-cap or write-cap.
|
||||
tahoe debug find-shares Locate sharefiles in node directories.
|
||||
tahoe debug catalog-shares Describe all shares in node dirs.
|
||||
tahoe debug corrupt-share Corrupt a share by flipping a bit.
|
||||
tahoe debug repl Open a Python interpreter.
|
||||
tahoe debug trial Run tests using Twisted Trial with the right imports.
|
||||
tahoe debug flogtool Utilities to access log files.
|
||||
t = BaseOptions.getUsage(self, width)
|
||||
t += """\
|
||||
|
||||
Please run e.g. 'tahoe debug dump-share --help' for more details on each
|
||||
subcommand.
|
||||
|
@ -70,7 +70,7 @@ class Options(usage.Options):
|
||||
return ("\nUsage: tahoe [global-options] <command> [command-options]\n"
|
||||
+ self.getUsage())
|
||||
|
||||
synopsis = "\nUsage: tahoe [global-opts]" # used only for subcommands
|
||||
synopsis = "\nUsage: tahoe [global-options]" # used only for subcommands
|
||||
|
||||
def getUsage(self, **kwargs):
|
||||
t = usage.Options.getUsage(self, **kwargs)
|
||||
|
@ -3,12 +3,17 @@ import os, sys, signal, time
|
||||
from allmydata.scripts.common import BasedirOptions
|
||||
from twisted.scripts import twistd
|
||||
from twisted.python import usage
|
||||
from allmydata.scripts.default_nodedir import _default_nodedir
|
||||
from allmydata.util import fileutil
|
||||
from allmydata.util.encodingutil import listdir_unicode, quote_local_unicode_path
|
||||
|
||||
|
||||
class StartOptions(BasedirOptions):
|
||||
subcommand_name = "start"
|
||||
optParameters = [
|
||||
("basedir", "C", None, "Specify which Tahoe base directory should be used. This has the same effect as the global --node-directory option. [default: %s]"
|
||||
% quote_local_unicode_path(_default_nodedir)),
|
||||
]
|
||||
|
||||
def parseArgs(self, basedir=None, *twistd_args):
|
||||
# This can't handle e.g. 'tahoe start --nodaemon', since '--nodaemon'
|
||||
@ -21,7 +26,7 @@ class StartOptions(BasedirOptions):
|
||||
self.twistd_args = twistd_args
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] %s [options] [NODEDIR [twistd-options]]" % (self.command_name, self.subcommand_name)
|
||||
return "Usage: %s [global-options] %s [options] [NODEDIR [twistd-options]]" % (self.command_name, self.subcommand_name)
|
||||
|
||||
def getUsage(self, width=None):
|
||||
t = BasedirOptions.getUsage(self, width) + "\n"
|
||||
@ -40,7 +45,7 @@ class StopOptions(BasedirOptions):
|
||||
BasedirOptions.parseArgs(self, basedir)
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s [global-opts] stop [options] [NODEDIR]" % (self.command_name,)
|
||||
return "Usage: %s [global-options] stop [options] [NODEDIR]" % (self.command_name,)
|
||||
|
||||
class RestartOptions(StartOptions):
|
||||
subcommand_name = "restart"
|
||||
|
@ -563,124 +563,124 @@ class CLI(CLITestMixin, unittest.TestCase):
|
||||
class Help(unittest.TestCase):
|
||||
def test_get(self):
|
||||
help = str(cli.GetOptions())
|
||||
self.failUnlessIn(" [global-opts] get [options] REMOTE_FILE LOCAL_FILE", help)
|
||||
self.failUnlessIn("[options] REMOTE_FILE LOCAL_FILE", help)
|
||||
self.failUnlessIn("% tahoe get FOO |less", help)
|
||||
|
||||
def test_put(self):
|
||||
help = str(cli.PutOptions())
|
||||
self.failUnlessIn(" [global-opts] put [options] LOCAL_FILE REMOTE_FILE", help)
|
||||
self.failUnlessIn("[options] LOCAL_FILE REMOTE_FILE", help)
|
||||
self.failUnlessIn("% cat FILE | tahoe put", help)
|
||||
|
||||
def test_ls(self):
|
||||
help = str(cli.ListOptions())
|
||||
self.failUnlessIn(" [global-opts] ls [options] [PATH]", help)
|
||||
self.failUnlessIn("[options] [PATH]", help)
|
||||
|
||||
def test_unlink(self):
|
||||
help = str(cli.UnlinkOptions())
|
||||
self.failUnlessIn(" [global-opts] unlink [options] REMOTE_FILE", help)
|
||||
self.failUnlessIn("[options] REMOTE_FILE", help)
|
||||
|
||||
def test_rm(self):
|
||||
help = str(cli.RmOptions())
|
||||
self.failUnlessIn(" [global-opts] rm [options] REMOTE_FILE", help)
|
||||
self.failUnlessIn("[options] REMOTE_FILE", help)
|
||||
|
||||
def test_mv(self):
|
||||
help = str(cli.MvOptions())
|
||||
self.failUnlessIn(" [global-opts] mv [options] FROM TO", help)
|
||||
self.failUnlessIn("[options] FROM TO", help)
|
||||
self.failUnlessIn("Use 'tahoe mv' to move files", help)
|
||||
|
||||
def test_cp(self):
|
||||
help = str(cli.CpOptions())
|
||||
self.failUnlessIn(" [global-opts] cp [options] FROM.. TO", help)
|
||||
self.failUnlessIn("[options] FROM.. TO", help)
|
||||
self.failUnlessIn("Use 'tahoe cp' to copy files", help)
|
||||
|
||||
def test_ln(self):
|
||||
help = str(cli.LnOptions())
|
||||
self.failUnlessIn(" [global-opts] ln [options] FROM_LINK TO_LINK", help)
|
||||
self.failUnlessIn("[options] FROM_LINK TO_LINK", help)
|
||||
self.failUnlessIn("Use 'tahoe ln' to duplicate a link", help)
|
||||
|
||||
def test_mkdir(self):
|
||||
help = str(cli.MakeDirectoryOptions())
|
||||
self.failUnlessIn(" [global-opts] mkdir [options] [REMOTE_DIR]", help)
|
||||
self.failUnlessIn("[options] [REMOTE_DIR]", help)
|
||||
self.failUnlessIn("Create a new directory", help)
|
||||
|
||||
def test_backup(self):
|
||||
help = str(cli.BackupOptions())
|
||||
self.failUnlessIn(" [global-opts] backup [options] FROM ALIAS:TO", help)
|
||||
self.failUnlessIn("[options] FROM ALIAS:TO", help)
|
||||
|
||||
def test_webopen(self):
|
||||
help = str(cli.WebopenOptions())
|
||||
self.failUnlessIn(" [global-opts] webopen [options] [ALIAS:PATH]", help)
|
||||
self.failUnlessIn("[options] [ALIAS:PATH]", help)
|
||||
|
||||
def test_manifest(self):
|
||||
help = str(cli.ManifestOptions())
|
||||
self.failUnlessIn(" [global-opts] manifest [options] [ALIAS:PATH]", help)
|
||||
self.failUnlessIn("[options] [ALIAS:PATH]", help)
|
||||
|
||||
def test_stats(self):
|
||||
help = str(cli.StatsOptions())
|
||||
self.failUnlessIn(" [global-opts] stats [options] [ALIAS:PATH]", help)
|
||||
self.failUnlessIn("[options] [ALIAS:PATH]", help)
|
||||
|
||||
def test_check(self):
|
||||
help = str(cli.CheckOptions())
|
||||
self.failUnlessIn(" [global-opts] check [options] [ALIAS:PATH]", help)
|
||||
self.failUnlessIn("[options] [ALIAS:PATH]", help)
|
||||
|
||||
def test_deep_check(self):
|
||||
help = str(cli.DeepCheckOptions())
|
||||
self.failUnlessIn(" [global-opts] deep-check [options] [ALIAS:PATH]", help)
|
||||
self.failUnlessIn("[options] [ALIAS:PATH]", help)
|
||||
|
||||
def test_create_alias(self):
|
||||
help = str(cli.CreateAliasOptions())
|
||||
self.failUnlessIn(" [global-opts] create-alias [options] ALIAS[:]", help)
|
||||
self.failUnlessIn("[options] ALIAS[:]", help)
|
||||
|
||||
def test_add_alias(self):
|
||||
help = str(cli.AddAliasOptions())
|
||||
self.failUnlessIn(" [global-opts] add-alias [options] ALIAS[:] DIRCAP", help)
|
||||
self.failUnlessIn("[options] ALIAS[:] DIRCAP", help)
|
||||
|
||||
def test_list_aliases(self):
|
||||
help = str(cli.ListAliasesOptions())
|
||||
self.failUnlessIn(" [global-opts] list-aliases [options]", help)
|
||||
self.failUnlessIn("[options]", help)
|
||||
|
||||
def test_start(self):
|
||||
help = str(startstop_node.StartOptions())
|
||||
self.failUnlessIn(" [global-opts] start [options] [NODEDIR [twistd-options]]", help)
|
||||
self.failUnlessIn("[options] [NODEDIR [twistd-options]]", help)
|
||||
|
||||
def test_stop(self):
|
||||
help = str(startstop_node.StopOptions())
|
||||
self.failUnlessIn(" [global-opts] stop [options] [NODEDIR]", help)
|
||||
self.failUnlessIn("[options] [NODEDIR]", help)
|
||||
|
||||
def test_restart(self):
|
||||
help = str(startstop_node.RestartOptions())
|
||||
self.failUnlessIn(" [global-opts] restart [options] [NODEDIR [twistd-options]]", help)
|
||||
self.failUnlessIn("[options] [NODEDIR [twistd-options]]", help)
|
||||
|
||||
def test_run(self):
|
||||
help = str(startstop_node.RunOptions())
|
||||
self.failUnlessIn(" [global-opts] run [options] [NODEDIR [twistd-options]]", help)
|
||||
self.failUnlessIn("[options] [NODEDIR [twistd-options]]", help)
|
||||
|
||||
def test_create_client(self):
|
||||
help = str(create_node.CreateClientOptions())
|
||||
self.failUnlessIn(" [global-opts] create-client [options] [NODEDIR]", help)
|
||||
self.failUnlessIn("[options] [NODEDIR]", help)
|
||||
|
||||
def test_create_node(self):
|
||||
help = str(create_node.CreateNodeOptions())
|
||||
self.failUnlessIn(" [global-opts] create-node [options] [NODEDIR]", help)
|
||||
self.failUnlessIn("[options] [NODEDIR]", help)
|
||||
|
||||
def test_create_introducer(self):
|
||||
help = str(create_node.CreateIntroducerOptions())
|
||||
self.failUnlessIn(" [global-opts] create-introducer [options] NODEDIR", help)
|
||||
self.failUnlessIn("[options] NODEDIR", help)
|
||||
|
||||
def test_debug_trial(self):
|
||||
help = str(debug.TrialOptions())
|
||||
self.failUnlessIn(" [global-opts] debug trial [options] [[file|package|module|TestCase|testmethod]...]", help)
|
||||
self.failUnlessIn(" [global-options] debug trial [options] [[file|package|module|TestCase|testmethod]...]", help)
|
||||
self.failUnlessIn("The 'tahoe debug trial' command uses the correct imports", help)
|
||||
|
||||
def test_debug_flogtool(self):
|
||||
options = debug.FlogtoolOptions()
|
||||
help = str(options)
|
||||
self.failUnlessIn(" [global-opts] debug flogtool ", help)
|
||||
self.failUnlessIn(" [global-options] debug flogtool ", help)
|
||||
self.failUnlessIn("The 'tahoe debug flogtool' command uses the correct imports", help)
|
||||
|
||||
for (option, shortcut, oClass, desc) in options.subCommands:
|
||||
subhelp = str(oClass())
|
||||
self.failUnlessIn(" [global-opts] debug flogtool %s " % (option,), subhelp)
|
||||
self.failUnlessIn(" [global-options] debug flogtool %s " % (option,), subhelp)
|
||||
|
||||
|
||||
class Ln(GridTestMixin, CLITestMixin, unittest.TestCase):
|
||||
|
Loading…
Reference in New Issue
Block a user