mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-20 17:52:50 +00:00
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
This commit is contained in:
parent
643eb4f372
commit
5874a7d3a7
@ -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,7 +21,7 @@ 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
|
||||
|
||||
@ -28,7 +29,7 @@ class DerivePubkeyOptions(usage.Options):
|
||||
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 @@ class AdminCommand(usage.Options):
|
||||
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 @@ _default_nodedir = get_default_nodedir()
|
||||
|
||||
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 @@ class CreateNodeOptions(CreateClientOptions):
|
||||
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.python import usage, failure
|
||||
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 @@ class DumpOptions(usage.Options):
|
||||
]
|
||||
|
||||
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 dump_MDMF_share(m, length, options):
|
||||
|
||||
|
||||
|
||||
class DumpCapOptions(usage.Options):
|
||||
class DumpCapOptions(BaseOptions):
|
||||
def getSynopsis(self):
|
||||
return "Usage: tahoe debug dump-cap [options] FILECAP"
|
||||
optParameters = [
|
||||
@ -420,7 +421,7 @@ class DumpCapOptions(usage.Options):
|
||||
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 @@ class FindSharesOptions(usage.Options):
|
||||
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 @@ class CatalogSharesOptions(usage.Options):
|
||||
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 @@ class CorruptShareOptions(usage.Options):
|
||||
]
|
||||
|
||||
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 corrupt_share(options):
|
||||
|
||||
|
||||
|
||||
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 @@ class DebugCommand(usage.Options):
|
||||
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,)
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
|
||||
import sys
|
||||
import os, sys
|
||||
from cStringIO import StringIO
|
||||
|
||||
from twisted.python import usage
|
||||
|
||||
from allmydata.scripts.common import BaseOptions
|
||||
from allmydata.scripts.common import get_default_nodedir
|
||||
from allmydata.scripts import debug, create_node, startstop_node, cli, keygen, stats_gatherer, admin
|
||||
from allmydata.util.encodingutil import quote_output, get_io_encoding
|
||||
|
||||
@ -15,7 +15,24 @@ def GROUP(s):
|
||||
return [("\n" + s, None, None, None)]
|
||||
|
||||
|
||||
class Options(BaseOptions, usage.Options):
|
||||
_default_nodedir = get_default_nodedir()
|
||||
|
||||
NODEDIR_HELP = ("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.")
|
||||
if _default_nodedir:
|
||||
NODEDIR_HELP += " [default for most commands: " + quote_output(_default_nodedir) + "]"
|
||||
|
||||
class Options(usage.Options):
|
||||
# unit tests can override these to point at StringIO instances
|
||||
stdin = sys.stdin
|
||||
stdout = sys.stdout
|
||||
stderr = sys.stderr
|
||||
|
||||
synopsis = "\nUsage: tahoe <command> [command options]"
|
||||
subCommands = ( GROUP("Administration")
|
||||
+ create_node.subCommands
|
||||
@ -30,6 +47,28 @@ class Options(BaseOptions, usage.Options):
|
||||
+ cli.subCommands
|
||||
)
|
||||
|
||||
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, NODEDIR_HELP],
|
||||
]
|
||||
|
||||
def opt_version(self):
|
||||
import allmydata
|
||||
print >>self.stdout, allmydata.get_package_versions_string(debug=True)
|
||||
self.no_command_needed = True
|
||||
|
||||
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
|
||||
|
||||
def getSynopsis(self):
|
||||
return "\nUsage: tahoe [global-options] <command> [command-options]"
|
||||
|
||||
def getUsage(self, **kwargs):
|
||||
t = usage.Options.getUsage(self, **kwargs)
|
||||
return t + "\nPlease run 'tahoe <command> --help' for more details on each command.\n"
|
||||
|
@ -1,12 +1,12 @@
|
||||
|
||||
import os, sys, signal, time
|
||||
from allmydata.scripts.common import BasedirMixin, BaseOptions
|
||||
from allmydata.scripts.common import BasedirOptions
|
||||
from allmydata.util import fileutil
|
||||
from allmydata.util.assertutil import precondition
|
||||
from allmydata.util.encodingutil import listdir_unicode, quote_output
|
||||
|
||||
|
||||
class StartOptions(BasedirMixin, BaseOptions):
|
||||
class StartOptions(BasedirOptions):
|
||||
optFlags = [
|
||||
["profile", "p", "Run under the Python profiler, putting results in 'profiling_results.prof'."],
|
||||
["syslog", None, "Tell the node to log to syslog, not a file."],
|
||||
@ -16,12 +16,12 @@ class StartOptions(BasedirMixin, BaseOptions):
|
||||
return "Usage: %s start [options] [NODEDIR]" % (self.command_name,)
|
||||
|
||||
|
||||
class StopOptions(BasedirMixin, BaseOptions):
|
||||
class StopOptions(BasedirOptions):
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s stop [options] [NODEDIR]" % (self.command_name,)
|
||||
|
||||
|
||||
class RestartOptions(BasedirMixin, BaseOptions):
|
||||
class RestartOptions(BasedirOptions):
|
||||
optFlags = [
|
||||
["profile", "p", "Run under the Python profiler, putting results in 'profiling_results.prof'."],
|
||||
["syslog", None, "Tell the node to log to syslog, not a file."],
|
||||
@ -31,13 +31,9 @@ class RestartOptions(BasedirMixin, BaseOptions):
|
||||
return "Usage: %s restart [options] [NODEDIR]" % (self.command_name,)
|
||||
|
||||
|
||||
class RunOptions(BasedirMixin, BaseOptions):
|
||||
class RunOptions(BasedirOptions):
|
||||
default_nodedir = u"."
|
||||
|
||||
optParameters = [
|
||||
["node-directory", "d", None, "Specify the directory of the node to be run. [default, for 'tahoe run' only: current directory]"],
|
||||
]
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s run [options] [NODEDIR]" % (self.command_name,)
|
||||
|
||||
|
@ -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 CreateStatsGathererOptions(BasedirMixin, BaseOptions):
|
||||
class CreateStatsGathererOptions(BasedirOptions):
|
||||
default_nodedir = None
|
||||
|
||||
optParameters = [
|
||||
["node-directory", "d", None, "Specify which directory the stats-gatherer should be created in. [no default]"],
|
||||
]
|
||||
|
||||
def getSynopsis(self):
|
||||
return "Usage: %s create-stats-gatherer [options] NODEDIR" % (self.command_name,)
|
||||
|
||||
|
@ -44,13 +44,19 @@ from allmydata.util.fileutil import abspath_expanduser_unicode
|
||||
|
||||
timeout = 480 # deep_check takes 360s on Zandr's linksys box, others take > 240s
|
||||
|
||||
def parse_options(basedir, command, args):
|
||||
o = runner.Options()
|
||||
o.parseOptions(["--node-directory", basedir, command] + args)
|
||||
while hasattr(o, "subOptions"):
|
||||
o = o.subOptions
|
||||
return o
|
||||
|
||||
class CLITestMixin(ReallyEqualMixin):
|
||||
def do_cli(self, verb, *args, **kwargs):
|
||||
nodeargs = [
|
||||
"--node-directory", self.get_clientdir(),
|
||||
]
|
||||
argv = [verb] + nodeargs + list(args)
|
||||
argv = nodeargs + [verb] + list(args)
|
||||
stdin = kwargs.get("stdin", "")
|
||||
stdout, stderr = StringIO(), StringIO()
|
||||
d = threads.deferToThread(runner.runner, argv, run_by_human=False,
|
||||
@ -73,69 +79,6 @@ class CLITestMixin(ReallyEqualMixin):
|
||||
|
||||
|
||||
class CLI(CLITestMixin, unittest.TestCase):
|
||||
# this test case only looks at argument-processing and simple stuff.
|
||||
def test_options(self):
|
||||
fileutil.rm_dir("cli/test_options")
|
||||
fileutil.make_dirs("cli/test_options")
|
||||
fileutil.make_dirs("cli/test_options/private")
|
||||
fileutil.write("cli/test_options/node.url", "http://localhost:8080/\n")
|
||||
filenode_uri = uri.WriteableSSKFileURI(writekey="\x00"*16,
|
||||
fingerprint="\x00"*32)
|
||||
private_uri = uri.DirectoryURI(filenode_uri).to_string()
|
||||
fileutil.write("cli/test_options/private/root_dir.cap", private_uri + "\n")
|
||||
o = cli.ListOptions()
|
||||
o.parseOptions(["--node-directory", "cli/test_options"])
|
||||
self.failUnlessReallyEqual(o['node-url'], "http://localhost:8080/")
|
||||
self.failUnlessReallyEqual(o.aliases[DEFAULT_ALIAS], private_uri)
|
||||
self.failUnlessReallyEqual(o.where, u"")
|
||||
|
||||
o = cli.ListOptions()
|
||||
o.parseOptions(["--node-directory", "cli/test_options",
|
||||
"--node-url", "http://example.org:8111/"])
|
||||
self.failUnlessReallyEqual(o['node-url'], "http://example.org:8111/")
|
||||
self.failUnlessReallyEqual(o.aliases[DEFAULT_ALIAS], private_uri)
|
||||
self.failUnlessReallyEqual(o.where, u"")
|
||||
|
||||
o = cli.ListOptions()
|
||||
o.parseOptions(["--node-directory", "cli/test_options",
|
||||
"--dir-cap", "root"])
|
||||
self.failUnlessReallyEqual(o['node-url'], "http://localhost:8080/")
|
||||
self.failUnlessReallyEqual(o.aliases[DEFAULT_ALIAS], "root")
|
||||
self.failUnlessReallyEqual(o.where, u"")
|
||||
|
||||
o = cli.ListOptions()
|
||||
other_filenode_uri = uri.WriteableSSKFileURI(writekey="\x11"*16,
|
||||
fingerprint="\x11"*32)
|
||||
other_uri = uri.DirectoryURI(other_filenode_uri).to_string()
|
||||
o.parseOptions(["--node-directory", "cli/test_options",
|
||||
"--dir-cap", other_uri])
|
||||
self.failUnlessReallyEqual(o['node-url'], "http://localhost:8080/")
|
||||
self.failUnlessReallyEqual(o.aliases[DEFAULT_ALIAS], other_uri)
|
||||
self.failUnlessReallyEqual(o.where, u"")
|
||||
|
||||
o = cli.ListOptions()
|
||||
o.parseOptions(["--node-directory", "cli/test_options",
|
||||
"--dir-cap", other_uri, "subdir"])
|
||||
self.failUnlessReallyEqual(o['node-url'], "http://localhost:8080/")
|
||||
self.failUnlessReallyEqual(o.aliases[DEFAULT_ALIAS], other_uri)
|
||||
self.failUnlessReallyEqual(o.where, u"subdir")
|
||||
|
||||
o = cli.ListOptions()
|
||||
self.failUnlessRaises(usage.UsageError,
|
||||
o.parseOptions,
|
||||
["--node-directory", "cli/test_options",
|
||||
"--node-url", "NOT-A-URL"])
|
||||
|
||||
o = cli.ListOptions()
|
||||
o.parseOptions(["--node-directory", "cli/test_options",
|
||||
"--node-url", "http://localhost:8080"])
|
||||
self.failUnlessReallyEqual(o["node-url"], "http://localhost:8080/")
|
||||
|
||||
o = cli.ListOptions()
|
||||
o.parseOptions(["--node-directory", "cli/test_options",
|
||||
"--node-url", "https://localhost/"])
|
||||
self.failUnlessReallyEqual(o["node-url"], "https://localhost/")
|
||||
|
||||
def _dump_cap(self, *args):
|
||||
config = debug.DumpCapOptions()
|
||||
config.stdout,config.stderr = StringIO(), StringIO()
|
||||
@ -730,11 +673,11 @@ class Help(unittest.TestCase):
|
||||
class CreateAlias(GridTestMixin, CLITestMixin, unittest.TestCase):
|
||||
|
||||
def _test_webopen(self, args, expected_url):
|
||||
woo = cli.WebopenOptions()
|
||||
all_args = ["--node-directory", self.get_clientdir()] + list(args)
|
||||
woo.parseOptions(all_args)
|
||||
o = runner.Options()
|
||||
o.parseOptions(["--node-directory", self.get_clientdir(), "webopen"]
|
||||
+ list(args))
|
||||
urls = []
|
||||
rc = cli.webopen(woo, urls.append)
|
||||
rc = cli.webopen(o, urls.append)
|
||||
self.failUnlessReallyEqual(rc, 0)
|
||||
self.failUnlessReallyEqual(len(urls), 1)
|
||||
self.failUnlessReallyEqual(urls[0], expected_url)
|
||||
@ -2747,25 +2690,20 @@ class Backup(GridTestMixin, CLITestMixin, StallMixin, unittest.TestCase):
|
||||
fileutil.make_dirs(basedir)
|
||||
nodeurl_path = os.path.join(basedir, 'node.url')
|
||||
fileutil.write(nodeurl_path, 'http://example.net:2357/')
|
||||
def parse(args): return parse_options(basedir, "backup", args)
|
||||
|
||||
# test simple exclude
|
||||
backup_options = cli.BackupOptions()
|
||||
backup_options.parseOptions(['--exclude', '*lyx', '--node-directory',
|
||||
basedir, 'from', 'to'])
|
||||
backup_options = parse(['--exclude', '*lyx', 'from', 'to'])
|
||||
filtered = list(backup_options.filter_listdir(root_listdir))
|
||||
self._check_filtering(filtered, root_listdir, (u'lib.a', u'_darcs', u'subdir'),
|
||||
(u'nice_doc.lyx',))
|
||||
# multiple exclude
|
||||
backup_options = cli.BackupOptions()
|
||||
backup_options.parseOptions(['--exclude', '*lyx', '--exclude', 'lib.?', '--node-directory',
|
||||
basedir, 'from', 'to'])
|
||||
backup_options = parse(['--exclude', '*lyx', '--exclude', 'lib.?', 'from', 'to'])
|
||||
filtered = list(backup_options.filter_listdir(root_listdir))
|
||||
self._check_filtering(filtered, root_listdir, (u'_darcs', u'subdir'),
|
||||
(u'nice_doc.lyx', u'lib.a'))
|
||||
# vcs metadata exclusion
|
||||
backup_options = cli.BackupOptions()
|
||||
backup_options.parseOptions(['--exclude-vcs', '--node-directory',
|
||||
basedir, 'from', 'to'])
|
||||
backup_options = parse(['--exclude-vcs', 'from', 'to'])
|
||||
filtered = list(backup_options.filter_listdir(subdir_listdir))
|
||||
self._check_filtering(filtered, subdir_listdir, (u'another_doc.lyx', u'run_snake_run.py',),
|
||||
(u'CVS', u'.svn', u'_darcs'))
|
||||
@ -2773,22 +2711,17 @@ class Backup(GridTestMixin, CLITestMixin, StallMixin, unittest.TestCase):
|
||||
exclusion_string = "_darcs\n*py\n.svn"
|
||||
excl_filepath = os.path.join(basedir, 'exclusion')
|
||||
fileutil.write(excl_filepath, exclusion_string)
|
||||
backup_options = cli.BackupOptions()
|
||||
backup_options.parseOptions(['--exclude-from', excl_filepath, '--node-directory',
|
||||
basedir, 'from', 'to'])
|
||||
backup_options = parse(['--exclude-from', excl_filepath, 'from', 'to'])
|
||||
filtered = list(backup_options.filter_listdir(subdir_listdir))
|
||||
self._check_filtering(filtered, subdir_listdir, (u'another_doc.lyx', u'CVS'),
|
||||
(u'.svn', u'_darcs', u'run_snake_run.py'))
|
||||
# test BackupConfigurationError
|
||||
self.failUnlessRaises(cli.BackupConfigurationError,
|
||||
backup_options.parseOptions,
|
||||
['--exclude-from', excl_filepath + '.no', '--node-directory',
|
||||
basedir, 'from', 'to'])
|
||||
parse,
|
||||
['--exclude-from', excl_filepath + '.no', 'from', 'to'])
|
||||
|
||||
# test that an iterator works too
|
||||
backup_options = cli.BackupOptions()
|
||||
backup_options.parseOptions(['--exclude', '*lyx', '--node-directory',
|
||||
basedir, 'from', 'to'])
|
||||
backup_options = parse(['--exclude', '*lyx', 'from', 'to'])
|
||||
filtered = list(backup_options.filter_listdir(iter(root_listdir)))
|
||||
self._check_filtering(filtered, root_listdir, (u'lib.a', u'_darcs', u'subdir'),
|
||||
(u'nice_doc.lyx',))
|
||||
@ -2805,18 +2738,15 @@ class Backup(GridTestMixin, CLITestMixin, StallMixin, unittest.TestCase):
|
||||
fileutil.make_dirs(basedir)
|
||||
nodeurl_path = os.path.join(basedir, 'node.url')
|
||||
fileutil.write(nodeurl_path, 'http://example.net:2357/')
|
||||
def parse(args): return parse_options(basedir, "backup", args)
|
||||
|
||||
# test simple exclude
|
||||
backup_options = cli.BackupOptions()
|
||||
backup_options.parseOptions(['--exclude', doc_pattern_arg, '--node-directory',
|
||||
basedir, 'from', 'to'])
|
||||
backup_options = parse(['--exclude', doc_pattern_arg, 'from', 'to'])
|
||||
filtered = list(backup_options.filter_listdir(root_listdir))
|
||||
self._check_filtering(filtered, root_listdir, (u'lib.a', u'_darcs', u'subdir'),
|
||||
(nice_doc,))
|
||||
# multiple exclude
|
||||
backup_options = cli.BackupOptions()
|
||||
backup_options.parseOptions(['--exclude', doc_pattern_arg, '--exclude', 'lib.?', '--node-directory',
|
||||
basedir, 'from', 'to'])
|
||||
backup_options = parse(['--exclude', doc_pattern_arg, '--exclude', 'lib.?', 'from', 'to'])
|
||||
filtered = list(backup_options.filter_listdir(root_listdir))
|
||||
self._check_filtering(filtered, root_listdir, (u'_darcs', u'subdir'),
|
||||
(nice_doc, u'lib.a'))
|
||||
@ -2824,17 +2754,13 @@ class Backup(GridTestMixin, CLITestMixin, StallMixin, unittest.TestCase):
|
||||
exclusion_string = doc_pattern_arg + "\nlib.?"
|
||||
excl_filepath = os.path.join(basedir, 'exclusion')
|
||||
fileutil.write(excl_filepath, exclusion_string)
|
||||
backup_options = cli.BackupOptions()
|
||||
backup_options.parseOptions(['--exclude-from', excl_filepath, '--node-directory',
|
||||
basedir, 'from', 'to'])
|
||||
backup_options = parse(['--exclude-from', excl_filepath, 'from', 'to'])
|
||||
filtered = list(backup_options.filter_listdir(root_listdir))
|
||||
self._check_filtering(filtered, root_listdir, (u'_darcs', u'subdir'),
|
||||
(nice_doc, u'lib.a'))
|
||||
|
||||
# test that an iterator works too
|
||||
backup_options = cli.BackupOptions()
|
||||
backup_options.parseOptions(['--exclude', doc_pattern_arg, '--node-directory',
|
||||
basedir, 'from', 'to'])
|
||||
backup_options = parse(['--exclude', doc_pattern_arg, 'from', 'to'])
|
||||
filtered = list(backup_options.filter_listdir(iter(root_listdir)))
|
||||
self._check_filtering(filtered, root_listdir, (u'lib.a', u'_darcs', u'subdir'),
|
||||
(nice_doc,))
|
||||
@ -2845,14 +2771,13 @@ class Backup(GridTestMixin, CLITestMixin, StallMixin, unittest.TestCase):
|
||||
fileutil.make_dirs(basedir)
|
||||
nodeurl_path = os.path.join(basedir, 'node.url')
|
||||
fileutil.write(nodeurl_path, 'http://example.net:2357/')
|
||||
def parse(args): return parse_options(basedir, "backup", args)
|
||||
|
||||
# ensure that tilde expansion is performed on exclude-from argument
|
||||
exclude_file = u'~/.tahoe/excludes.dummy'
|
||||
backup_options = cli.BackupOptions()
|
||||
|
||||
mock.return_value = StringIO()
|
||||
backup_options.parseOptions(['--exclude-from', unicode_to_argv(exclude_file),
|
||||
'--node-directory', basedir, 'from', 'to'])
|
||||
parse(['--exclude-from', unicode_to_argv(exclude_file), 'from', 'to'])
|
||||
self.failUnlessIn(((abspath_expanduser_unicode(exclude_file),), {}), mock.call_args_list)
|
||||
|
||||
def test_ignore_symlinks(self):
|
||||
@ -3765,3 +3690,111 @@ class Webopen(GridTestMixin, CLITestMixin, unittest.TestCase):
|
||||
_cleanup(None)
|
||||
raise
|
||||
return d
|
||||
|
||||
class Options(unittest.TestCase):
|
||||
# this test case only looks at argument-processing and simple stuff.
|
||||
|
||||
def parse(self, args, stdout=None):
|
||||
o = runner.Options()
|
||||
if stdout is not None:
|
||||
o.stdout = stdout
|
||||
o.parseOptions(args)
|
||||
while hasattr(o, "subOptions"):
|
||||
o = o.subOptions
|
||||
return o
|
||||
|
||||
def test_list(self):
|
||||
fileutil.rm_dir("cli/test_options")
|
||||
fileutil.make_dirs("cli/test_options")
|
||||
fileutil.make_dirs("cli/test_options/private")
|
||||
fileutil.write("cli/test_options/node.url", "http://localhost:8080/\n")
|
||||
filenode_uri = uri.WriteableSSKFileURI(writekey="\x00"*16,
|
||||
fingerprint="\x00"*32)
|
||||
private_uri = uri.DirectoryURI(filenode_uri).to_string()
|
||||
fileutil.write("cli/test_options/private/root_dir.cap", private_uri + "\n")
|
||||
def parse2(args): return parse_options("cli/test_options", "ls", args)
|
||||
o = parse2([])
|
||||
self.failUnlessEqual(o['node-url'], "http://localhost:8080/")
|
||||
self.failUnlessEqual(o.aliases[DEFAULT_ALIAS], private_uri)
|
||||
self.failUnlessEqual(o.where, u"")
|
||||
|
||||
o = parse2(["--node-url", "http://example.org:8111/"])
|
||||
self.failUnlessEqual(o['node-url'], "http://example.org:8111/")
|
||||
self.failUnlessEqual(o.aliases[DEFAULT_ALIAS], private_uri)
|
||||
self.failUnlessEqual(o.where, u"")
|
||||
|
||||
o = parse2(["--dir-cap", "root"])
|
||||
self.failUnlessEqual(o['node-url'], "http://localhost:8080/")
|
||||
self.failUnlessEqual(o.aliases[DEFAULT_ALIAS], "root")
|
||||
self.failUnlessEqual(o.where, u"")
|
||||
|
||||
other_filenode_uri = uri.WriteableSSKFileURI(writekey="\x11"*16,
|
||||
fingerprint="\x11"*32)
|
||||
other_uri = uri.DirectoryURI(other_filenode_uri).to_string()
|
||||
o = parse2(["--dir-cap", other_uri])
|
||||
self.failUnlessEqual(o['node-url'], "http://localhost:8080/")
|
||||
self.failUnlessEqual(o.aliases[DEFAULT_ALIAS], other_uri)
|
||||
self.failUnlessEqual(o.where, u"")
|
||||
|
||||
o = parse2(["--dir-cap", other_uri, "subdir"])
|
||||
self.failUnlessEqual(o['node-url'], "http://localhost:8080/")
|
||||
self.failUnlessEqual(o.aliases[DEFAULT_ALIAS], other_uri)
|
||||
self.failUnlessEqual(o.where, u"subdir")
|
||||
|
||||
self.failUnlessRaises(usage.UsageError, parse2,
|
||||
["--node-url", "NOT-A-URL"])
|
||||
|
||||
o = parse2(["--node-url", "http://localhost:8080"])
|
||||
self.failUnlessEqual(o["node-url"], "http://localhost:8080/")
|
||||
|
||||
o = parse2(["--node-url", "https://localhost/"])
|
||||
self.failUnlessEqual(o["node-url"], "https://localhost/")
|
||||
|
||||
def test_version(self):
|
||||
# "tahoe --version" dumps text to stdout and exits
|
||||
stdout = StringIO()
|
||||
self.failUnlessRaises(SystemExit, self.parse, ["--version"], stdout)
|
||||
self.failUnlessIn("allmydata-tahoe", stdout.getvalue())
|
||||
# but "tahoe SUBCOMMAND --version" should be rejected
|
||||
self.failUnlessRaises(usage.UsageError, self.parse,
|
||||
["start", "--version"])
|
||||
self.failUnlessRaises(usage.UsageError, self.parse,
|
||||
["start", "--version-and-path"])
|
||||
|
||||
def test_quiet(self):
|
||||
# accepted as an overall option, but not on subcommands
|
||||
o = self.parse(["--quiet", "start"])
|
||||
self.failUnless(o.parent["quiet"])
|
||||
self.failUnlessRaises(usage.UsageError, self.parse,
|
||||
["start", "--quiet"])
|
||||
|
||||
def test_basedir(self):
|
||||
# accept a --node-directory option before the verb, or a --basedir
|
||||
# option after, or a basedir argument after, but none in the wrong
|
||||
# place, and not more than one of the three.
|
||||
o = self.parse(["start"])
|
||||
self.failUnlessEqual(o["basedir"], os.path.expanduser("~/.tahoe"))
|
||||
o = self.parse(["start", "here"])
|
||||
self.failUnlessEqual(o["basedir"], os.path.abspath("here"))
|
||||
o = self.parse(["start", "--basedir", "there"])
|
||||
self.failUnlessEqual(o["basedir"], os.path.abspath("there"))
|
||||
o = self.parse(["--node-directory", "there", "start"])
|
||||
self.failUnlessEqual(o["basedir"], os.path.abspath("there"))
|
||||
|
||||
self.failUnlessRaises(usage.UsageError, self.parse,
|
||||
["--basedir", "there", "start"])
|
||||
self.failUnlessRaises(usage.UsageError, self.parse,
|
||||
["start", "--node-directory", "there"])
|
||||
|
||||
self.failUnlessRaises(usage.UsageError, self.parse,
|
||||
["--node-directory=there",
|
||||
"start", "--basedir=here"])
|
||||
self.failUnlessRaises(usage.UsageError, self.parse,
|
||||
["start", "--basedir=here", "anywhere"])
|
||||
self.failUnlessRaises(usage.UsageError, self.parse,
|
||||
["--node-directory=there",
|
||||
"start", "anywhere"])
|
||||
self.failUnlessRaises(usage.UsageError, self.parse,
|
||||
["--node-directory=there",
|
||||
"start", "--basedir=here", "anywhere"])
|
||||
|
||||
|
@ -759,8 +759,8 @@ class DeepCheckWebGood(DeepCheckBase, unittest.TestCase):
|
||||
|
||||
def do_cli_manifest_stream1(self):
|
||||
basedir = self.get_clientdir(0)
|
||||
d = self._run_cli(["manifest",
|
||||
"--node-directory", basedir,
|
||||
d = self._run_cli(["--node-directory", basedir,
|
||||
"manifest",
|
||||
self.root_uri])
|
||||
def _check((out,err)):
|
||||
self.failUnlessEqual(err, "")
|
||||
@ -787,8 +787,8 @@ class DeepCheckWebGood(DeepCheckBase, unittest.TestCase):
|
||||
|
||||
def do_cli_manifest_stream2(self):
|
||||
basedir = self.get_clientdir(0)
|
||||
d = self._run_cli(["manifest",
|
||||
"--node-directory", basedir,
|
||||
d = self._run_cli(["--node-directory", basedir,
|
||||
"manifest",
|
||||
"--raw",
|
||||
self.root_uri])
|
||||
def _check((out,err)):
|
||||
@ -800,8 +800,8 @@ class DeepCheckWebGood(DeepCheckBase, unittest.TestCase):
|
||||
|
||||
def do_cli_manifest_stream3(self):
|
||||
basedir = self.get_clientdir(0)
|
||||
d = self._run_cli(["manifest",
|
||||
"--node-directory", basedir,
|
||||
d = self._run_cli(["--node-directory", basedir,
|
||||
"manifest",
|
||||
"--storage-index",
|
||||
self.root_uri])
|
||||
def _check((out,err)):
|
||||
@ -812,8 +812,8 @@ class DeepCheckWebGood(DeepCheckBase, unittest.TestCase):
|
||||
|
||||
def do_cli_manifest_stream4(self):
|
||||
basedir = self.get_clientdir(0)
|
||||
d = self._run_cli(["manifest",
|
||||
"--node-directory", basedir,
|
||||
d = self._run_cli(["--node-directory", basedir,
|
||||
"manifest",
|
||||
"--verify-cap",
|
||||
self.root_uri])
|
||||
def _check((out,err)):
|
||||
@ -828,8 +828,8 @@ class DeepCheckWebGood(DeepCheckBase, unittest.TestCase):
|
||||
|
||||
def do_cli_manifest_stream5(self):
|
||||
basedir = self.get_clientdir(0)
|
||||
d = self._run_cli(["manifest",
|
||||
"--node-directory", basedir,
|
||||
d = self._run_cli(["--node-directory", basedir,
|
||||
"manifest",
|
||||
"--repair-cap",
|
||||
self.root_uri])
|
||||
def _check((out,err)):
|
||||
@ -844,8 +844,8 @@ class DeepCheckWebGood(DeepCheckBase, unittest.TestCase):
|
||||
|
||||
def do_cli_stats1(self):
|
||||
basedir = self.get_clientdir(0)
|
||||
d = self._run_cli(["stats",
|
||||
"--node-directory", basedir,
|
||||
d = self._run_cli(["--node-directory", basedir,
|
||||
"stats",
|
||||
self.root_uri])
|
||||
def _check3((out,err)):
|
||||
lines = [l.strip() for l in out.split("\n") if l]
|
||||
@ -864,8 +864,8 @@ class DeepCheckWebGood(DeepCheckBase, unittest.TestCase):
|
||||
|
||||
def do_cli_stats2(self):
|
||||
basedir = self.get_clientdir(0)
|
||||
d = self._run_cli(["stats",
|
||||
"--node-directory", basedir,
|
||||
d = self._run_cli(["--node-directory", basedir,
|
||||
"stats",
|
||||
"--raw",
|
||||
self.root_uri])
|
||||
def _check4((out,err)):
|
||||
|
@ -284,7 +284,7 @@ class CreateNode(unittest.TestCase):
|
||||
|
||||
# test the --node-directory form
|
||||
n3 = os.path.join(basedir, command + "-n3")
|
||||
argv = ["--quiet", command, "--node-directory", n3]
|
||||
argv = ["--quiet", "--node-directory", n3, command]
|
||||
rc, out, err = self.run_tahoe(argv)
|
||||
self.failUnlessEqual(err, "")
|
||||
self.failUnlessEqual(out, "")
|
||||
|
@ -1440,7 +1440,7 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase):
|
||||
|
||||
def run(ignored, verb, *args, **kwargs):
|
||||
stdin = kwargs.get("stdin", "")
|
||||
newargs = [verb] + nodeargs + list(args)
|
||||
newargs = nodeargs + [verb] + list(args)
|
||||
return self._run_cli(newargs, stdin=stdin)
|
||||
|
||||
def _check_ls((out,err), expected_children, unexpected_children=[]):
|
||||
@ -1745,7 +1745,7 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase):
|
||||
# tahoe_ls doesn't currently handle the error correctly: it tries to
|
||||
# JSON-parse a traceback.
|
||||
## def _ls_missing(res):
|
||||
## argv = ["ls"] + nodeargs + ["bogus"]
|
||||
## argv = nodeargs + ["ls", "bogus"]
|
||||
## return self._run_cli(argv)
|
||||
## d.addCallback(_ls_missing)
|
||||
## def _check_ls_missing((out,err)):
|
||||
@ -1769,7 +1769,7 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase):
|
||||
def _run_in_subprocess(ignored, verb, *args, **kwargs):
|
||||
stdin = kwargs.get("stdin")
|
||||
env = kwargs.get("env")
|
||||
newargs = [verb, "--node-directory", self.getdir("client0")] + list(args)
|
||||
newargs = ["--node-directory", self.getdir("client0"), verb] + list(args)
|
||||
return self.run_bintahoe(newargs, stdin=stdin, env=env)
|
||||
|
||||
def _check_succeeded(res, check_stderr=True):
|
||||
|
Loading…
x
Reference in New Issue
Block a user