Merge branch 'path-info' into ca-drv-exotic

This commit is contained in:
John Ericson 2023-04-01 16:40:32 -04:00
commit eeecfacb43
17 changed files with 191 additions and 135 deletions

View file

@ -1292,8 +1292,11 @@ drvName, Bindings * attrs, Value & v)
auto method = ingestionMethod.value_or(FileIngestionMethod::Flat); auto method = ingestionMethod.value_or(FileIngestionMethod::Flat);
DerivationOutput::CAFixed dof { DerivationOutput::CAFixed dof {
.ca = ContentAddressWithReferences::fromParts(
std::move(method),
std::move(h),
// FIXME non-trivial fixed refs set // 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.env["out"] = state.store->printStorePath(dof.path(*state.store, drvName, "out"));
@ -1315,13 +1318,13 @@ drvName, Bindings * attrs, Value & v)
if (isImpure) if (isImpure)
drv.outputs.insert_or_assign(i, drv.outputs.insert_or_assign(i,
DerivationOutput::Impure { DerivationOutput::Impure {
.method = method, .method = method.raw,
.hashType = ht, .hashType = ht,
}); });
else else
drv.outputs.insert_or_assign(i, drv.outputs.insert_or_assign(i,
DerivationOutput::CAFloating { DerivationOutput::CAFloating {
.method = method, .method = method.raw,
.hashType = ht, .hashType = ht,
}); });
} }

View file

