From 69b42c6cb7ec5d4a6ba1f54b75d1fceb94ef3fac Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@lothar.com>
Date: Sat, 27 Nov 2010 00:38:09 -0800
Subject: [PATCH] remove --multiple/-m option from all CLI commands: closes
 #1262

I personally used "tahoe start/restart -m ../MY-TESTNET/node*" all the time,
to spin up or update a local testgrid while iterating over new code. However,
with the recent switch from "subprocess.Popen(/bin/twistd)" to "import and
call twistd.run()" in scripts/startstop_node.py (yay fewer processes!),
"start -m" broke, and fixing it requires os.fork, which is unavailable on
windows (boo windows!). And I was probably the only one using -m. So in the
interests of uniformity among platforms and simpler code (yay negative code
days!), we're just removing -m from everything. I will start using a little
shell script or something to simulate the removed functionality.

This patch also cleans up CLI-function calling a bit: get the basedir from
the config dict (instead of sometimes from a separate argument), and always
return a numeric exit code.
---
 src/allmydata/scripts/common.py         | 34 ++++++++-----------------
 src/allmydata/scripts/create_node.py    | 13 ++++++----
 src/allmydata/scripts/keygen.py         |  3 ++-
 src/allmydata/scripts/runner.py         |  5 +---
 src/allmydata/scripts/startstop_node.py | 30 +++++-----------------
 src/allmydata/scripts/stats_gatherer.py |  3 ++-
 src/allmydata/test/test_runner.py       | 15 +----------
 7 files changed, 31 insertions(+), 72 deletions(-)

diff --git a/src/allmydata/scripts/common.py b/src/allmydata/scripts/common.py
index 96879b68..5eb31477 100644
--- a/src/allmydata/scripts/common.py
+++ b/src/allmydata/scripts/common.py
@@ -53,43 +53,29 @@ class BaseOptions(usage.Options):
 
 class BasedirMixin:
     default_nodedir = _default_nodedir
-    allow_multiple = True
 
     optParameters = [
         ["basedir", "C", None, "Same as --node-directory."],
     ]
-    optFlags = [
-        ["multiple", "m", "Specify multiple node directories at once."],
-    ]
 
-    def parseArgs(self, *args):
+    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['node-directory'] or self['basedir']:
-            self.basedirs = [argv_to_abspath(self['node-directory'] or self['basedir'])]
+        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:
-            self.basedirs = []
-
-        if self.allow_multiple and self['multiple']:
-            self.basedirs.extend(map(argv_to_abspath, args))
-        else:
-            if len(args) > 1:
-                raise usage.UsageError("I wasn't expecting so many arguments." +
-                    (self.allow_multiple and
-                     " Use the --multiple option to specify more than one node directory." or ""))
-
-            if len(args) == 0 and self.default_nodedir and not self.basedirs:
-                self.basedirs.append(self.default_nodedir)
-            elif len(args) > 0:
-                self.basedirs.append(argv_to_abspath(args[0]))
+            b = self.default_nodedir
+        self['basedir'] = b
 
     def postOptions(self):
-        if not self.basedirs:
+        if not self['basedir']:
             raise usage.UsageError("A base directory for the node must be provided.")
-        del self['basedir']
-        self['basedirs'] = self.basedirs
 
 
 DEFAULT_ALIAS = u"tahoe"
diff --git a/src/allmydata/scripts/create_node.py b/src/allmydata/scripts/create_node.py
index d12c0285..8f8e7850 100644
--- a/src/allmydata/scripts/create_node.py
+++ b/src/allmydata/scripts/create_node.py
@@ -89,7 +89,8 @@ def write_node_config(c, config):
     c.write("\n")
 
 
-def create_node(basedir, config, out=sys.stdout, err=sys.stderr):
+def create_node(config, out=sys.stdout, err=sys.stderr):
+    basedir = config['basedir']
     # This should always be called with an absolute Unicode basedir.
     precondition(isinstance(basedir, unicode), basedir)
 
