From 2eec38279d0517b1485714363794e19836ed2f5e Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@lothar.com>
Date: Fri, 1 Aug 2008 19:10:41 -0700
Subject: [PATCH] CLI: add create-alias command, to merge mkdir and add-alias
 into a single (secure-from-argv-snooping) step

---
 docs/CLI.txt                             |  6 ++++-
 src/allmydata/scripts/cli.py             | 11 ++++++++
 src/allmydata/scripts/tahoe_add_alias.py | 28 +++++++++++++++++++++
 src/allmydata/test/test_cli.py           | 32 +++++++++++++++++++++++-
 4 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/docs/CLI.txt b/docs/CLI.txt
index a822630f..a4f76a74 100644
--- a/docs/CLI.txt
+++ b/docs/CLI.txt
@@ -199,11 +199,15 @@ tahoe add-alias fun DIRCAP
 
   tahoe add-alias fun URI:DIR2:ovjy4yhylqlfoqg2vcze36dhde:4d4f47qko2xm5g7osgo2yyidi5m4muyo2vjjy53q4vjju2u55mfa
 
- This create an alias "fun:" and configures it to use the given directory
+ This creates an alias "fun:" and configures it to use the given directory
  cap. Once this is done, "tahoe ls fun:" will list the contents of this
  directory. Use "tahoe add-alias tahoe DIRCAP" to set the contents of the
  default "tahoe:" alias.
 
+tahoe create-alias fun
+
+ This combines 'tahoe mkdir' and 'tahoe add-alias' into a single step.
+
 tahoe list-aliases
 
  This displays a table of all configured aliases.
diff --git a/src/allmydata/scripts/cli.py b/src/allmydata/scripts/cli.py
index b76d30dc..42388f35 100644
--- a/src/allmydata/scripts/cli.py
+++ b/src/allmydata/scripts/cli.py
@@ -56,6 +56,10 @@ class AddAliasOptions(VDriveOptions):
         self.alias = alias
         self.cap = cap
 
+class CreateAliasOptions(VDriveOptions):
+    def parseArgs(self, alias):
+        self.alias = alias
+
 class ListAliasOptions(VDriveOptions):
     pass
 
@@ -192,6 +196,7 @@ class ReplOptions(usage.Options):
 subCommands = [
     ["mkdir", None, MakeDirectoryOptions, "Create a new directory"],
     ["add-alias", None, AddAliasOptions, "Add a new alias cap"],
+    ["create-alias", None, CreateAliasOptions, "Create a new alias cap"],
     ["list-aliases", None, ListAliasOptions, "List all alias caps"],
     ["ls", None, ListOptions, "List a directory"],
     ["get", None, GetOptions, "Retrieve a file from the virtual drive."],
@@ -214,6 +219,11 @@ def add_alias(options):
     rc = tahoe_add_alias.add_alias(options)
     return rc
 
+def create_alias(options):
+    from allmydata.scripts import tahoe_add_alias
+    rc = tahoe_add_alias.create_alias(options)
+    return rc
+
 def list_aliases(options):
     from allmydata.scripts import tahoe_add_alias
     rc = tahoe_add_alias.list_aliases(options)
@@ -282,6 +292,7 @@ def repl(options):
 dispatch = {
     "mkdir": mkdir,
     "add-alias": add_alias,
+    "create-alias": create_alias,
     "list-aliases": list_aliases,
     "ls": list,
     "get": get,
diff --git a/src/allmydata/scripts/tahoe_add_alias.py b/src/allmydata/scripts/tahoe_add_alias.py
index 162faf55..383bb1ab 100644
--- a/src/allmydata/scripts/tahoe_add_alias.py
+++ b/src/allmydata/scripts/tahoe_add_alias.py
@@ -1,6 +1,7 @@
 
 import os.path
 from allmydata import uri
+from allmydata.scripts.common_http import do_http, check_http_error
 from allmydata.scripts.common import get_aliases
 
 def add_alias(options):
@@ -20,6 +21,33 @@ def add_alias(options):
     print >>stdout, "Alias '%s' added" % (alias,)
     return 0
 
+def create_alias(options):
+    # mkdir+add_alias
+    nodedir = options['node-directory']
+    alias = options.alias
+    stdout = options.stdout
+    stderr = options.stderr
+    aliasfile = os.path.join(nodedir, "private", "aliases")
+    assert ":" not in alias
+    assert " " not in alias
+
+    nodeurl = options['node-url']
+    if not nodeurl.endswith("/"):
+        nodeurl += "/"
+    url = nodeurl + "uri?t=mkdir"
+    resp = do_http("POST", url)
+    rc = check_http_error(resp, stderr)
+    if rc:
+        return rc
+    new_uri = resp.read().strip()
+
+    # probably check for others..
+    f = open(aliasfile, "a")
+    f.write("%s: %s\n" % (alias, new_uri))
+    f.close()
+    print >>stdout, "Alias '%s' created" % (alias,)
+    return 0
+
 def list_aliases(options):
     nodedir = options['node-directory']
     stdout = options.stdout
diff --git a/src/allmydata/test/test_cli.py b/src/allmydata/test/test_cli.py
index 431c3489..15b230c8 100644
--- a/src/allmydata/test/test_cli.py
+++ b/src/allmydata/test/test_cli.py
@@ -1,4 +1,5 @@
 
+import os.path
 from twisted.trial import unittest
 from cStringIO import StringIO
 import urllib
@@ -9,7 +10,7 @@ from allmydata import uri
 # at least import the CLI scripts, even if we don't have any real tests for
 # them yet.
 from allmydata.scripts import tahoe_ls, tahoe_get, tahoe_put, tahoe_rm
-from allmydata.scripts.common import DEFAULT_ALIAS
+from allmydata.scripts.common import DEFAULT_ALIAS, get_aliases
 _hush_pyflakes = [tahoe_ls, tahoe_get, tahoe_put, tahoe_rm]
 
 from allmydata.scripts import cli, debug, runner
@@ -216,6 +217,35 @@ class CLI(unittest.TestCase):
         self.failUnless("storage index: nt4fwemuw7flestsezvo2eveke" in output, output)
         self.failUnless("fingerprint: 737p57x6737p57x6737p57x6737p57x6737p57x6737p57x6737a" in output, output)
 
+class CreateAlias(SystemTestMixin, unittest.TestCase):
+
+    def do_cli(self, verb, *args, **kwargs):
+        nodeargs = [
+            "--node-directory", self.getdir("client0"),
+            ]
+        argv = [verb] + nodeargs + list(args)
+        stdin = kwargs.get("stdin", "")
+        stdout, stderr = StringIO(), StringIO()
+        d = threads.deferToThread(runner.runner, argv, run_by_human=False,
+                                  stdin=StringIO(stdin),
+                                  stdout=stdout, stderr=stderr)
+        def _done(res):
+            return stdout.getvalue(), stderr.getvalue()
+        d.addCallback(_done)
+        return d
+
+    def test_create(self):
+        self.basedir = os.path.dirname(self.mktemp())
+        d = self.set_up_nodes()
+        d.addCallback(lambda res: self.do_cli("create-alias", "tahoe"))
+        def _done((stdout,stderr)):
+            self.failUnless("Alias 'tahoe' created" in stdout)
+            self.failIf(stderr)
+            aliases = get_aliases(self.getdir("client0"))
+            self.failUnless("tahoe" in aliases)
+            self.failUnless(aliases["tahoe"].startswith("URI:DIR2:"))
+        d.addCallback(_done)
+        return d
 
 class Put(SystemTestMixin, unittest.TestCase):
 
-- 
2.45.2