#include "args.hh" #include "content-address.hh" #include "split.hh" namespace nix { std::string FixedOutputHash::printMethodAlgo() const { return makeFileIngestionPrefix(method) + printHashType(hash.type); } std::string makeFileIngestionPrefix(const FileIngestionMethod m) { switch (m) { case FileIngestionMethod::Flat: return ""; case FileIngestionMethod::Recursive: return "r:"; default: throw Error("impossible, caught both cases"); } } std::string makeFixedOutputCA(FileIngestionMethod method, const Hash & hash) { return "fixed:" + makeFileIngestionPrefix(method) + hash.to_string(Base32, true); } // FIXME Put this somewhere? template struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded; std::string renderContentAddress(ContentAddress ca) { return std::visit(overloaded { [](TextHash th) { return "text:" + th.hash.to_string(Base32, true); }, [](FixedOutputHash fsh) { return makeFixedOutputCA(fsh.method, fsh.hash); } }, ca); } ContentAddress parseContentAddress(std::string_view rawCa) { auto rest = rawCa; std::string_view prefix; { auto optPrefix = splitPrefixTo(rest, ':'); if (!optPrefix) throw UsageError("not a content address because it is not in the form ':': %s", rawCa); prefix = *optPrefix; } auto parseHashType_ = [&](){ auto hashTypeRaw = splitPrefixTo(rest, ':'); if (!hashTypeRaw) throw UsageError("content address hash must be in form ':', but found: %s", rawCa); HashType hashType = parseHashType(*hashTypeRaw); return std::move(hashType); }; // Switch on prefix if (prefix == "text") { // No parsing of the 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 TextHash { .hash = Hash::parseNonSRIUnprefixed(rest, std::move(hashType)), }; } else if (prefix == "fixed") { // Parse method auto method = FileIngestionMethod::Flat; if (splitPrefix(rest, "r:")) method = FileIngestionMethod::Recursive; HashType hashType = parseHashType_(); return FixedOutputHash { .method = method, .hash = Hash::parseNonSRIUnprefixed(rest, std::move(hashType)), }; } else throw UsageError("content address prefix '%s' is unrecognized. Recogonized prefixes are 'text' or 'fixed'", prefix); }; std::optional parseContentAddressOpt(std::string_view rawCaOpt) { return rawCaOpt == "" ? std::optional {} : parseContentAddress(rawCaOpt); }; std::string renderContentAddress(std::optional ca) { return ca ? renderContentAddress(*ca) : ""; } Hash getContentAddressHash(const ContentAddress & ca) { return std::visit(overloaded { [](TextHash th) { return th.hash; }, [](FixedOutputHash fsh) { return fsh.hash; } }, ca); } }