aboutsummaryrefslogtreecommitdiff
path: root/src/nix/sigs.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix/sigs.cc')
-rw-r--r--src/nix/sigs.cc139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc
new file mode 100644
index 000000000..9932aa4a9
--- /dev/null
+++ b/src/nix/sigs.cc
@@ -0,0 +1,139 @@
+#include "command.hh"
+#include "shared.hh"
+#include "store-api.hh"
+#include "thread-pool.hh"
+
+#include <atomic>
+
+using namespace nix;
+
+struct CmdCopySigs : StorePathsCommand
+{
+ Strings substituterUris;
+
+ CmdCopySigs()
+ {
+ mkFlag('s', "substituter", {"store-uri"}, "use signatures from specified store", 1,
+ [&](Strings ss) { substituterUris.push_back(ss.front()); });
+ }
+
+ std::string name() override
+ {
+ return "copy-sigs";
+ }
+
+ std::string description() override
+ {
+ return "copy path signatures from substituters (like binary caches)";
+ }
+
+ void run(ref<Store> store, Paths storePaths) override
+ {
+ if (substituterUris.empty())
+ throw UsageError("you must specify at least one substituter using ‘-s’");
+
+ // FIXME: factor out commonality with MixVerify.
+ std::vector<ref<Store>> substituters;
+ for (auto & s : substituterUris)
+ substituters.push_back(openStoreAt(s));
+
+ ThreadPool pool;
+
+ std::string doneLabel = "done";
+ std::atomic<size_t> added{0};
+
+ logger->setExpected(doneLabel, storePaths.size());
+
+ auto doPath = [&](const Path & storePath) {
+ Activity act(*logger, lvlInfo, format("getting signatures for ‘%s’") % storePath);
+
+ checkInterrupt();
+
+ auto info = store->queryPathInfo(storePath);
+
+ StringSet newSigs;
+
+ for (auto & store2 : substituters) {
+ try {
+ auto info2 = store2->queryPathInfo(storePath);
+
+ /* Don't import signatures that don't match this
+ binary. */
+ if (info->narHash != info2->narHash ||
+ info->narSize != info2->narSize ||
+ info->references != info2->references)
+ continue;
+
+ for (auto & sig : info2->sigs)
+ if (!info->sigs.count(sig))
+ newSigs.insert(sig);
+ } catch (InvalidPath &) {
+ }
+ }
+
+ if (!newSigs.empty()) {
+ store->addSignatures(storePath, newSigs);
+ added += newSigs.size();
+ }
+
+ logger->incProgress(doneLabel);
+ };
+
+ for (auto & storePath : storePaths)
+ pool.enqueue(std::bind(doPath, storePath));
+
+ pool.process();
+
+ printMsg(lvlInfo, format("imported %d signatures") % added);
+ }
+};
+
+static RegisterCommand r1(make_ref<CmdCopySigs>());
+
+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>());