about summary refs log tree commit diff
path: root/third_party/nix/src/libstore/local-binary-cache-store.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/nix/src/libstore/local-binary-cache-store.cc')
-rw-r--r--third_party/nix/src/libstore/local-binary-cache-store.cc93
1 files changed, 93 insertions, 0 deletions
diff --git a/third_party/nix/src/libstore/local-binary-cache-store.cc b/third_party/nix/src/libstore/local-binary-cache-store.cc
new file mode 100644
index 0000000000..4555de5047
--- /dev/null
+++ b/third_party/nix/src/libstore/local-binary-cache-store.cc
@@ -0,0 +1,93 @@
+#include <utility>
+
+#include <absl/strings/match.h>
+
+#include "libstore/binary-cache-store.hh"
+#include "libstore/globals.hh"
+#include "libstore/nar-info-disk-cache.hh"
+
+namespace nix {
+
+class LocalBinaryCacheStore : public BinaryCacheStore {
+ private:
+  Path binaryCacheDir;
+
+ public:
+  LocalBinaryCacheStore(const Params& params, Path binaryCacheDir)
+      : BinaryCacheStore(params), binaryCacheDir(std::move(binaryCacheDir)) {}
+
+  void init() override;
+
+  std::string getUri() override { return "file://" + binaryCacheDir; }
+
+ protected:
+  bool fileExists(const std::string& path) override;
+
+  void upsertFile(const std::string& path, const std::string& data,
+                  const std::string& mimeType) override;
+
+  void getFile(const std::string& path, Sink& sink) override {
+    try {
+      readFile(binaryCacheDir + "/" + path, sink);
+    } catch (SysError& e) {
+      if (e.errNo == ENOENT) {
+        throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache",
+                                    path);
+      }
+    }
+  }
+
+  PathSet queryAllValidPaths() override {
+    PathSet paths;
+
+    for (auto& entry : readDirectory(binaryCacheDir)) {
+      if (entry.name.size() != 40 || !absl::EndsWith(entry.name, ".narinfo")) {
+        continue;
+      }
+      paths.insert(storeDir + "/" +
+                   entry.name.substr(0, entry.name.size() - 8));
+    }
+
+    return paths;
+  }
+};
+
+void LocalBinaryCacheStore::init() {
+  createDirs(binaryCacheDir + "/nar");
+  BinaryCacheStore::init();
+}
+
+static void atomicWrite(const Path& path, const std::string& s) {
+  Path tmp = path + ".tmp." + std::to_string(getpid());
+  AutoDelete del(tmp, false);
+  writeFile(tmp, s);
+  if (rename(tmp.c_str(), path.c_str()) != 0) {
+    throw SysError(format("renaming '%1%' to '%2%'") % tmp % path);
+  }
+  del.cancel();
+}
+
+bool LocalBinaryCacheStore::fileExists(const std::string& path) {
+  return pathExists(binaryCacheDir + "/" + path);
+}
+
+void LocalBinaryCacheStore::upsertFile(const std::string& path,
+                                       const std::string& data,
+                                       const std::string& mimeType) {
+  atomicWrite(binaryCacheDir + "/" + path, data);
+}
+
+static RegisterStoreImplementation regStore(
+    [](const std::string& uri,
+       const Store::Params& params) -> std::shared_ptr<Store> {
+      if (getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") == "1" ||
+          std::string(uri, 0, 7) != "file://") {
+        return nullptr;
+      }
+      auto store =
+          std::make_shared<LocalBinaryCacheStore>(params, std::string(uri, 7));
+      store->init();
+      return store;
+    });
+
+}  // namespace nix