diff options
Diffstat (limited to 'src/libstore/content-address.cc')
-rw-r--r-- | src/libstore/content-address.cc | 132 |
1 files changed, 103 insertions, 29 deletions
diff --git a/src/libstore/content-address.cc b/src/libstore/content-address.cc index d9a8a4535..034a9485b 100644 --- a/src/libstore/content-address.cc +++ b/src/libstore/content-address.cc @@ -22,6 +22,27 @@ std::string makeFileIngestionPrefix(FileIngestionMethod m) } } +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:" @@ -44,14 +65,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); } @@ -59,7 +80,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 }; @@ -83,19 +104,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); @@ -104,25 +125,25 @@ static ContentAddressMethod parseContentAddressMethodPrefix(std::string_view & r ContentAddress parseContentAddress(std::string_view rawCa) { auto rest = rawCa; - ContentAddressMethod caMethod = parseContentAddressMethodPrefix(rest); + auto [caMethod, hashType_] = parseContentAddressMethodPrefix(rest); + auto hashType = hashType_; // work around clang bug - 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); + 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); } -ContentAddressMethod parseContentAddressMethod(std::string_view caMethod) +std::pair<ContentAddressMethod, HashType> parseContentAddressMethod(std::string_view caMethod) { std::string asPrefix = std::string{caMethod} + ":"; // parseContentAddressMethodPrefix takes its argument by reference @@ -140,6 +161,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 = { .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); +} + +ContentAddressMethod getContentAddressMethod(const ContentAddressWithReferences & ca) +{ + return std::visit(overloaded { + [](const TextInfo & th) -> ContentAddressMethod { + return TextHashMethod {}; + }, + [](const FixedOutputInfo & fsh) -> ContentAddressMethod { + return fsh.hash.method; + }, + }, ca); +} + Hash getContentAddressHash(const ContentAddress & ca) { return std::visit(overloaded { @@ -179,4 +236,21 @@ ContentAddressWithReferences caWithoutRefs(const ContentAddress & ca) { }, ca); } +Hash getContentAddressHash(const ContentAddressWithReferences & ca) +{ + return std::visit(overloaded { + [](const TextInfo & th) { + return th.hash.hash; + }, + [](const FixedOutputInfo & fsh) { + return fsh.hash.hash; + }, + }, ca); +} + +std::string printMethodAlgo(const ContentAddressWithReferences & ca) { + return makeContentAddressingPrefix(getContentAddressMethod(ca)) + + printHashType(getContentAddressHash(ca).type); +} + } |