From d8b3505cf54b34233059f03f175235dedc383db9 Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@allmydata.com>
Date: Thu, 22 Jan 2009 21:38:36 -0700
Subject: [PATCH] filenode: add get_repair_cap(), which uses the read-write
 filecap for immutable files, and the verifycap for immutable files

---
 src/allmydata/immutable/filenode.py | 7 +++++++
 src/allmydata/interfaces.py         | 8 ++++++++
 src/allmydata/mutable/filenode.py   | 5 +++++
 src/allmydata/test/test_filenode.py | 4 ++++
 4 files changed, 24 insertions(+)

diff --git a/src/allmydata/immutable/filenode.py b/src/allmydata/immutable/filenode.py
index b8df90ce..c44acffa 100644
--- a/src/allmydata/immutable/filenode.py
+++ b/src/allmydata/immutable/filenode.py
@@ -192,6 +192,10 @@ class FileNode(_ImmutableFileNodeBase, log.PrefixingLogMixin):
     def get_verify_cap(self):
         return self.u.get_verify_cap()
 
+    def get_repair_cap(self):
+        # CHK files can be repaired with just the verifycap
+        return self.u.get_verify_cap()
+
     def get_storage_index(self):
         return self.u.storage_index
 
@@ -298,6 +302,9 @@ class LiteralFileNode(_ImmutableFileNodeBase):
     def get_verify_cap(self):
         return None
 
+    def get_repair_cap(self):
+        return None
+
     def get_storage_index(self):
         return None
 
diff --git a/src/allmydata/interfaces.py b/src/allmydata/interfaces.py
index 563ba72c..524b75f0 100644
--- a/src/allmydata/interfaces.py
+++ b/src/allmydata/interfaces.py
@@ -424,6 +424,14 @@ class IFilesystemNode(Interface):
         get_readonly_uri() will return the same thing as get_uri().
         """
 
+    def get_repair_cap():
+        """Return an IURI instance that can be used to repair the file, or
+        None if this node cannot be repaired (either because it is not
+        distributed, like a LIT file, or because the node does not represent
+        sufficient authority to create a repair-cap, like a read-only RSA
+        mutable file node [which cannot create the correct write-enablers]).
+        """
+
     def get_verify_cap():
         """Return an IVerifierURI instance that represents the
         'verifiy/refresh capability' for this node. The holder of this
diff --git a/src/allmydata/mutable/filenode.py b/src/allmydata/mutable/filenode.py
index 5c2e183d..d5b3fbc8 100644
--- a/src/allmydata/mutable/filenode.py
+++ b/src/allmydata/mutable/filenode.py
@@ -220,6 +220,11 @@ class MutableFileNode:
     def get_verify_cap(self):
         return IMutableFileURI(self._uri).get_verify_cap()
 
+    def get_repair_cap(self):
+        if self._uri.is_readonly():
+            return None
+        return self._uri
+
     def _do_serialized(self, cb, *args, **kwargs):
         # note: to avoid deadlock, this callable is *not* allowed to invoke
         # other serialized methods within this (or any other)
diff --git a/src/allmydata/test/test_filenode.py b/src/allmydata/test/test_filenode.py
index 48d1b140..f0677665 100644
--- a/src/allmydata/test/test_filenode.py
+++ b/src/allmydata/test/test_filenode.py
@@ -42,6 +42,7 @@ class Node(unittest.TestCase):
         d[fn1] = 1 # exercise __hash__
         v = fn1.get_verify_cap()
         self.failUnless(isinstance(v, uri.CHKFileVerifierURI))
+        self.failUnlessEqual(fn1.get_repair_cap(), v)
 
 
     def test_literal_filenode(self):
@@ -64,6 +65,7 @@ class Node(unittest.TestCase):
 
         v = fn1.get_verify_cap()
         self.failUnlessEqual(v, None)
+        self.failUnlessEqual(fn1.get_repair_cap(), None)
 
         d = fn1.download(download.Data())
         def _check(res):
@@ -124,9 +126,11 @@ class Node(unittest.TestCase):
         self.failUnlessEqual(nro_u, u.get_readonly().to_string())
         self.failUnlessEqual(nro.is_mutable(), True)
         self.failUnlessEqual(nro.is_readonly(), True)
+        self.failUnlessEqual(nro.get_repair_cap(), None) # RSAmut needs writecap
 
         v = n.get_verify_cap()
         self.failUnless(isinstance(v, uri.SSKVerifierURI))
+        self.failUnlessEqual(n.get_repair_cap(), n._uri) # TODO: n.get_uri()
 
 class LiteralChecker(unittest.TestCase):
     def test_literal_filenode(self):
-- 
2.45.2