about summary refs log tree commit diff
path: root/src/nix
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-04-05T13·30+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-04-05T14·39+0200
commitd0f5719c2a2e5a0eea49dc072b26e7d161564bbb (patch)
tree48589fd3963b008418004a2fca383a29c347e1be /src/nix
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
Diffstat (limited to 'src/nix')
-rw-r--r--src/nix/sigs.cc133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc
new file mode 100644
index 0000000000..e3544a1fd0
--- /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>());