about summary refs log tree commit diff
path: root/src/libstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/binary-cache-store.cc35
-rw-r--r--src/libstore/binary-cache-store.hh3
-rw-r--r--src/libstore/build.cc6
-rw-r--r--src/libstore/crypto.cc11
-rw-r--r--src/libstore/crypto.hh12
-rw-r--r--src/libstore/http-binary-cache-store.cc76
-rw-r--r--src/libstore/local-binary-cache-store.cc24
-rw-r--r--src/libstore/local-store.cc8
-rw-r--r--src/libstore/store-api.hh4
9 files changed, 142 insertions, 37 deletions
diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc
index 02e73d2ce1fa..5ded16d028b0 100644
--- a/src/libstore/binary-cache-store.cc
+++ b/src/libstore/binary-cache-store.cc
@@ -14,21 +14,18 @@
 namespace nix {
 
 BinaryCacheStore::BinaryCacheStore(std::shared_ptr<Store> localStore,
-    const Path & secretKeyFile, const Path & publicKeyFile)
+    const Path & secretKeyFile)
     : localStore(localStore)
 {
-    if (secretKeyFile != "")
+    if (secretKeyFile != "") {
         secretKey = std::unique_ptr<SecretKey>(new SecretKey(readFile(secretKeyFile)));
-
-    if (publicKeyFile != "") {
         publicKeys = std::unique_ptr<PublicKeys>(new PublicKeys);
-        auto key = PublicKey(readFile(publicKeyFile));
-        publicKeys->emplace(key.name, key);
+        publicKeys->emplace(secretKey->name, secretKey->toPublicKey());
     }
 
     StringSink sink;
     sink << narVersionMagic1;
-    narMagic = sink.s;
+    narMagic = *sink.s;
 }
 
 void BinaryCacheStore::init()
@@ -200,14 +197,16 @@ Paths BinaryCacheStore::importPaths(bool requireSignature, Source & source,
 struct TeeSource : Source
 {
     Source & readSource;
-    std::string data;
-    TeeSource(Source & readSource) : readSource(readSource)
+    ref<std::string> data;
+    TeeSource(Source & readSource)
+        : readSource(readSource)
+        , data(make_ref<std::string>())
     {
     }
     size_t read(unsigned char * data, size_t len)
     {
         size_t n = readSource.read(data, len);
-        this->data.append((char *) data, n);
+        this->data->append((char *) data, n);
         return n;
     }
 };
@@ -257,7 +256,7 @@ Path BinaryCacheStore::addToStore(const string & name, const Path & srcPath,
     Hash h;
     if (recursive) {
         dumpPath(srcPath, sink, filter);
-        h = hashString(hashAlgo, sink.s);
+        h = hashString(hashAlgo, *sink.s);
     } else {
         auto s = readFile(srcPath);
         dumpString(s, sink);
@@ -268,7 +267,7 @@ Path BinaryCacheStore::addToStore(const string & name, const Path & srcPath,
     info.path = makeFixedOutputPath(recursive, hashAlgo, h, name);
 
     if (repair || !isValidPath(info.path))
-        addToCache(info, sink.s);
+        addToCache(info, *sink.s);
 
     return info.path;
 }
@@ -283,7 +282,7 @@ Path BinaryCacheStore::addTextToStore(const string & name, const string & s,
     if (repair || !isValidPath(info.path)) {
         StringSink sink;
         dumpString(s, sink);
-        addToCache(info, sink.s);
+        addToCache(info, *sink.s);
     }
 
     return info.path;
@@ -313,7 +312,7 @@ void BinaryCacheStore::buildPaths(const PathSet & paths, BuildMode buildMode)
         StringSink sink;
         dumpPath(storePath, sink);
 
-        addToCache(info, sink.s);
+        addToCache(info, *sink.s);
     }
 }
 
@@ -352,8 +351,7 @@ struct BinaryCacheStoreAccessor : public FSAccessor
         StringSink sink;
         store->exportPath(storePath, false, sink);
 
-        // FIXME: gratuitous string copying.
-        auto accessor = makeNarAccessor(make_ref<std::string>(sink.s));
+        auto accessor = makeNarAccessor(sink.s);
         nars.emplace(storePath, accessor);
         return {accessor, restPath};
     }
@@ -412,12 +410,11 @@ Path BinaryCacheStore::importPath(Source & source, std::shared_ptr<FSAccessor> a
     bool haveSignature = readInt(source) == 1;
     assert(!haveSignature);
 
-    addToCache(info, tee.data);
+    addToCache(info, *tee.data);
 
     auto accessor_ = std::dynamic_pointer_cast<BinaryCacheStoreAccessor>(accessor);
     if (accessor_)
-        // FIXME: more gratuitous string copying
-        accessor_->nars.emplace(info.path, makeNarAccessor(make_ref<std::string>(tee.data)));
+        accessor_->nars.emplace(info.path, makeNarAccessor(tee.data));
 
     return info.path;
 }
diff --git a/src/libstore/binary-cache-store.hh b/src/libstore/binary-cache-store.hh
index 6feb84cd2b10..c99556f33692 100644
--- a/src/libstore/binary-cache-store.hh
+++ b/src/libstore/binary-cache-store.hh
@@ -31,8 +31,7 @@ private:
 
 protected:
 
-    BinaryCacheStore(std::shared_ptr<Store> localStore,
-        const Path & secretKeyFile, const Path & publicKeyFile);
+    BinaryCacheStore(std::shared_ptr<Store> localStore, const Path & secretKeyFile);
 
     [[noreturn]] void notImpl();
 
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 7d124f6f0ee0..ed4e0f659da3 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -2009,7 +2009,7 @@ void DerivationGoal::startBuilder()
                         throw SysError(format("linking ‘%1%’ to ‘%2%’") % p % i);
                     StringSink sink;
                     dumpPath(i, sink);
-                    StringSource source(sink.s);
+                    StringSource source(*sink.s);
                     restorePath(p, source);
                 }
             }
