From 1d8e45218480bd6c6aca272a9b001360bf4711ff Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@allmydata.com>
Date: Tue, 20 May 2008 14:36:04 -0700
Subject: [PATCH] CLI: add 'list-aliases', factor out get_aliases

---
 docs/CLI.txt                             | 15 ++++++++-
 src/allmydata/scripts/cli.py             | 41 ++++++++----------------
 src/allmydata/scripts/common.py          | 27 ++++++++++++++++
 src/allmydata/scripts/tahoe_add_alias.py |  9 ++++++
 src/allmydata/test/test_system.py        | 18 +++++++++++
 5 files changed, 81 insertions(+), 29 deletions(-)

diff --git a/docs/CLI.txt b/docs/CLI.txt
index 0a896172..eab28bb4 100644
--- a/docs/CLI.txt
+++ b/docs/CLI.txt
@@ -138,13 +138,15 @@ The best way to get started with Tahoe is to create a node, start it, then
 use the following command to create a new directory and set it as your
 "tahoe:" alias:
 
- tahoe set-alias tahoe `tahoe mkdir`
+ tahoe add-alias tahoe `tahoe mkdir`
 
 After that you can use "tahoe ls tahoe:" and "tahoe cp local.txt tahoe:",
 and both will refer to the directory that you've just created.
 
 === Command Syntax Summary ===
 
+tahoe add-alias alias cap
+tahoe list-aliases
 tahoe mkdir
 tahoe mkdir [alias:]path
 tahoe ls [alias:][path]
@@ -163,6 +165,17 @@ tahoe mkdir
  This creates a new empty unlinked directory, and prints its write-cap to
  stdout. The new directory is not attached to anything else.
 
+tahoe add-alias work DIRCAP
+
+ This create an alias "work:" and configures it to use the given directory
+ cap. Once this is done, "tahoe ls work:" will list the contents of this
+ directory. Use "tahoe add-alias tahoe DIRCAP" to set the contents of the
+ default "tahoe:" alias.
+
+tahoe list-aliases
+
+ This displays a table of all configured aliases.
+
 tahoe mkdir subdir
 tahoe mkdir /subdir
 
diff --git a/src/allmydata/scripts/cli.py b/src/allmydata/scripts/cli.py
index f965e24b..9d0ea68f 100644
--- a/src/allmydata/scripts/cli.py
+++ b/src/allmydata/scripts/cli.py
@@ -1,7 +1,7 @@
 
 import os.path, re, sys
 from twisted.python import usage
-from allmydata.scripts.common import BaseOptions
+from allmydata.scripts.common import BaseOptions, get_aliases
 
 NODEURL_RE=re.compile("http://([^:]*)(:([1-9][0-9]*))?")
 
@@ -40,38 +40,12 @@ class VDriveOptions(BaseOptions, usage.Options):
             node_url_file = os.path.join(self['node-directory'], "node.url")
             self['node-url'] = open(node_url_file, "r").read().strip()
 
-        aliases = self.get_aliases(self['node-directory'])
+        aliases = get_aliases(self['node-directory'])
         if self['dir-cap']:
             aliases["tahoe"] = self['dir-cap']
         self.aliases = aliases # maps alias name to dircap
 
 
-    def get_aliases(self, nodedir):
-        from allmydata import uri
-        aliases = {}
-        aliasfile = os.path.join(nodedir, "private", "aliases")
-        rootfile = os.path.join(nodedir, "private", "root_dir.cap")
-        try:
-            f = open(rootfile, "r")
-            rootcap = f.read().strip()
-            if rootcap:
-                aliases["tahoe"] = uri.from_string_dirnode(rootcap).to_string()
-        except EnvironmentError:
-            pass
-        try:
-            f = open(aliasfile, "r")
-            for line in f.readlines():
-                line = line.strip()
-                if line.startswith("#"):
-                    continue
-                name, cap = line.split(":", 1)
-                # normalize it: remove http: prefix, urldecode
-                cap = cap.strip()
-                aliases[name] = uri.from_string_dirnode(cap).to_string()
-        except EnvironmentError:
-            pass
-        return aliases
-
 class MakeDirectoryOptions(VDriveOptions):
     def parseArgs(self, where=""):
         self.where = where
@@ -82,6 +56,9 @@ class AddAliasOptions(VDriveOptions):
         self.alias = alias
         self.cap = cap
 
