aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/content-address.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/content-address.cc')
-rw-r--r--src/libstore/content-address.cc173
1 files changed, 142 insertions, 31 deletions
diff --git a/src/libstore/content-address.cc b/src/libstore/content-address.cc
index 055b216db..04f7ac214 100644
--- a/src/libstore/content-address.cc
+++ b/src/libstore/content-address.cc
@@ -21,6 +21,27 @@ std::string makeFileIngestionPrefix(FileIngestionMethod m)
}
}
+std::string ContentAddressMethod::renderPrefix() const
+{
+ return std::visit(overloaded {
+ [](TextIngestionMethod) -> 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 = TextIngestionMethod {};
+ return method;
+}
+
std::string ContentAddress::render() const
{
return std::visit(overloaded {
@@ -36,14 +57,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 TextIngestionMethod & 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 +72,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,46 +96,47 @@ 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 {
+ TextIngestionMethod {},
+ 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);
}
-ContentAddress ContentAddress::parse(std::string_view rawCa) {
+ContentAddress ContentAddress::parse(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.raw);
+ return std::visit(overloaded {
+ [&](TextIngestionMethod &) {
+ return ContentAddress(TextHash {
+ .hash = Hash::parseNonSRIUnprefixed(rest, hashType)
+ });
+ },
+ [&](FileIngestionMethod & fim) {
+ return ContentAddress(FixedOutputHash {
+ .method = fim,
+ .hash = Hash::parseNonSRIUnprefixed(rest, hashType),
+ });
+ },
+ }, caMethod.raw);
}
-ContentAddressMethod ContentAddressMethod::parse(std::string_view caMethod)
+std::pair<ContentAddressMethod, HashType> ContentAddressMethod::parse(std::string_view caMethod)
{
std::string asPrefix = std::string{caMethod} + ":";
// parseContentAddressMethodPrefix takes its argument by reference
@@ -134,6 +156,36 @@ std::string renderContentAddress(std::optional<ContentAddress> ca)
return ca ? ca->render() : "";
}
+ContentAddress ContentAddress::fromParts(
+ ContentAddressMethod method, Hash hash) noexcept
+{
+ return std::visit(overloaded {
+ [&](TextIngestionMethod _) -> ContentAddress {
+ return TextHash {
+ .hash = std::move(hash),
+ };
+ },
+ [&](FileIngestionMethod m2) -> ContentAddress {
+ return FixedOutputHash {
+ .method = std::move(m2),
+ .hash = std::move(hash),
+ };
+ },
+ }, method.raw);
+}
+
+ContentAddressMethod ContentAddress::getMethod() const
+{
+ return std::visit(overloaded {
+ [](const TextHash & th) -> ContentAddressMethod {
+ return TextIngestionMethod {};
+ },
+ [](const FixedOutputHash & fsh) -> ContentAddressMethod {
+ return fsh.method;
+ },
+ }, raw);
+}
+
const Hash & ContentAddress::getHash() const
{
return std::visit(overloaded {
@@ -146,6 +198,12 @@ const Hash & ContentAddress::getHash() const
}, raw);
}
+std::string ContentAddress::printMethodAlgo() const
+{
+ return getMethod().renderPrefix()
+ + printHashType(getHash().type);
+}
+
bool StoreReferences::empty() const
{
return !self && others.empty();
@@ -156,7 +214,8 @@ size_t StoreReferences::size() const
return (self ? 1 : 0) + others.size();
}
-ContentAddressWithReferences ContentAddressWithReferences::withoutRefs(const ContentAddress & ca) {
+ContentAddressWithReferences ContentAddressWithReferences::withoutRefs(const ContentAddress & ca) noexcept
+{
return std::visit(overloaded {
[&](const TextHash & h) -> ContentAddressWithReferences {
return TextInfo {
@@ -173,4 +232,56 @@ ContentAddressWithReferences ContentAddressWithReferences::withoutRefs(const Con
}, ca.raw);
}
+std::optional<ContentAddressWithReferences> ContentAddressWithReferences::fromPartsOpt(
+ ContentAddressMethod method, Hash hash, StoreReferences refs) noexcept
+{
+ return std::visit(overloaded {
+ [&](TextIngestionMethod _) -> std::optional<ContentAddressWithReferences> {
+ if (refs.self)
+ return std::nullopt;
+ return ContentAddressWithReferences {
+ TextInfo {
+ .hash = { .hash = std::move(hash) },
+ .references = std::move(refs.others),
+ }
+ };
+ },
+ [&](FileIngestionMethod m2) -> std::optional<ContentAddressWithReferences> {
+ return ContentAddressWithReferences {
+ 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 TextIngestionMethod {};
+ },
+ [](const FixedOutputInfo & fsh) -> ContentAddressMethod {
+ return fsh.hash.method;
+ },
+ }, raw);
+}
+
+Hash ContentAddressWithReferences::getHash() const
+{
+ return std::visit(overloaded {
+ [](const TextInfo & th) {
+ return th.hash.hash;
+ },
+ [](const FixedOutputInfo & fsh) {
+ return fsh.hash.hash;
+ },
+ }, raw);
+}
+
}