@@ -2666,8 +2666,8 @@ void DerivationGoal::registerOutputs()
             StringSink sink;
             dumpPath(actualPath, sink);
             deletePath(actualPath);
-            sink.s = rewriteHashes(sink.s, rewritesFromTmp);
-            StringSource source(sink.s);
+            sink.s = make_ref<std::string>(rewriteHashes(*sink.s, rewritesFromTmp));
+            StringSource source(*sink.s);
             restorePath(actualPath, source);
 
             rewritten = true;
diff --git a/src/libstore/crypto.cc b/src/libstore/crypto.cc
index c1b57e51d9b4..53e94e1f5997 100644
--- a/src/libstore/crypto.cc
+++ b/src/libstore/crypto.cc
@@ -55,6 +55,17 @@ std::string SecretKey::signDetached(const std::string & data) const
 #endif
 }
 
+PublicKey SecretKey::toPublicKey() const
+{
+#if HAVE_SODIUM
+    unsigned char pk[crypto_sign_PUBLICKEYBYTES];
+    crypto_sign_ed25519_sk_to_pk(pk, (unsigned char *) key.data());
+    return PublicKey(name, std::string((char *) pk, crypto_sign_PUBLICKEYBYTES));
+#else
+    noSodium();
+#endif
+}
+
 PublicKey::PublicKey(const string & s)
     : Key(s)
 {
diff --git a/src/libstore/crypto.hh b/src/libstore/crypto.hh
index a1489e753649..33b79cb2e8fe 100644
--- a/src/libstore/crypto.hh
+++ b/src/libstore/crypto.hh
@@ -15,19 +15,31 @@ struct Key
        ‘<name>:<key-in-base64>’. */
     Key(const std::string & s);
 
+protected:
+    Key(const std::string & name, const std::string & key)
+        : name(name), key(key) { }
 };
 
+struct PublicKey;
+
 struct SecretKey : Key
 {
     SecretKey(const std::string & s);
 
     /* Return a detached signature of the given string. */
     std::string signDetached(const std::string & s) const;
+
+    PublicKey toPublicKey() const;
 };
 
 struct PublicKey : Key
 {
     PublicKey(const std::string & data);
+
+private:
+    PublicKey(const std::string & name, const std::string & key)
+        : Key(name, key) { }
+    friend class SecretKey;
 };
 
 typedef std::map<std::string, PublicKey> PublicKeys;
diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc
new file mode 100644
index 000000000000..9614d0b4cf35
--- /dev/null
+++ b/src/libstore/http-binary-cache-store.cc
@@ -0,0 +1,76 @@
+#include "binary-cache-store.hh"
+#include "download.hh"
+#include "globals.hh"
+
+namespace nix {
+
+class HttpBinaryCacheStore : public BinaryCacheStore
+{
+private:
+
+    Path cacheUri;
+
+    ref<Downloader> downloader;
+
+public:
+
+    HttpBinaryCacheStore(std::shared_ptr<Store> localStore,
+        const Path & secretKeyFile, const Path & _cacheUri)
+        : BinaryCacheStore(localStore, secretKeyFile)
+        , cacheUri(_cacheUri)
+        , downloader(makeDownloader())
+    {
+        if (cacheUri.back() == '/')
+            cacheUri.pop_back();
+    }
+
+    void init() override
+    {
+        // FIXME: do this lazily?
+        if (!fileExists("nix-cache-info"))
+            throw Error(format("‘%s’ does not appear to be a binary cache") % cacheUri);
+    }
+
+protected:
+
+    bool fileExists(const std::string & path) override
+    {
+        try {
+            DownloadOptions options;
+            options.showProgress = DownloadOptions::no;
+            options.head = true;
+            downloader->download(cacheUri + "/" + path, options);
+            return true;
+        } catch (DownloadError & e) {
+            if (e.error == Downloader::NotFound)
+                return false;
+            throw;
+        }
+    }
+
+    void upsertFile(const std::string & path, const std::string & data)
+    {
+        throw Error("uploading to an HTTP binary cache is not supported");
+    }
+
+    std::string getFile(const std::string & path) override
+    {
+        DownloadOptions options;
+        options.showProgress = DownloadOptions::no;
+        return downloader->download(cacheUri + "/" + path, options).data;
+    }
+
+};
+
+static RegisterStoreImplementation regStore([](const std::string & uri) -> std::shared_ptr<Store> {
+    if (std::string(uri, 0, 7) != "http://" &&
+        std::string(uri, 0, 8) != "https://") return 0;
+    auto store = std::make_shared<HttpBinaryCacheStore>(std::shared_ptr<Store>(0),
+        settings.get("binary-cache-secret-key-file", string("")),
+        uri);
+    store->init();
+    return store;
+});
+
+}
+
diff --git a/src/libstore/local-binary-cache-store.cc b/src/libstore/local-binary-cache-store.cc
index a10c9d1069d5..efd6d47254f2 100644
--- a/src/libstore/local-binary-cache-store.cc
+++ b/src/libstore/local-binary-cache-store.cc
@@ -1,4 +1,5 @@
 #include "binary-cache-store.hh"