@ -2451,12 +2451,12 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
break; break;
} }
}, },
}, outputHash.method); }, outputHash.method.raw);
auto got = caSink.finish().first; auto got = caSink.finish().first;
ValidPathInfo newInfo0 { ValidPathInfo newInfo0 {
worker.store, worker.store,
outputPathName(drv->name, outputName), outputPathName(drv->name, outputName),
contentAddressFromMethodHashAndRefs( ContentAddressWithReferences::fromParts(
outputHash.method, outputHash.method,
std::move(got), std::move(got),
rewriteRefs()), rewriteRefs()),
@ -2506,16 +2506,16 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
}, },
[&](const DerivationOutput::CAFixed & dof) { [&](const DerivationOutput::CAFixed & dof) {
auto wanted = getContentAddressHash(dof.ca); auto wanted = dof.ca.getHash();
auto newInfo0 = newInfoFromCA(DerivationOutputCAFloating { auto newInfo0 = newInfoFromCA(DerivationOutputCAFloating {
.method = getContentAddressMethod(dof.ca), .method = dof.ca.getMethod(),
.hashType = wanted.type, .hashType = wanted.type,
}); });
/* Check wanted hash */ /* Check wanted hash */
assert(newInfo0.ca); assert(newInfo0.ca);
auto got = getContentAddressHash(*newInfo0.ca); auto got = newInfo0.ca->getHash();
if (wanted != got) { if (wanted != got) {
/* Throw an error after registering the path as /* Throw an error after registering the path as
valid. */ valid. */

View file

@ -97,7 +97,7 @@ void PathSubstitutionGoal::tryNext()
if (ca) { if (ca) {
subPath = sub->makeFixedOutputPathFromCA( subPath = sub->makeFixedOutputPathFromCA(
std::string { storePath.name() }, std::string { storePath.name() },
caWithoutRefs(*ca)); ContentAddressWithReferences::withoutRefs(*ca));
if (sub->storeDir == worker.store.storeDir) if (sub->storeDir == worker.store.storeDir)
assert(subPath == storePath); assert(subPath == storePath);
} else if (sub->storeDir != worker.store.storeDir) { } else if (sub->storeDir != worker.store.storeDir) {

View file

@ -9,7 +9,6 @@ std::string FixedOutputHash::printMethodAlgo() const
return makeFileIngestionPrefix(method) + printHashType(hash.type); return makeFileIngestionPrefix(method) + printHashType(hash.type);
} }
std::string makeFileIngestionPrefix(FileIngestionMethod m) std::string makeFileIngestionPrefix(FileIngestionMethod m)
{ {
switch (m) { switch (m) {
@ -22,17 +21,17 @@ std::string makeFileIngestionPrefix(FileIngestionMethod m)
} }
} }
std::string makeContentAddressingPrefix(ContentAddressMethod m) { std::string ContentAddressMethod::renderPrefix() const {
return std::visit(overloaded { return std::visit(overloaded {
[](TextHashMethod) -> std::string { return "text:"; }, [](TextHashMethod) -> std::string { return "text:"; },
[](FileIngestionMethod m2) { [](FileIngestionMethod m2) {
/* Not prefixed for back compat with things that couldn't produce text before. */ /* Not prefixed for back compat with things that couldn't produce text before. */
return makeFileIngestionPrefix(m2); return makeFileIngestionPrefix(m2);
}, },
}, m); }, raw);
} }
ContentAddressMethod parseContentAddressingPrefix(std::string_view & m) ContentAddressMethod ContentAddressMethod::parsePrefix(std::string_view & m)
{ {
ContentAddressMethod method = FileIngestionMethod::Flat; ContentAddressMethod method = FileIngestionMethod::Flat;
if (splitPrefix(m, "r:")) if (splitPrefix(m, "r:"))
@ -42,35 +41,35 @@ ContentAddressMethod parseContentAddressingPrefix(std::string_view & m)
return method; return method;
} }
std::string renderContentAddress(ContentAddress ca) std::string ContentAddress::render() const
{ {
return std::visit(overloaded { return std::visit(overloaded {
[](TextHash & th) { [](const TextHash & th) {
return "text:" return "text:"
+ th.hash.to_string(Base32, true); + th.hash.to_string(Base32, true);
}, },
[](FixedOutputHash & fsh) { [](const FixedOutputHash & fsh) {
return "fixed:" return "fixed:"
+ makeFileIngestionPrefix(fsh.method) + makeFileIngestionPrefix(fsh.method)
+ fsh.hash.to_string(Base32, true); + fsh.hash.to_string(Base32, true);
} }
}, ca); }, raw);
} }
std::string renderContentAddressMethodAndHash(ContentAddressMethod cam, HashType ht) std::string ContentAddressMethod::render(HashType ht) const
{ {
return std::visit(overloaded { return std::visit(overloaded {
[&](TextHashMethod & th) { [&](const TextHashMethod & th) {
return std::string{"text:"} + printHashType(ht); return std::string{"text:"} + printHashType(ht);
}, },
[&](FileIngestionMethod & fim) { [&](const FileIngestionMethod & fim) {
return "fixed:" + makeFileIngestionPrefix(fim) + printHashType(ht); return "fixed:" + makeFileIngestionPrefix(fim) + printHashType(ht);
} }
}, cam); }, raw);
} }
/* /**
Parses content address strings up to the hash. * Parses content address strings up to the hash.
*/ */
static std::pair<ContentAddressMethod, HashType> parseContentAddressMethodPrefix(std::string_view & rest) static std::pair<ContentAddressMethod, HashType> parseContentAddressMethodPrefix(std::string_view & rest)
{ {
@ -114,7 +113,7 @@ static std::pair<ContentAddressMethod, HashType> parseContentAddressMethodPrefix
throw UsageError("content address prefix '%s' is unrecognized. Recogonized prefixes are 'text' or 'fixed'", prefix); throw UsageError("content address prefix '%s' is unrecognized. Recogonized prefixes are 'text' or 'fixed'", prefix);
} }
ContentAddress parseContentAddress(std::string_view rawCa) { ContentAddress ContentAddress::parse(std::string_view rawCa) {
auto rest = rawCa; auto rest = rawCa;
auto [caMethod, hashType_] = parseContentAddressMethodPrefix(rest); auto [caMethod, hashType_] = parseContentAddressMethodPrefix(rest);
@ -132,10 +131,10 @@ ContentAddress parseContentAddress(std::string_view rawCa) {
.hash = Hash::parseNonSRIUnprefixed(rest, hashType), .hash = Hash::parseNonSRIUnprefixed(rest, hashType),
}); });
}, },
}, caMethod); }, caMethod.raw);
} }
std::pair<ContentAddressMethod, HashType> parseContentAddressMethod(std::string_view caMethod) std::pair<ContentAddressMethod, HashType> ContentAddressMethod::parse(std::string_view caMethod)
{ {
std::string asPrefix = std::string{caMethod} + ":"; std::string asPrefix = std::string{caMethod} + ":";
// parseContentAddressMethodPrefix takes its argument by reference // parseContentAddressMethodPrefix takes its argument by reference
@ -143,18 +142,20 @@ std::pair<ContentAddressMethod, HashType> parseContentAddressMethod(std::string_
return parseContentAddressMethodPrefix(asPrefixView); return parseContentAddressMethodPrefix(asPrefixView);
} }
std::optional<ContentAddress> parseContentAddressOpt(std::string_view rawCaOpt) std::optional<ContentAddress> ContentAddress::parseOpt(std::string_view rawCaOpt)
{ {
return rawCaOpt == "" ? std::optional<ContentAddress>() : parseContentAddress(rawCaOpt); return rawCaOpt == ""
? std::nullopt
: std::optional { ContentAddress::parse(rawCaOpt) };
}; };
std::string renderContentAddress(std::optional<ContentAddress> ca) std::string renderContentAddress(std::optional<ContentAddress> ca)
{ {
return ca ? renderContentAddress(*ca) : ""; return ca ? ca->render() : "";
} }
ContentAddressWithReferences contentAddressFromMethodHashAndRefs( ContentAddressWithReferences ContentAddressWithReferences::fromParts(
ContentAddressMethod method, Hash && hash, StoreReferences && refs) ContentAddressMethod method, Hash hash, StoreReferences refs)
{ {
return std::visit(overloaded { return std::visit(overloaded {
[&](TextHashMethod _) -> ContentAddressWithReferences { [&](TextHashMethod _) -> ContentAddressWithReferences {
@ -174,10 +175,10 @@ ContentAddressWithReferences contentAddressFromMethodHashAndRefs(
.references = std::move(refs), .references = std::move(refs),
}; };
}, },
}, method); }, method.raw);
} }
ContentAddressMethod getContentAddressMethod(const ContentAddressWithReferences & ca) ContentAddressMethod ContentAddressWithReferences::getMethod() const
{ {
return std::visit(overloaded { return std::visit(overloaded {
[](const TextInfo & th) -> ContentAddressMethod { [](const TextInfo & th) -> ContentAddressMethod {
@ -186,19 +187,19 @@ ContentAddressMethod getContentAddressMethod(const ContentAddressWithReferences
[](const FixedOutputInfo & fsh) -> ContentAddressMethod { [](const FixedOutputInfo & fsh) -> ContentAddressMethod {
return fsh.hash.method; return fsh.hash.method;
}, },
}, ca); }, raw);
} }
Hash getContentAddressHash(const ContentAddress & ca) const Hash & ContentAddress::getHash() const
{ {
return std::visit(overloaded { return std::visit(overloaded {
[](const TextHash & th) { [](const TextHash & th) -> auto & {
return th.hash; return th.hash;
}, },
[](const FixedOutputHash & fsh) { [](const FixedOutputHash & fsh) -> auto & {
return fsh.hash; return fsh.hash;
}, },
}, ca); }, raw);
} }
bool StoreReferences::empty() const bool StoreReferences::empty() const
@ -211,7 +212,7 @@ size_t StoreReferences::size() const
return (self ? 1 : 0) + others.size(); return (self ? 1 : 0) + others.size();
} }
ContentAddressWithReferences caWithoutRefs(const ContentAddress & ca) { ContentAddressWithReferences ContentAddressWithReferences::withoutRefs(const ContentAddress & ca) {
return std::visit(overloaded { return std::visit(overloaded {
[&](const TextHash & h) -> ContentAddressWithReferences { [&](const TextHash & h) -> ContentAddressWithReferences {
return TextInfo { return TextInfo {
@ -225,10 +226,10 @@ ContentAddressWithReferences caWithoutRefs(const ContentAddress & ca) {
.references = {}, .references = {},
}; };
}, },
}, ca); }, ca.raw);
} }
Hash getContentAddressHash(const ContentAddressWithReferences & ca) Hash ContentAddressWithReferences::getHash() const
{ {
return std::visit(overloaded { return std::visit(overloaded {
[](const TextInfo & th) { [](const TextInfo & th) {
@ -237,12 +238,12 @@ Hash getContentAddressHash(const ContentAddressWithReferences & ca)
[](const FixedOutputInfo & fsh) { [](const FixedOutputInfo & fsh) {
return fsh.hash.hash; return fsh.hash.hash;
}, },
}, ca); }, raw);
} }
std::string printMethodAlgo(const ContentAddressWithReferences & ca) { std::string ContentAddressWithReferences::printMethodAlgo() const {
return makeContentAddressingPrefix(getContentAddressMethod(ca)) return getMethod().renderPrefix()
+ printHashType(getContentAddressHash(ca).type); + printHashType(getHash().type);
} }
} }

View file

@ -45,7 +45,6 @@ enum struct FileIngestionMethod : uint8_t {
*/ */
std::string makeFileIngestionPrefix(FileIngestionMethod m); std::string makeFileIngestionPrefix(FileIngestionMethod m);
/** /**
* An enumeration of all the ways we can serialize file system objects. * An enumeration of all the ways we can serialize file system objects.
* *
@ -54,25 +53,40 @@ std::string makeFileIngestionPrefix(FileIngestionMethod m);
* with info on references, and we have `ContentAddressWithReferences`, * with info on references, and we have `ContentAddressWithReferences`,
* as defined further below. * as defined further below.
*/ */
struct ContentAddressMethod
{
typedef std::variant< typedef std::variant<
TextHashMethod, TextHashMethod,
FileIngestionMethod FileIngestionMethod
> ContentAddressMethod; > Raw;
/* Parse and pretty print the algorithm which indicates how the files Raw raw;
were ingested, with the the fixed output case not prefixed for back
compat. */
std::string makeContentAddressingPrefix(ContentAddressMethod m); GENERATE_CMP(ContentAddressMethod, me->raw);
ContentAddressMethod parseContentAddressingPrefix(std::string_view & m); /* The moral equivalent of `using Raw::Raw;` */
ContentAddressMethod(auto &&... arg)
: raw(std::forward<decltype(arg)>(arg)...)
{ }
/* Parse and pretty print a content addressing method and hash in a
nicer way, prefixing both cases. */
std::string renderContentAddressMethodAndHash(ContentAddressMethod cam, HashType ht); /**
* 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::pair<ContentAddressMethod, HashType> parseContentAddressMethod(std::string_view caMethod); 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;
};
/* /*
@ -122,25 +136,43 @@ struct FixedOutputHash {
* - fixed:<r?>:<ht>:<h>: For paths computed by * - fixed:<r?>:<ht>:<h>: For paths computed by
* Store::makeFixedOutputPath() / Store::addToStore(). * Store::makeFixedOutputPath() / Store::addToStore().
*/ */
struct ContentAddress
{
typedef std::variant< typedef std::variant<
TextHash, TextHash,
FixedOutputHash FixedOutputHash
> ContentAddress; > Raw;
Raw raw;
GENERATE_CMP(ContentAddress, me->raw);
/* The moral equivalent of `using Raw::Raw;` */
ContentAddress(auto &&... arg)
: raw(std::forward<decltype(arg)>(arg)...)
{ }
/** /**
* Compute the content-addressability assertion (ValidPathInfo::ca) for * Compute the content-addressability assertion (ValidPathInfo::ca) for
* paths created by Store::makeFixedOutputPath() / Store::addToStore(). * paths created by Store::makeFixedOutputPath() / Store::addToStore().
*/ */
std::string renderContentAddress(ContentAddress ca); std::string render() const;
static ContentAddress parse(std::string_view rawCa);
static std::optional<ContentAddress> parseOpt(std::string_view rawCaOpt);
const Hash & getHash() const;
};
std::string renderContentAddress(std::optional<ContentAddress> ca); std::string renderContentAddress(std::optional<ContentAddress> ca);
ContentAddress parseContentAddress(std::string_view rawCa);
std::optional<ContentAddress> parseContentAddressOpt(std::string_view rawCaOpt);
Hash getContentAddressHash(const ContentAddress & ca);
/*
* Full content address
*
* See the schema for store paths in store-api.cc
*/
/** /**
* A set of references to other store objects. * A set of references to other store objects.
@ -174,12 +206,6 @@ struct StoreReferences {
GENERATE_CMP(StoreReferences, me->self, me->others); GENERATE_CMP(StoreReferences, me->self, me->others);
}; };
/*
* Full content address
*
* See the schema for store paths in store-api.cc
*/
// This matches the additional info that we need for makeTextPath // This matches the additional info that we need for makeTextPath
struct TextInfo { struct TextInfo {
TextHash hash; TextHash hash;
@ -207,23 +233,47 @@ struct FixedOutputInfo {
* *
* A ContentAddress without a Hash. * A ContentAddress without a Hash.
*/ */
struct ContentAddressWithReferences
{
typedef std::variant< typedef std::variant<
TextInfo, TextInfo,
FixedOutputInfo FixedOutputInfo
> ContentAddressWithReferences; > Raw;
Raw raw;
GENERATE_CMP(ContentAddressWithReferences, me->raw);
/* The moral equivalent of `using Raw::Raw;` */
ContentAddressWithReferences(auto &&... arg)
: raw(std::forward<decltype(arg)>(arg)...)
{ }
/** /**
* Create a ContentAddressWithReferences from a mere ContentAddress, by * Create a ContentAddressWithReferences from a mere ContentAddress, by
* assuming no references in all cases. * assuming no references in all cases.
*/ */
ContentAddressWithReferences caWithoutRefs(const ContentAddress &); static ContentAddressWithReferences withoutRefs(const ContentAddress &);
ContentAddressWithReferences contentAddressFromMethodHashAndRefs( /**
ContentAddressMethod method, Hash && hash, StoreReferences && refs); * 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 getContentAddressMethod(const ContentAddressWithReferences & ca); ContentAddressMethod getMethod() const;
Hash getContentAddressHash(const ContentAddressWithReferences & ca);
std::string printMethodAlgo(const ContentAddressWithReferences &); Hash getHash() const;
std::string printMethodAlgo() const;
};
} }

View file

@ -401,12 +401,12 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
logger->startWork(); logger->startWork();
auto pathInfo = [&]() { auto pathInfo = [&]() {
// NB: FramedSource must be out of scope before logger->stopWork(); // NB: FramedSource must be out of scope before logger->stopWork();
auto [contentAddressMethod, hashType_] = parseContentAddressMethod(camStr); auto [contentAddressMethod, hashType_] = ContentAddressMethod::parse(camStr);
auto hashType = hashType_; // work around clang bug auto hashType = hashType_; // work around clang bug
FramedSource source(from); FramedSource source(from);
// TODO this is essentially RemoteStore::addCAToStore. Move it up to Store. // TODO this is essentially RemoteStore::addCAToStore. Move it up to Store.
return std::visit(overloaded { return std::visit(overloaded {
[&](TextHashMethod &) { [&](const TextHashMethod &) {
if (hashType != htSHA256) if (hashType != htSHA256)
throw UnimplementedError("Only SHA-256 is supported for adding text-hashed data, but '%1' was given", throw UnimplementedError("Only SHA-256 is supported for adding text-hashed data, but '%1' was given",
printHashType(hashType)); printHashType(hashType));
@ -415,11 +415,11 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
auto path = store->addTextToStore(name, contents, refs, repair); auto path = store->addTextToStore(name, contents, refs, repair);
return store->queryPathInfo(path); return store->queryPathInfo(path);
}, },
[&](FileIngestionMethod & fim) { [&](const FileIngestionMethod & fim) {
auto path = store->addToStoreFromDump(source, name, fim, hashType, repair, refs); auto path = store->addToStoreFromDump(source, name, fim, hashType, repair, refs);
return store->queryPathInfo(path); return store->queryPathInfo(path);
}, },
}, contentAddressMethod); }, contentAddressMethod.raw);
}(); }();
logger->stopWork(); logger->stopWork();
@ -884,7 +884,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
info.references = worker_proto::read(*store, from, Phantom<StorePathSet> {}); info.references = worker_proto::read(*store, from, Phantom<StorePathSet> {});
from >> info.registrationTime >> info.narSize >> info.ultimate; from >> info.registrationTime >> info.narSize >> info.ultimate;
info.sigs = readStrings<StringSet>(from); info.sigs = readStrings<StringSet>(from);
info.ca = parseContentAddressOpt(readString(from)); info.ca = ContentAddress::parseOpt(readString(from));
from >> repair >> dontCheckSigs; from >> repair >> dontCheckSigs;
if (!trusted && dontCheckSigs) if (!trusted && dontCheckSigs)
dontCheckSigs = false; dontCheckSigs = false;

View file

@ -215,7 +215,7 @@ static DerivationOutput parseDerivationOutput(const Store & store,
std::string_view pathS, std::string_view hashAlgo, std::string_view hashS) std::string_view pathS, std::string_view hashAlgo, std::string_view hashS)
{ {
if (hashAlgo != "") { if (hashAlgo != "") {
ContentAddressMethod method = parseContentAddressingPrefix(hashAlgo); ContentAddressMethod method = ContentAddressMethod::parsePrefix(hashAlgo);
const auto hashType = parseHashType(hashAlgo); const auto hashType = parseHashType(hashAlgo);
if (hashS == "impure") { if (hashS == "impure") {
experimentalFeatureSettings.require(Xp::ImpureDerivations); experimentalFeatureSettings.require(Xp::ImpureDerivations);
@ -228,9 +228,11 @@ static DerivationOutput parseDerivationOutput(const Store & store,
validatePath(pathS); validatePath(pathS);
auto hash = Hash::parseNonSRIUnprefixed(hashS, hashType); auto hash = Hash::parseNonSRIUnprefixed(hashS, hashType);
return DerivationOutput::CAFixed { return DerivationOutput::CAFixed {
.ca = ContentAddressWithReferences::fromParts(
std::move(method),
std::move(hash),
// FIXME non-trivial fixed refs set // FIXME non-trivial fixed refs set
.ca = contentAddressFromMethodHashAndRefs( {}),
method, std::move(hash), {}),
}; };
} else { } else {
experimentalFeatureSettings.require(Xp::CaDerivations); experimentalFeatureSettings.require(Xp::CaDerivations);
@ -381,12 +383,12 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
}, },
[&](const DerivationOutput::CAFixed & dof) { [&](const DerivationOutput::CAFixed & dof) {
s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(dof.path(store, name, i.first))); s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(dof.path(store, name, i.first)));
s += ','; printUnquotedString(s, printMethodAlgo(dof.ca)); s += ','; printUnquotedString(s, dof.ca.printMethodAlgo());
s += ','; printUnquotedString(s, getContentAddressHash(dof.ca).to_string(Base16, false)); s += ','; printUnquotedString(s, dof.ca.getHash().to_string(Base16, false));
}, },
[&](const DerivationOutput::CAFloating & dof) { [&](const DerivationOutput::CAFloating & dof) {
s += ','; printUnquotedString(s, ""); s += ','; printUnquotedString(s, "");
s += ','; printUnquotedString(s, makeContentAddressingPrefix(dof.method) + printHashType(dof.hashType)); s += ','; printUnquotedString(s, dof.method.renderPrefix() + printHashType(dof.hashType));
s += ','; printUnquotedString(s, ""); s += ','; printUnquotedString(s, "");
}, },
[&](const DerivationOutput::Deferred &) { [&](const DerivationOutput::Deferred &) {
@ -397,7 +399,7 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
[&](const DerivationOutputImpure & doi) { [&](const DerivationOutputImpure & doi) {
// FIXME // FIXME
s += ','; printUnquotedString(s, ""); s += ','; printUnquotedString(s, "");
s += ','; printUnquotedString(s, makeContentAddressingPrefix(doi.method) + printHashType(doi.hashType)); s += ','; printUnquotedString(s, doi.method.renderPrefix() + printHashType(doi.hashType));
s += ','; printUnquotedString(s, "impure"); s += ','; printUnquotedString(s, "impure");
} }
}, i.second.raw()); }, i.second.raw());
@ -614,8 +616,8 @@ DrvHash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOut
for (const auto & i : drv.outputs) { for (const auto & i : drv.outputs) {
auto & dof = std::get<DerivationOutput::CAFixed>(i.second.raw()); auto & dof = std::get<DerivationOutput::CAFixed>(i.second.raw());
auto hash = hashString(htSHA256, "fixed:out:" auto hash = hashString(htSHA256, "fixed:out:"
+ printMethodAlgo(dof.ca) + ":" + dof.ca.printMethodAlgo() + ":"
+ getContentAddressHash(dof.ca).to_string(Base16, false) + ":" + dof.ca.getHash().to_string(Base16, false) + ":"
+ store.printStorePath(dof.path(store, drv.name, i.first))); + store.printStorePath(dof.path(store, drv.name, i.first)));
outputHashes.insert_or_assign(i.first, std::move(hash)); outputHashes.insert_or_assign(i.first, std::move(hash));
} }
@ -765,12 +767,12 @@ void writeDerivation(Sink & out, const Store & store, const BasicDerivation & dr
}, },
[&](const DerivationOutput::CAFixed & dof) { [&](const DerivationOutput::CAFixed & dof) {
out << store.printStorePath(dof.path(store, drv.name, i.first)) out << store.printStorePath(dof.path(store, drv.name, i.first))
<< printMethodAlgo(dof.ca) << dof.ca.printMethodAlgo()
<< getContentAddressHash(dof.ca).to_string(Base16, false); << dof.ca.getHash().to_string(Base16, false);
}, },
[&](const DerivationOutput::CAFloating & dof) { [&](const DerivationOutput::CAFloating & dof) {
out << "" out << ""
<< (makeContentAddressingPrefix(dof.method) + printHashType(dof.hashType)) << (dof.method.renderPrefix() + printHashType(dof.hashType))
<< ""; << "";
}, },
[&](const DerivationOutput::Deferred &) { [&](const DerivationOutput::Deferred &) {
@ -780,7 +782,7 @@ void writeDerivation(Sink & out, const Store & store, const BasicDerivation & dr
}, },
[&](const DerivationOutput::Impure & doi) { [&](const DerivationOutput::Impure & doi) {
out << "" out << ""
<< (makeContentAddressingPrefix(doi.method) + printHashType(doi.hashType)) << (doi.method.renderPrefix() + printHashType(doi.hashType))
<< "impure"; << "impure";
}, },
}, i.second.raw()); }, i.second.raw());
@ -898,16 +900,16 @@ nlohmann::json DerivationOutput::toJSON(
}, },
[&](const DerivationOutput::CAFixed & dof) { [&](const DerivationOutput::CAFixed & dof) {
res["path"] = store.printStorePath(dof.path(store, drvName, outputName)); res["path"] = store.printStorePath(dof.path(store, drvName, outputName));
res["hashAlgo"] = printMethodAlgo(dof.ca); res["hashAlgo"] = dof.ca.printMethodAlgo();
res["hash"] = getContentAddressHash(dof.ca).to_string(Base16, false); res["hash"] = dof.ca.getHash().to_string(Base16, false);
// FIXME print refs? // FIXME print refs?
}, },
[&](const DerivationOutput::CAFloating & dof) { [&](const DerivationOutput::CAFloating & dof) {
res["hashAlgo"] = makeContentAddressingPrefix(dof.method) + printHashType(dof.hashType); res["hashAlgo"] = dof.method.renderPrefix() + printHashType(dof.hashType);
}, },
[&](const DerivationOutput::Deferred &) {}, [&](const DerivationOutput::Deferred &) {},
[&](const DerivationOutput::Impure & doi) { [&](const DerivationOutput::Impure & doi) {
res["hashAlgo"] = makeContentAddressingPrefix(doi.method) + printHashType(doi.hashType); res["hashAlgo"] = doi.method.renderPrefix() + printHashType(doi.hashType);
res["impure"] = true; res["impure"] = true;
}, },
}, raw()); }, raw());

View file

@ -156,7 +156,7 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
throw Error("NAR hash is now mandatory"); throw Error("NAR hash is now mandatory");
info->narHash = Hash::parseAnyPrefixed(s); info->narHash = Hash::parseAnyPrefixed(s);
} }
info->ca = parseContentAddressOpt(readString(conn->from)); info->ca = ContentAddress::parseOpt(readString(conn->from));
info->sigs = readStrings<StringSet>(conn->from); info->sigs = readStrings<StringSet>(conn->from);
auto s = readString(conn->from); auto s = readString(conn->from);

View file

@ -944,7 +944,7 @@ std::shared_ptr<const ValidPathInfo> LocalStore::queryPathInfoInternal(State & s
if (s) info->sigs = tokenizeString<StringSet>(s, " "); if (s) info->sigs = tokenizeString<StringSet>(s, " ");
s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 7); s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 7);
if (s) info->ca = parseContentAddressOpt(s); if (s) info->ca = ContentAddress::parseOpt(s);
/* Get the references. */ /* Get the references. */
auto useQueryReferences(state.stmts->QueryReferences.use()(info->id)); auto useQueryReferences(state.stmts->QueryReferences.use()(info->id));
@ -1150,7 +1150,7 @@ void LocalStore::querySubstitutablePathInfos(const StorePathCAMap & paths, Subst
if (path.second) { if (path.second) {
subPath = makeFixedOutputPathFromCA( subPath = makeFixedOutputPathFromCA(
path.first.name(), path.first.name(),
caWithoutRefs(*path.second)); ContentAddressWithReferences::withoutRefs(*path.second));
if (sub->storeDir == storeDir) if (sub->storeDir == storeDir)
assert(subPath == path.first); assert(subPath == path.first);
if (subPath != path.first) if (subPath != path.first)
@ -1329,7 +1329,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
printStorePath(info.path), info.narSize, hashResult.second); printStorePath(info.path), info.narSize, hashResult.second);
if (info.ca) { if (info.ca) {
if (auto foHash = std::get_if<FixedOutputHash>(&*info.ca)) { if (auto foHash = std::get_if<FixedOutputHash>(&info.ca->raw)) {
auto actualFoHash = hashCAPath( auto actualFoHash = hashCAPath(
foHash->method, foHash->method,
foHash->hash.type, foHash->hash.type,
@ -1342,7 +1342,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
actualFoHash.hash.to_string(Base32, true)); actualFoHash.hash.to_string(Base32, true));
} }
} }
if (auto textHash = std::get_if<TextHash>(&*info.ca)) { if (auto textHash = std::get_if<TextHash>(&info.ca->raw)) {
auto actualTextHash = hashString(htSHA256, readFile(realPath)); auto actualTextHash = hashString(htSHA256, readFile(realPath));
if (textHash->hash != actualTextHash) { if (textHash->hash != actualTextHash) {
throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s", throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s",

View file

@ -100,7 +100,7 @@ std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv)
return std::nullopt; return std::nullopt;
return fi.hash; return fi.hash;
}, },
}, dof->ca); }, dof->ca.raw);
} }
return std::nullopt; return std::nullopt;
} }

View file

@ -273,7 +273,7 @@ public:
narInfo->deriver = StorePath(queryNAR.getStr(9)); narInfo->deriver = StorePath(queryNAR.getStr(9));
for (auto & sig : tokenizeString<Strings>(queryNAR.getStr(10), " ")) for (auto & sig : tokenizeString<Strings>(queryNAR.getStr(10), " "))
narInfo->sigs.insert(sig); narInfo->sigs.insert(sig);
narInfo->ca = parseContentAddressOpt(queryNAR.getStr(11)); narInfo->ca = ContentAddress::parseOpt(queryNAR.getStr(11));
return {oValid, narInfo}; return {oValid, narInfo};
}); });

