From b482ebbbc8b42e6730983b0a79e1982cade15435 Mon Sep 17 00:00:00 2001 From: Tom Hubrecht Date: Mon, 5 Jan 2026 11:16:37 +0100 Subject: [PATCH] treewide: Rename Base to HashFormat Co-authored-by: Yueh-Shun Li `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 --- lix/legacy/build-remote.cc | 2 +- lix/legacy/nix-store.cc | 10 +- lix/libexpr/eval-cache.cc | 2 +- lix/libexpr/primops.cc | 4 +- lix/libexpr/primops/fetchTree.cc | 18 +-- lix/libfetchers/fetchers.cc | 12 +- lix/libfetchers/git.cc | 9 +- lix/libfetchers/github.cc | 30 +++-- lix/libfetchers/mercurial.cc | 10 +- lix/libfetchers/tarball.cc | 2 +- lix/libstore/binary-cache-store.cc | 16 +-- lix/libstore/build/local-derivation-goal.cc | 6 +- lix/libstore/builtins/fetchurl.cc | 3 +- lix/libstore/content-address.cc | 20 ++-- lix/libstore/derivations.cc | 31 ++--- lix/libstore/export-import.cc | 8 +- lix/libstore/gc.cc | 2 +- lix/libstore/legacy-ssh-store.cc | 2 +- lix/libstore/local-store.cc | 27 +++-- lix/libstore/nar-info-disk-cache.cc | 4 +- lix/libstore/nar-info.cc | 4 +- lix/libstore/optimise-store.cc | 4 +- lix/libstore/path-info.cc | 7 +- lix/libstore/path.cc | 2 +- lix/libstore/realisation.hh | 4 +- lix/libstore/remote-store.cc | 2 +- lix/libstore/serve-protocol.cc | 2 +- lix/libstore/store-api.cc | 34 +++--- lix/libstore/store-api.hh | 11 +- lix/libstore/worker-protocol.cc | 2 +- lix/libutil/hash.cc | 21 ++-- lix/libutil/hash.hh | 23 +++- lix/nix/flake.cc | 14 ++- lix/nix/hash.cc | 121 ++++++++++---------- lix/nix/path-info.cc | 14 ++- lix/nix/prefetch.cc | 8 +- lix/nix/verify.cc | 8 +- perl/lib/Nix/Store.xs | 12 +- tests/unit/libutil/hash.cc | 40 ++++--- 39 files changed, 320 insertions(+), 231 deletions(-) diff --git a/lix/legacy/build-remote.cc b/lix/legacy/build-remote.cc index 1b7786ca8..63203093f 100644 --- a/lix/legacy/build-remote.cc +++ b/lix/legacy/build-remote.cc @@ -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); } diff --git a/lix/legacy/nix-store.cc b/lix/legacy/nix-store.cc index 56f68ccb1..9d9c3549e 100644 --- a/lix/legacy/nix-store.cc +++ b/lix/legacy/nix-store.cc @@ -467,7 +467,7 @@ opQuery(std::shared_ptr 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, 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; } } diff --git a/lix/libexpr/eval-cache.cc b/lix/libexpr/eval-cache.cc index aa8937d5b..474a3a75b 100644 --- a/lix/libexpr/eval-cache.cc +++ b/lix/libexpr/eval-cache.cc @@ -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(); diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index 1c196ace3..51d8106a7 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -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 diff --git a/lix/libexpr/primops/fetchTree.cc b/lix/libexpr/primops/fetchTree.cc index 49b8ebd90..55935fba8 100644 --- a/lix/libexpr/primops/fetchTree.cc +++ b/lix/libexpr/primops/fetchTree.cc @@ -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( - "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( + "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(); } } diff --git a/lix/libfetchers/fetchers.cc b/lix/libfetchers/fetchers.cc index 30c9ce47b..3ccde2bba 100644 --- a/lix/libfetchers/fetchers.cc +++ b/lix/libfetchers/fetchers.cc @@ -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()) { diff --git a/lix/libfetchers/git.cc b/lix/libfetchers/git.cc index 7cc655149..e40e2e4f0 100644 --- a/lix/libfetchers/git.cc +++ b/lix/libfetchers/git.cc @@ -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) { 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 = [&]() diff --git a/lix/libfetchers/github.cc b/lix/libfetchers/github.cc index 970e1e345..4b36c066c 100644 --- a/lix/libfetchers/github.cc +++ b/lix/libfetchers/github.cc @@ -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 }; diff --git a/lix/libfetchers/mercurial.cc b/lix/libfetchers/mercurial.cc index 96d256145..9b5769261 100644 --- a/lix/libfetchers/mercurial.cc +++ b/lix/libfetchers/mercurial.cc @@ -250,7 +250,10 @@ struct MercurialInputScheme : InputScheme auto checkHashType = [&](const std::optional & 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. */ diff --git a/lix/libfetchers/tarball.cc b/lix/libfetchers/tarball.cc index e602716f9..2436ba8f0 100644 --- a/lix/libfetchers/tarball.cc +++ b/lix/libfetchers/tarball.cc @@ -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; } diff --git a/lix/libstore/binary-cache-store.cc b/lix/libstore/binary-cache-store.cc index 3f16626d0..6e14cf4ad 100644 --- a/lix/libstore/binary-cache-store.cc +++ b/lix/libstore/binary-cache-store.cc @@ -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(now2 - now1).count(); printMsg(lvlTalkative, "copying path '%1%' (%2% bytes, compressed %3$.1f%% in %4% ms) to binary cache", diff --git a/lix/libstore/build/local-derivation-goal.cc b/lix/libstore/build/local-derivation-goal.cc index ea194e41c..f84071a4f 100644 --- a/lix/libstore/build/local-derivation-goal.cc +++ b/lix/libstore/build/local-derivation-goal.cc @@ -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) )); diff --git a/lix/libstore/builtins/fetchurl.cc b/lix/libstore/builtins/fetchurl.cc index 8642713d7..7e123ad30 100644 --- a/lix/libstore/builtins/fetchurl.cc +++ b/lix/libstore/builtins/fetchurl.cc @@ -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) { diff --git a/lix/libstore/content-address.cc b/lix/libstore/content-address.cc index 29b621e13..b58a554b2 100644 --- a/lix/libstore/content-address.cc +++ b/lix/libstore/content-address.cc @@ -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); } /** diff --git a/lix/libstore/derivations.cc b/lix/libstore/derivations.cc index 11d2dd1f4..ca04385f1 100644 --- a/lix/libstore/derivations.cc +++ b/lix/libstore/derivations.cc @@ -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 outputHashes; for (const auto & i : drv.outputs) { auto & dof = std::get(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 { + [&](const DerivationOutput::InputAddressed & doi) + -> std::tuple { return {store.printStorePath(doi.path), "", ""}; }, - [&](const DerivationOutput::CAFixed & dof - ) -> std::tuple { + [&](const DerivationOutput::CAFixed & dof) + -> std::tuple { 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); diff --git a/lix/libstore/export-import.cc b/lix/libstore/export-import.cc index 34bf587be..2ea3c1638 100644 --- a/lix/libstore/export-import.cc +++ b/lix/libstore/export-import.cc @@ -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 diff --git a/lix/libstore/gc.cc b/lix/libstore/gc.cc index 28c032c35..37d51a7d3 100644 --- a/lix/libstore/gc.cc +++ b/lix/libstore/gc.cc @@ -54,7 +54,7 @@ static void makeSymlink(const Path & link, const Path & target) kj::Promise> 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()}; diff --git a/lix/libstore/legacy-ssh-store.cc b/lix/libstore/legacy-ssh-store.cc index db98b026e..7ea1a69b3 100644 --- a/lix/libstore/legacy-ssh-store.cc +++ b/lix/libstore/legacy-ssh-store.cc @@ -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, diff --git a/lix/libstore/local-store.cc b/lix/libstore/local-store.cc index f01b4efa1..1c3b72088 100644 --- a/lix/libstore/local-store.cc +++ b/lix/libstore/local-store.cc @@ -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 { diff --git a/lix/libstore/nar-info-disk-cache.cc b/lix/libstore/nar-info-disk-cache.cc index 0e3bce2b1..ee5a4f138 100644 --- a/lix/libstore/nar-info-disk-cache.cc +++ b/lix/libstore/nar-info-disk-cache.cc @@ -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) diff --git a/lix/libstore/nar-info.cc b/lix/libstore/nar-info.cc index 00da9ce61..5524ffce4 100644 --- a/lix/libstore/nar-info.cc +++ b/lix/libstore/nar-info.cc @@ -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"; diff --git a/lix/libstore/optimise-store.cc b/lix/libstore/optimise-store.cc index 3429fbf2d..66c6e0cd8 100644 --- a/lix/libstore/optimise-store.cc +++ b/lix/libstore/optimise-store.cc @@ -156,10 +156,10 @@ std::optional 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. */ diff --git a/lix/libstore/path-info.cc b/lix/libstore/path-info.cc index d0b0aacd5..c39733fe3 100644 --- a/lix/libstore/path-info.cc +++ b/lix/libstore/path-info.cc @@ -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)); } diff --git a/lix/libstore/path.cc b/lix/libstore/path.cc index f99710768..4e7a4c5e1 100644 --- a/lix/libstore/path.cc +++ b/lix/libstore/path.cc @@ -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()); diff --git a/lix/libstore/realisation.hh b/lix/libstore/realisation.hh index f263c6494..1a8cc9097 100644 --- a/lix/libstore/realisation.hh +++ b/lix/libstore/realisation.hh @@ -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 &); diff --git a/lix/libstore/remote-store.cc b/lix/libstore/remote-store.cc index 317c51d67..b783d1627 100644 --- a/lix/libstore/remote-store.cc +++ b/lix/libstore/remote-store.cc @@ -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, diff --git a/lix/libstore/serve-protocol.cc b/lix/libstore/serve-protocol.cc index 4abea4541..3f8d962ce 100644 --- a/lix/libstore/serve-protocol.cc +++ b/lix/libstore/serve-protocol.cc @@ -87,7 +87,7 @@ WireFormatGenerator ServeProto::Serialise::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; } diff --git a/lix/libstore/store-api.cc b/lix/libstore/store-api.cc index e34002e12..652a14a99 100644 --- a/lix/libstore/store-api.cc +++ b/lix/libstore/store-api.cc @@ -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> Store::pathInfoToJSON(const StorePathSet & storePaths, - bool includeImpureInfo, bool showClosureSize, - Base hashBase, - AllowInvalidFlag allowInvalid) +kj::Promise> 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) diff --git a/lix/libstore/store-api.hh b/lix/libstore/store-api.hh index 0ed598700..b2348841b 100644 --- a/lix/libstore/store-api.hh +++ b/lix/libstore/store-api.hh @@ -714,10 +714,13 @@ public: * @param showClosureSize If true, the closure size of each path is * included. */ - kj::Promise> pathInfoToJSON(const StorePathSet & storePaths, - bool includeImpureInfo, bool showClosureSize, - Base hashBase = Base::Base32, - AllowInvalidFlag allowInvalid = DisallowInvalid); + kj::Promise> 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, diff --git a/lix/libstore/worker-protocol.cc b/lix/libstore/worker-protocol.cc index 8b1ba4127..4a85bce21 100644 --- a/lix/libstore/worker-protocol.cc +++ b/lix/libstore/worker-protocol.cc @@ -145,7 +145,7 @@ UnkeyedValidPathInfo WorkerProto::Serialise::read(ReadConn WireFormatGenerator WorkerProto::Serialise::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; diff --git a/lix/libutil/hash.cc b/lix/libutil/hash.cc index ea792c932..fde37d2a7 100644 --- a/lix/libutil/hash.cc +++ b/lix/libutil/hash.cc @@ -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(hash), hashSize)); break; - case Base::Base64: - case Base::SRI: + case HashFormat::Base64: + case HashFormat::SRI: s += base64Encode(std::string_view(charptr_cast(hash), hashSize)); break; } @@ -219,7 +218,7 @@ Hash newHashAllowEmpty(std::string_view hashStr, std::optional 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); diff --git a/lix/libutil/hash.hh b/lix/libutil/hash.hh index 79858fd99..1a1858a59 100644 --- a/lix/libutil/hash.hh +++ b/lix/libutil/hash.hh @@ -32,8 +32,21 @@ const int sha512HashSize = 64; extern std::set 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 ":", 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; diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index 757d22258..c299516f8 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -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) + ); } } }; diff --git a/lix/nix/hash.cc b/lix/nix/hash.cc index 6cb4a1573..402efd6f4 100644 --- a/lix/nix/hash.cc +++ b/lix/nix/hash.cc @@ -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 paths; std::optional 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 ht; std::vector 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>(aio, FileIngestionMethod::Flat); - ; - }}, - {"path", - [](auto & aio) { - return make_ref>(aio, FileIngestionMethod::Recursive); - }}, - {"to-base16", - [](auto & aio) { return make_ref>(aio, Base::Base16); }}, - {"to-base32", - [](auto & aio) { return make_ref>(aio, Base::Base32); }}, - {"to-base64", - [](auto & aio) { return make_ref>(aio, Base::Base64); }}, - {"to-sri", [](auto & aio) { return make_ref>(aio, Base::SRI); }}, - }) + {"file", + [](auto & aio) { + return make_ref>(aio, FileIngestionMethod::Flat); + ; + }}, + {"path", + [](auto & aio) { + return make_ref>(aio, FileIngestionMethod::Recursive); + }}, + {"to-base16", + [](auto & aio) { return make_ref>(aio, HashFormat::Base16); }}, + {"to-base32", + [](auto & aio) { return make_ref>(aio, HashFormat::Base32); }}, + {"to-base64", + [](auto & aio) { return make_ref>(aio, HashFormat::Base64); }}, + {"to-sri", [](auto & aio) { return make_ref>(aio, HashFormat::SRI); }}, + }) { } @@ -173,7 +175,7 @@ static int compatNixHash(AsyncIoRoot & aio, std::string programName, Strings arg { std::optional ht; bool flat = false; - Base base = Base::Base16; + HashFormat format = HashFormat::Base16; bool truncate = false; enum { opHash, opTo } op = opHash; std::vector 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 cmd(aio, flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive); + MixAio 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 cmd(aio, base); + MixAio cmd(aio, format); cmd.args = ss; if (ht.has_value()) cmd.ht = ht; cmd.run(); diff --git a/lix/nix/path-info.cc b/lix/nix/path-info.cc index c258f1050..4ee1183a2 100644 --- a/lix/nix/path-info.cc +++ b/lix/nix/path-info.cc @@ -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 { diff --git a/lix/nix/prefetch.cc b/lix/nix/prefetch.cc index b1af28bab..a3161263d 100644 --- a/lix/nix/prefetch.cc +++ b/lix/nix/prefetch.cc @@ -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) + ); } } }; diff --git a/lix/nix/verify.cc b/lix/nix/verify.cc index 7a5b6c051..24c6c6b8b 100644 --- a/lix/nix/verify.cc +++ b/lix/nix/verify.cc @@ -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) + ); } } diff --git a/perl/lib/Nix/Store.xs b/perl/lib/Nix/Store.xs index dfdd64d28..6f85e5972 100644 --- a/perl/lib/Nix/Store.xs +++ b/perl/lib/Nix/Store.xs @@ -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()); diff --git a/tests/unit/libutil/hash.cc b/tests/unit/libutil/hash.cc index 4f8994935..f1bf4e3a4 100644 --- a/tests/unit/libutil/hash.cc +++ b/tests/unit/libutil/hash.cc @@ -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" + ); } }