Sat Jul 10 22:10:59 MDT 2010  zooko@zooko.com
  * minor code clean-up in dirnode.py
  Impose micro-POLA by passing only the writekey instead of the whole node object to {{{_encrypt_rw_uri()}}}. Remove DummyImmutableFileNode in nodemaker.py, which is obviated by this. Add micro-optimization by precomputing the netstring of the empty string and branching on whether the writekey is present or not outside of {{{_encrypt_rw_uri()}}}. Add doc about writekey to docstring.

New patches:

[minor code clean-up in dirnode.py
zooko@zooko.com**20100711041059
 Ignore-this: 5301818c5a3212ea4ae7f1c7c6840765
 Impose micro-POLA by passing only the writekey instead of the whole node object to {{{_encrypt_rw_uri()}}}. Remove DummyImmutableFileNode in nodemaker.py, which is obviated by this. Add micro-optimization by precomputing the netstring of the empty string and branching on whether the writekey is present or not outside of {{{_encrypt_rw_uri()}}}. Add doc about writekey to docstring.
] {
hunk ./src/allmydata/dirnode.py 174
         new_contents = self.node._pack_contents(children)
         return new_contents
 
+def _encrypt_rw_uri(writekey, rw_uri):
+    precondition(isinstance(rw_uri, str), rw_uri)
+    precondition(isinstance(writekey, str), writekey)
 
hunk ./src/allmydata/dirnode.py 178
-def _encrypt_rw_uri(filenode, rw_uri):
-    assert isinstance(rw_uri, str)
-    writekey = filenode.get_writekey()
-    if not writekey:
-        return ""
     salt = hashutil.mutable_rwcap_salt_hash(rw_uri)
     key = hashutil.mutable_rwcap_key_hash(salt, writekey)
     cryptor = AES(key)
hunk ./src/allmydata/dirnode.py 188
     # The MAC is not checked by readers in Tahoe >= 1.3.0, but we still
     # produce it for the sake of older readers.
 
-
-def pack_children(filenode, childrenx, deep_immutable=False):
+def pack_children(childrenx, writekey, deep_immutable=False):
     # initial_children must have metadata (i.e. {} instead of None)
     children = {}
     for (namex, (node, metadata)) in childrenx.iteritems():
hunk ./src/allmydata/dirnode.py 196
                      "directory creation requires metadata to be a dict, not None", metadata)
         children[normalize(namex)] = (node, metadata)
 
-    return _pack_normalized_children(filenode, children, deep_immutable=deep_immutable)
+    return _pack_normalized_children(children, writekey=writekey, deep_immutable=deep_immutable)
 
 
hunk ./src/allmydata/dirnode.py 199
-def _pack_normalized_children(filenode, children, deep_immutable=False):
+ZERO_LEN_NETSTR=netstring('')
+def _pack_normalized_children(children, writekey, deep_immutable=False):
     """Take a dict that maps:
          children[unicode_nfc_name] = (IFileSystemNode, metadata_dict)
     and pack it into a single string, for use as the contents of the backing
hunk ./src/allmydata/dirnode.py 209
     as the pre-packed entry, which is faster than re-packing everything each
     time.
 
+    If writekey is provided then I will superencrypt the child's writecap with
+    writekey.
+
     If deep_immutable is True, I will require that all my children are deeply
     immutable, and will raise a MustBeDeepImmutableError if not.
     """
hunk ./src/allmydata/dirnode.py 215
+    precondition((writekey is None) or isinstance(writekey, str), writekey)
 
     has_aux = isinstance(children, AuxValueDict)
     entries = []
hunk ./src/allmydata/dirnode.py 236
             if rw_uri is None:
                 rw_uri = ""
             assert isinstance(rw_uri, str), rw_uri
-            
+
             # should be prevented by MustBeDeepImmutableError check above
             assert not (rw_uri and deep_immutable)
 
hunk ./src/allmydata/dirnode.py 244
             if ro_uri is None:
                 ro_uri = ""
             assert isinstance(ro_uri, str), ro_uri
