about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--third_party/nix/src/libstore/rpc-store.cc52
-rw-r--r--third_party/nix/src/libutil/hash.cc15
-rw-r--r--third_party/nix/src/libutil/hash.hh2
-rw-r--r--third_party/nix/src/nix-daemon/nix-daemon-proto.cc2
4 files changed, 69 insertions, 2 deletions
diff --git a/third_party/nix/src/libstore/rpc-store.cc b/third_party/nix/src/libstore/rpc-store.cc
index f0abdd42ef..0b57127610 100644
--- a/third_party/nix/src/libstore/rpc-store.cc
+++ b/third_party/nix/src/libstore/rpc-store.cc
@@ -1,6 +1,7 @@
 #include "rpc-store.hh"
 
 #include <algorithm>
+#include <filesystem>
 #include <memory>
 
 #include <absl/status/status.h>
@@ -20,6 +21,7 @@
 #include "libproto/worker.grpc.pb.h"
 #include "libproto/worker.pb.h"
 #include "libstore/store-api.hh"
+#include "libutil/archive.hh"
 #include "libutil/hash.hh"
 #include "libutil/types.hh"
 
@@ -54,6 +56,32 @@ T FillFrom(const U& src) {
   return result;
 }
 
+class AddToStorePathWriterSink : public BufferedSink {
+ public:
+  explicit AddToStorePathWriterSink(
+      std::unique_ptr<
+          grpc_impl::ClientWriter<class nix::proto::AddToStoreRequest>>&&
+          writer)
+      : writer_(std::move(writer)), good_(true) {}
+
+  bool good() override { return good_; }
+
+  void write(const unsigned char* data, size_t len) override {
+    proto::AddToStoreRequest req;
+    req.set_data(data, len);
+    if (!writer_->Write(req)) {
+      good_ = false;
+    }
+  }
+
+  grpc::Status Finish() { return writer_->Finish(); }
+
+ private:
+  std::unique_ptr<grpc_impl::ClientWriter<class nix::proto::AddToStoreRequest>>
+      writer_;
+  bool good_;
+};
+
 constexpr absl::StatusCode GRPCStatusCodeToAbsl(grpc::StatusCode code) {
   switch (code) {
     case grpc::StatusCode::OK:
@@ -304,7 +332,29 @@ void RpcStore::addToStore(const ValidPathInfo& info,
 Path RpcStore::addToStore(const std::string& name, const Path& srcPath,
                           bool recursive, HashType hashAlgo, PathFilter& filter,
                           RepairFlag repair) {
-  throw Unsupported(absl::StrCat("Not implemented ", __func__));
+  if (repair != 0u) {
+    throw Error(
+        "repairing is not supported when building through the Nix daemon");
+  }
+
+  ClientContext ctx;
+  proto::StorePath response;
+  auto writer = stub_->AddToStore(&ctx, &response);
+
+  proto::AddToStoreRequest metadata_req;
+  metadata_req.mutable_meta()->set_base_name(name);
+  // TODO(grfn): what is fixed?
+  metadata_req.mutable_meta()->set_fixed(!(hashAlgo == htSHA256 && recursive));
+  metadata_req.mutable_meta()->set_recursive(recursive);
+  metadata_req.mutable_meta()->set_hash_type(HashTypeToProto(hashAlgo));
+  writer->Write(metadata_req);
+
+  AddToStorePathWriterSink sink(std::move(writer));
+  dumpPath(std::filesystem::absolute(srcPath), sink);
+  sink.flush();
+  SuccessOrThrow(sink.Finish());
+
+  return response.path();
 }
 
 Path RpcStore::addTextToStore(const std::string& name,
diff --git a/third_party/nix/src/libutil/hash.cc b/third_party/nix/src/libutil/hash.cc
index 97cc137b11..f7ee44728f 100644
--- a/third_party/nix/src/libutil/hash.cc
+++ b/third_party/nix/src/libutil/hash.cc
@@ -35,6 +35,21 @@ std::optional<HashType> hash_type_from(nix::proto::HashType hash_type) {
   }
 }
 
+nix::proto::HashType HashTypeToProto(HashType hash_type) {
+  switch (hash_type) {
+    case HashType::htMD5:
+      return nix::proto::HashType::MD5;
+    case HashType::htSHA1:
+      return nix::proto::HashType::SHA1;
+    case HashType::htSHA256:
+      return nix::proto::HashType::SHA256;
+    case HashType::htSHA512:
+      return nix::proto::HashType::SHA512;
+    default:
+      return nix::proto::HashType::UNKNOWN;
+  }
+}
+
 void Hash::init() {
   if (type == htMD5) {
     hashSize = md5HashSize;
diff --git a/third_party/nix/src/libutil/hash.hh b/third_party/nix/src/libutil/hash.hh
index bc32f91463..4d52702aee 100644
--- a/third_party/nix/src/libutil/hash.hh
+++ b/third_party/nix/src/libutil/hash.hh
@@ -16,6 +16,8 @@ enum HashType : char { htUnknown, htMD5, htSHA1, htSHA256, htSHA512 };
 
 std::optional<HashType> hash_type_from(nix::proto::HashType hash_type);
 
+nix::proto::HashType HashTypeToProto(HashType hash_type);
+
 const int md5HashSize = 16;
 const int sha1HashSize = 20;
 const int sha256HashSize = 32;
diff --git a/third_party/nix/src/nix-daemon/nix-daemon-proto.cc b/third_party/nix/src/nix-daemon/nix-daemon-proto.cc
index b3ecc9d5b9..fe580b08a2 100644
--- a/third_party/nix/src/nix-daemon/nix-daemon-proto.cc
+++ b/third_party/nix/src/nix-daemon/nix-daemon-proto.cc
@@ -146,7 +146,7 @@ class WorkerServiceImpl final : public WorkerService::Service {
           proto::AddToStoreRequest metadata_request;
           auto has_metadata = reader->Read(&metadata_request);
 
-          if (!has_metadata || metadata_request.has_meta()) {
+          if (!has_metadata || !metadata_request.has_meta()) {
             return Status(grpc::StatusCode::INVALID_ARGUMENT,
                           "Metadata must be set before sending file content");
           }