Permalink
Browse files

bin/tahoe: clean up global-vs-subcommand arguments like --node-directory

The new rules for "bin/tahoe ARG1.. SUBCOMMAND ARG2.." arg:

* --node-directory is only accepted in ARG1, not ARG2
* create-*/start/stop/restart accept --basedir in ARG2, or an explicit
  basedir argument
* only one of --node-directory/--basedir/explicit-basedir is accepted
* --quiet/--version is only accepted in ARG1, not ARG2

Closes #166
  • Loading branch information...
1 parent f86a411 commit de15710cc29bb8104f9ee0f9e365f28c7ec7d24d @warner committed Jun 18, 2012
@@ -1,12 +1,13 @@
from twisted.python import usage
+from allmydata.scripts.common import BaseOptions
-class GenerateKeypairOptions(usage.Options):
+class GenerateKeypairOptions(BaseOptions):
def getSynopsis(self):
return "Usage: tahoe admin generate-keypair"
def getUsage(self, width=None):
- t = usage.Options.getUsage(self, width)
+ t = BaseOptions.getUsage(self, width)
t += """
Generate a public/private keypair, dumped to stdout as two lines of ASCII..
@@ -20,15 +21,15 @@ def print_keypair(options):
print >>out, "private:", privkey_vs
print >>out, "public:", pubkey_vs
-class DerivePubkeyOptions(usage.Options):
+class DerivePubkeyOptions(BaseOptions):
def parseArgs(self, privkey):
self.privkey = privkey
def getSynopsis(self):
return "Usage: tahoe admin derive-pubkey PRIVKEY"
def getUsage(self, width=None):
- t = usage.Options.getUsage(self, width)
+ t = BaseOptions.getUsage(self, width)
t += """
Given a private (signing) key that was previously generated with
generate-keypair, derive the public key and print it to stdout.
@@ -45,7 +46,7 @@ def derive_pubkey(options):
print >>out, "public:", pubkey_vs
return 0
-class AdminCommand(usage.Options):
+class AdminCommand(BaseOptions):
subCommands = [
("generate-keypair", None, GenerateKeypairOptions,
"Generate a public/private keypair, write to stdout."),
@@ -58,7 +59,7 @@ def postOptions(self):
def getSynopsis(self):
return "Usage: tahoe admin SUBCOMMAND"
def getUsage(self, width=None):
- t = usage.Options.getUsage(self, width)
+ t = BaseOptions.getUsage(self, width)
t += """
Please run e.g. 'tahoe admin generate-keypair --help' for more details on
each subcommand.
@@ -1,6 +1,7 @@
import os.path, re, fnmatch
from twisted.python import usage
-from allmydata.scripts.common import BaseOptions, get_aliases, get_default_nodedir, DEFAULT_ALIAS
+from allmydata.scripts.common import get_aliases, get_default_nodedir, \
+ DEFAULT_ALIAS, BaseOptions
from allmydata.util.encodingutil import argv_to_unicode, argv_to_abspath, quote_output
NODEURL_RE=re.compile("http(s?)://([^:]*)(:([1-9][0-9]*))?")
@@ -9,23 +10,18 @@
class VDriveOptions(BaseOptions):
optParameters = [
- ["node-directory", "d", None,
- "Specify which Tahoe node directory should be used. The directory "
- "should either contain a full Tahoe node, or a file named node.url "
- "that points to some other Tahoe node. It should also contain a file "
- "named '" + os.path.join('private', 'aliases') + "' which contains the "
- "mapping from alias name to root dirnode URI." + (
- _default_nodedir and (" [default: " + quote_output(_default_nodedir) + "]") or "")],
["node-url", "u", None,
- "Specify the URL of the Tahoe gateway node, such as 'http://127.0.0.1:3456'. "
+ "Specify the URL of the Tahoe gateway node, such as "
+ "'http://127.0.0.1:3456'. "
"This overrides the URL found in the --node-directory ."],
["dir-cap", None, None,
"Specify which dirnode URI should be used as the 'tahoe' alias."]
]
def postOptions(self):
- if self['node-directory']:
- self['node-directory'] = argv_to_abspath(self['node-directory'])
+ self["quiet"] = self.parent["quiet"]
+ if self.parent['node-directory']:
+ self['node-directory'] = argv_to_abspath(self.parent['node-directory'])
else:
self['node-directory'] = _default_nodedir
@@ -25,58 +25,42 @@ def get_default_nodedir():
class BaseOptions(usage.Options):
- # unit tests can override these to point at StringIO instances
- stdin = sys.stdin
- stdout = sys.stdout
- stderr = sys.stderr
-
- optFlags = [
- ["quiet", "q", "Operate silently."],
- ["version", "V", "Display version numbers."],
- ["version-and-path", None, "Display version numbers and paths to their locations."],
- ]
- optParameters = [
- ["node-directory", "d", None, "Specify which Tahoe node directory should be used." + (
- _default_nodedir and (" [default for most commands: " + quote_output(_default_nodedir) + "]") or "")],
- ]
-
def __init__(self):
super(BaseOptions, self).__init__()
self.command_name = os.path.basename(sys.argv[0])
if self.command_name == 'trial':
self.command_name = 'tahoe'
+ # Only allow "tahoe --version", not e.g. "tahoe start --version"
def opt_version(self):
- import allmydata
- print >>self.stdout, allmydata.get_package_versions_string(debug=True)
- self.no_command_needed = True
+ raise usage.UsageError("--version not allowed on subcommands")
- def opt_version_and_path(self):
- import allmydata
- print >>self.stdout, allmydata.get_package_versions_string(show_paths=True, debug=True)
- self.no_command_needed = True
-
-
-class BasedirMixin:
+class BasedirOptions(BaseOptions):
default_nodedir = _default_nodedir
optParameters = [
- ["basedir", "C", None, "Same as --node-directory."],
+ ["basedir", "C", None, "Same as --node-directory (default %s)."
+ % get_default_nodedir()],
]
def parseArgs(self, basedir=None):
- if self['node-directory'] and self['basedir']:
- raise usage.UsageError("The --node-directory (or -d) and --basedir (or -C) "
- "options cannot both be used.")
+ if self.parent['node-directory'] and self['basedir']:
+ raise usage.UsageError("The --node-directory (or -d) and --basedir (or -C) options cannot both be used.")
+ if self.parent['node-directory'] and basedir:
+ raise usage.UsageError("The --node-directory (or -d) option and a basedir argument cannot both be used.")
+ if self['basedir'] and basedir:
+ raise usage.UsageError("The --basedir (or -C) option and a basedir argument cannot both be used.")
if basedir:
b = argv_to_abspath(basedir)
elif self['basedir']:
b = argv_to_abspath(self['basedir'])
- elif self['node-directory']:
- b = argv_to_abspath(self['node-directory'])
- else:
+ elif self.parent['node-directory']:
+ b = argv_to_abspath(self.parent['node-directory'])
+ elif self.default_nodedir:
b = self.default_nodedir
+ else:
+ raise usage.UsageError("No default basedir available, you must provide one with --node-directory, --basedir, or a basedir argument")
self['basedir'] = b
def postOptions(self):
@@ -1,11 +1,11 @@
import os, sys
-from allmydata.scripts.common import BasedirMixin, BaseOptions
+from allmydata.scripts.common import BasedirOptions
from allmydata.util.assertutil import precondition
from allmydata.util.encodingutil import listdir_unicode, argv_to_unicode, quote_output
import allmydata
-class CreateClientOptions(BasedirMixin, BaseOptions):
+class CreateClientOptions(BasedirOptions):
optParameters = [
# we provide 'create-node'-time options for the most common
# configuration knobs. The rest can be controlled by editing
@@ -29,13 +29,9 @@ def getSynopsis(self):
return "Usage: %s create-node [options] [NODEDIR]" % (self.command_name,)
-class CreateIntroducerOptions(BasedirMixin, BaseOptions):
+class CreateIntroducerOptions(BasedirOptions):
default_nodedir = None
- optParameters = [
- ["node-directory", "d", None, "Specify which directory the introducer should be created in. [no default]"],
- ]
-
def getSynopsis(self):
return "Usage: %s create-introducer [options] NODEDIR" % (self.command_name,)
@@ -6,9 +6,10 @@
from twisted.internet import defer
from twisted.scripts import trial as twisted_trial
from foolscap.logging import cli as foolscap_cli
+from allmydata.scripts.common import BaseOptions
-class DumpOptions(usage.Options):
+class DumpOptions(BaseOptions):
def getSynopsis(self):
return "Usage: tahoe debug dump-share SHARE_FILENAME"
@@ -18,7 +19,7 @@ def getSynopsis(self):
]
def getUsage(self, width=None):
- t = usage.Options.getUsage(self, width)
+ t = BaseOptions.getUsage(self, width)
t += """
Print lots of information about the given share, by parsing the share's
contents. This includes share type, lease information, encoding parameters,
@@ -405,7 +406,7 @@ def printoffset(name, value, shift=0):
-class DumpCapOptions(usage.Options):
+class DumpCapOptions(BaseOptions):
def getSynopsis(self):
return "Usage: tahoe debug dump-cap [options] FILECAP"
optParameters = [
@@ -420,7 +421,7 @@ def parseArgs(self, cap):
self.cap = cap
def getUsage(self, width=None):
- t = usage.Options.getUsage(self, width)
+ t = BaseOptions.getUsage(self, width)
t += """
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
@@ -607,7 +608,7 @@ def dump_uri_instance(u, nodeid, secret, out, show_header=True):
else:
print >>out, "unknown cap type"
-class FindSharesOptions(usage.Options):
+class FindSharesOptions(BaseOptions):
def getSynopsis(self):
return "Usage: tahoe debug find-shares STORAGE_INDEX NODEDIRS.."
@@ -617,7 +618,7 @@ def parseArgs(self, storage_index_s, *nodedirs):
self.nodedirs = map(argv_to_abspath, nodedirs)
def getUsage(self, width=None):
- t = usage.Options.getUsage(self, width)
+ t = BaseOptions.getUsage(self, width)
t += """
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,
@@ -657,7 +658,7 @@ def find_shares(options):
return 0
-class CatalogSharesOptions(usage.Options):
+class CatalogSharesOptions(BaseOptions):
"""
"""
@@ -671,7 +672,7 @@ def getSynopsis(self):
return "Usage: tahoe debug catalog-shares NODEDIRS.."
def getUsage(self, width=None):
- t = usage.Options.getUsage(self, width)
+ t = BaseOptions.getUsage(self, width)
t += """
Locate all shares in the given node directories, and emit a one-line summary
of each share. Run it like this:
@@ -879,7 +880,7 @@ def catalog_shares_one_abbrevdir(si_s, si_dir, now, out, err):
print >>err, "Error processing %s" % quote_output(si_dir)
failure.Failure().printTraceback(err)
-class CorruptShareOptions(usage.Options):
+class CorruptShareOptions(BaseOptions):
def getSynopsis(self):
return "Usage: tahoe debug corrupt-share SHARE_FILENAME"
@@ -888,7 +889,7 @@ def getSynopsis(self):
]
def getUsage(self, width=None):
- t = usage.Options.getUsage(self, width)
+ t = BaseOptions.getUsage(self, width)
t += """
Corrupt the given share by flipping a bit. This will cause a
verifying/downloading client to log an integrity-check failure incident, and
@@ -959,7 +960,7 @@ def flip_bit(start, end):
-class ReplOptions(usage.Options):
+class ReplOptions(BaseOptions):
def getSynopsis(self):
return "Usage: tahoe debug repl"
@@ -1042,7 +1043,7 @@ def flogtool(config):
return foolscap_cli.run_flogtool()
-class DebugCommand(usage.Options):
+class DebugCommand(BaseOptions):
subCommands = [
["dump-share", None, DumpOptions,
"Unpack and display the contents of a share (uri_extension and leases)."],
@@ -1060,7 +1061,7 @@ def postOptions(self):
def getSynopsis(self):
return ""
def getUsage(self, width=None):
- #t = usage.Options.getUsage(self, width)
+ #t = BaseOptions.getUsage(self, width)
t = """Usage: tahoe debug SUBCOMMAND
Subcommands:
tahoe debug dump-share Unpack and display the contents of a share.
@@ -1,16 +1,12 @@
import os, sys
-from allmydata.scripts.common import BasedirMixin, BaseOptions
+from allmydata.scripts.common import BasedirOptions
from allmydata.util.assertutil import precondition
from allmydata.util.encodingutil import listdir_unicode, quote_output
-class CreateKeyGeneratorOptions(BasedirMixin, BaseOptions):
+class CreateKeyGeneratorOptions(BasedirOptions):
default_nodedir = None
- optParameters = [
- ["node-directory", "d", None, "Specify which directory the key-generator should be created in. [no default]"],
- ]
-
def getSynopsis(self):
return "Usage: %s create-key-generator [options] NODEDIR" % (self.command_name,)
Oops, something went wrong.

1 comment on commit de15710

Contributor
zooko commented on de15710 Apr 9, 2013

Okay, I read through this and didn't see any problem with it!

Please sign in to comment.