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..
print >>out, "private:", privkey_vs
print >>out, "public:", pubkey_vs
-class DerivePubkeyOptions(usage.Options):
+class DerivePubkeyOptions(BaseOptions):
def parseArgs(self, privkey):
self.privkey = privkey
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.
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."),
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.
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]*))?")
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
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):
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
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,)
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"
]
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,
-class DumpCapOptions(usage.Options):
+class DumpCapOptions(BaseOptions):
def getSynopsis(self):
return "Usage: tahoe debug dump-cap [options] FILECAP"
optParameters = [
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
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.."
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,
return 0
-class CatalogSharesOptions(usage.Options):
+class CatalogSharesOptions(BaseOptions):
"""
"""
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:
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"
]
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
-class ReplOptions(usage.Options):
+class ReplOptions(BaseOptions):
def getSynopsis(self):
return "Usage: tahoe debug repl"
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)."],
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.
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,)
-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
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
+ 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"
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."],
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."],
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,)
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,)
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,
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()
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)
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'))
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',))
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'))
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,))
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):
_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"])
+
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, "")
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)):
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)):
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)):
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)):
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]
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)):
# 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, "")
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=[]):
# 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)):
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):