about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/store-api.cc3
-rw-r--r--src/nix/sigs.cc50
2 files changed, 52 insertions, 1 deletions
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index b47376e5594a..b9939feda477 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -312,6 +312,9 @@ void Store::exportPaths(const Paths & paths,
 
 std::string ValidPathInfo::fingerprint() const
 {
+    if (narSize == 0 || narHash.type == htUnknown)
+        throw Error(format("cannot calculate fingerprint of path ‘%s’ because its size/hash is not known")
+            % path);
     return
         "1;" + path + ";"
         + printHashType(narHash.type) + ":" + printHash32(narHash) + ";"
diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc
index e3544a1fd0b6..bcc46c3e7d4f 100644
--- a/src/nix/sigs.cc
+++ b/src/nix/sigs.cc
@@ -34,7 +34,7 @@ struct CmdCopySigs : StorePathsCommand
         restoreAffinity(); // FIXME
 
         if (substituterUris.empty())
-            throw UsageError("you must specify at least one subtituter using ‘-s’");
+            throw UsageError("you must specify at least one substituter using ‘-s’");
 
         // FIXME: factor out commonality with MixVerify.
         std::vector<ref<Store>> substituters;
@@ -131,3 +131,51 @@ struct CmdQueryPathSigs : StorePathsCommand
 };
 
 static RegisterCommand r2(make_ref<CmdQueryPathSigs>());
+
+struct CmdSignPaths : StorePathsCommand
+{
+    Path secretKeyFile;
+
+    CmdSignPaths()
+    {
+        mkFlag('k', "key-file", {"file"}, "file containing the secret signing key", &secretKeyFile);
+    }
+
+    std::string name() override
+    {
+        return "sign-paths";
+    }
+
+    std::string description() override
+    {
+        return "sign the specified paths";
+    }
+
+    void run(ref<Store> store, Paths storePaths) override
+    {
+        if (secretKeyFile.empty())
+            throw UsageError("you must specify a secret key file using ‘-k’");
+
+        SecretKey secretKey(readFile(secretKeyFile));
+
+        size_t added{0};
+
+        for (auto & storePath : storePaths) {
+            auto info = store->queryPathInfo(storePath);
+
+            auto info2(info);
+            info2.sigs.clear();
+            info2.sign(secretKey);
+            assert(!info2.sigs.empty());
+
+            if (!info.sigs.count(*info2.sigs.begin())) {
+                store->addSignatures(storePath, info2.sigs);
+                added++;
+            }
+        }
+
+        printMsg(lvlInfo, format("added %d signatures") % added);
+    }
+};
+
+static RegisterCommand r3(make_ref<CmdSignPaths>());