View file

@ -74,7 +74,7 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
else if (name == "CA") { else if (name == "CA") {
if (ca) throw corrupt(); if (ca) throw corrupt();
// FIXME: allow blank ca or require skipping field? // FIXME: allow blank ca or require skipping field?
ca = parseContentAddressOpt(value); ca = ContentAddress::parseOpt(value);
} }
pos = eol + 1; pos = eol + 1;

View file

@ -49,7 +49,7 @@ std::optional<ContentAddressWithReferences> ValidPathInfo::contentAddressWithRef
}, },
}; };
}, },
}, *ca); }, ca->raw);
} }
bool ValidPathInfo::isContentAddressed(const Store & store) const bool ValidPathInfo::isContentAddressed(const Store & store) const
@ -116,7 +116,7 @@ ValidPathInfo::ValidPathInfo(
this->references.insert(path); this->references.insert(path);
this->ca = std::move((FixedOutputHash &&) foi); this->ca = std::move((FixedOutputHash &&) foi);
}, },
}, std::move(ca)); }, std::move(ca).raw);
} }
@ -136,7 +136,7 @@ ValidPathInfo ValidPathInfo::read(Source & source, const Store & store, unsigned
if (format >= 16) { if (format >= 16) {
source >> info.ultimate; source >> info.ultimate;
info.sigs = readStrings<StringSet>(source); info.sigs = readStrings<StringSet>(source);
info.ca = parseContentAddressOpt(readString(source)); info.ca = ContentAddress::parseOpt(readString(source));
} }
return info; return info;
} }

