about summary refs log tree commit diff
path: root/src/libstore/store-api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/store-api.cc')
-rw-r--r--src/libstore/store-api.cc60
1 files changed, 48 insertions, 12 deletions
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index af002dcc8c33..5dd56f905d57 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -202,6 +202,22 @@ Path Store::makeFixedOutputPath(bool recursive,
 }
 
 
+Path Store::makeTextPath(const string & name, const Hash & hash,
+    const PathSet & references) const
+{
+    assert(hash.type == htSHA256);
+    /* Stuff the references (if any) into the type.  This is a bit
+       hacky, but we can't put them in `s' since that would be
+       ambiguous. */
+    string type = "text";
+    for (auto & i : references) {
+        type += ":";
+        type += i;
+    }
+    return makeStorePath(type, hash, name);
+}
+
+
 std::pair<Path, Hash> Store::computeStorePathForPath(const Path & srcPath,
     bool recursive, HashType hashAlgo, PathFilter & filter) const
 {
@@ -215,16 +231,7 @@ std::pair<Path, Hash> Store::computeStorePathForPath(const Path & srcPath,
 Path Store::computeStorePathForText(const string & name, const string & s,
     const PathSet & references) const
 {
-    Hash hash = hashString(htSHA256, s);
-    /* Stuff the references (if any) into the type.  This is a bit
-       hacky, but we can't put them in `s' since that would be
-       ambiguous. */
-    string type = "text";
-    for (auto & i : references) {
-        type += ":";
-        type += i;
-    }
-    return makeStorePath(type, hash, name);
+    return makeTextPath(name, hashString(htSHA256, s), references);
 }
 
 
@@ -432,9 +439,38 @@ void ValidPathInfo::sign(const SecretKey & secretKey)
 }
 
 
-unsigned int ValidPathInfo::checkSignatures(const PublicKeys & publicKeys) const
+bool ValidPathInfo::isContentAddressed(const Store & store) const
+{
+    auto warn = [&]() {
+        printMsg(lvlError, format("warning: path ‘%s’ claims to be content-addressed but isn't") % path);
+    };
+
+    if (hasPrefix(ca, "text:")) {
+        auto hash = parseHash(std::string(ca, 5));
+        if (store.makeTextPath(storePathToName(path), hash, references) == path)
+            return true;
+        else
+            warn();
+    }
+
+    else if (hasPrefix(ca, "fixed:")) {
+        bool recursive = ca.compare(6, 2, "r:") == 0;
+        auto hash = parseHash(std::string(ca, recursive ? 8 : 6));
+        if (store.makeFixedOutputPath(recursive, hash, storePathToName(path)) == path)
+            return true;
+        else
+            warn();
+    }
+
+    return false;
+}
+
+
+size_t ValidPathInfo::checkSignatures(const Store & store, const PublicKeys & publicKeys) const
 {
-    unsigned int good = 0;
+    if (isContentAddressed(store)) return maxSigs;
+
+    size_t good = 0;
     for (auto & sig : sigs)
         if (checkSignature(publicKeys, sig))
             good++;