libutil/hash: Add default values for Hash::to_string

The sane default is to print in SRI format, and include the hash type

Change-Id: I7efcb5dcfbe56c82dbf1928e2bb35cdd3ff089c6
This commit is contained in:
Tom Hubrecht
2026-01-10 18:26:15 +00:00
parent 16d884bd1f
commit e29263b638
23 changed files with 52 additions and 59 deletions
+3 -3
View File
@@ -467,7 +467,7 @@ opQuery(std::shared_ptr<Store> store, AsyncIoRoot & aio, Strings opFlags, String
auto info = aio.blockOn(store->queryPathInfo(j));
if (query == qHash) {
assert(info->narHash.type == HashType::SHA256);
cout << fmt("%s\n", info->narHash.to_string(HashFormat::Base32, true));
cout << fmt("%s\n", info->narHash.to_string(HashFormat::Base32));
} else if (query == qSize)
cout << fmt("%d\n", info->narSize);
}
@@ -859,8 +859,8 @@ opVerifyPath(std::shared_ptr<Store> store, AsyncIoRoot & aio, Strings opFlags, S
printError(
"path '%s' was modified! expected hash '%s', got '%s'",
store->printStorePath(path),
info->narHash.to_string(HashFormat::SRI, true),
current.first.to_string(HashFormat::SRI, true)
info->narHash.to_string(),
current.first.to_string()
);
status = 1;
}
+3 -3
View File
@@ -32,7 +32,7 @@ void emitTreeAttrs(
auto narHash = input.getNarHash();
assert(narHash);
attrs.alloc("narHash").mkString(narHash->to_string(HashFormat::SRI, true));
attrs.alloc("narHash").mkString(narHash->to_string());
if (input.getType() == "git")
attrs.alloc("submodules").mkBool(
@@ -318,8 +318,8 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
.make<EvalError>(
"hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s",
*url,
expectedHash->to_string(HashFormat::SRI, true),
hash.to_string(HashFormat::SRI, true)
expectedHash->to_string(),
hash.to_string()
)
.withExitStatus(102)
.debugThrow();
+3 -3
View File
@@ -178,7 +178,7 @@ try {
};
auto narHash = TRY_AWAIT(store->queryPathInfo(tree.storePath))->narHash;
input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true));
input.attrs.insert_or_assign("narHash", narHash.to_string());
if (auto prevNarHash = getNarHash()) {
if (narHash != *prevNarHash)
@@ -187,8 +187,8 @@ try {
"NAR hash mismatch in input '%s' (%s), expected '%s', got '%s'",
to_string(),
tree.actualPath,
prevNarHash->to_string(HashFormat::SRI, true),
narHash.to_string(HashFormat::SRI, true)
prevNarHash->to_string(),
narHash.to_string()
);
}
+1 -1
View File
@@ -579,7 +579,7 @@ struct GitInputScheme : InputScheme
if (hash.has_value() && !(hash->type == HashType::SHA1 || hash->type == HashType::SHA256))
throw Error(
"Hash '%s' is not supported by Git. Supported types are sha1 and sha256.",
hash->to_string(HashFormat::Base16, true)
hash->to_string(HashFormat::Base16)
);
};
+1 -1
View File
@@ -252,7 +252,7 @@ struct MercurialInputScheme : InputScheme
if (hash.has_value() && hash->type != HashType::SHA1)
throw Error(
"Hash '%s' is not supported by Mercurial. Only sha1 is supported.",
hash->to_string(HashFormat::Base16, true)
hash->to_string(HashFormat::Base16)
);
};
+1 -1
View File
@@ -293,7 +293,7 @@ struct CurlInputScheme : InputScheme
// NAR hashes are preferred over file hashes since tar/zip
// files don't have a canonical representation.
if (auto narHash = input.getNarHash())
url.query.insert_or_assign("narHash", narHash->to_string(HashFormat::SRI, true));
url.query.insert_or_assign("narHash", narHash->to_string());
return url;
}
+2 -2
View File
@@ -2105,8 +2105,8 @@ try {
"specified: %s\n got: %s\n expected path: %s\n got path: %s",
worker.store.printStorePath(drvPath),
guessedUrl,
wanted.to_string(HashFormat::SRI, true),
got.to_string(HashFormat::SRI, true),
wanted.to_string(),
got.to_string(),
worker.store.printStorePath(dof.path(worker.store, drv->name, outputName)),
worker.store.printStorePath(newInfo0.path)
));
+1 -1
View File
@@ -62,7 +62,7 @@ std::string ContentAddress::render() const
},
method.raw
)
+ this->hash.to_string(HashFormat::Base32, true);
+ this->hash.to_string(HashFormat::Base32);
}
/**
+2 -2
View File
@@ -42,8 +42,8 @@ try {
throw Error(
"hash of path '%s' has changed from '%s' to '%s'!",
printStorePath(path),
info->narHash.to_string(HashFormat::SRI, true),
hash.to_string(HashFormat::SRI, true)
info->narHash.to_string(),
hash.to_string()
);
teeSink
+8 -8
View File
@@ -655,7 +655,7 @@ try {
state.stmts->RegisterValidPath.use()
(printStorePath(info.path))
(info.narHash.to_string(HashFormat::Base16, true))
(info.narHash.to_string(HashFormat::Base16))
(info.registrationTime == 0 ? time(0) : info.registrationTime)
(info.deriver ? printStorePath(*info.deriver) : "", (bool) info.deriver)
(info.narSize, info.narSize != 0)
@@ -768,7 +768,7 @@ void LocalStore::updatePathInfo(DBState & state, const ValidPathInfo & info)
{
state.stmts->UpdatePathInfo.use()
(info.narSize, info.narSize != 0)
(info.narHash.to_string(HashFormat::Base16, true))
(info.narHash.to_string(HashFormat::Base16))
(info.ultimate ? 1 : 0, info.ultimate)
(concatStringsSep(" ", info.sigs), !info.sigs.empty())
(renderContentAddress(info.ca), (bool) info.ca)
@@ -1143,8 +1143,8 @@ try {
throw Error(
"hash mismatch importing path '%s';\n specified: %s\n got: %s",
printStorePath(info.path),
info.narHash.to_string(HashFormat::SRI, true),
hashResult.first.to_string(HashFormat::SRI, true)
info.narHash.to_string(),
hashResult.first.to_string()
);
if (hashResult.second != info.narSize)
@@ -1162,8 +1162,8 @@ try {
throw Error(
"ca hash mismatch importing path '%s';\n specified: %s\n got: %s",
printStorePath(info.path),
specified.hash.to_string(HashFormat::SRI, true),
actualHash.hash.to_string(HashFormat::SRI, true)
specified.hash.to_string(),
actualHash.hash.to_string()
);
}
}
@@ -1551,8 +1551,8 @@ try {
printError(
"path '%s' was modified! expected hash '%s', got '%s'",
toRealPath(printStorePath(i)),
info->narHash.to_string(HashFormat::SRI, true),
current.first.to_string(HashFormat::SRI, true)
info->narHash.to_string(),
current.first.to_string()
);
if (repair) TRY_AWAIT(repairPath(i)); else errors = true;
} else {
+2 -2
View File
@@ -288,9 +288,9 @@ public:
(std::string(info->path.name()))
(narInfo ? narInfo->url : "", narInfo != 0)
(narInfo ? narInfo->compression : "", narInfo != 0)
(narInfo && narInfo->fileHash ? narInfo->fileHash->to_string(HashFormat::Base32, true) : "", narInfo && narInfo->fileHash)
(narInfo && narInfo->fileHash ? narInfo->fileHash->to_string(HashFormat::Base32) : "", narInfo && narInfo->fileHash)
(narInfo ? narInfo->fileSize : 0, narInfo != 0 && narInfo->fileSize)
(info->narHash.to_string(HashFormat::Base32, true))
(info->narHash.to_string(HashFormat::Base32))
(info->narSize)
(concatStringsSep(" ", info->shortRefs()))
(info->deriver ? std::string(info->deriver->to_string()) : "", (bool) info->deriver)
+2 -2
View File
@@ -105,10 +105,10 @@ std::string NarInfo::to_string(const Store & store) const
assert(compression != "");
res += "Compression: " + compression + "\n";
assert(fileHash && fileHash->type == HashType::SHA256);
res += "FileHash: " + fileHash->to_string(HashFormat::Base32, true) + "\n";
res += "FileHash: " + fileHash->to_string(HashFormat::Base32) + "\n";
res += "FileSize: " + std::to_string(fileSize) + "\n";
assert(narHash.type == HashType::SHA256);
res += "NarHash: " + narHash.to_string(HashFormat::Base32, true) + "\n";
res += "NarHash: " + narHash.to_string(HashFormat::Base32) + "\n";
res += "NarSize: " + std::to_string(narSize) + "\n";
res += "References: " + concatStringsSep(" ", shortRefs()) + "\n";
+1 -1
View File
@@ -156,7 +156,7 @@ std::optional<struct ::stat> LocalStore::optimisePath_(
contents of the symlink (i.e. the result of readlink()), not
the contents of the target (which may not even exist). */
Hash hash = hashPath(HashType::SHA256, path).first;
debug("'%1%' has hash '%2%'", path, hash.to_string(HashFormat::Base32, true));
debug("'%1%' has hash '%2%'", path, hash.to_string(HashFormat::Base32));
/* Check if this is a known hash. */
Path linkPath = linksDir + "/" + hash.to_string(HashFormat::Base32, false);
+1 -1
View File
@@ -28,7 +28,7 @@ std::string ValidPathInfo::fingerprint(const Store & store) const
if (narSize == 0)
throw Error("cannot calculate fingerprint of path '%s' because its size is not known",
store.printStorePath(path));
return "1;" + store.printStorePath(path) + ";" + narHash.to_string(HashFormat::Base32, true) + ";"
return "1;" + store.printStorePath(path) + ";" + narHash.to_string(HashFormat::Base32) + ";"
+ std::to_string(narSize) + ";" + concatStringsSep(",", store.printStorePathSet(references));
}
+1 -1
View File
@@ -40,7 +40,7 @@ struct DrvOutput {
std::string strHash() const
{
return drvHash.to_string(HashFormat::Base16, true);
return drvHash.to_string(HashFormat::Base16);
}
static DrvOutput parse(const std::string &);
+1 -1
View File
@@ -87,7 +87,7 @@ WireFormatGenerator ServeProto::Serialise<UnkeyedValidPathInfo>::write(WriteConn
co_yield info.narSize; // downloadSize, lie a little
co_yield info.narSize;
if (GET_PROTOCOL_MINOR(conn.version) >= 4) {
co_yield info.narHash.to_string(HashFormat::Base32, true);
co_yield info.narHash.to_string(HashFormat::Base32);
co_yield renderContentAddress(info.ca);
co_yield info.sigs;
}
+3 -3
View File
@@ -178,7 +178,7 @@ StorePath Store::makeStorePath(std::string_view type,
StorePath Store::makeStorePath(std::string_view type,
const Hash & hash, std::string_view name) const
{
return makeStorePath(type, hash.to_string(HashFormat::Base16, true), name);
return makeStorePath(type, hash.to_string(HashFormat::Base16), name);
}
@@ -219,8 +219,8 @@ StorePath Store::makeFixedOutputPath(std::string_view name, const FixedOutputInf
"output:out",
hashString(
HashType::SHA256,
"fixed:out:" + makeFileIngestionPrefix(info.method)
+ info.hash.to_string(HashFormat::Base16, true) + ":"
"fixed:out:" + makeFileIngestionPrefix(info.method) + info.hash.to_string(HashFormat::Base16)
+ ":"
),
name
);
+1 -8
View File
@@ -8,20 +8,16 @@
#include "lix/libutil/serialise.hh"
#include "lix/libutil/file-system.hh"
namespace nix {
namespace detail {
using EvpMdCtxPtr = std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)>;
}
MakeError(BadHash, Error);
enum class HashType : char { MD5 = 42, SHA1, SHA256, SHA512 };
@@ -136,7 +132,7 @@ public:
* or base-64. By default, this is prefixed by the hash type
* (e.g. "sha256:").
*/
std::string to_string(HashFormat format, bool includeType) const;
std::string to_string(HashFormat format = HashFormat::SRI, bool includeType = true) const;
std::string gitRev() const
{
@@ -198,7 +194,6 @@ std::optional<HashType> parseHashTypeOpt(std::string_view s);
*/
std::string_view printHashType(HashType ht);
struct AbstractHashSink : virtual Sink
{
virtual HashResult finish() = 0;
@@ -225,6 +220,4 @@ inline HashResult hashSource(HashType ht, Source & source)
source.drainInto(h);
return h.finish();
}
}
+2 -2
View File
@@ -1532,14 +1532,14 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON
if (json) {
auto res = JSON::object();
res["storePath"] = store->printStorePath(tree.storePath);
res["hash"] = hash.to_string(HashFormat::SRI, true);
res["hash"] = hash.to_string();
logger->cout(res.dump());
} else {
notice(
"Downloaded '%s' to '%s' (hash '%s').",
lockedRef.to_string(),
store->printStorePath(tree.storePath),
hash.to_string(HashFormat::SRI, true)
hash.to_string()
);
}
}
+2 -2
View File
@@ -345,14 +345,14 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON
if (json) {
auto res = JSON::object();
res["storePath"] = store->printStorePath(storePath);
res["hash"] = hash.to_string(HashFormat::SRI, true);
res["hash"] = hash.to_string();
logger->cout(res.dump());
} else {
notice(
"Downloaded '%s' to '%s' (hash '%s').",
url,
store->printStorePath(storePath),
hash.to_string(HashFormat::SRI, true)
hash.to_string()
);
}
}
+2 -2
View File
@@ -117,8 +117,8 @@ struct CmdVerify : StorePathsCommand
printError(
"path '%s' was modified! expected hash '%s', got '%s'",
store->printStorePath(info->path),
info->narHash.to_string(HashFormat::SRI, true),
hash.first.to_string(HashFormat::SRI, true)
info->narHash.to_string(),
hash.first.to_string()
);
}
}
+1 -1
View File
@@ -92,7 +92,7 @@ SV * queryReferences(char * path)
SV * queryPathHash(char * path)
PPCODE:
try {
auto s = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)))->narHash.to_string(HashFormat::Base32, true);
auto s = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)))->narHash.to_string(HashFormat::Base32);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
+8 -8
View File
@@ -14,28 +14,28 @@ namespace nix {
// values taken from: https://tools.ietf.org/html/rfc1321
auto s1 = "";
auto hash = hashString(HashType::MD5, s1);
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e");
ASSERT_EQ(hash.to_string(HashFormat::Base16), "md5:d41d8cd98f00b204e9800998ecf8427e");
}
TEST(hashString, testKnownMD5Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc1321
auto s2 = "abc";
auto hash = hashString(HashType::MD5, s2);
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72");
ASSERT_EQ(hash.to_string(HashFormat::Base16), "md5:900150983cd24fb0d6963f7d28e17f72");
}
TEST(hashString, testKnownSHA1Hashes1) {
// values taken from: https://tools.ietf.org/html/rfc3174
auto s = "abc";
auto hash = hashString(HashType::SHA1, s);
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "sha1:a9993e364706816aba3e25717850c26c9cd0d89d");
ASSERT_EQ(hash.to_string(HashFormat::Base16), "sha1:a9993e364706816aba3e25717850c26c9cd0d89d");
}
TEST(hashString, testKnownSHA1Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc3174
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
auto hash = hashString(HashType::SHA1, s);
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
ASSERT_EQ(hash.to_string(HashFormat::Base16), "sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
}
TEST(hashString, testKnownSHA256Hashes1) {
@@ -44,7 +44,7 @@ namespace nix {
auto hash = hashString(HashType::SHA256, s);
ASSERT_EQ(
hash.to_string(HashFormat::Base16, true),
hash.to_string(HashFormat::Base16),
"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
);
}
@@ -54,7 +54,7 @@ namespace nix {
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
auto hash = hashString(HashType::SHA256, s);
ASSERT_EQ(
hash.to_string(HashFormat::Base16, true),
hash.to_string(HashFormat::Base16),
"sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
);
}
@@ -64,7 +64,7 @@ namespace nix {
auto s = "abc";
auto hash = hashString(HashType::SHA512, s);
ASSERT_EQ(
hash.to_string(HashFormat::Base16, true),
hash.to_string(HashFormat::Base16),
"sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9"
"7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd"
"454d4423643ce80e2a9ac94fa54ca49f"
@@ -76,7 +76,7 @@ namespace nix {
auto hash = hashString(HashType::SHA512, s);
ASSERT_EQ(
hash.to_string(HashFormat::Base16, true),
hash.to_string(HashFormat::Base16),
"sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1"
"7299aeadb6889018501d289e4900f7e4331b99dec4b5433a"
"c7d329eeb6dd26545e96e55b874be909"