aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/content-address.cc
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2020-10-12 23:51:23 +0000
committerJohn Ericson <John.Ericson@Obsidian.Systems>2020-10-13 02:15:48 +0000
commita4e5de1b9d26584615946057430df9e63d842f53 (patch)
treed671fa1b72a1c884869acadf2f397ce5cf495475 /src/libstore/content-address.cc
parenta0f369aa3fe9f2d223f45123db952ba7889c3c01 (diff)
Derivations can output "text-hashed" data
In particular, this means that derivations can output derivations. But that ramification isn't (yet!) useful as we would want, since there is no way to have a dependent derivation that is itself a dependent derivation.
Diffstat (limited to 'src/libstore/content-address.cc')
-rw-r--r--src/libstore/content-address.cc139
1 files changed, 106 insertions, 33 deletions
diff --git a/src/libstore/content-address.cc b/src/libstore/content-address.cc
index d68c60f4f..4226213b9 100644
--- a/src/libstore/content-address.cc
+++ b/src/libstore/content-address.cc
@@ -10,7 +10,7 @@ std::string FixedOutputHash::printMethodAlgo() const
}
-std::string makeFileIngestionPrefix(const FileIngestionMethod m)
+std::string makeFileIngestionPrefix(FileIngestionMethod m)
{
switch (m) {
case FileIngestionMethod::Flat:
@@ -21,6 +21,27 @@ std::string makeFileIngestionPrefix(const 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,24 @@ 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);
+
+ 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_view asPrefix {std::string{caMethod} + ":"};
return parseContentAddressMethodPrefix(asPrefix);
@@ -137,6 +157,42 @@ std::string renderContentAddress(std::optional<ContentAddress> ca)
return ca ? renderContentAddress(*ca) : "";
}
+ContentAddressWithReferences contentAddressFromMethodHashAndRefs(
+ ContentAddressMethod method, Hash && hash, PathReferences<StorePath> && refs)
+{
+ return std::visit(overloaded {
+ [&](TextHashMethod _) -> ContentAddressWithReferences {
+ if (refs.hasSelfReference)
+ throw UsageError("Cannot have a self reference with text hashing scheme");
+ return TextInfo {
+ { .hash = std::move(hash) },
+ std::move(refs.references),
+ };
+ },
+ [&](FileIngestionMethod m2) -> ContentAddressWithReferences {
+ return FixedOutputInfo {
+ {
+ .method = m2,
+ .hash = std::move(hash),
+ },
+ std::move(refs),
+ };
+ },
+ }, method);
+}
+
+ContentAddressMethod getContentAddressMethod(const ContentAddressWithReferences & ca)
+{
+ return std::visit(overloaded {
+ [](TextInfo th) -> ContentAddressMethod {
+ return TextHashMethod {};
+ },
+ [](FixedOutputInfo fsh) -> ContentAddressMethod {
+ return fsh.method;
+ },
+ }, ca);
+}
+
Hash getContentAddressHash(const ContentAddress & ca)
{
return std::visit(overloaded {
@@ -160,4 +216,21 @@ ContentAddressWithReferences caWithoutRefs(const ContentAddress & ca) {
}, ca);
}
+Hash getContentAddressHash(const ContentAddressWithReferences & ca)
+{
+ return std::visit(overloaded {
+ [](TextInfo th) {
+ return th.hash;
+ },
+ [](FixedOutputInfo fsh) {
+ return fsh.hash;
+ },
+ }, ca);
+}
+
+std::string printMethodAlgo(const ContentAddressWithReferences & ca) {
+ return makeContentAddressingPrefix(getContentAddressMethod(ca))
+ + printHashType(getContentAddressHash(ca).type);
+}
+
}