View file

@ -44,7 +44,7 @@ void write(const Store & store, Sink & out, const StorePath & storePath)
ContentAddress read(const Store & store, Source & from, Phantom<ContentAddress> _) ContentAddress read(const Store & store, Source & from, Phantom<ContentAddress> _)
{ {
return parseContentAddress(readString(from)); return ContentAddress::parse(readString(from));
} }
void write(const Store & store, Sink & out, const ContentAddress & ca) void write(const Store & store, Sink & out, const ContentAddress & ca)
@ -134,7 +134,7 @@ void write(const Store & store, Sink & out, const std::optional<StorePath> & sto
std::optional<ContentAddress> read(const Store & store, Source & from, Phantom<std::optional<ContentAddress>> _) std::optional<ContentAddress> read(const Store & store, Source & from, Phantom<std::optional<ContentAddress>> _)
{ {
return parseContentAddressOpt(readString(from)); return ContentAddress::parseOpt(readString(from));
} }
void write(const Store & store, Sink & out, const std::optional<ContentAddress> & caOpt) void write(const Store & store, Sink & out, const std::optional<ContentAddress> & caOpt)
@ -546,7 +546,7 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
conn->to conn->to
<< wopAddToStore << wopAddToStore
<< name << name
<< renderContentAddressMethodAndHash(caMethod, hashType); << caMethod.render(hashType);
worker_proto::write(*this, conn->to, references); worker_proto::write(*this, conn->to, references);
conn->to << repair; conn->to << repair;
@ -607,7 +607,7 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
} }
} }
}, caMethod); }, caMethod.raw);
auto path = parseStorePath(readString(conn->from)); auto path = parseStorePath(readString(conn->from));
// Release our connection to prevent a deadlock in queryPathInfo(). // Release our connection to prevent a deadlock in queryPathInfo().
conn_.reset(); conn_.reset();