+#include "globals.hh"
 
 namespace nix {
 
@@ -11,8 +12,7 @@ private:
 public:
 
     LocalBinaryCacheStore(std::shared_ptr<Store> localStore,
-        const Path & secretKeyFile, const Path & publicKeyFile,
-        const Path & binaryCacheDir);
+        const Path & secretKeyFile, const Path & binaryCacheDir);
 
     void init() override;
 
@@ -27,9 +27,8 @@ protected:
 };
 
 LocalBinaryCacheStore::LocalBinaryCacheStore(std::shared_ptr<Store> localStore,
-    const Path & secretKeyFile, const Path & publicKeyFile,
-    const Path & binaryCacheDir)
-    : BinaryCacheStore(localStore, secretKeyFile, publicKeyFile)
+    const Path & secretKeyFile, const Path & binaryCacheDir)
+    : BinaryCacheStore(localStore, secretKeyFile)
     , binaryCacheDir(binaryCacheDir)
 {
 }
@@ -65,13 +64,20 @@ std::string LocalBinaryCacheStore::getFile(const std::string & path)
     return readFile(binaryCacheDir + "/" + path);
 }
 
+ref<Store> openLocalBinaryCacheStore(std::shared_ptr<Store> localStore,
+    const Path & secretKeyFile, const Path & binaryCacheDir)
+{
+    auto store = make_ref<LocalBinaryCacheStore>(
+        localStore, secretKeyFile, binaryCacheDir);
+    store->init();
+    return store;
+}
+
 static RegisterStoreImplementation regStore([](const std::string & uri) -> std::shared_ptr<Store> {
     if (std::string(uri, 0, 7) != "file://") return 0;
-    auto store = std::make_shared<LocalBinaryCacheStore>(std::shared_ptr<Store>(0),
-        "", "", // FIXME: allow the signing key to be set
+    return openLocalBinaryCacheStore(std::shared_ptr<Store>(0),
+        settings.get("binary-cache-secret-key-file", string("")),
         std::string(uri, 7));
-    store->init();
-    return store;
 });
 
 }
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 9a570668128e..8a2b7bb9164e 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -1415,9 +1415,9 @@ Path LocalStore::addToStore(const string & name, const Path & _srcPath,
     if (recursive)
         dumpPath(srcPath, sink, filter);
     else
-        sink.s = readFile(srcPath);
+        sink.s = make_ref<std::string>(readFile(srcPath));
 
-    return addToStoreFromDump(sink.s, name, recursive, hashAlgo, repair);
+    return addToStoreFromDump(*sink.s, name, recursive, hashAlgo, repair);
 }
 
 
@@ -1442,14 +1442,14 @@ Path LocalStore::addTextToStore(const string & name, const string & s,
 
             StringSink sink;
             dumpString(s, sink);
-            auto hash = hashString(htSHA256, sink.s);
+            auto hash = hashString(htSHA256, *sink.s);
 
             optimisePath(dstPath);
 
             ValidPathInfo info;
             info.path = dstPath;
             info.narHash = hash;
-            info.narSize = sink.s.size();
+            info.narSize = sink.s->size();
             info.references = references;
             registerValidPath(info);
         }
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 97e834ed2bd8..adec0fb788c8 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -453,6 +453,10 @@ ref<Store> openStoreAt(const std::string & uri);
 ref<Store> openStore();
 
 
+ref<Store> openLocalBinaryCacheStore(std::shared_ptr<Store> localStore,
+    const Path & secretKeyFile, const Path & binaryCacheDir);
+
+
 /* Store implementation registration. */
 typedef std::function<std::shared_ptr<Store>(const std::string & uri)> OpenStore;