treewide: Rename Base to HashFormat

Co-authored-by: Yueh-Shun Li <shamrocklee@posteo.net>

`base` is ambiguous, since it's not about the digital bases, but about
the format of hashes. Base16, Base32 and Base64 are all character maps
for binary encoding.

Documentation of the format is also added.

Cherry-pick of:
https://github.com/NixOS/nix/pull/7708/commits/838c70f62116328ce01cb41a01886e4f1b9a727f
https://github.com/NixOS/nix/pull/7708/commits/5043e6cf4ea537dfe599470797c5b310ab0e94b9

Change-Id: Ief5425f3c2056a4cca75838091e4dfa5cca88872
This commit is contained in:
Tom Hubrecht
2026-01-06 11:22:06 +00:00
parent b730fab286
commit b482ebbbc8
39 changed files with 320 additions and 231 deletions
+1 -1
View File
@@ -69,7 +69,7 @@ static std::string makeLockFilename(const std::string & storeUri) {
// This avoids issues with the escaped URI being very long and causing
// path too long errors, while also avoiding any possibility of collision
// caused by simple truncation.
auto hash = hashString(HashType::SHA256, storeUri).to_string(Base::Base32, false);
auto hash = hashString(HashType::SHA256, storeUri).to_string(HashFormat::Base32, false);
return escapeUri(storeUri).substr(0, 48) + "-" + hash.substr(0, 16);
}
+6 -4
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(Base::Base32, true));
cout << fmt("%s\n", info->narHash.to_string(HashFormat::Base32, true));
} else if (query == qSize)
cout << fmt("%d\n", info->narSize);
}
@@ -856,10 +856,12 @@ opVerifyPath(std::shared_ptr<Store> store, AsyncIoRoot & aio, Strings opFlags, S
aio.blockOn(aio.blockOn(store->narFromPath(path))->drainInto(sink));
auto current = sink.finish();
if (current.first != info->narHash) {
printError("path '%s' was modified! expected hash '%s', got '%s'",
printError(
"path '%s' was modified! expected hash '%s', got '%s'",
store->printStorePath(path),
info->narHash.to_string(Base::SRI, true),
current.first.to_string(Base::SRI, true));
info->narHash.to_string(HashFormat::SRI, true),
current.first.to_string(HashFormat::SRI, true)
);
status = 1;
}
}
+1 -1
View File
@@ -42,7 +42,7 @@ struct AttrDb
Path cacheDir = getCacheDir() + "/nix/eval-cache-v5";
createDirs(cacheDir);
Path dbPath = cacheDir + "/" + fingerprint.to_string(Base::Base16, false) + ".sqlite";
Path dbPath = cacheDir + "/" + fingerprint.to_string(HashFormat::Base16, false) + ".sqlite";
state->db = SQLite(dbPath);
state->db.isCache();
+2 -2
View File
@@ -1494,7 +1494,7 @@ static void prim_hashFile(EvalState & state, Value * * args, Value & v)
auto path = realisePath(state, *args[1]);
v.mkString(hashString(*ht, path.readFile()).to_string(Base::Base16, false));
v.mkString(hashString(*ht, path.readFile()).to_string(HashFormat::Base16, false));
}
static std::string_view fileTypeToString(InputAccessor::Type type)
@@ -2776,7 +2776,7 @@ static void prim_hashString(EvalState & state, Value * * args, Value & v)
NixStringContext context; // discarded
auto s = state.forceString(*args[1], context, noPos, "while evaluating the second argument passed to builtins.hashString");
v.mkString(hashString(*ht, s).to_string(Base::Base16, false));
v.mkString(hashString(*ht, s).to_string(HashFormat::Base16, false));
}
struct RegexCache
+10 -8
View File
@@ -32,7 +32,7 @@ void emitTreeAttrs(
auto narHash = input.getNarHash();
assert(narHash);
attrs.alloc("narHash").mkString(narHash->to_string(Base::SRI, true));
attrs.alloc("narHash").mkString(narHash->to_string(HashFormat::SRI, true));
if (input.getType() == "git")
attrs.alloc("submodules").mkBool(
@@ -314,13 +314,15 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
? state.aio.blockOn(state.ctx.store->queryPathInfo(storePath))->narHash
: hashFile(HashType::SHA256, state.ctx.store->toRealPath(storePath));
if (hash != *expectedHash) {
state.ctx.errors.make<EvalError>(
"hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s",
*url,
expectedHash->to_string(Base::SRI, true),
hash.to_string(Base::SRI, true)
).withExitStatus(102)
.debugThrow();
state.ctx.errors
.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)
)
.withExitStatus(102)
.debugThrow();
}
}
+9 -3
View File
@@ -178,12 +178,18 @@ try {
};
auto narHash = TRY_AWAIT(store->queryPathInfo(tree.storePath))->narHash;
input.attrs.insert_or_assign("narHash", narHash.to_string(Base::SRI, true));
input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true));
if (auto prevNarHash = getNarHash()) {
if (narHash != *prevNarHash)
throw Error((unsigned int) 102, "NAR hash mismatch in input '%s' (%s), expected '%s', got '%s'",
to_string(), tree.actualPath, prevNarHash->to_string(Base::SRI, true), narHash.to_string(Base::SRI, true));
throw Error(
(unsigned int) 102,
"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)
);
}
if (auto prevLastModified = getLastModified()) {
+6 -3
View File
@@ -58,8 +58,8 @@ bool touchCacheFile(const Path & path, time_t touch_time)
Path getCachePath(std::string_view key)
{
return getCacheDir() + "/nix/gitv3/" +
hashString(HashType::SHA256, key).to_string(Base::Base32, false);
return getCacheDir() + "/nix/gitv3/"
+ hashString(HashType::SHA256, key).to_string(HashFormat::Base32, false);
}
// Returns the name of the HEAD branch.
@@ -577,7 +577,10 @@ struct GitInputScheme : InputScheme
auto checkHashType = [&](const std::optional<Hash> & hash)
{
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(Base::Base16, true));
throw Error(
"Hash '%s' is not supported by Git. Supported types are sha1 and sha256.",
hash->to_string(HashFormat::Base16, true)
);
};
auto getLockedAttrs = [&]()
+21 -9
View File
@@ -152,7 +152,9 @@ struct GitArchiveInputScheme : InputScheme
auto path = owner + "/" + repo;
assert(!(ref && rev));
if (ref) path += "/" + *ref;
if (rev) path += "/" + rev->to_string(Base::Base16, false);
if (rev) {
path += "/" + rev->to_string(HashFormat::Base16, false);
}
return ParsedURL {
.scheme = schemeType(),
.path = path,
@@ -304,8 +306,12 @@ struct GitHubInputScheme : GitArchiveInputScheme
? "https://%s/%s/%s/archive/%s.tar.gz"
: "https://api.%s/repos/%s/%s/tarball/%s";
const auto url = fmt(urlFmt, host, getOwner(input), getRepo(input),
input.getRev()->to_string(Base::Base16, false));
const auto url =
fmt(urlFmt,
host,
getOwner(input),
getRepo(input),
input.getRev()->to_string(HashFormat::Base16, false));
return DownloadUrl { url, headers };
}
@@ -388,9 +394,12 @@ struct GitLabInputScheme : GitArchiveInputScheme
// is 10 reqs/sec/ip-addr. See
// https://docs.gitlab.com/ee/user/gitlab_com/index.html#gitlabcom-specific-rate-limits
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
auto url = fmt("https://%s/api/v4/projects/%s%%2F%s/repository/archive.tar.gz?sha=%s",
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(Base::Base16, false));
auto url =
fmt("https://%s/api/v4/projects/%s%%2F%s/repository/archive.tar.gz?sha=%s",
host,
getStrAttr(input.attrs, "owner"),
getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(HashFormat::Base16, false));
Headers headers = makeHeadersWithAuthTokens(host);
return DownloadUrl { url, headers };
@@ -487,9 +496,12 @@ struct SourceHutInputScheme : GitArchiveInputScheme
DownloadUrl getDownloadUrl(const Input & input) const override
{
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
auto url = fmt("https://%s/%s/%s/archive/%s.tar.gz",
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(Base::Base16, false));
auto url =
fmt("https://%s/%s/%s/archive/%s.tar.gz",
host,
getStrAttr(input.attrs, "owner"),
getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(HashFormat::Base16, false));
Headers headers = makeHeadersWithAuthTokens(host);
return DownloadUrl { url, headers };
+8 -2
View File
@@ -250,7 +250,10 @@ struct MercurialInputScheme : InputScheme
auto checkHashType = [&](const std::optional<Hash> & hash)
{
if (hash.has_value() && hash->type != HashType::SHA1)
throw Error("Hash '%s' is not supported by Mercurial. Only sha1 is supported.", hash->to_string(Base::Base16, true));
throw Error(
"Hash '%s' is not supported by Mercurial. Only sha1 is supported.",
hash->to_string(HashFormat::Base16, true)
);
};
@@ -296,7 +299,10 @@ struct MercurialInputScheme : InputScheme
}
}
Path cacheDir = fmt("%s/nix/hg/%s", getCacheDir(), hashString(HashType::SHA256, actualUrl).to_string(Base::Base32, false));
Path cacheDir =
fmt("%s/nix/hg/%s",
getCacheDir(),
hashString(HashType::SHA256, actualUrl).to_string(HashFormat::Base32, false));
/* If this is a commit hash that we already have, we don't
have to pull again. */
+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(Base::SRI, true));
url.query.insert_or_assign("narHash", narHash->to_string(HashFormat::SRI, true));
return url;
}
+8 -8
View File
@@ -164,14 +164,14 @@ try {
auto [fileHash, fileSize] = fileHashSink.finish();
narInfo->fileHash = fileHash;
narInfo->fileSize = fileSize;
narInfo->url = "nar/" + narInfo->fileHash->to_string(Base::Base32, false) + ".nar"
+ (config().compression == "xz" ? ".xz" :
config().compression == "bzip2" ? ".bz2" :
config().compression == "zstd" ? ".zst" :
config().compression == "lzip" ? ".lzip" :
config().compression == "lz4" ? ".lz4" :
config().compression == "br" ? ".br" :
"");
narInfo->url = "nar/" + narInfo->fileHash->to_string(HashFormat::Base32, false) + ".nar"
+ (config().compression == "xz" ? ".xz"
: config().compression == "bzip2" ? ".bz2"
: config().compression == "zstd" ? ".zst"
: config().compression == "lzip" ? ".lzip"
: config().compression == "lz4" ? ".lz4"
: config().compression == "br" ? ".br"
: "");
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
printMsg(lvlTalkative, "copying path '%1%' (%2% bytes, compressed %3$.1f%% in %4% ms) to binary cache",
+3 -3
View File
@@ -897,7 +897,7 @@ void LocalDerivationGoal::initTmpDir() {
env[i.first] = i.second;
} else {
auto hash = hashString(HashType::SHA256, i.first);
std::string fn = ".attr-" + hash.to_string(Base::Base32, false);
std::string fn = ".attr-" + hash.to_string(HashFormat::Base32, false);
Path p = tmpDir + "/" + fn;
/* TODO(jade): we should have BorrowedFD instead of OwnedFD. */
AutoCloseFD passAsFileFd{sys::openat(
@@ -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(Base::SRI, true),
got.to_string(Base::SRI, true),
wanted.to_string(HashFormat::SRI, true),
got.to_string(HashFormat::SRI, true),
worker.store.printStorePath(dof.path(worker.store, drv->name, outputName)),
worker.store.printStorePath(newInfo0.path)
));
+1 -2
View File
@@ -72,8 +72,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData,
Hash h = newHashAllowEmpty(getAttr("outputHash"), ht);
fetch(
aio,
hashedMirror + printHashType(h.type) + "/"
+ h.to_string(Base::Base16, false)
hashedMirror + printHashType(h.type) + "/" + h.to_string(HashFormat::Base16, false)
);
return;
} catch (Error & e) {
+10 -10
View File
@@ -53,16 +53,16 @@ std::string ContentAddressMethod::render(HashType ht) const
std::string ContentAddress::render() const
{
return std::visit(overloaded {
[](const TextIngestionMethod &) -> std::string {
return "text:";
},
[](const FileIngestionMethod & method) {
return "fixed:"
+ makeFileIngestionPrefix(method);
},
}, method.raw)
+ this->hash.to_string(Base::Base32, true);
return std::visit(
overloaded{
[](const TextIngestionMethod &) -> std::string { return "text:"; },
[](const FileIngestionMethod & method) {
return "fixed:" + makeFileIngestionPrefix(method);
},
},
method.raw
)
+ this->hash.to_string(HashFormat::Base32, true);
}
/**
+18 -13
View File
@@ -431,7 +431,8 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
[&](const DerivationOutput::CAFixed & dof) {
s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(dof.path(store, name, i.first)));
s += ','; printUnquotedString(s, dof.ca.printMethodAlgo());
s += ','; printUnquotedString(s, dof.ca.hash.to_string(Base::Base16, false));
s += ',';
printUnquotedString(s, dof.ca.hash.to_string(HashFormat::Base16, false));
},
}, i.second.raw);
s += ')';
@@ -590,10 +591,12 @@ try {
std::map<std::string, Hash> outputHashes;
for (const auto & i : drv.outputs) {
auto & dof = std::get<DerivationOutput::CAFixed>(i.second.raw);
auto hash = hashString(HashType::SHA256, "fixed:out:"
+ dof.ca.printMethodAlgo() + ":"
+ dof.ca.hash.to_string(Base::Base16, false) + ":"
+ store.printStorePath(dof.path(store, drv.name, i.first)));
auto hash = hashString(
HashType::SHA256,
"fixed:out:" + dof.ca.printMethodAlgo() + ":"
+ dof.ca.hash.to_string(HashFormat::Base16, false) + ":"
+ store.printStorePath(dof.path(store, drv.name, i.first))
);
outputHashes.insert_or_assign(i.first, std::move(hash));
}
co_return DrvHash {
@@ -608,7 +611,7 @@ try {
const auto h = get(res.hashes, outputName);
if (!h)
throw Error("no hash for output '%s' of derivation '%s'", outputName, drv.name);
inputs2[h->to_string(Base::Base16, false)].insert(outputName);
inputs2[h->to_string(HashFormat::Base16, false)].insert(outputName);
}
}
@@ -711,16 +714,16 @@ WireFormatGenerator serializeDerivation(const Store & store, const BasicDerivati
co_yield i.first;
auto [path, algo, hash] = std::visit(
overloaded{
[&](const DerivationOutput::InputAddressed & doi
) -> std::tuple<std::string, std::string, std::string> {
[&](const DerivationOutput::InputAddressed & doi)
-> std::tuple<std::string, std::string, std::string> {
return {store.printStorePath(doi.path), "", ""};
},
[&](const DerivationOutput::CAFixed & dof
) -> std::tuple<std::string, std::string, std::string> {
[&](const DerivationOutput::CAFixed & dof)
-> std::tuple<std::string, std::string, std::string> {
return {
store.printStorePath(dof.path(store, drv.name, i.first)),
dof.ca.printMethodAlgo(),
dof.ca.hash.to_string(Base::Base16, false)
dof.ca.hash.to_string(HashFormat::Base16, false)
};
},
},
@@ -750,7 +753,9 @@ void writeDerivation(Sink & out, const Store & store, const BasicDerivation & dr
std::string hashPlaceholder(const OutputNameView outputName)
{
// FIXME: memoize?
return "/" + hashString(HashType::SHA256, concatStrings("nix-output:", outputName)).to_string(Base::Base32, false);
return "/"
+ hashString(HashType::SHA256, concatStrings("nix-output:", outputName))
.to_string(HashFormat::Base32, false);
}
@@ -833,7 +838,7 @@ JSON DerivationOutput::toJSON(
[&](const DerivationOutput::CAFixed & dof) {
res["path"] = store.printStorePath(dof.path(store, drvName, outputName));
res["hashAlgo"] = dof.ca.printMethodAlgo();
res["hash"] = dof.ca.hash.to_string(Base::Base16, false);
res["hash"] = dof.ca.hash.to_string(HashFormat::Base16, false);
// FIXME print refs?
},
}, raw);
+6 -2
View File
@@ -39,8 +39,12 @@ try {
Don't complain if the stored hash is zero (unknown). */
Hash hash = hashSink.currentHash().first;
if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
throw Error("hash of path '%s' has changed from '%s' to '%s'!",
printStorePath(path), info->narHash.to_string(Base::SRI, true), hash.to_string(Base::SRI, true));
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)
);
teeSink
<< exportMagic
+1 -1
View File
@@ -54,7 +54,7 @@ static void makeSymlink(const Path & link, const Path & target)
kj::Promise<Result<void>> LocalStore::addIndirectRoot(const Path & path)
try {
std::string hash = hashString(HashType::SHA1, path).to_string(Base::Base32, false);
std::string hash = hashString(HashType::SHA1, path).to_string(HashFormat::Base32, false);
Path realRoot = canonPath(fmt("%1%/%2%/auto/%3%", config().stateDir, gcRootsDir, hash));
makeSymlink(realRoot, path);
return {result::success()};
+1 -1
View File
@@ -315,7 +315,7 @@ struct LegacySSHStore final : public Store
ServeProto::Command::AddToStoreNar,
printStorePath(info.path),
(info.deriver ? printStorePath(*info.deriver) : ""),
info.narHash.to_string(Base::Base16, false),
info.narHash.to_string(HashFormat::Base16, false),
ServeProto::write(*conn, info.references),
info.registrationTime,
info.narSize,
+17 -10
View File
@@ -655,7 +655,7 @@ try {
state.stmts->RegisterValidPath.use()
(printStorePath(info.path))
(info.narHash.to_string(Base::Base16, true))
(info.narHash.to_string(HashFormat::Base16, true))
(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(Base::Base16, true))
(info.narHash.to_string(HashFormat::Base16, true))
(info.ultimate ? 1 : 0, info.ultimate)
(concatStringsSep(" ", info.sigs), !info.sigs.empty())
(renderContentAddress(info.ca), (bool) info.ca)
@@ -1140,8 +1140,12 @@ try {
auto hashResult = hashSink.finish();
if (hashResult.first != info.narHash)
throw Error("hash mismatch importing path '%s';\n specified: %s\n got: %s",
printStorePath(info.path), info.narHash.to_string(Base::SRI, true), hashResult.first.to_string(Base::SRI, true));
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)
);
if (hashResult.second != info.narSize)
throw Error("size mismatch importing path '%s';\n specified: %s\n got: %s",
@@ -1155,10 +1159,12 @@ try {
info.path
);
if (specified.hash != actualHash.hash) {
throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s",
throw Error(
"ca hash mismatch importing path '%s';\n specified: %s\n got: %s",
printStorePath(info.path),
specified.hash.to_string(Base::SRI, true),
actualHash.hash.to_string(Base::SRI, true));
specified.hash.to_string(HashFormat::SRI, true),
actualHash.hash.to_string(HashFormat::SRI, true)
);
}
}
@@ -1505,7 +1511,8 @@ try {
for (auto & link : readDirectory(linksDir)) {
printMsg(lvlTalkative, "checking contents of '%s'", link.name);
Path linkPath = linksDir + "/" + link.name;
std::string hash = hashPath(HashType::SHA256, linkPath).first.to_string(Base::Base32, false);
std::string hash =
hashPath(HashType::SHA256, linkPath).first.to_string(HashFormat::Base32, false);
if (hash != link.name) {
printError("link '%s' was modified! expected hash '%s', got '%s'",
linkPath, link.name, hash);
@@ -1544,8 +1551,8 @@ try {
printError(
"path '%s' was modified! expected hash '%s', got '%s'",
toRealPath(printStorePath(i)),
info->narHash.to_string(Base::SRI, true),
current.first.to_string(Base::SRI, true)
info->narHash.to_string(HashFormat::SRI, true),
current.first.to_string(HashFormat::SRI, true)
);
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(Base::Base32, true) : "", narInfo && narInfo->fileHash)
(narInfo && narInfo->fileHash ? narInfo->fileHash->to_string(HashFormat::Base32, true) : "", narInfo && narInfo->fileHash)
(narInfo ? narInfo->fileSize : 0, narInfo != 0 && narInfo->fileSize)
(info->narHash.to_string(Base::Base32, true))
(info->narHash.to_string(HashFormat::Base32, true))
(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(Base::Base32, true) + "\n";
res += "FileHash: " + fileHash->to_string(HashFormat::Base32, true) + "\n";
res += "FileSize: " + std::to_string(fileSize) + "\n";
assert(narHash.type == HashType::SHA256);
res += "NarHash: " + narHash.to_string(Base::Base32, true) + "\n";
res += "NarHash: " + narHash.to_string(HashFormat::Base32, true) + "\n";
res += "NarSize: " + std::to_string(narSize) + "\n";
res += "References: " + concatStringsSep(" ", shortRefs()) + "\n";
+2 -2
View File
@@ -156,10 +156,10 @@ 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(Base::Base32, true));
debug("'%1%' has hash '%2%'", path, hash.to_string(HashFormat::Base32, true));
/* Check if this is a known hash. */
Path linkPath = linksDir + "/" + hash.to_string(Base::Base32, false);
Path linkPath = linksDir + "/" + hash.to_string(HashFormat::Base32, false);
auto stLinkOpt = maybeLstat(linkPath);
/* Maybe delete the link, if it has been corrupted. */
+2 -5
View File
@@ -28,11 +28,8 @@ 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(Base::Base32, true) + ";"
+ std::to_string(narSize) + ";"
+ concatStringsSep(",", store.printStorePathSet(references));
return "1;" + store.printStorePath(path) + ";" + narHash.to_string(HashFormat::Base32, true) + ";"
+ std::to_string(narSize) + ";" + concatStringsSep(",", store.printStorePathSet(references));
}
+1 -1
View File
@@ -47,7 +47,7 @@ StorePath::StorePath(std::string_view _baseName)
}
StorePath::StorePath(const Hash & hash, std::string_view _name)
: baseName((hash.to_string(Base::Base32, false) + "-").append(std::string(_name)))
: baseName((hash.to_string(HashFormat::Base32, false) + "-").append(std::string(_name)))
{
assert(hash.base32Len() == HASH_PART_LEN);
checkName(baseName, name());
+3 -1
View File
@@ -39,7 +39,9 @@ struct DrvOutput {
std::string to_string() const;
std::string strHash() const
{ return drvHash.to_string(Base::Base16, true); }
{
return drvHash.to_string(HashFormat::Base16, true);
}
static DrvOutput parse(const std::string &);
+1 -1
View File
@@ -421,7 +421,7 @@ try {
WorkerProto::Op::AddToStoreNar,
printStorePath(info.path),
(info.deriver ? printStorePath(*info.deriver) : ""),
info.narHash.to_string(Base::Base16, false),
info.narHash.to_string(HashFormat::Base16, false),
WorkerProto::write(*conn, info.references),
info.registrationTime,
info.narSize,
+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(Base::Base32, true);
co_yield info.narHash.to_string(HashFormat::Base32, true);
co_yield renderContentAddress(info.ca);
co_yield info.sigs;
}
+20 -14
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(Base::Base16, true), name);
return makeStorePath(type, hash.to_string(HashFormat::Base16, true), name);
}
@@ -215,12 +215,15 @@ StorePath Store::makeFixedOutputPath(std::string_view name, const FixedOutputInf
throw Error("fixed output derivation '%s' is not allowed to refer to other store paths.\nYou may need to use the 'unsafeDiscardReferences' derivation attribute, see the manual for more details.",
name);
}
return makeStorePath("output:out",
hashString(HashType::SHA256,
"fixed:out:"
+ makeFileIngestionPrefix(info.method)
+ info.hash.to_string(Base::Base16, true) + ":"),
name);
return makeStorePath(
"output:out",
hashString(
HashType::SHA256,
"fixed:out:" + makeFileIngestionPrefix(info.method)
+ info.hash.to_string(HashFormat::Base16, true) + ":"
),
name
);
}
}
@@ -801,7 +804,7 @@ try {
auto info = TRY_AWAIT(queryPathInfo(i));
if (showHash) {
s += info->narHash.to_string(Base::Base16, false) + "\n";
s += info->narHash.to_string(HashFormat::Base16, false) + "\n";
s += fmt("%1%\n", info->narSize);
}
@@ -852,10 +855,13 @@ try {
co_return result::current_exception();
}
kj::Promise<Result<JSON>> Store::pathInfoToJSON(const StorePathSet & storePaths,
bool includeImpureInfo, bool showClosureSize,
Base hashBase,
AllowInvalidFlag allowInvalid)
kj::Promise<Result<JSON>> Store::pathInfoToJSON(
const StorePathSet & storePaths,
bool includeImpureInfo,
bool showClosureSize,
HashFormat hashFormat,
AllowInvalidFlag allowInvalid
)
try {
JSON::array_t jsonList = JSON::array();
@@ -867,7 +873,7 @@ try {
jsonPath["path"] = printStorePath(info->path);
jsonPath["valid"] = true;
jsonPath["narHash"] = info->narHash.to_string(hashBase, true);
jsonPath["narHash"] = info->narHash.to_string(hashFormat, true);
jsonPath["narSize"] = info->narSize;
{
@@ -909,7 +915,7 @@ try {
if (!narInfo->url.empty())
jsonPath["url"] = narInfo->url;
if (narInfo->fileHash)
jsonPath["downloadHash"] = narInfo->fileHash->to_string(hashBase, true);
jsonPath["downloadHash"] = narInfo->fileHash->to_string(hashFormat, true);
if (narInfo->fileSize)
jsonPath["downloadSize"] = narInfo->fileSize;
if (showClosureSize)
+7 -4
View File
@@ -714,10 +714,13 @@ public:
* @param showClosureSize If true, the closure size of each path is
* included.
*/
kj::Promise<Result<JSON>> pathInfoToJSON(const StorePathSet & storePaths,
bool includeImpureInfo, bool showClosureSize,
Base hashBase = Base::Base32,
AllowInvalidFlag allowInvalid = DisallowInvalid);
kj::Promise<Result<JSON>> pathInfoToJSON(
const StorePathSet & storePaths,
bool includeImpureInfo,
bool showClosureSize,
HashFormat hashFormat = HashFormat::Base32,
AllowInvalidFlag allowInvalid = DisallowInvalid
);
/**
* @return the size of the closure of the specified path, that is,
+1 -1
View File
@@ -145,7 +145,7 @@ UnkeyedValidPathInfo WorkerProto::Serialise<UnkeyedValidPathInfo>::read(ReadConn
WireFormatGenerator WorkerProto::Serialise<UnkeyedValidPathInfo>::write(WriteConn conn, const UnkeyedValidPathInfo & pathInfo)
{
co_yield (pathInfo.deriver ? conn.store.printStorePath(*pathInfo.deriver) : "");
co_yield pathInfo.narHash.to_string(Base::Base16, false);
co_yield pathInfo.narHash.to_string(HashFormat::Base16, false);
co_yield WorkerProto::write(conn, pathInfo.references);
co_yield pathInfo.registrationTime;
co_yield pathInfo.narSize;
+10 -11
View File
@@ -82,26 +82,25 @@ static std::string printHash16(const Hash & hash)
std::string printHash16or32(const Hash & hash)
{
return hash.to_string(hash.type == HashType::MD5 ? Base::Base16 : Base::Base32, false);
return hash.to_string(hash.type == HashType::MD5 ? HashFormat::Base16 : HashFormat::Base32, false);
}
std::string Hash::to_string(Base base, bool includeType) const
std::string Hash::to_string(HashFormat format, bool includeType) const
{
std::string s;
if (base == Base::SRI || includeType) {
if (format == HashFormat::SRI || includeType) {
s += printHashType(type);
s += base == Base::SRI ? '-' : ':';
s += format == HashFormat::SRI ? '-' : ':';
}
switch (base) {
case Base::Base16:
switch (format) {
case HashFormat::Base16:
s += printHash16(*this);
break;
case Base::Base32:
case HashFormat::Base32:
s += base32EncodeStr(std::string_view(charptr_cast<const char *>(hash), hashSize));
break;
case Base::Base64:
case Base::SRI:
case HashFormat::Base64:
case HashFormat::SRI:
s += base64Encode(std::string_view(charptr_cast<const char *>(hash), hashSize));
break;
}
@@ -219,7 +218,7 @@ Hash newHashAllowEmpty(std::string_view hashStr, std::optional<HashType> ht)
if (!ht)
throw BadHash("empty hash requires explicit hash type");
Hash h(*ht);
printTaggedWarning("found empty hash, assuming '%s'", h.to_string(Base::SRI, true));
printTaggedWarning("found empty hash, assuming '%s'", h.to_string(HashFormat::SRI, true));
return h;
} else
return Hash::parseAny(hashStr, ht);
+18 -5
View File
@@ -32,8 +32,21 @@ const int sha512HashSize = 64;
extern std::set<std::string> hashTypes;
enum class Base : int { Base64, Base32, Base16, SRI };
/**
* @brief Enumeration representing the hash formats.
*/
enum class HashFormat : int {
/// @brief Base 64 encoding.
/// @see [IETF RFC 4648, section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4).
Base64,
/// @brief Nix-specific base-32 encoding. @see base32Chars
Base32,
/// @brief Lowercase hexadecimal encoding. @see base16Chars
Base16,
/// @brief "<hash algo>:<Base 64 hash>", format of the SRI integrity attribute.
/// @see W3C recommendation [Subresource Intergrity](https://www.w3.org/TR/SRI/).
SRI
};
struct Hash
{
@@ -123,16 +136,16 @@ public:
* or base-64. By default, this is prefixed by the hash type
* (e.g. "sha256:").
*/
std::string to_string(Base base, bool includeType) const;
std::string to_string(HashFormat format, bool includeType) const;
std::string gitRev() const
{
return to_string(Base::Base16, false);
return to_string(HashFormat::Base16, false);
}
std::string gitShortRev() const
{
return std::string(to_string(Base::Base16, false), 0, 7);
return std::string(to_string(HashFormat::Base16, false), 0, 7);
}
static Hash dummy;
+8 -6
View File
@@ -238,7 +238,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
j["url"] = flake.lockedRef.to_string(); // FIXME: rename to lockedUrl
j["locked"] = fetchers::attrsToJSON(flake.lockedRef.toAttrs());
if (auto rev = flake.lockedRef.input.getRev())
j["revision"] = rev->to_string(Base::Base16, false);
j["revision"] = rev->to_string(HashFormat::Base16, false);
if (auto dirtyRev = fetchers::maybeGetStrAttr(flake.lockedRef.toAttrs(), "dirtyRev"))
j["dirtyRevision"] = *dirtyRev;
if (auto revCount = flake.lockedRef.input.getRevCount())
@@ -264,8 +264,8 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
store->printStorePath(flake.sourceInfo->storePath));
if (auto rev = flake.lockedRef.input.getRev())
logger->cout(
ANSI_BOLD "Revision:" ANSI_NORMAL " %s",
rev->to_string(Base::Base16, false));
ANSI_BOLD "Revision:" ANSI_NORMAL " %s", rev->to_string(HashFormat::Base16, false)
);
if (auto dirtyRev = fetchers::maybeGetStrAttr(flake.lockedRef.toAttrs(), "dirtyRev"))
logger->cout(
ANSI_BOLD "Revision:" ANSI_NORMAL " %s",
@@ -1532,13 +1532,15 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON
if (json) {
auto res = JSON::object();
res["storePath"] = store->printStorePath(tree.storePath);
res["hash"] = hash.to_string(Base::SRI, true);
res["hash"] = hash.to_string(HashFormat::SRI, true);
logger->cout(res.dump());
} else {
notice("Downloaded '%s' to '%s' (hash '%s').",
notice(
"Downloaded '%s' to '%s' (hash '%s').",
lockedRef.to_string(),
store->printStorePath(tree.storePath),
hash.to_string(Base::SRI, true));
hash.to_string(HashFormat::SRI, true)
);
}
}
};
+62 -59
View File
@@ -9,39 +9,39 @@
namespace nix {
struct CmdHashBase : Command
struct CmdHashFormat : Command
{
FileIngestionMethod mode;
Base base = Base::SRI;
HashFormat format = HashFormat::SRI;
bool truncate = false;
HashType ht = HashType::SHA256;
std::vector<std::string> paths;
std::optional<std::string> modulus;
CmdHashBase(FileIngestionMethod mode) : mode(mode)
CmdHashFormat(FileIngestionMethod mode) : mode(mode)
{
addFlag({
.longName = "sri",
.description = "Print the hash in SRI format.",
.handler = {&base, Base::SRI},
.handler = {&format, HashFormat::SRI},
});
addFlag({
.longName = "base64",
.description = "Print the hash in base-64 format.",
.handler = {&base, Base::Base64},
.handler = {&format, HashFormat::Base64},
});
addFlag({
.longName = "base32",
.description = "Print the hash in base-32 (Nix-specific) format.",
.handler = {&base, Base::Base32},
.handler = {&format, HashFormat::Base32},
});
addFlag({
.longName = "base16",
.description = "Print the hash in base-16 format.",
.handler = {&base, Base::Base16},
.handler = {&format, HashFormat::Base16},
});
addFlag(Flag::mkHashTypeFlag("type", &ht));
@@ -91,18 +91,18 @@ struct CmdHashBase : Command
? computeHashModulo(ht, *modulus, source).first
: hashSource(ht, source).first;
if (truncate && h.hashSize > 20) h = compressHash(h, 20);
logger->cout(h.to_string(base, base == Base::SRI));
logger->cout(h.to_string(format, format == HashFormat::SRI));
}
}
};
struct CmdToBase : Command
struct CmdToHashFormat : Command
{
Base base;
HashFormat format;
std::optional<HashType> ht;
std::vector<std::string> args;
CmdToBase(Base base) : base(base)
CmdToHashFormat(HashFormat format) : format(format)
{
addFlag(Flag::mkHashTypeOptFlag("type", &ht));
expectArgs("strings", &args);
@@ -110,17 +110,19 @@ struct CmdToBase : Command
std::string description() override
{
return fmt("convert a hash to %s representation",
base == Base::Base16 ? "base-16" :
base == Base::Base32 ? "base-32" :
base == Base::Base64 ? "base-64" :
"SRI");
return fmt(
"convert a hash to %s representation",
format == HashFormat::Base16 ? "base-16"
: format == HashFormat::Base32 ? "base-32"
: format == HashFormat::Base64 ? "base-64"
: "SRI"
);
}
void run() override
{
for (auto s : args)
logger->cout(Hash::parseAny(s, ht).to_string(base, base == Base::SRI));
logger->cout(Hash::parseAny(s, ht).to_string(format, format == HashFormat::SRI));
}
};
@@ -128,23 +130,23 @@ struct CmdHash : MultiCommand
{
CmdHash()
: MultiCommand({
{"file",
[](auto & aio) {
return make_ref<MixAio<CmdHashBase>>(aio, FileIngestionMethod::Flat);
;
}},
{"path",
[](auto & aio) {
return make_ref<MixAio<CmdHashBase>>(aio, FileIngestionMethod::Recursive);
}},
{"to-base16",
[](auto & aio) { return make_ref<MixAio<CmdToBase>>(aio, Base::Base16); }},
{"to-base32",
[](auto & aio) { return make_ref<MixAio<CmdToBase>>(aio, Base::Base32); }},
{"to-base64",
[](auto & aio) { return make_ref<MixAio<CmdToBase>>(aio, Base::Base64); }},
{"to-sri", [](auto & aio) { return make_ref<MixAio<CmdToBase>>(aio, Base::SRI); }},
})
{"file",
[](auto & aio) {
return make_ref<MixAio<CmdHashFormat>>(aio, FileIngestionMethod::Flat);
;
}},
{"path",
[](auto & aio) {
return make_ref<MixAio<CmdHashFormat>>(aio, FileIngestionMethod::Recursive);
}},
{"to-base16",
[](auto & aio) { return make_ref<MixAio<CmdToHashFormat>>(aio, HashFormat::Base16); }},
{"to-base32",
[](auto & aio) { return make_ref<MixAio<CmdToHashFormat>>(aio, HashFormat::Base32); }},
{"to-base64",
[](auto & aio) { return make_ref<MixAio<CmdToHashFormat>>(aio, HashFormat::Base64); }},
{"to-sri", [](auto & aio) { return make_ref<MixAio<CmdToHashFormat>>(aio, HashFormat::SRI); }},
})
{
}
@@ -173,7 +175,7 @@ static int compatNixHash(AsyncIoRoot & aio, std::string programName, Strings arg
{
std::optional<HashType> ht;
bool flat = false;
Base base = Base::Base16;
HashFormat format = HashFormat::Base16;
bool truncate = false;
enum { opHash, opTo } op = opHash;
std::vector<std::string> ss;
@@ -184,50 +186,51 @@ static int compatNixHash(AsyncIoRoot & aio, std::string programName, Strings arg
else if (*arg == "--version")
printVersion("nix-hash");
else if (*arg == "--flat") flat = true;
else if (*arg == "--base16") base = Base::Base16;
else if (*arg == "--base32") base = Base::Base32;
else if (*arg == "--base64") base = Base::Base64;
else if (*arg == "--sri") base = Base::SRI;
else if (*arg == "--truncate") truncate = true;
else if (*arg == "--type") {
else if (*arg == "--base16") {
format = HashFormat::Base16;
} else if (*arg == "--base32") {
format = HashFormat::Base32;
} else if (*arg == "--base64") {
format = HashFormat::Base64;
} else if (*arg == "--sri") {
format = HashFormat::SRI;
} else if (*arg == "--truncate") {
truncate = true;
} else if (*arg == "--type") {
std::string s = getArg(*arg, arg, end);
ht = parseHashType(s);
}
else if (*arg == "--to-base16") {
} else if (*arg == "--to-base16") {
op = opTo;
base = Base::Base16;
}
else if (*arg == "--to-base32") {
format = HashFormat::Base16;
} else if (*arg == "--to-base32") {
op = opTo;
base = Base::Base32;
}
else if (*arg == "--to-base64") {
format = HashFormat::Base32;
} else if (*arg == "--to-base64") {
op = opTo;
base = Base::Base64;
}
else if (*arg == "--to-sri") {
format = HashFormat::Base64;
} else if (*arg == "--to-sri") {
op = opTo;
base = Base::SRI;
}
else if (*arg != "" && arg->at(0) == '-')
format = HashFormat::SRI;
} else if (*arg != "" && arg->at(0) == '-') {
return false;
else
} else {
ss.push_back(*arg);
}
return true;
}).parseCmdline(argv);
if (op == opHash) {
MixAio<CmdHashBase> cmd(aio, flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive);
MixAio<CmdHashFormat> cmd(aio, flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive);
if (!ht.has_value()) ht = HashType::MD5;
cmd.ht = ht.value();
cmd.base = base;
cmd.format = format;
cmd.truncate = truncate;
cmd.paths = ss;
cmd.run();
}
else {
MixAio<CmdToBase> cmd(aio, base);
MixAio<CmdToHashFormat> cmd(aio, format);
cmd.args = ss;
if (ht.has_value()) cmd.ht = ht;
cmd.run();
+10 -4
View File
@@ -91,10 +91,16 @@ struct CmdPathInfo : StorePathsCommand, MixJSON
pathLen = std::max(pathLen, store->printStorePath(storePath).size());
if (json) {
std::cout << aio().blockOn(store->pathInfoToJSON(
// FIXME: preserve order?
StorePathSet(storePaths.begin(), storePaths.end()),
true, showClosureSize, Base::SRI, AllowInvalid)).dump();
std::cout << aio()
.blockOn(store->pathInfoToJSON(
// FIXME: preserve order?
StorePathSet(storePaths.begin(), storePaths.end()),
true,
showClosureSize,
HashFormat::SRI,
AllowInvalid
))
.dump();
}
else {
+5 -3
View File
@@ -341,13 +341,15 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON
if (json) {
auto res = JSON::object();
res["storePath"] = store->printStorePath(storePath);
res["hash"] = hash.to_string(Base::SRI, true);
res["hash"] = hash.to_string(HashFormat::SRI, true);
logger->cout(res.dump());
} else {
notice("Downloaded '%s' to '%s' (hash '%s').",
notice(
"Downloaded '%s' to '%s' (hash '%s').",
url,
store->printStorePath(storePath),
hash.to_string(Base::SRI, true));
hash.to_string(HashFormat::SRI, true)
);
}
}
};
+5 -3
View File
@@ -114,10 +114,12 @@ struct CmdVerify : StorePathsCommand
ACTIVITY_RESULT_SYNC(
aio, act2, resCorruptedPath, store->printStorePath(info->path)
);
printError("path '%s' was modified! expected hash '%s', got '%s'",
printError(
"path '%s' was modified! expected hash '%s', got '%s'",
store->printStorePath(info->path),
info->narHash.to_string(Base::SRI, true),
hash.first.to_string(Base::SRI, true));
info->narHash.to_string(HashFormat::SRI, true),
hash.first.to_string(HashFormat::SRI, true)
);
}
}
+6 -6
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(Base::Base32, true);
auto s = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)))->narHash.to_string(HashFormat::Base32, true);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -118,7 +118,7 @@ SV * queryPathInfo(char * path, int base32)
XPUSHs(&PL_sv_undef);
else
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0)));
auto s = info->narHash.to_string(base32 ? Base::Base32 : Base::Base16, true);
auto s = info->narHash.to_string(base32 ? HashFormat::Base32 : HashFormat::Base16, true);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
mXPUSHi(info->registrationTime);
mXPUSHi(info->narSize);
@@ -210,7 +210,7 @@ SV * hashPath(char * algo, int base32, char * path)
PPCODE:
try {
Hash h = hashPath(parseHashType(algo), path).first;
auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
auto s = h.to_string(base32 ? HashFormat::Base32 : HashFormat::Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -221,7 +221,7 @@ SV * hashFile(char * algo, int base32, char * path)
PPCODE:
try {
Hash h = hashFile(parseHashType(algo), path);
auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
auto s = h.to_string(base32 ? HashFormat::Base32 : HashFormat::Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -232,7 +232,7 @@ SV * hashString(char * algo, int base32, char * s)
PPCODE:
try {
Hash h = hashString(parseHashType(algo), s);
auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
auto s = h.to_string(base32 ? HashFormat::Base32 : HashFormat::Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -243,7 +243,7 @@ SV * convertHash(char * algo, char * s, int toBase32)
PPCODE:
try {
auto h = Hash::parseAny(s, parseHashType(algo));
auto s = h.to_string(toBase32 ? Base::Base32 : Base::Base16, false);
auto s = h.to_string(toBase32 ? HashFormat::Base32 : HashFormat::Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
+24 -16
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(Base::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e");
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "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(Base::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72");
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "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(Base::Base16, true),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d");
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "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(Base::Base16, true),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
}
TEST(hashString, testKnownSHA256Hashes1) {
@@ -43,35 +43,43 @@ namespace nix {
auto s = "abc";
auto hash = hashString(HashType::SHA256, s);
ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
ASSERT_EQ(
hash.to_string(HashFormat::Base16, true),
"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
);
}
TEST(hashString, testKnownSHA256Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
auto hash = hashString(HashType::SHA256, s);
ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
ASSERT_EQ(
hash.to_string(HashFormat::Base16, true),
"sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
);
}
TEST(hashString, testKnownSHA512Hashes1) {
// values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abc";
auto hash = hashString(HashType::SHA512, s);
ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9"
"7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd"
"454d4423643ce80e2a9ac94fa54ca49f");
ASSERT_EQ(
hash.to_string(HashFormat::Base16, true),
"sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9"
"7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd"
"454d4423643ce80e2a9ac94fa54ca49f"
);
}
TEST(hashString, testKnownSHA512Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
auto hash = hashString(HashType::SHA512, s);
ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1"
"7299aeadb6889018501d289e4900f7e4331b99dec4b5433a"
"c7d329eeb6dd26545e96e55b874be909");
ASSERT_EQ(
hash.to_string(HashFormat::Base16, true),
"sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1"
"7299aeadb6889018501d289e4900f7e4331b99dec4b5433a"
"c7d329eeb6dd26545e96e55b874be909"
);
}
}