@@ -144,14 +145,15 @@ def create_node(basedir, config, out=sys.stdout, err=sys.stderr):
         print >>out, " The node cannot connect to a grid without it."
     if not config.get("nickname", ""):
         print >>out, " Please set [node]nickname= in tahoe.cfg"
+    return 0
 
-
-def create_client(basedir, config, out=sys.stdout, err=sys.stderr):
+def create_client(config, out=sys.stdout, err=sys.stderr):
     config['no-storage'] = True
-    return create_node(basedir, config, out=out, err=err)
+    return create_node(config, out=out, err=err)
 
 
-def create_introducer(basedir, config, out=sys.stdout, err=sys.stderr):
+def create_introducer(config, out=sys.stdout, err=sys.stderr):
+    basedir = config['basedir']
     # This should always be called with an absolute Unicode basedir.
     precondition(isinstance(basedir, unicode), basedir)
 
@@ -173,6 +175,7 @@ def create_introducer(basedir, config, out=sys.stdout, err=sys.stderr):
     c.close()
 
     print >>out, "Introducer created in %s" % quote_output(basedir)
+    return 0
 
 
 subCommands = [
diff --git a/src/allmydata/scripts/keygen.py b/src/allmydata/scripts/keygen.py
index c1d09786..f2f78097 100644
--- a/src/allmydata/scripts/keygen.py
+++ b/src/allmydata/scripts/keygen.py
@@ -29,7 +29,8 @@ application = service.Application("allmydata_key_generator")
 k.setServiceParent(application)
 """
 
-def create_key_generator(basedir, config, out=sys.stdout, err=sys.stderr):
+def create_key_generator(config, out=sys.stdout, err=sys.stderr):
+    basedir = config['basedir']
     # This should always be called with an absolute Unicode basedir.
     precondition(isinstance(basedir, unicode), basedir)
 
diff --git a/src/allmydata/scripts/runner.py b/src/allmydata/scripts/runner.py
index 96333de9..1cd8a712 100644
--- a/src/allmydata/scripts/runner.py
+++ b/src/allmydata/scripts/runner.py
@@ -87,11 +87,8 @@ def runner(argv,
     so.stderr = stderr
     so.stdin = stdin
 
-    rc = 0
     if command in create_dispatch:
-        f = create_dispatch[command]
-        for basedir in so.basedirs:
-            rc = f(basedir, so, stdout, stderr) or rc
+        rc = create_dispatch[command](so, stdout, stderr)
     elif command in startstop_node.dispatch:
         rc = startstop_node.dispatch[command](so, stdout, stderr)
     elif command in debug.dispatch:
diff --git a/src/allmydata/scripts/startstop_node.py b/src/allmydata/scripts/startstop_node.py
index bc2616ea..893f2f30 100644
--- a/src/allmydata/scripts/startstop_node.py
+++ b/src/allmydata/scripts/startstop_node.py
@@ -22,14 +22,13 @@ class RestartOptions(BasedirMixin, BaseOptions):
 
 class RunOptions(BasedirMixin, BaseOptions):
     default_nodedir = u"."
-    allow_multiple = False
 
     optParameters = [
         ["node-directory", "d", None, "Specify the directory of the node to be run. [default, for 'tahoe run' only: current directory]"],
-        ["multiple", "m", None, "['tahoe run' cannot accept multiple node directories]"],
     ]
 
-def do_start(basedir, opts, out=sys.stdout, err=sys.stderr):
+def start(opts, out=sys.stdout, err=sys.stderr):
+    basedir = opts['basedir']
     print >>out, "STARTING", quote_output(basedir)
     if not os.path.isdir(basedir):
         print >>err, "%s does not look like a directory at all" % quote_output(basedir)
@@ -65,7 +64,8 @@ def do_start(basedir, opts, out=sys.stdout, err=sys.stderr):
     # we'll never get here. If application setup fails (e.g. ImportError),
     # run() will raise an exception.
 
-def do_stop(basedir, out=sys.stdout, err=sys.stderr):
+def stop(config, out=sys.stdout, err=sys.stderr):
+    basedir = config['basedir']
     print >>out, "STOPPING", quote_output(basedir)
     pidfile = os.path.join(basedir, "twistd.pid")
     if not os.path.exists(pidfile):
@@ -121,38 +121,22 @@ def do_stop(basedir, out=sys.stdout, err=sys.stderr):
     # we define rc=1 to mean "I think something is still running, sorry"
     return 1
 
-def start(config, stdout, stderr):
-    rc = 0
-    for basedir in config['basedirs']:
-        rc = do_start(basedir, config, stdout, stderr) or rc
-    return rc
-
-def stop(config, stdout, stderr):
-    rc = 0
-    for basedir in config['basedirs']:
-        rc = do_stop(basedir, stdout, stderr) or rc
-    return rc
-
 def restart(config, stdout, stderr):
-    rc = 0
-    for basedir in config['basedirs']:
-        rc = do_stop(basedir, stdout, stderr) or rc
+    rc = stop(config, stdout, stderr)
     if rc == 2:
         print >>stderr, "ignoring couldn't-stop"
         rc = 0
     if rc:
         print >>stderr, "not restarting"
         return rc
-    for basedir in config['basedirs']:
-        rc = do_start(basedir, config, stdout, stderr) or rc
-    return rc
+    return start(config, stdout, stderr)
 
 def run(config, stdout, stderr):
     from twisted.internet import reactor
     from twisted.python import log, logfile
     from allmydata import client
 
-    basedir = config['basedirs'][0]
+    basedir = config['basedir']
     precondition(isinstance(basedir, unicode), basedir)
 
     if not os.path.isdir(basedir):
diff --git a/src/allmydata/scripts/stats_gatherer.py b/src/allmydata/scripts/stats_gatherer.py
index 0764bfc5..54113ea7 100644
--- a/src/allmydata/scripts/stats_gatherer.py
+++ b/src/allmydata/scripts/stats_gatherer.py
@@ -26,7 +26,8 @@ g.setServiceParent(application)
 """
 
 
-def create_stats_gatherer(basedir, config, out=sys.stdout, err=sys.stderr):
+def create_stats_gatherer(config, out=sys.stdout, err=sys.stderr):
+    basedir = config['basedir']
     # This should always be called with an absolute Unicode basedir.
     precondition(isinstance(basedir, unicode), basedir)
 
diff --git a/src/allmydata/test/test_runner.py b/src/allmydata/test/test_runner.py
index 6a49f6bb..a87911ef 100644
--- a/src/allmydata/test/test_runner.py
+++ b/src/allmydata/test/test_runner.py
@@ -246,20 +246,7 @@ class CreateNode(unittest.TestCase):
         self.failUnless(os.path.exists(n3))
         self.failUnless(os.path.exists(os.path.join(n3, tac)))
 
-        # test the --multiple form
-        n4 = os.path.join(basedir, command + "-n4")
-        n5 = os.path.join(basedir, command + "-n5")
-        argv = ["--quiet", command, "--multiple", n4, n5]
-        rc, out, err = self.run_tahoe(argv)
-        self.failUnlessEqual(err, "")
-        self.failUnlessEqual(out, "")
-        self.failUnlessEqual(rc, 0)
-        self.failUnless(os.path.exists(n4))
-        self.failUnless(os.path.exists(os.path.join(n4, tac)))
-        self.failUnless(os.path.exists(n5))
-        self.failUnless(os.path.exists(os.path.join(n5, tac)))
-
-        # make sure it rejects too many arguments without --multiple
+        # make sure it rejects too many arguments
         argv = [command, "basedir", "extraarg"]
         self.failUnlessRaises(usage.UsageError,
                               runner.runner, argv,
-- 
2.45.2