aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-04-05 15:30:22 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-04-05 16:39:23 +0200
commitd0f5719c2a2e5a0eea49dc072b26e7d161564bbb (patch)
tree48589fd3963b008418004a2fca383a29c347e1be
parent80da7a637559aadb6544599adc9f5807188cb9e5 (diff)
Add "nix copy-sigs" command
This imports signatures from one store into another. E.g. $ nix copy-sigs -r /run/current-system -s https://cache.nixos.org/ imported 595 signatures
-rw-r--r--src/libstore/binary-cache-store.hh3
-rw-r--r--src/libstore/local-store.cc22
-rw-r--r--src/libstore/local-store.hh2
-rw-r--r--src/libstore/remote-store.cc9
-rw-r--r--src/libstore/remote-store.hh2
-rw-r--r--src/libstore/store-api.hh4
-rw-r--r--src/libstore/worker-protocol.hh1
-rw-r--r--src/nix-daemon/nix-daemon.cc12
-rw-r--r--src/nix/sigs.cc133
9 files changed, 185 insertions, 3 deletions
diff --git a/src/libstore/binary-cache-store.hh b/src/libstore/binary-cache-store.hh
index de6941561..0020f89ee 100644
--- a/src/libstore/binary-cache-store.hh
+++ b/src/libstore/binary-cache-store.hh
@@ -170,6 +170,9 @@ public:
ref<FSAccessor> getFSAccessor() override;
+ void addSignatures(const Path & storePath, const StringSet & sigs)
+ { notImpl(); }
+
};
}
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 9b961b192..28e340af7 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -312,7 +312,7 @@ void LocalStore::openDB(bool create)
stmtRegisterValidPath.create(db,
"insert into ValidPaths (path, hash, registrationTime, deriver, narSize, ultimate) values (?, ?, ?, ?, ?, ?);");
stmtUpdatePathInfo.create(db,
- "update ValidPaths set narSize = ?, hash = ?, ultimate = ? where path = ?;");
+ "update ValidPaths set narSize = ?, hash = ?, ultimate = ?, sigs = ? where path = ?;");
stmtAddReference.create(db,
"insert or replace into Refs (referrer, reference) values (?, ?);");
stmtQueryPathInfo.create(db,
@@ -683,14 +683,14 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
}
-/* Update path info in the database. Currently only updates the
- narSize field. */
+/* Update path info in the database. */
void LocalStore::updatePathInfo(const ValidPathInfo & info)
{
stmtUpdatePathInfo.use()
(info.narSize, info.narSize != 0)
("sha256:" + printHash(info.narHash))
(info.ultimate ? 1 : 0, info.ultimate)
+ (concatStringsSep(" ", info.sigs), !info.sigs.empty())
(info.path)
.exec();
}
@@ -1694,4 +1694,20 @@ void LocalStore::vacuumDB()
}
+void LocalStore::addSignatures(const Path & storePath, const StringSet & sigs)
+{
+ retrySQLite<void>([&]() {
+ SQLiteTxn txn(db);
+
+ auto info = queryPathInfo(storePath);
+
+ info.sigs.insert(sigs.begin(), sigs.end());
+
+ updatePathInfo(info);
+
+ txn.commit();
+ });
+}
+
+
}
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index e90894277..ec8146e68 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -182,6 +182,8 @@ public:
void setSubstituterEnv();
+ void addSignatures(const Path & storePath, const StringSet & sigs) override;
+
private:
Path schemaPath;
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 7893f2a4c..4d5d689dc 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -554,6 +554,15 @@ bool RemoteStore::verifyStore(bool checkContents, bool repair)
}
+void RemoteStore::addSignatures(const Path & storePath, const StringSet & sigs)
+{
+ auto conn(connections->get());
+ conn->to << wopAddSignatures << storePath << sigs;
+ conn->processStderr();
+ readInt(conn->from);
+}
+
+
RemoteStore::Connection::~Connection()
{
try {
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 85c8292c7..cede4d332 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -93,6 +93,8 @@ public:
bool verifyStore(bool checkContents, bool repair) override;
+ void addSignatures(const Path & storePath, const StringSet & sigs) override;
+
private:
struct Connection
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 7c6e4c079..4ea360b9d 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -346,6 +346,10 @@ public:
/* Return an object to access files in the Nix store. */
virtual ref<FSAccessor> getFSAccessor() = 0;
+ /* Add signatures to the specified store path. The signatures are
+ not verified. */
+ virtual void addSignatures(const Path & storePath, const StringSet & sigs) = 0;
+
/* Utility functions. */
/* Read a derivation, after ensuring its existence through
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index 4f60c3adc..c10598d5d 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -45,6 +45,7 @@ typedef enum {
wopOptimiseStore = 34,
wopVerifyStore = 35,
wopBuildDerivation = 36,
+ wopAddSignatures = 37,
} WorkerOp;
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc
index 527f6bca9..439cd3dc0 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix-daemon/nix-daemon.cc
@@ -543,6 +543,18 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
break;
}
+ case wopAddSignatures: {
+ Path path = readStorePath(from);
+ StringSet sigs = readStrings<StringSet>(from);
+ startWork();
+ if (!trusted)
+ throw Error("you are not privileged to add signatures");
+ store->addSignatures(path, sigs);
+ stopWork();
+ to << 1;
+ break;
+ }
+
default:
throw Error(format("invalid operation %1%") % op);
}
diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc
new file mode 100644
index 000000000..e3544a1fd
--- /dev/null
+++ b/src/nix/sigs.cc
@@ -0,0 +1,133 @@
+#include "affinity.hh" // FIXME
+#include "command.hh"
+#include "progress-bar.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
+ {
+ restoreAffinity(); // FIXME
+
+ if (substituterUris.empty())
+ throw UsageError("you must specify at least one subtituter using ā€˜-sā€™");
+
+ // FIXME: factor out commonality with MixVerify.
+ std::vector<ref<Store>> substituters;
+ for (auto & s : substituterUris)
+ substituters.push_back(openStoreAt(s));
+
+ ProgressBar progressBar;
+
+ ThreadPool pool;
+
+ std::atomic<size_t> done{0};
+ std::atomic<size_t> added{0};
+
+ auto showProgress = [&]() {
+ return (format("[%d/%d done]") % done % storePaths.size()).str();
+ };
+
+ progressBar.updateStatus(showProgress());
+
+ auto doPath = [&](const Path & storePath) {
+ auto activity(progressBar.startActivity(format("getting signatures for ā€˜%sā€™") % storePath));
+
+ checkInterrupt();
+
+ auto info = store->queryPathInfo(storePath);
+
+ StringSet newSigs;
+
+ for (auto & store2 : substituters) {
+ if (!store2->isValidPath(storePath)) continue;
+ 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);
+ }
+
+ if (!newSigs.empty()) {
+ store->addSignatures(storePath, newSigs);
+ added += newSigs.size();
+ }
+
+ done++;
+ progressBar.updateStatus(showProgress());
+ };
+
+ for (auto & storePath : storePaths)
+ pool.enqueue(std::bind(doPath, storePath));
+
+ pool.process();
+
+ progressBar.done();
+
+ printMsg(lvlInfo, format("imported %d signatures") % added);
+ }
+};
+
+static RegisterCommand r1(make_ref<CmdCopySigs>());
+
+struct CmdQueryPathSigs : StorePathsCommand
+{
+ CmdQueryPathSigs()
+ {
+ }
+
+ std::string name() override
+ {
+ return "query-path-sigs";
+ }
+
+ std::string description() override
+ {
+ return "print store path signatures";
+ }
+
+ void run(ref<Store> store, Paths storePaths) override
+ {
+ for (auto & storePath : storePaths) {
+ auto info = store->queryPathInfo(storePath);
+ std::cout << storePath << " ";
+ if (info.ultimate) std::cout << "ultimate ";
+ for (auto & sig : info.sigs)
+ std::cout << sig << " ";
+ std::cout << "\n";
+ }
+ }
+};
+
+static RegisterCommand r2(make_ref<CmdQueryPathSigs>());