From 03134eedb5b7a059953bc6c9cafff2213673c103 Mon Sep 17 00:00:00 2001
From: david-sarah <david-sarah@jacaranda.org>
Date: Fri, 19 Feb 2010 22:13:13 -0800
Subject: [PATCH] Improve behaviour of 'tahoe ls' for unknown objects,
 addressing kevan's comments

---
 src/allmydata/scripts/cli.py      | 24 +++++++++++++++++++++++-
 src/allmydata/scripts/common.py   |  8 ++++++--
 src/allmydata/scripts/tahoe_ls.py | 10 ++++++++--
 3 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/src/allmydata/scripts/cli.py b/src/allmydata/scripts/cli.py
index 1ac6ad0e..c2efe9d3 100644
--- a/src/allmydata/scripts/cli.py
+++ b/src/allmydata/scripts/cli.py
@@ -85,7 +85,29 @@ class ListOptions(VDriveOptions):
     def parseArgs(self, where=""):
         self.where = where
 
-    longdesc = """List the contents of some portion of the grid."""
+    longdesc = """
+    List the contents of some portion of the grid.
+
+    When the -l or --long option is used, each line is shown in the
+    following format:
+
+    drwx <size> <date/time> <name in this directory>
+
+    where each of the letters on the left may be replaced by '-'.
+    If 'd' is present, it indicates that the object is a directory.
+    If the 'd' is replaced by a '?', the object type is unknown.
+    'rwx' is a Unix-like permissions mask: if the mask includes 'w',
+    then the object is writable through its link in this directory.
+    The 'x' is a legacy of Unix filesystems. In Tahoe it is used
+    only to indicate that the contents of a directory can be listed.
+
+    Directories have no size, so their size field is shown as '-'.
+    Otherwise the size of the file, when known, is given in bytes.
+    The size of mutable files or unknown objects is shown as '?'.
+
+    The date/time shows when this link in the Tahoe filesystem was
+    last modified.
+    """
 
 class GetOptions(VDriveOptions):
     def parseArgs(self, arg1, arg2=None):
diff --git a/src/allmydata/scripts/common.py b/src/allmydata/scripts/common.py
index 7b6f78aa..0ee7a3d0 100644
--- a/src/allmydata/scripts/common.py
+++ b/src/allmydata/scripts/common.py
@@ -139,11 +139,15 @@ def get_alias(aliases, path, default):
     # raised.
     path = path.strip()
     if uri.has_uri_prefix(path):
-        # The only way to get a sub-path is to use URI:blah:./foo, and we
-        # strip out the :./ sequence.
+        # We used to require "URI:blah:./foo" in order to get a subpath,
+        # stripping out the ":./" sequence. We still allow that for compatibility,
+        # but now also allow just "URI:blah/foo".
         sep = path.find(":./")
         if sep != -1:
             return path[:sep], path[sep+3:]
+        sep = path.find("/")
+        if sep != -1:
+            return path[:sep], path[sep+1:]
         return path, ""
     colon = path.find(":")
     if colon == -1:
diff --git a/src/allmydata/scripts/tahoe_ls.py b/src/allmydata/scripts/tahoe_ls.py
index a169d82b..bb204ddc 100644
--- a/src/allmydata/scripts/tahoe_ls.py
+++ b/src/allmydata/scripts/tahoe_ls.py
@@ -55,7 +55,7 @@ def list(options):
     children = {}
     if nodetype == "dirnode":
         children = d['children']
-    elif nodetype == "filenode":
+    else:
         childname = path.split("/")[-1]
         children = {childname: (nodetype, d)}
         if "metadata" not in d:
@@ -67,6 +67,7 @@ def list(options):
     # maxwidth so we can format them tightly. Size, filename, and URI are the
     # variable-width ones.
     rows = []
+    has_unknowns = False
 
     for name in childnames:
         name = unicode(name)
@@ -101,11 +102,12 @@ def list(options):
             classify = "/"
         elif childtype == "filenode":
             t0 = "-"
-            size = str(child[1]['size'])
+            size = str(child[1].get("size", "?"))
             classify = ""
             if rw_uri:
                 classify = "*"
         else:
+            has_unknowns = True
             t0 = "?"
             size = "?"
             classify = "?"
@@ -161,6 +163,10 @@ def list(options):
     for row in rows:
         print >>stdout, (fmt % tuple(row)).rstrip()
 
+    if has_unknowns:
+        print >>stderr, "\nThis listing included unknown objects. Using a webapi server that supports" \
+                        "\na later version of Tahoe may help."
+
     return 0
 
 # error cases that need improvement:
-- 
2.45.2