From 6237aeabd722839e5fd229709437293a94728eaa Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@lothar.com>
Date: Thu, 2 Jul 2009 15:25:37 -0700
Subject: [PATCH] create_node_from_uri: take both writecap+readcap, move logic
 out of dirnode.py

---
 src/allmydata/client.py            |  4 +++-
 src/allmydata/dirnode.py           | 15 ++++++++++-----
 src/allmydata/interfaces.py        | 13 +++++++++----
 src/allmydata/test/test_dirnode.py |  4 +++-
 src/allmydata/test/test_mutable.py |  4 +++-
 src/allmydata/test/test_web.py     |  4 +++-
 6 files changed, 31 insertions(+), 13 deletions(-)

diff --git a/src/allmydata/client.py b/src/allmydata/client.py
index 5dd00d9f..08d559e5 100644
--- a/src/allmydata/client.py
+++ b/src/allmydata/client.py
@@ -404,8 +404,10 @@ class Client(node.Node, pollmixin.PollMixin):
     # dirnodes. The first takes a URI and produces a filenode or (new-style)
     # dirnode. The other three create brand-new filenodes/dirnodes.
 
-    def create_node_from_uri(self, u):
+    def create_node_from_uri(self, u, readcap=None):
         # this returns synchronously.
+        if not u:
+            u = readcap
         u = IURI(u)
         u_s = u.to_string()
         if u_s not in self._node_cache:
diff --git a/src/allmydata/dirnode.py b/src/allmydata/dirnode.py
index f0f8421d..b8113b3a 100644
--- a/src/allmydata/dirnode.py
+++ b/src/allmydata/dirnode.py
@@ -15,8 +15,7 @@ from allmydata.check_results import DeepCheckResults, \
 from allmydata.monitor import Monitor
 from allmydata.util import hashutil, mathutil, base32, log
 from allmydata.util.assertutil import _assert, precondition
-from allmydata.util.hashutil import netstring
-from allmydata.util.netstring import split_netstring
+from allmydata.util.netstring import netstring, split_netstring
 from allmydata.uri import NewDirectoryURI, LiteralFileURI, from_string
 from pycryptopp.cipher.aes import AES
 
@@ -189,9 +188,7 @@ class NewDirectoryNode:
         return plaintext
 
     def _create_node(self, rwcap, rocap):
-        if rwcap:
-            return self._client.create_node_from_uri(rwcap)
-        return self._client.create_node_from_uri(rocap)
+        return self._client.create_node_from_uri(rwcap, rocap)
 
     def _unpack_contents(self, data):
         # the directory is serialized as a list of netstrings, one per child.
@@ -212,6 +209,10 @@ class NewDirectoryNode:
             rwcap = None
             if writeable:
                 rwcap = self._decrypt_rwcapdata(rwcapdata)
+            if not rwcap:
+                rwcap = None # rwcap is None or a non-empty string
+            if not rocap:
+                rocap = None # rocap is None or a non-empty string
             child = self._create_node(rwcap, rocap)
             metadata = simplejson.loads(metadata_s)
             assert isinstance(metadata, dict)
@@ -230,8 +231,12 @@ class NewDirectoryNode:
                     or IDirectoryNode.providedBy(child)), (name,child)
             assert isinstance(metadata, dict)
             rwcap = child.get_uri() # might be RO if the child is not writeable
+            if rwcap is None:
+                rwcap = ""
             assert isinstance(rwcap, str), rwcap
             rocap = child.get_readonly_uri()
+            if rocap is None:
+                rocap = ""
             assert isinstance(rocap, str), rocap
             entry = "".join([netstring(name.encode("utf-8")),
                              netstring(rocap),
diff --git a/src/allmydata/interfaces.py b/src/allmydata/interfaces.py
index 2aa26564..86e83124 100644
--- a/src/allmydata/interfaces.py
+++ b/src/allmydata/interfaces.py
@@ -2007,11 +2007,16 @@ class IClient(Interface):
         @return: a Deferred that fires with the new IDirectoryNode instance.
         """
 
-    def create_node_from_uri(uri):
+    def create_node_from_uri(uri, rouri):
         """Create a new IFilesystemNode instance from the uri, synchronously.
-        @param uri: a string or IURI-providing instance. This could be for a
-                    LiteralFileNode, a CHK file node, a mutable file node, or
-                    a directory node
+        @param uri: a string or IURI-providing instance, or None. This could
+                    be for a LiteralFileNode, a CHK file node, a mutable file
+                    node, or a directory node
+        @param rouri: a string or IURI-providing instance, or None. If the
+                      main uri is None, I will use the rouri instead. If I
+                      recognize the format of the main uri, I will ignore the
+                      rouri (because it can be derived from the writecap).
+
         @return: an instance that provides IFilesystemNode (or more usefully
                  one of its subclasses). File-specifying URIs will result in
                  IFileNode or IMutableFileNode -providing instances, like
diff --git a/src/allmydata/test/test_dirnode.py b/src/allmydata/test/test_dirnode.py
index 45567198..0321726a 100644
--- a/src/allmydata/test/test_dirnode.py
+++ b/src/allmydata/test/test_dirnode.py
@@ -76,7 +76,9 @@ class FakeClient:
         d.addCallback(_got_data)
         return d
 
-    def create_node_from_uri(self, u):
+    def create_node_from_uri(self, u, readcap=None):
+        if not u:
+            u = readcap
         u = IURI(u)
         if (INewDirectoryURI.providedBy(u)
             or IReadonlyNewDirectoryURI.providedBy(u)):
diff --git a/src/allmydata/test/test_mutable.py b/src/allmydata/test/test_mutable.py
index 91765fe0..a5fc9b89 100644
--- a/src/allmydata/test/test_mutable.py
+++ b/src/allmydata/test/test_mutable.py
@@ -208,7 +208,9 @@ class FakeClient:
     def get_history(self):
         return None
 
-    def create_node_from_uri(self, u):
+    def create_node_from_uri(self, u, readcap=None):
+        if not u:
+            u = readcap
         u = IURI(u)
         assert IMutableFileURI.providedBy(u), u
         res = self.mutable_file_node_class(self).init_from_uri(u)
diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
index c3bd3875..c6638ce7 100644
--- a/src/allmydata/test/test_web.py
+++ b/src/allmydata/test/test_web.py
@@ -63,7 +63,9 @@ class FakeClient(service.MultiService):
     def get_storage_broker(self):
         return self.storage_broker
 
-    def create_node_from_uri(self, auri):
+    def create_node_from_uri(self, auri, readcap=None):
+        if not auri:
+            auri = readcap
         precondition(isinstance(auri, str), auri)
         u = uri.from_string(auri)
         if (INewDirectoryURI.providedBy(u)
-- 
2.45.2