+class ListAliasOptions(VDriveOptions):
+    pass
+
 class ListOptions(VDriveOptions):
     optFlags = [
         ("long", "l", "Use long format: show file sizes, and timestamps"),
@@ -180,6 +157,7 @@ class ReplOptions(usage.Options):
 subCommands = [
     ["mkdir", None, MakeDirectoryOptions, "Create a new directory"],
     ["add-alias", None, AddAliasOptions, "Add 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."],
     ["put", None, PutOptions, "Upload a file into the virtual drive."],
@@ -206,6 +184,12 @@ def add_alias(config, stdout, stderr):
                                    stdout, stderr)
     return rc
 
+def list_aliases(config, stdout, stderr):
+    from allmydata.scripts import tahoe_add_alias
+    rc = tahoe_add_alias.list_aliases(config['node-directory'],
+                                      stdout, stderr)
+    return rc
+
 def list(config, stdout, stderr):
     from allmydata.scripts import tahoe_ls
     rc = tahoe_ls.list(config['node-url'],
@@ -299,6 +283,7 @@ def repl(config, stdout, stderr):
 dispatch = {
     "mkdir": mkdir,
     "add-alias": add_alias,
+    "list-aliases": list_aliases,
     "ls": list,
     "get": get,
     "put": put,
diff --git a/src/allmydata/scripts/common.py b/src/allmydata/scripts/common.py
index 03817c36..44e8950a 100644
--- a/src/allmydata/scripts/common.py
+++ b/src/allmydata/scripts/common.py
@@ -64,6 +64,33 @@ class NoDefaultBasedirMixin(BasedirMixin):
 
 DEFAULT_ALIAS = "tahoe"
 
+
+def get_aliases(nodedir):
+    from allmydata import uri
+    aliases = {}
+    aliasfile = os.path.join(nodedir, "private", "aliases")
+    rootfile = os.path.join(nodedir, "private", "root_dir.cap")
+    try:
+        f = open(rootfile, "r")
+        rootcap = f.read().strip()
+        if rootcap:
+            aliases["tahoe"] = uri.from_string_dirnode(rootcap).to_string()
+    except EnvironmentError:
+        pass
+    try:
+        f = open(aliasfile, "r")
+        for line in f.readlines():
+            line = line.strip()
+            if line.startswith("#"):
+                continue
+            name, cap = line.split(":", 1)
+            # normalize it: remove http: prefix, urldecode
+            cap = cap.strip()
+            aliases[name] = uri.from_string_dirnode(cap).to_string()
+    except EnvironmentError:
+        pass
+    return aliases
+
 def get_alias(aliases, path, default):
     # transform "work:path/filename" into (aliases["work"], "path/filename")
     # We special-case URI:
diff --git a/src/allmydata/scripts/tahoe_add_alias.py b/src/allmydata/scripts/tahoe_add_alias.py
index c45091a6..c526b853 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 import get_aliases
 
 def add_alias(nodedir, alias, cap, stdout, stderr):
     aliasfile = os.path.join(nodedir, "private", "aliases")
@@ -14,3 +15,11 @@ def add_alias(nodedir, alias, cap, stdout, stderr):
     print >>stdout, "Alias '%s' added" % (alias,)
     return 0
 
+def list_aliases(nodedir, stdout, stderr):
+    aliases = get_aliases(nodedir)
+    alias_names = sorted(aliases.keys())
+    max_width = max([len(name) for name in alias_names] + [0])
+    fmt = "%" + str(max_width) + "s: %s"
+    for name in alias_names:
+        print >>stdout, fmt % (name, aliases[name])
+
diff --git a/src/allmydata/test/test_system.py b/src/allmydata/test/test_system.py
index 00b4891d..ef189968 100644
--- a/src/allmydata/test/test_system.py
+++ b/src/allmydata/test/test_system.py
@@ -1560,9 +1560,20 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, testutil.StallMixin,
         d.addCallback(run, "ls")
         d.addCallback(_check_ls, ["personal", "s2-ro", "s2-rw"])
 
+        d.addCallback(run, "list-aliases")
+        def _check_aliases_1((out,err)):
+            self.failUnlessEqual(err, "")
+            self.failUnlessEqual(out, "tahoe: %s\n" % private_uri)
+        d.addCallback(_check_aliases_1)
+
         # now that that's out of the way, remove root_dir.cap and work with
         # new files
         d.addCallback(lambda res: os.unlink(root_file))
+        d.addCallback(run, "list-aliases")
+        def _check_aliases_2((out,err)):
+            self.failUnlessEqual(err, "")
+            self.failUnlessEqual(out, "")
+        d.addCallback(_check_aliases_2)
 
         d.addCallback(run, "mkdir")
         def _got_dir( (out,err) ):
@@ -1570,6 +1581,13 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, testutil.StallMixin,
             return out.strip()
         d.addCallback(_got_dir)
         d.addCallback(lambda newcap: run(None, "add-alias", "tahoe", newcap))
+
+        d.addCallback(run, "list-aliases")
+        def _check_aliases_3((out,err)):
+            self.failUnlessEqual(err, "")
+            self.failUnless("tahoe: " in out)
+        d.addCallback(_check_aliases_3)
+
         def _check_empty_dir((out,err)):
             self.failUnlessEqual(out, "")
             self.failUnlessEqual(err, "")
-- 
2.45.2