aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/build/local-derivation-goal.cc54
-rw-r--r--src/libstore/content-address.cc137
-rw-r--r--src/libstore/content-address.hh47
-rw-r--r--src/libstore/daemon.cc10
-rw-r--r--src/libstore/derivations.cc56
-rw-r--r--src/libstore/derivations.hh8
-rw-r--r--src/libstore/local-store.cc2
-rw-r--r--src/libstore/misc.cc18
-rw-r--r--src/libstore/remote-store.cc20
-rw-r--r--src/libstore/remote-store.hh1
-rw-r--r--src/libstore/tests/derivation.cc25
11 files changed, 265 insertions, 113 deletions
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index 4fb7aa9d8..7cb80977d 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -2423,37 +2423,43 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
throw BuildError(
"output path %1% without valid stats info",
actualPath);
- if (outputHash.method == FileIngestionMethod::Flat) {
+ if (outputHash.method == ContentAddressMethod { FileIngestionMethod::Flat } ||
+ outputHash.method == ContentAddressMethod { TextHashMethod {} })
+ {
/* The output path should be a regular file without execute permission. */
if (!S_ISREG(st->st_mode) || (st->st_mode & S_IXUSR) != 0)
throw BuildError(
"output path '%1%' should be a non-executable regular file "
- "since recursive hashing is not enabled (outputHashMode=flat)",
+ "since recursive hashing is not enabled (one of outputHashMode={flat,text} is true)",
actualPath);
}
rewriteOutput();
/* FIXME optimize and deduplicate with addToStore */
std::string oldHashPart { scratchPath->hashPart() };
HashModuloSink caSink { outputHash.hashType, oldHashPart };
- switch (outputHash.method) {
- case FileIngestionMethod::Recursive:
- dumpPath(actualPath, caSink);
- break;
- case FileIngestionMethod::Flat:
- readFile(actualPath, caSink);
- break;
- }
+ std::visit(overloaded {
+ [&](const TextHashMethod &) {
+ readFile(actualPath, caSink);
+ },
+ [&](const FileIngestionMethod & m2) {
+ switch (m2) {
+ case FileIngestionMethod::Recursive:
+ dumpPath(actualPath, caSink);
+ break;
+ case FileIngestionMethod::Flat:
+ readFile(actualPath, caSink);
+ break;
+ }
+ },
+ }, outputHash.method.raw);
auto got = caSink.finish().first;
ValidPathInfo newInfo0 {
worker.store,
outputPathName(drv->name, outputName),
- FixedOutputInfo {
- .hash = {
- .method = outputHash.method,
- .hash = got,
- },
- .references = rewriteRefs(),
- },
+ ContentAddressWithReferences::fromParts(
+ outputHash.method,
+ std::move(got),
+ rewriteRefs()),
Hash::dummy,
};
if (*scratchPath != newInfo0.path) {
@@ -2500,13 +2506,14 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
},
[&](const DerivationOutput::CAFixed & dof) {
- auto newInfo0 = newInfoFromCA(DerivationOutput::CAFloating {
- .method = dof.hash.method,
- .hashType = dof.hash.hash.type,
+ auto wanted = dof.ca.getHash();
+
+ auto newInfo0 = newInfoFromCA(DerivationOutputCAFloating {
+ .method = dof.ca.getMethod(),
+ .hashType = wanted.type,
});
/* Check wanted hash */
- const Hash & wanted = dof.hash.hash;
assert(newInfo0.ca);
auto got = newInfo0.ca->getHash();
if (wanted != got) {
@@ -2519,6 +2526,11 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
wanted.to_string(SRI, true),
got.to_string(SRI, true)));
}
+ if (!newInfo.references.empty())
+ delayedException = std::make_exception_ptr(
+ BuildError("illegal path references in fixed-output derivation '%s'",
+ worker.store.printStorePath(drvPath)));
+
return newInfo0;
},
diff --git a/src/libstore/content-address.cc b/src/libstore/content-address.cc
index 055b216db..8c04dd285 100644
--- a/src/libstore/content-address.cc
+++ b/src/libstore/content-address.cc
@@ -21,6 +21,26 @@ std::string makeFileIngestionPrefix(FileIngestionMethod m)
}
}
+std::string ContentAddressMethod::renderPrefix() const {
+ return std::visit(overloaded {
+ [](TextHashMethod) -> std::string { return "text:"; },
+ [](FileIngestionMethod m2) {
+ /* Not prefixed for back compat with things that couldn't produce text before. */
+ return makeFileIngestionPrefix(m2);
+ },
+ }, raw);
+}
+
+ContentAddressMethod ContentAddressMethod::parsePrefix(std::string_view & m)
+{
+ ContentAddressMethod method = FileIngestionMethod::Flat;
+ if (splitPrefix(m, "r:"))
+ method = FileIngestionMethod::Recursive;
+ else if (splitPrefix(m, "text:"))
+ method = TextHashMethod {};
+ return method;
+}
+
std::string ContentAddress::render() const
{
return std::visit(overloaded {
@@ -36,14 +56,14 @@ std::string ContentAddress::render() const
}, raw);
}
-std::string ContentAddressMethod::render() const
+std::string ContentAddressMethod::render(HashType ht) const
{
return std::visit(overloaded {
- [](const TextHashMethod & th) {
- return std::string{"text:"} + printHashType(htSHA256);
+ [&](const TextHashMethod & th) {
+ return std::string{"text:"} + printHashType(ht);
},
- [](const FixedOutputHashMethod & fshm) {
- return "fixed:" + makeFileIngestionPrefix(fshm.fileIngestionMethod) + printHashType(fshm.hashType);
+ [&](const FileIngestionMethod & fim) {
+ return "fixed:" + makeFileIngestionPrefix(fim) + printHashType(ht);
}
}, raw);
}
@@ -51,7 +71,7 @@ std::string ContentAddressMethod::render() const
/**
* Parses content address strings up to the hash.
*/
-static ContentAddressMethod parseContentAddressMethodPrefix(std::string_view & rest)
+static std::pair<ContentAddressMethod, HashType> parseContentAddressMethodPrefix(std::string_view & rest)
{
std::string_view wholeInput { rest };
@@ -75,19 +95,19 @@ static ContentAddressMethod parseContentAddressMethodPrefix(std::string_view & r
if (prefix == "text") {
// No parsing of the ingestion method, "text" only support flat.
HashType hashType = parseHashType_();
- if (hashType != htSHA256)
- throw Error("text content address hash should use %s, but instead uses %s",
- printHashType(htSHA256), printHashType(hashType));
- return TextHashMethod {};
+ return {
+ TextHashMethod {},
+ std::move(hashType),
+ };
} else if (prefix == "fixed") {
// Parse method
auto method = FileIngestionMethod::Flat;
if (splitPrefix(rest, "r:"))
method = FileIngestionMethod::Recursive;
HashType hashType = parseHashType_();
- return FixedOutputHashMethod {
- .fileIngestionMethod = method,
- .hashType = std::move(hashType),
+ return {
+ std::move(method),
+ std::move(hashType),
};
} else
throw UsageError("content address prefix '%s' is unrecognized. Recogonized prefixes are 'text' or 'fixed'", prefix);
@@ -96,25 +116,25 @@ static ContentAddressMethod parseContentAddressMethodPrefix(std::string_view & r
ContentAddress ContentAddress::parse(std::string_view rawCa) {
auto rest = rawCa;
- ContentAddressMethod caMethod = parseContentAddressMethodPrefix(rest);
-
- return std::visit(
- overloaded {
- [&](TextHashMethod & thm) {
- return ContentAddress(TextHash {
- .hash = Hash::parseNonSRIUnprefixed(rest, htSHA256)
- });
- },
- [&](FixedOutputHashMethod & fohMethod) {
- return ContentAddress(FixedOutputHash {
- .method = fohMethod.fileIngestionMethod,
- .hash = Hash::parseNonSRIUnprefixed(rest, std::move(fohMethod.hashType)),
- });
- },
- }, caMethod.raw);
-}
-
-ContentAddressMethod ContentAddressMethod::parse(std::string_view caMethod)
+ auto [caMethod, hashType_] = parseContentAddressMethodPrefix(rest);
+ auto hashType = hashType_; // work around clang bug
+
+ return std::visit(overloaded {
+ [&](TextHashMethod &) {
+ return ContentAddress(TextHash {
+ .hash = Hash::parseNonSRIUnprefixed(rest, hashType)
+ });
+ },
+ [&](FileIngestionMethod & fim) {
+ return ContentAddress(FixedOutputHash {
+ .method = fim,
+ .hash = Hash::parseNonSRIUnprefixed(rest, hashType),
+ });
+ },
+ }, caMethod.raw);
+}
+
+std::pair<ContentAddressMethod, HashType> ContentAddressMethod::parse(std::string_view caMethod)
{
std::string asPrefix = std::string{caMethod} + ":";
// parseContentAddressMethodPrefix takes its argument by reference
@@ -134,6 +154,42 @@ std::string renderContentAddress(std::optional<ContentAddress> ca)
return ca ? ca->render() : "";
}
+ContentAddressWithReferences ContentAddressWithReferences::fromParts(
+ ContentAddressMethod method, Hash hash, StoreReferences refs)
+{
+ return std::visit(overloaded {
+ [&](TextHashMethod _) -> ContentAddressWithReferences {
+ if (refs.self)
+ throw UsageError("Cannot have a self reference with text hashing scheme");
+ return TextInfo {
+ .hash = { .hash = std::move(hash) },
+ .references = std::move(refs.others),
+ };
+ },
+ [&](FileIngestionMethod m2) -> ContentAddressWithReferences {
+ return FixedOutputInfo {
+ .hash = {
+ .method = m2,
+ .hash = std::move(hash),
+ },
+ .references = std::move(refs),
+ };
+ },
+ }, method.raw);
+}
+
+ContentAddressMethod ContentAddressWithReferences::getMethod() const
+{
+ return std::visit(overloaded {
+ [](const TextInfo & th) -> ContentAddressMethod {
+ return TextHashMethod {};
+ },
+ [](const FixedOutputInfo & fsh) -> ContentAddressMethod {
+ return fsh.hash.method;
+ },
+ }, raw);
+}
+
const Hash & ContentAddress::getHash() const
{
return std::visit(overloaded {
@@ -173,4 +229,21 @@ ContentAddressWithReferences ContentAddressWithReferences::withoutRefs(const Con
}, ca.raw);
}
+Hash ContentAddressWithReferences::getHash() const
+{
+ return std::visit(overloaded {
+ [](const TextInfo & th) {
+ return th.hash.hash;
+ },
+ [](const FixedOutputInfo & fsh) {
+ return fsh.hash.hash;
+ },
+ }, raw);
+}
+
+std::string ContentAddressWithReferences::printMethodAlgo() const {
+ return getMethod().renderPrefix()
+ + printHashType(getHash().type);
+}
+
}
diff --git a/src/libstore/content-address.hh b/src/libstore/content-address.hh
index 737bf9a41..7704d2f00 100644
--- a/src/libstore/content-address.hh
+++ b/src/libstore/content-address.hh
@@ -45,13 +45,6 @@ enum struct FileIngestionMethod : uint8_t {
*/
std::string makeFileIngestionPrefix(FileIngestionMethod m);
-struct FixedOutputHashMethod {
- FileIngestionMethod fileIngestionMethod;
- HashType hashType;
-
- GENERATE_CMP(FixedOutputHashMethod, me->fileIngestionMethod, me->hashType);
-};
-
/**
* An enumeration of all the ways we can serialize file system objects.
*
@@ -64,7 +57,7 @@ struct ContentAddressMethod
{
typedef std::variant<
TextHashMethod,
- FixedOutputHashMethod
+ FileIngestionMethod
> Raw;
Raw raw;
@@ -76,9 +69,23 @@ struct ContentAddressMethod
: raw(std::forward<decltype(arg)>(arg)...)
{ }
- static ContentAddressMethod parse(std::string_view rawCaMethod);
- std::string render() const;
+ /**
+ * Parse and pretty print the algorithm which indicates how the files
+ * were ingested, with the the fixed output case not prefixed for back
+ * compat.
+ */
+ static ContentAddressMethod parsePrefix(std::string_view & m);
+
+ std::string renderPrefix() const;
+
+ /**
+ * Parse and pretty print a content addressing method and hash type in a
+ * nicer way, prefixing both cases.
+ */
+ static std::pair<ContentAddressMethod, HashType> parse(std::string_view rawCaMethod);
+
+ std::string render(HashType ht) const;
};
@@ -247,6 +254,26 @@ struct ContentAddressWithReferences
* assuming no references in all cases.
*/
static ContentAddressWithReferences withoutRefs(const ContentAddress &);
+
+ /**
+ * Create a ContentAddressWithReferences from 3 parts:
+ *
+ * @param method Way ingesting the file system data.
+ *
+ * @param hash Hash of ingested file system data.
+ *
+ * @param refs References to other store objects or oneself.
+ *
+ * Do note that not all combinations are supported.
+ */
+ static ContentAddressWithReferences fromParts(
+ ContentAddressMethod method, Hash hash, StoreReferences refs);
+
+ ContentAddressMethod getMethod() const;
+
+ Hash getHash() const;
+
+ std::string printMethodAlgo() const;
};
}
diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc
index 0169eef1a..0e2169035 100644
--- a/src/libstore/daemon.cc
+++ b/src/libstore/daemon.cc
@@ -401,18 +401,22 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
logger->startWork();
auto pathInfo = [&]() {
// NB: FramedSource must be out of scope before logger->stopWork();
- ContentAddressMethod contentAddressMethod = ContentAddressMethod::parse(camStr);
+ auto [contentAddressMethod, hashType_] = ContentAddressMethod::parse(camStr);
+ auto hashType = hashType_; // work around clang bug
FramedSource source(from);
// TODO this is essentially RemoteStore::addCAToStore. Move it up to Store.
return std::visit(overloaded {
[&](const TextHashMethod &) {
+ if (hashType != htSHA256)
+ throw UnimplementedError("Only SHA-256 is supported for adding text-hashed data, but '%1' was given",
+ printHashType(hashType));
// We could stream this by changing Store
std::string contents = source.drain();
auto path = store->addTextToStore(name, contents, refs, repair);
return store->queryPathInfo(path);
},
- [&](const FixedOutputHashMethod & fohm) {
- auto path = store->addToStoreFromDump(source, name, fohm.fileIngestionMethod, fohm.hashType, repair, refs);
+ [&](const FileIngestionMethod & fim) {
+ auto path = store->addToStoreFromDump(source, name, fim, hashType, repair, refs);
return store->queryPathInfo(path);
},
}, contentAddressMethod.raw);
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index fdb5f999a..aaae864f4 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -2,6 +2,7 @@
#include "store-api.hh"
#include "globals.hh"
#include "util.hh"
+#include "split.hh"
#include "worker-protocol.hh"
#include "fs-accessor.hh"
#include <boost/container/small_vector.hpp>
@@ -35,9 +36,9 @@ std::optional<StorePath> DerivationOutput::path(const Store & store, std::string
StorePath DerivationOutput::CAFixed::path(const Store & store, std::string_view drvName, std::string_view outputName) const
{
- return store.makeFixedOutputPath(
+ return store.makeFixedOutputPathFromCA(
outputPathName(drvName, outputName),
- { hash, {} });
+ ca);
}
@@ -211,29 +212,27 @@ static StringSet parseStrings(std::istream & str, bool arePaths)
static DerivationOutput parseDerivationOutput(const Store & store,
- std::string_view pathS, std::string_view hashAlgo, std::string_view hash)
+ std::string_view pathS, std::string_view hashAlgo, std::string_view hashS)
{
if (hashAlgo != "") {
- auto method = FileIngestionMethod::Flat;
- if (hashAlgo.substr(0, 2) == "r:") {
- method = FileIngestionMethod::Recursive;
- hashAlgo = hashAlgo.substr(2);
- }
+ ContentAddressMethod method = ContentAddressMethod::parsePrefix(hashAlgo);
const auto hashType = parseHashType(hashAlgo);
- if (hash == "impure") {
+ if (hashS == "impure") {
experimentalFeatureSettings.require(Xp::ImpureDerivations);
assert(pathS == "");
return DerivationOutput::Impure {
.method = std::move(method),
.hashType = std::move(hashType),
};
- } else if (hash != "") {
+ } else if (hashS != "") {
validatePath(pathS);
+ auto hash = Hash::parseNonSRIUnprefixed(hashS, hashType);
return DerivationOutput::CAFixed {
- .hash = FixedOutputHash {
- .method = std::move(method),
- .hash = Hash::parseNonSRIUnprefixed(hash, hashType),
- },
+ .ca = ContentAddressWithReferences::fromParts(
+ std::move(method),
+ std::move(hash),
+ // FIXME non-trivial fixed refs set
+ {}),
};
} else {
experimentalFeatureSettings.require(Xp::CaDerivations);
@@ -384,12 +383,12 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
},
[&](const DerivationOutput::CAFixed & dof) {
s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(dof.path(store, name, i.first)));
- s += ','; printUnquotedString(s, dof.hash.printMethodAlgo());
- s += ','; printUnquotedString(s, dof.hash.hash.to_string(Base16, false));
+ s += ','; printUnquotedString(s, dof.ca.printMethodAlgo());
+ s += ','; printUnquotedString(s, dof.ca.getHash().to_string(Base16, false));
},
[&](const DerivationOutput::CAFloating & dof) {
s += ','; printUnquotedString(s, "");
- s += ','; printUnquotedString(s, makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType));
+ s += ','; printUnquotedString(s, dof.method.renderPrefix() + printHashType(dof.hashType));
s += ','; printUnquotedString(s, "");
},
[&](const DerivationOutput::Deferred &) {
@@ -400,7 +399,7 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
[&](const DerivationOutputImpure & doi) {
// FIXME
s += ','; printUnquotedString(s, "");
- s += ','; printUnquotedString(s, makeFileIngestionPrefix(doi.method) + printHashType(doi.hashType));
+ s += ','; printUnquotedString(s, doi.method.renderPrefix() + printHashType(doi.hashType));
s += ','; printUnquotedString(s, "impure");
}
}, i.second.raw());
@@ -617,8 +616,8 @@ DrvHash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOut
for (const auto & i : drv.outputs) {
auto & dof = std::get<DerivationOutput::CAFixed>(i.second.raw());
auto hash = hashString(htSHA256, "fixed:out:"
- + dof.hash.printMethodAlgo() + ":"
- + dof.hash.hash.to_string(Base16, false) + ":"
+ + dof.ca.printMethodAlgo() + ":"
+ + dof.ca.getHash().to_string(Base16, false) + ":"
+ store.printStorePath(dof.path(store, drv.name, i.first)));
outputHashes.insert_or_assign(i.first, std::move(hash));
}
@@ -768,12 +767,12 @@ void writeDerivation(Sink & out, const Store & store, const BasicDerivation & dr
},
[&](const DerivationOutput::CAFixed & dof) {
out << store.printStorePath(dof.path(store, drv.name, i.first))
- << dof.hash.printMethodAlgo()
- << dof.hash.hash.to_string(Base16, false);
+ << dof.ca.printMethodAlgo()
+ << dof.ca.getHash().to_string(Base16, false);
},
[&](const DerivationOutput::CAFloating & dof) {
out << ""
- << (makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType))
+ << (dof.method.renderPrefix() + printHashType(dof.hashType))
<< "";
},
[&](const DerivationOutput::Deferred &) {
@@ -783,7 +782,7 @@ void writeDerivation(Sink & out, const Store & store, const BasicDerivation & dr
},
[&](const DerivationOutput::Impure & doi) {
out << ""
- << (makeFileIngestionPrefix(doi.method) + printHashType(doi.hashType))
+ << (doi.method.renderPrefix() + printHashType(doi.hashType))
<< "impure";
},
}, i.second.raw());
@@ -901,15 +900,16 @@ nlohmann::json DerivationOutput::toJSON(
},
[&](const DerivationOutput::CAFixed & dof) {
res["path"] = store.printStorePath(dof.path(store, drvName, outputName));
- res["hashAlgo"] = dof.hash.printMethodAlgo();
- res["hash"] = dof.hash.hash.to_string(Base16, false);
+ res["hashAlgo"] = dof.ca.printMethodAlgo();
+ res["hash"] = dof.ca.getHash().to_string(Base16, false);
+ // FIXME print refs?
},
[&](const DerivationOutput::CAFloating & dof) {
- res["hashAlgo"] = makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType);
+ res["hashAlgo"] = dof.method.renderPrefix() + printHashType(dof.hashType);
},
[&](const DerivationOutput::Deferred &) {},
[&](const DerivationOutput::Impure & doi) {
- res["hashAlgo"] = makeFileIngestionPrefix(doi.method) + printHashType(doi.hashType);
+ res["hashAlgo"] = doi.method.renderPrefix() + printHashType(doi.hashType);
res["impure"] = true;
},
}, raw());
diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh
index a5731f18d..dff6b472c 100644
--- a/src/libstore/derivations.hh
+++ b/src/libstore/derivations.hh
@@ -32,9 +32,9 @@ struct DerivationOutputInputAddressed
struct DerivationOutputCAFixed
{
/**
- * hash used for expected hash computation
+ * hash and refs used for expected hash computation
*/
- FixedOutputHash hash;
+ ContentAddressWithReferences ca; /* hash and refs used for validating output */
/**
* Return the \ref StorePath "store path" corresponding to this output
@@ -55,7 +55,7 @@ struct DerivationOutputCAFloating
/**
* How the file system objects will be serialized for hashing
*/
- FileIngestionMethod method;
+ ContentAddressMethod method;
/**
* How the serialization will be hashed
@@ -78,7 +78,7 @@ struct DerivationOutputImpure
/**
* How the file system objects will be serialized for hashing
*/
- FileIngestionMethod method;
+ ContentAddressMethod method;
/**
* How the serialization will be hashed
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index b49d5462b..63039e6ad 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -750,7 +750,7 @@ void LocalStore::checkDerivationOutputs(const StorePath & drvPath, const Derivat
envHasRightPath(doia.path, i.first);
},
[&](const DerivationOutput::CAFixed & dof) {
- StorePath path = makeFixedOutputPath(drvName, { dof.hash, {} });
+ auto path = dof.path(*this, drvName, i.first);
envHasRightPath(path, i.first);
},
[&](const DerivationOutput::CAFloating &) {
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index 89148d415..39bdfec6e 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -86,9 +86,21 @@ void Store::computeFSClosure(const StorePath & startPath,
std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv)
{
auto out = drv.outputs.find("out");
- if (out != drv.outputs.end()) {
- if (const auto * v = std::get_if<DerivationOutput::CAFixed>(&out->second.raw()))
- return v->hash;
+ if (out == drv.outputs.end())
+ return std::nullopt;
+ if (auto dof = std::get_if<DerivationOutput::CAFixed>(&out->second)) {
+ return std::visit(overloaded {
+ [&](const TextInfo & ti) -> std::optional<ContentAddress> {
+ if (!ti.references.empty())
+ return std::nullopt;
+ return ti.hash;
+ },
+ [&](const FixedOutputInfo & fi) -> std::optional<ContentAddress> {
+ if (!fi.references.empty())
+ return std::nullopt;
+ return fi.hash;
+ },
+ }, dof->ca.raw);
}
return std::nullopt;
}
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index ac98e76d2..1c6b8530d 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -534,6 +534,7 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
Source & dump,
std::string_view name,
ContentAddressMethod caMethod,
+ HashType hashType,
const StorePathSet & references,
RepairFlag repair)
{
@@ -545,7 +546,7 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
conn->to
<< wopAddToStore
<< name
- << caMethod.render();
+ << caMethod.render(hashType);
worker_proto::write(*this, conn->to, references);
conn->to << repair;
@@ -566,25 +567,28 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
std::visit(overloaded {
[&](const TextHashMethod & thm) -> void {
+ if (hashType != htSHA256)
+ throw UnimplementedError("Only SHA-256 is supported for adding text-hashed data, but '%1' was given",
+ printHashType(hashType));
std::string s = dump.drain();
conn->to << wopAddTextToStore << name << s;
worker_proto::write(*this, conn->to, references);
conn.processStderr();
},
- [&](const FixedOutputHashMethod & fohm) -> void {
+ [&](const FileIngestionMethod & fim) -> void {
conn->to
<< wopAddToStore
<< name
- << ((fohm.hashType == htSHA256 && fohm.fileIngestionMethod == FileIngestionMethod::Recursive) ? 0 : 1) /* backwards compatibility hack */
- << (fohm.fileIngestionMethod == FileIngestionMethod::Recursive ? 1 : 0)
- << printHashType(fohm.hashType);
+ << ((hashType == htSHA256 && fim == FileIngestionMethod::Recursive) ? 0 : 1) /* backwards compatibility hack */
+ << (fim == FileIngestionMethod::Recursive ? 1 : 0)
+ << printHashType(hashType);
try {
conn->to.written = 0;
connections->incCapacity();
{
Finally cleanup([&]() { connections->decCapacity(); });
- if (fohm.fileIngestionMethod == FileIngestionMethod::Recursive) {
+ if (fim == FileIngestionMethod::Recursive) {
dump.drainInto(conn->to);
} else {
std::string contents = dump.drain();
@@ -615,7 +619,7 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
StorePath RemoteStore::addToStoreFromDump(Source & dump, std::string_view name,
FileIngestionMethod method, HashType hashType, RepairFlag repair, const StorePathSet & references)
{
- return addCAToStore(dump, name, FixedOutputHashMethod{ .fileIngestionMethod = method, .hashType = hashType }, references, repair)->path;
+ return addCAToStore(dump, name, method, hashType, references, repair)->path;
}
@@ -715,7 +719,7 @@ StorePath RemoteStore::addTextToStore(
RepairFlag repair)
{
StringSource source(s);
- return addCAToStore(source, name, TextHashMethod{}, references, repair)->path;
+ return addCAToStore(source, name, TextHashMethod {}, htSHA256, references, repair)->path;
}
void RemoteStore::registerDrvOutput(const Realisation & info)
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 999151239..3ff22ed66 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -73,6 +73,7 @@ public:
Source & dump,
std::string_view name,
ContentAddressMethod caMethod,
+ HashType hashType,
const StorePathSet & references,
RepairFlag repair);
diff --git a/src/libstore/tests/derivation.cc b/src/libstore/tests/derivation.cc
index 12be8504d..4dd14dcce 100644
--- a/src/libstore/tests/derivation.cc
+++ b/src/libstore/tests/derivation.cc
@@ -35,9 +35,28 @@ TEST_JSON(DerivationOutput, caFixed,
"path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"
})",
(DerivationOutput::CAFixed {
- .hash = {
- .method = FileIngestionMethod::Recursive,
- .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
+ .ca = FixedOutputInfo {
+ .hash = {
+ .method = FileIngestionMethod::Recursive,
+ .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
+ },
+ .references = {},
+ },
+ }),
+ "drv-name", "output-name")
+
+TEST_JSON(DerivationOutput, caFixedText,
+ R"({
+ "hashAlgo": "text:sha256",
+ "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
+ "path": "/nix/store/6s1zwabh956jvhv4w9xcdb5jiyanyxg1-drv-name-output-name"
+ })",
+ (DerivationOutput::CAFixed {
+ .ca = TextInfo {
+ .hash = {
+ .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
+ },
+ .references = {},
},
}),
"drv-name", "output-name")