+            if writekey is not None:
+                writecap = netstring(_encrypt_rw_uri(writekey, rw_uri))
+            else:
+                writecap = ZERO_LEN_NETSTR
             entry = "".join([netstring(name.encode("utf-8")),
                              netstring(strip_prefix_for_ro(ro_uri, deep_immutable)),
hunk ./src/allmydata/dirnode.py 250
-                             netstring(_encrypt_rw_uri(filenode, rw_uri)),
+                             writecap,
                              netstring(simplejson.dumps(metadata))])
         entries.append(netstring(entry))
     return "".join(entries)
hunk ./src/allmydata/dirnode.py 377
 
     def _pack_contents(self, children):
         # expects children in the same format as _unpack_contents returns
-        return _pack_normalized_children(self._node, children)
+        return _pack_normalized_children(children, self._node.get_writekey())
 
     def is_readonly(self):
         return self._node.is_readonly()
hunk ./src/allmydata/nodemaker.py 11
 from allmydata.unknown import UnknownNode
 from allmydata import uri
 
-class DummyImmutableFileNode:
-    def get_writekey(self):
-        return None
-
 class NodeMaker:
     implements(INodeMaker)
 
hunk ./src/allmydata/nodemaker.py 46
         # this returns synchronously. It starts with a "cap string".
         assert isinstance(writecap, (str, type(None))), type(writecap)
         assert isinstance(readcap,  (str, type(None))), type(readcap)
-        
+
         bigcap = writecap or readcap
         if not bigcap:
             # maybe the writecap was hidden because we're in a readonly
hunk ./src/allmydata/nodemaker.py 96
 
     def create_new_mutable_directory(self, initial_children={}):
         d = self.create_mutable_file(lambda n:
-                                     pack_children(n, initial_children))
+                                     pack_children(initial_children, n.get_writekey()))
         d.addCallback(self._create_dirnode)
         return d
 
hunk ./src/allmydata/nodemaker.py 103
     def create_immutable_directory(self, children, convergence=None):
         if convergence is None:
             convergence = self.secret_holder.get_convergence_secret()
-        n = DummyImmutableFileNode() # writekey=None
-        packed = pack_children(n, children, deep_immutable=True)
+        packed = pack_children(children, None, deep_immutable=True)
         uploadable = Data(packed, convergence)
         d = self.uploader.upload(uploadable, history=self.history)
         d.addCallback(lambda results: self.create_from_cap(None, results.uri))
hunk ./src/allmydata/test/test_dirnode.py 1249
 
         kids = self._make_kids(nm, ["imm", "lit", "write", "read",
                                     "dirwrite", "dirread"])
-        packed = dirnode.pack_children(fn, kids, deep_immutable=False)
+        packed = dirnode.pack_children(kids, fn.get_writekey(), deep_immutable=False)
         self.failUnlessIn("lit", packed)
 
         kids = self._make_kids(nm, ["imm", "lit"])
hunk ./src/allmydata/test/test_dirnode.py 1253
-        packed = dirnode.pack_children(fn, kids, deep_immutable=True)
+        packed = dirnode.pack_children(kids, fn.get_writekey(), deep_immutable=True)
         self.failUnlessIn("lit", packed)
 
         kids = self._make_kids(nm, ["imm", "lit", "write"])
hunk ./src/allmydata/test/test_dirnode.py 1259
         self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
                               dirnode.pack_children,
-                              fn, kids, deep_immutable=True)
+                              kids, fn.get_writekey(), deep_immutable=True)
 
         # read-only is not enough: all children must be immutable
         kids = self._make_kids(nm, ["imm", "lit", "read"])
hunk ./src/allmydata/test/test_dirnode.py 1265
         self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
                               dirnode.pack_children,
-                              fn, kids, deep_immutable=True)
+                              kids, fn.get_writekey(), deep_immutable=True)
 
         kids = self._make_kids(nm, ["imm", "lit", "dirwrite"])
         self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
hunk ./src/allmydata/test/test_dirnode.py 1270
                               dirnode.pack_children,
-                              fn, kids, deep_immutable=True)
+                              kids, fn.get_writekey(), deep_immutable=True)
 
         kids = self._make_kids(nm, ["imm", "lit", "dirread"])
         self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
