diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/primops.cc | 37 | ||||
-rw-r--r-- | src/libstore/build/local-derivation-goal.cc | 54 | ||||
-rw-r--r-- | src/libstore/content-address.cc | 138 | ||||
-rw-r--r-- | src/libstore/content-address.hh | 31 | ||||
-rw-r--r-- | src/libstore/daemon.cc | 10 | ||||
-rw-r--r-- | src/libstore/derivations.cc | 48 | ||||
-rw-r--r-- | src/libstore/derivations.hh | 6 | ||||
-rw-r--r-- | src/libstore/local-store.cc | 2 | ||||
-rw-r--r-- | src/libstore/misc.cc | 18 | ||||
-rw-r--r-- | src/libstore/remote-store.cc | 20 | ||||
-rw-r--r-- | src/libstore/remote-store.hh | 1 | ||||
-rw-r--r-- | src/nix/show-derivation.cc | 9 |
12 files changed, 246 insertions, 128 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 0113659d1..1d11b29de 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1040,7 +1040,7 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * bool isImpure = false; std::optional<std::string> outputHash; std::string outputHashAlgo; - std::optional<FileIngestionMethod> ingestionMethod; + std::optional<ContentAddressMethod> ingestionMethod; StringSet outputs; outputs.insert("out"); @@ -1053,6 +1053,7 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * auto handleHashMode = [&](const std::string_view s) { if (s == "recursive") ingestionMethod = FileIngestionMethod::Recursive; else if (s == "flat") ingestionMethod = FileIngestionMethod::Flat; + else if (s == "text") ingestionMethod = TextHashMethod {}; else state.debugThrowLastTrace(EvalError({ .msg = hintfmt("invalid value '%s' for 'outputHashMode' attribute", s), @@ -1194,8 +1195,11 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * state.store->computeFSClosure(state.store->parseStorePath(std::string_view(path).substr(1)), refs); for (auto & j : refs) { drv.inputSrcs.insert(j); - if (j.isDerivation()) - drv.inputDrvs[j] = state.store->readDerivation(j).outputNames(); + if (j.isDerivation()) { + Derivation jDrv = state.store->readDerivation(j); + if(jDrv.type().hasKnownOutputPaths()) + drv.inputDrvs[j] = jDrv.outputNames(); + } } } @@ -1224,9 +1228,9 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * })); /* Check whether the derivation name is valid. */ - if (isDerivation(drvName)) + if (isDerivation(drvName) && ingestionMethod != ContentAddressMethod { TextHashMethod { } }) state.debugThrowLastTrace(EvalError({ - .msg = hintfmt("derivation names are not allowed to end in '%s'", drvExtension), + .msg = hintfmt("derivation names are allowed to end in '%s' only if they produce a single derivation file", drvExtension), .errPos = state.positions[posDrvName] })); @@ -1244,21 +1248,14 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * auto h = newHashAllowEmpty(*outputHash, parseHashTypeOpt(outputHashAlgo)); auto method = ingestionMethod.value_or(FileIngestionMethod::Flat); - auto outPath = state.store->makeFixedOutputPath(drvName, FixedOutputInfo { - { - .method = method, - .hash = h, - }, - .references = {}, - }); - drv.env["out"] = state.store->printStorePath(outPath); - drv.outputs.insert_or_assign("out", - DerivationOutput::CAFixed { - .hash = FixedOutputHash { - .method = method, - .hash = std::move(h), - }, - }); + + DerivationOutput::CAFixed dof { + // FIXME non-trivial fixed refs set + .ca = contentAddressFromMethodHashAndRefs(method, std::move(h), {}), + }; + + drv.env["out"] = state.store->printStorePath(dof.path(*state.store, drvName, "out")); + drv.outputs.insert_or_assign("out", std::move(dof)); } else if (contentAddressed || isImpure) { diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index ff24bd088..c7b3d9325 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -2452,38 +2452,44 @@ 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); auto got = caSink.finish().first; ValidPathInfo newInfo0 { worker.store, { .name = outputPathName(drv->name, outputName), - .info = FixedOutputInfo { - { - .method = outputHash.method, - .hash = got, - }, - .references = rewriteRefs(), - }, + .info = contentAddressFromMethodHashAndRefs( + outputHash.method, + std::move(got), + rewriteRefs()), }, Hash::dummy, }; @@ -2528,13 +2534,14 @@ DrvOutputs LocalDerivationGoal::registerOutputs() }, [&](const DerivationOutput::CAFixed & dof) { - auto newInfo0 = newInfoFromCA(DerivationOutput::CAFloating { - .method = dof.hash.method, - .hashType = dof.hash.hash.type, + auto wanted = getContentAddressHash(dof.ca); + + auto newInfo0 = newInfoFromCA(DerivationOutputCAFloating { + .method = getContentAddressMethod(dof.ca), + .hashType = wanted.type, }); /* Check wanted hash */ - const Hash & wanted = dof.hash.hash; assert(newInfo0.ca); auto got = getContentAddressHash(*newInfo0.ca); if (wanted != got) { @@ -2547,6 +2554,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 3b8a773b7..05b289ee7 100644 --- a/src/libstore/content-address.cc +++ b/src/libstore/content-address.cc @@ -21,6 +21,27 @@ std::string makeFileIngestionPrefix(FileIngestionMethod m) assert(false); } +std::string makeContentAddressingPrefix(ContentAddressMethod m) { + 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); + }, + }, m); +} + +ContentAddressMethod parseContentAddressingPrefix(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 makeFixedOutputCA(FileIngestionMethod method, const Hash & hash) { return "fixed:" @@ -43,14 +64,14 @@ std::string renderContentAddress(ContentAddress ca) }, ca); } -std::string renderContentAddressMethod(ContentAddressMethod cam) +std::string renderContentAddressMethodAndHash(ContentAddressMethod cam, HashType ht) { return std::visit(overloaded { - [](TextHashMethod & th) { - return std::string{"text:"} + printHashType(htSHA256); + [&](TextHashMethod & th) { + return std::string{"text:"} + printHashType(ht); }, - [](FixedOutputHashMethod & fshm) { - return "fixed:" + makeFileIngestionPrefix(fshm.fileIngestionMethod) + printHashType(fshm.hashType); + [&](FileIngestionMethod & fim) { + return "fixed:" + makeFileIngestionPrefix(fim) + printHashType(ht); } }, cam); } @@ -58,7 +79,7 @@ std::string renderContentAddressMethod(ContentAddressMethod cam) /* 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 }; @@ -82,19 +103,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); @@ -103,25 +124,25 @@ static ContentAddressMethod parseContentAddressMethodPrefix(std::string_view & r ContentAddress parseContentAddress(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); -} - -ContentAddressMethod parseContentAddressMethod(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); +} + +std::pair<ContentAddressMethod, HashType> parseContentAddressMethod(std::string_view caMethod) { std::string asPrefix = std::string{caMethod} + ":"; // parseContentAddressMethodPrefix takes its argument by reference @@ -139,6 +160,42 @@ std::string renderContentAddress(std::optional<ContentAddress> ca) return ca ? renderContentAddress(*ca) : ""; } +ContentAddressWithReferences contentAddressFromMethodHashAndRefs( + 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 = std::move(hash) }, + .references = std::move(refs.others), + }; + }, + [&](FileIngestionMethod m2) -> ContentAddressWithReferences { + return FixedOutputInfo { + { + .method = m2, + .hash = std::move(hash), + }, + .references = std::move(refs), + }; + }, + }, method); +} + +ContentAddressMethod getContentAddressMethod(const ContentAddressWithReferences & ca) +{ + return std::visit(overloaded { + [](const TextInfo & th) -> ContentAddressMethod { + return TextHashMethod {}; + }, + [](const FixedOutputInfo & fsh) -> ContentAddressMethod { + return fsh.method; + }, + }, ca); +} + Hash getContentAddressHash(const ContentAddress & ca) { return std::visit(overloaded { @@ -168,4 +225,21 @@ ContentAddressWithReferences caWithoutRefs(const ContentAddress & ca) { }, ca); } +Hash getContentAddressHash(const ContentAddressWithReferences & ca) +{ + return std::visit(overloaded { + [](const TextInfo & th) { + return th.hash; + }, + [](const FixedOutputInfo & fsh) { + return fsh.hash; + }, + }, ca); +} + +std::string printMethodAlgo(const ContentAddressWithReferences & ca) { + return makeContentAddressingPrefix(getContentAddressMethod(ca)) + + printHashType(getContentAddressHash(ca).type); +} + } diff --git a/src/libstore/content-address.hh b/src/libstore/content-address.hh index f8a4d5370..c07fe0a88 100644 --- a/src/libstore/content-address.hh +++ b/src/libstore/content-address.hh @@ -22,11 +22,6 @@ enum struct FileIngestionMethod : uint8_t { Recursive = true }; -struct FixedOutputHashMethod { - FileIngestionMethod fileIngestionMethod; - HashType hashType; -}; - /* Compute the prefix to the hash algorithm which indicates how the files were ingested. */ std::string makeFileIngestionPrefix(FileIngestionMethod m); @@ -38,12 +33,24 @@ std::string makeFileIngestionPrefix(FileIngestionMethod m); further below. */ typedef std::variant< TextHashMethod, - FixedOutputHashMethod + FileIngestionMethod > ContentAddressMethod; -ContentAddressMethod parseContentAddressMethod(std::string_view rawCaMethod); +/* Parse and pretty print the algorithm which indicates how the files + were ingested, with the the fixed output case not prefixed for back + compat. */ + +std::string makeContentAddressingPrefix(ContentAddressMethod m); + +ContentAddressMethod parseContentAddressingPrefix(std::string_view & m); + +/* Parse and pretty print a content addressing method and hash in a + nicer way, prefixing both cases. */ + +std::string renderContentAddressMethodAndHash(ContentAddressMethod cam, HashType ht); + +std::pair<ContentAddressMethod, HashType> parseContentAddressMethod(std::string_view caMethod); -std::string renderContentAddressMethod(ContentAddressMethod caMethod); /* * Mini content address @@ -125,6 +132,14 @@ typedef std::variant< ContentAddressWithReferences caWithoutRefs(const ContentAddress &); +ContentAddressWithReferences contentAddressFromMethodHashAndRefs( + ContentAddressMethod method, Hash && hash, StoreReferences && refs); + +ContentAddressMethod getContentAddressMethod(const ContentAddressWithReferences & ca); +Hash getContentAddressHash(const ContentAddressWithReferences & ca); + +std::string printMethodAlgo(const ContentAddressWithReferences &); + struct StorePathDescriptor { std::string name; ContentAddressWithReferences info; diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 605f871fc..275c2b635 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -396,18 +396,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 = parseContentAddressMethod(camStr); + auto [contentAddressMethod, hashType_] = parseContentAddressMethod(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 { [&](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); }, - [&](FixedOutputHashMethod & fohm) { - auto path = store->addToStoreFromDump(source, name, fohm.fileIngestionMethod, fohm.hashType, repair, refs); + [&](FileIngestionMethod & fim) { + auto path = store->addToStoreFromDump(source, name, fim, hashType, repair, refs); return store->queryPathInfo(path); }, }, contentAddressMethod); diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 156a2b425..c2c0520f5 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> @@ -34,9 +35,10 @@ 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( - outputPathName(drvName, outputName), - { hash, {} }); + return store.makeFixedOutputPathFromCA(StorePathDescriptor { + .name = outputPathName(drvName, outputName), + .info = ca, + }); } @@ -210,29 +212,25 @@ 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 = parseContentAddressingPrefix(hashAlgo); const auto hashType = parseHashType(hashAlgo); - if (hash == "impure") { + if (hashS == "impure") { settings.requireExperimentalFeature(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), - }, + // FIXME non-trivial fixed refs set + .ca = contentAddressFromMethodHashAndRefs( + method, std::move(hash), {}), }; } else { settings.requireExperimentalFeature(Xp::CaDerivations); @@ -383,12 +381,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, printMethodAlgo(dof.ca)); + s += ','; printUnquotedString(s, getContentAddressHash(dof.ca).to_string(Base16, false)); }, [&](const DerivationOutput::CAFloating & dof) { s += ','; printUnquotedString(s, ""); - s += ','; printUnquotedString(s, makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType)); + s += ','; printUnquotedString(s, makeContentAddressingPrefix(dof.method) + printHashType(dof.hashType)); s += ','; printUnquotedString(s, ""); }, [&](const DerivationOutput::Deferred &) { @@ -399,7 +397,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, makeContentAddressingPrefix(doi.method) + printHashType(doi.hashType)); s += ','; printUnquotedString(s, "impure"); } }, i.second.raw()); @@ -616,8 +614,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) + ":" + + printMethodAlgo(dof.ca) + ":" + + getContentAddressHash(dof.ca).to_string(Base16, false) + ":" + store.printStorePath(dof.path(store, drv.name, i.first))); outputHashes.insert_or_assign(i.first, std::move(hash)); } @@ -773,12 +771,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); + << printMethodAlgo(dof.ca) + << getContentAddressHash(dof.ca).to_string(Base16, false); }, [&](const DerivationOutput::CAFloating & dof) { out << "" - << (makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType)) + << (makeContentAddressingPrefix(dof.method) + printHashType(dof.hashType)) << ""; }, [&](const DerivationOutput::Deferred &) { @@ -788,7 +786,7 @@ void writeDerivation(Sink & out, const Store & store, const BasicDerivation & dr }, [&](const DerivationOutput::Impure & doi) { out << "" - << (makeFileIngestionPrefix(doi.method) + printHashType(doi.hashType)) + << (makeContentAddressingPrefix(doi.method) + printHashType(doi.hashType)) << "impure"; }, }, i.second.raw()); diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index f3cd87fb1..cd6117a59 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -26,7 +26,7 @@ struct DerivationOutputInputAddressed according to that fixed output. */ struct DerivationOutputCAFixed { - FixedOutputHash hash; /* hash used for expected hash computation */ + ContentAddressWithReferences ca; /* hash and refs used for validating output */ StorePath path(const Store & store, std::string_view drvName, std::string_view outputName) const; }; @@ -36,7 +36,7 @@ struct DerivationOutputCAFixed struct DerivationOutputCAFloating { /* information used for expected hash computation */ - FileIngestionMethod method; + ContentAddressMethod method; HashType hashType; }; @@ -51,7 +51,7 @@ struct DerivationOutputDeferred {}; struct DerivationOutputImpure { /* information used for expected hash computation */ - FileIngestionMethod method; + ContentAddressMethod method; HashType hashType; }; diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index b32953f3f..23cf2e3ef 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -738,7 +738,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 87f85c3cc..9a38a0713 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -85,9 +85,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 static_cast<TextHash>(ti); + }, + [&](const FixedOutputInfo & fi) -> std::optional<ContentAddress> { + if (!fi.references.empty()) + return std::nullopt; + return static_cast<FixedOutputHash>(fi); + }, + }, dof->ca); } return std::nullopt; } diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 1f8098b85..bfe85d83b 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 - << renderContentAddressMethod(caMethod); + << renderContentAddressMethodAndHash(caMethod, 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 11d089cd2..9cf97c0d2 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/nix/show-derivation.cc b/src/nix/show-derivation.cc index af2e676a4..9d69c19f2 100644 --- a/src/nix/show-derivation.cc +++ b/src/nix/show-derivation.cc @@ -71,15 +71,16 @@ struct CmdShowDerivation : InstallablesCommand }, [&](const DerivationOutput::CAFixed & dof) { outputObj["path"] = store->printStorePath(dof.path(*store, drv.name, outputName)); - outputObj["hashAlgo"] = dof.hash.printMethodAlgo(); - outputObj["hash"] = dof.hash.hash.to_string(Base16, false); + outputObj["hashAlgo"] = printMethodAlgo(dof.ca); + outputObj["hash"] = getContentAddressHash(dof.ca).to_string(Base16, false); + // FIXME print refs? }, [&](const DerivationOutput::CAFloating & dof) { - outputObj["hashAlgo"] = makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType); + outputObj["hashAlgo"] = makeContentAddressingPrefix(dof.method) + printHashType(dof.hashType); }, [&](const DerivationOutput::Deferred &) {}, [&](const DerivationOutput::Impure & doi) { - outputObj["hashAlgo"] = makeFileIngestionPrefix(doi.method) + printHashType(doi.hashType); + outputObj["hashAlgo"] = makeContentAddressingPrefix(doi.method) + printHashType(doi.hashType); outputObj["impure"] = true; }, }, output.raw()); |