View file

@ -221,7 +221,7 @@ StorePath Store::makeFixedOutputPathFromCA(std::string_view name, const ContentA
[&](const FixedOutputInfo & foi) { [&](const FixedOutputInfo & foi) {
return makeFixedOutputPath(name, foi); return makeFixedOutputPath(name, foi);
} }
}, ca); }, ca.raw);
} }

View file

@ -970,7 +970,7 @@ static void opServe(Strings opFlags, Strings opArgs)
info.references = worker_proto::read(*store, in, Phantom<StorePathSet> {}); info.references = worker_proto::read(*store, in, Phantom<StorePathSet> {});
in >> info.registrationTime >> info.narSize >> info.ultimate; in >> info.registrationTime >> info.narSize >> info.ultimate;
info.sigs = readStrings<StringSet>(in); info.sigs = readStrings<StringSet>(in);
info.ca = parseContentAddressOpt(readString(in)); info.ca = ContentAddress::parseOpt(readString(in));
if (info.narSize == 0) if (info.narSize == 0)
throw Error("narInfo is too old and missing the narSize field"); throw Error("narInfo is too old and missing the narSize field");

View file

@ -124,7 +124,7 @@ std::tuple<StorePath, Hash> prefetchFile(
auto info = store->addToStoreSlow(*name, tmpFile, ingestionMethod, hashType, expectedHash); auto info = store->addToStoreSlow(*name, tmpFile, ingestionMethod, hashType, expectedHash);
storePath = info.path; storePath = info.path;
assert(info.ca); assert(info.ca);
hash = getContentAddressHash(*info.ca); hash = info.ca->getHash();
} }
return {storePath.value(), hash.value()}; return {storePath.value(), hash.value()};