hunk ./src/allmydata/test/test_dirnode.py 1275
                               dirnode.pack_children,
-                              fn, kids, deep_immutable=True)
+                              kids, fn.get_writekey(), deep_immutable=True)
 
 class FakeMutableFile:
     implements(IMutableFileNode)
}

Context:

[upcase_since_on_welcome
terrellrussell@gmail.com**20100708193903] 
[server_version_on_welcome_page.dpatch.txt
freestorm77@gmail.com**20100605191721
 Ignore-this: b450c76dc875f5ac8cca229a666cbd0a
 
 
 - The storage server version is 0 for all storage nodes in the Welcome Page
 
 
] 
[NEWS: add NEWS snippets about two recent patches
zooko@zooko.com**20100708162058
 Ignore-this: 6c9da6a0ad7351a960bdd60f81532899
] 
[directory_html_top_banner.dpatch
freestorm77@gmail.com**20100622205301
 Ignore-this: 1d770d975e0c414c996564774f049bca
 
 The div tag with the link "Return to Welcome page" on the directory.xhtml page is not correct
 
] 
[tahoe_css_toolbar.dpatch
freestorm77@gmail.com**20100622210046
 Ignore-this: 5b3ebb2e0f52bbba718a932f80c246c0
 
 CSS modification to be correctly diplayed with Internet Explorer 8
 
 The links on the top of page directory.xhtml are not diplayed in the same line as display with Firefox.
 
] 
[runnin_test_tahoe_css.dpatch
freestorm77@gmail.com**20100622214714
 Ignore-this: e0db73d68740aad09a7b9ae60a08c05c
 
 Runnin test for changes in tahoe.css file
 
] 
[runnin_test_directory_xhtml.dpatch
freestorm77@gmail.com**20100622201403
 Ignore-this: f8962463fce50b9466405cb59fe11d43
 
 Runnin test for diretory.xhtml top banner
 
] 
[stringutils.py: tolerate sys.stdout having no 'encoding' attribute.
david-sarah@jacaranda.org**20100626040817
 Ignore-this: f42cad81cef645ee38ac1df4660cc850
] 
[quickstart.html: python 2.5 -> 2.6 as recommended version
david-sarah@jacaranda.org**20100705175858
 Ignore-this: bc3a14645ea1d5435002966ae903199f
] 
[SFTP: don't call .stopProducing on the producer registered with OverwriteableFileConsumer (which breaks with warner's new downloader).
david-sarah@jacaranda.org**20100628231926
 Ignore-this: 131b7a5787bc85a9a356b5740d9d996f
] 
[docs/how_to_make_a_tahoe-lafs_release.txt: trivial correction, install.html should now be quickstart.html.
david-sarah@jacaranda.org**20100625223929
 Ignore-this: 99a5459cac51bd867cc11ad06927ff30
] 
[setup: in the Makefile, refuse to upload tarballs unless someone has passed the environment variable "BB_BRANCH" with value "trunk"
zooko@zooko.com**20100619034928
 Ignore-this: 276ddf9b6ad7ec79e27474862e0f7d6
] 
[trivial: tiny update to in-line comment
zooko@zooko.com**20100614045715
 Ignore-this: 10851b0ed2abfed542c97749e5d280bc
 (I'm actually committing this patch as a test of the new eager-annotation-computation of trac-darcs.)
] 
[docs: about.html link to home page early on, and be decentralized storage instead of cloud storage this time around
zooko@zooko.com**20100619065318
 Ignore-this: dc6db03f696e5b6d2848699e754d8053
] 
[docs: update about.html, especially to have a non-broken link to quickstart.html, and also to comment out the broken links to "for Paranoids" and "for Corporates"
zooko@zooko.com**20100619065124
 Ignore-this: e292c7f51c337a84ebfeb366fbd24d6c
] 
[TAG allmydata-tahoe-1.7.0
zooko@zooko.com**20100619052631
 Ignore-this: d21e27afe6d85e2e3ba6a3292ba2be1
] 
Patch bundle hash:
78405c9323962dcc85027948fa9d1129eb35efd4
