Merge changes I526cceed,Ia4e2f1fa,I22e66972,I9fbd55a9,Ifca22e44 into main

* changes:
  sqlite: add a Use::fromStrNullable
  util: implement charptr_cast
  tree-wide: fix a pile of lints
  refactor: make HashType and Base enum classes for type safety
  build: integrate clang-tidy into CI
This commit is contained in:
jade 2024-08-08 22:43:10 +00:00 committed by Gerrit Code Review
commit 757041c3e7
83 changed files with 552 additions and 357 deletions

View file

@ -282,6 +282,10 @@
# cheaper x86_64-linux compute in CI. # cheaper x86_64-linux compute in CI.
# It is clangStdenv because clang's sanitizers are nicer. # It is clangStdenv because clang's sanitizers are nicer.
asanBuild = self.packages.x86_64-linux.nix-clangStdenv.override { asanBuild = self.packages.x86_64-linux.nix-clangStdenv.override {
# Improve caching of non-code changes by not changing the
# derivation name every single time, since this will never be seen
# by users anyway.
versionSuffix = "";
sanitize = [ sanitize = [
"address" "address"
"undefined" "undefined"
@ -310,6 +314,17 @@
touch $out touch $out
''; '';
# clang-tidy run against the Lix codebase using the Lix clang-tidy plugin
clang-tidy =
let
nixpkgs = nixpkgsFor.x86_64-linux.native;
inherit (nixpkgs) pkgs;
in
pkgs.callPackage ./package.nix {
versionSuffix = "";
lintInsteadOfBuild = true;
};
# Make sure that nix-env still produces the exact same result # Make sure that nix-env still produces the exact same result
# on a particular version of Nixpkgs. # on a particular version of Nixpkgs.
evalNixpkgs = evalNixpkgs =

View file

@ -28,6 +28,8 @@
libcpuid, libcpuid,
libseccomp, libseccomp,
libsodium, libsodium,
lix-clang-tidy ? null,
llvmPackages,
lsof, lsof,
lowdown, lowdown,
mdbook, mdbook,
@ -67,6 +69,8 @@
# Turn compiler warnings into errors. # Turn compiler warnings into errors.
werror ? false, werror ? false,
lintInsteadOfBuild ? false,
# Not a real argument, just the only way to approximate let-binding some # Not a real argument, just the only way to approximate let-binding some
# stuff for argument defaults. # stuff for argument defaults.
__forDefaults ? { __forDefaults ? {
@ -144,6 +148,7 @@ let
(fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts) (fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts)
]; ];
in in
assert (lintInsteadOfBuild -> lix-clang-tidy != null);
stdenv.mkDerivation (finalAttrs: { stdenv.mkDerivation (finalAttrs: {
inherit pname version; inherit pname version;
@ -156,12 +161,13 @@ stdenv.mkDerivation (finalAttrs: {
topLevelBuildFiles topLevelBuildFiles
functionalTestFiles functionalTestFiles
] ]
++ lib.optionals (!finalAttrs.dontBuild || internalApiDocs) [ ++ lib.optionals (!finalAttrs.dontBuild || internalApiDocs || lintInsteadOfBuild) [
./doc ./doc
./misc ./misc
./src ./src
./COPYING ./COPYING
] ]
++ lib.optionals lintInsteadOfBuild [ ./.clang-tidy ]
) )
); );
}; };
@ -175,7 +181,7 @@ stdenv.mkDerivation (finalAttrs: {
"doc" "doc"
]; ];
dontBuild = false; dontBuild = lintInsteadOfBuild;
mesonFlags = mesonFlags =
let let
@ -190,14 +196,15 @@ stdenv.mkDerivation (finalAttrs: {
"-Dsandbox-shell=${lib.getExe' busybox-sandbox-shell "busybox"}" "-Dsandbox-shell=${lib.getExe' busybox-sandbox-shell "busybox"}"
] ]
++ lib.optional hostPlatform.isStatic "-Denable-embedded-sandbox-shell=true" ++ lib.optional hostPlatform.isStatic "-Denable-embedded-sandbox-shell=true"
++ lib.optional (finalAttrs.dontBuild) "-Denable-build=false" ++ lib.optional (finalAttrs.dontBuild && !lintInsteadOfBuild) "-Denable-build=false"
++ lib.optional lintInsteadOfBuild "-Dlix-clang-tidy-checks-path=${lix-clang-tidy}/lib/liblix-clang-tidy.so"
++ [ ++ [
# mesonConfigurePhase automatically passes -Dauto_features=enabled, # mesonConfigurePhase automatically passes -Dauto_features=enabled,
# so we must explicitly enable or disable features that we are not passing # so we must explicitly enable or disable features that we are not passing
# dependencies for. # dependencies for.
(lib.mesonEnable "gc" enableGC) (lib.mesonEnable "gc" enableGC)
(lib.mesonEnable "internal-api-docs" internalApiDocs) (lib.mesonEnable "internal-api-docs" internalApiDocs)
(lib.mesonBool "enable-tests" finalAttrs.finalPackage.doCheck) (lib.mesonBool "enable-tests" (finalAttrs.finalPackage.doCheck || lintInsteadOfBuild))
(lib.mesonBool "enable-docs" canRunInstalled) (lib.mesonBool "enable-docs" canRunInstalled)
(lib.mesonBool "werror" werror) (lib.mesonBool "werror" werror)
] ]
@ -230,7 +237,13 @@ stdenv.mkDerivation (finalAttrs: {
] ]
++ lib.optional hostPlatform.isLinux util-linuxMinimal ++ lib.optional hostPlatform.isLinux util-linuxMinimal
++ lib.optional (!officialRelease && buildUnreleasedNotes) build-release-notes ++ lib.optional (!officialRelease && buildUnreleasedNotes) build-release-notes
++ lib.optional internalApiDocs doxygen; ++ lib.optional internalApiDocs doxygen
++ lib.optionals lintInsteadOfBuild [
# required for a wrapped clang-tidy
llvmPackages.clang-tools
# required for run-clang-tidy
llvmPackages.clang-unwrapped
];
buildInputs = buildInputs =
[ [
@ -257,7 +270,10 @@ stdenv.mkDerivation (finalAttrs: {
++ lib.optional hostPlatform.isx86_64 libcpuid ++ lib.optional hostPlatform.isx86_64 libcpuid
# There have been issues building these dependencies # There have been issues building these dependencies
++ lib.optional (hostPlatform.canExecute buildPlatform) aws-sdk-cpp-nix ++ lib.optional (hostPlatform.canExecute buildPlatform) aws-sdk-cpp-nix
++ lib.optionals (finalAttrs.dontBuild) maybePropagatedInputs; ++ lib.optionals (finalAttrs.dontBuild) maybePropagatedInputs
# I am so sorry. This is because checkInputs are required to pass
# configure, but we don't actually want to *run* the checks here.
++ lib.optionals lintInsteadOfBuild finalAttrs.checkInputs;
nativeCheckInputs = [ expect ]; nativeCheckInputs = [ expect ];
@ -315,7 +331,7 @@ stdenv.mkDerivation (finalAttrs: {
enableParallelBuilding = true; enableParallelBuilding = true;
doCheck = canRunInstalled; doCheck = canRunInstalled && !lintInsteadOfBuild;
mesonCheckFlags = [ mesonCheckFlags = [
"--suite=check" "--suite=check"
@ -327,8 +343,19 @@ stdenv.mkDerivation (finalAttrs: {
# Make sure the internal API docs are already built, because mesonInstallPhase # Make sure the internal API docs are already built, because mesonInstallPhase
# won't let us build them there. They would normally be built in buildPhase, # won't let us build them there. They would normally be built in buildPhase,
# but the internal API docs are conventionally built with doBuild = false. # but the internal API docs are conventionally built with doBuild = false.
preInstall = lib.optional internalApiDocs '' preInstall =
meson ''${mesonBuildFlags:-} compile "$installTargets" (lib.optionalString internalApiDocs ''
meson ''${mesonBuildFlags:-} compile "$installTargets"
'')
# evil, but like above, we do not want to run an actual build phase
+ lib.optionalString lintInsteadOfBuild ''
ninja clang-tidy
'';
installPhase = lib.optionalString lintInsteadOfBuild ''
runHook preInstall
touch $out
runHook postInstall
''; '';
postInstall = postInstall =
@ -396,12 +423,10 @@ stdenv.mkDerivation (finalAttrs: {
mkShell, mkShell,
bashInteractive, bashInteractive,
clang-tools,
clangbuildanalyzer, clangbuildanalyzer,
doxygen, doxygen,
glibcLocales, glibcLocales,
just, just,
llvmPackages,
nixfmt-rfc-style, nixfmt-rfc-style,
skopeo, skopeo,
xonsh, xonsh,
@ -454,7 +479,7 @@ stdenv.mkDerivation (finalAttrs: {
++ [ (lib.mesonBool "enable-pch-std" stdenv.cc.isClang) ]; ++ [ (lib.mesonBool "enable-pch-std" stdenv.cc.isClang) ];
packages = packages =
lib.optional (stdenv.cc.isClang && hostPlatform == buildPlatform) clang-tools lib.optional (stdenv.cc.isClang && hostPlatform == buildPlatform) llvmPackages.clang-tools
++ [ ++ [
# Why are we providing a bashInteractive? Well, when you run # Why are we providing a bashInteractive? Well, when you run
# `bash` from inside `nix develop`, say, because you are using it # `bash` from inside `nix develop`, say, because you are using it

View file

@ -77,7 +77,7 @@ SV * queryReferences(char * path)
SV * queryPathHash(char * path) SV * queryPathHash(char * path)
PPCODE: PPCODE:
try { try {
auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(Base32, true); auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(Base::Base32, true);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());
@ -103,7 +103,7 @@ SV * queryPathInfo(char * path, int base32)
XPUSHs(&PL_sv_undef); XPUSHs(&PL_sv_undef);
else else
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0)));
auto s = info->narHash.to_string(base32 ? Base32 : Base16, true); auto s = info->narHash.to_string(base32 ? Base::Base32 : Base::Base16, true);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
mXPUSHi(info->registrationTime); mXPUSHi(info->registrationTime);
mXPUSHi(info->narSize); mXPUSHi(info->narSize);
@ -205,7 +205,7 @@ SV * hashPath(char * algo, int base32, char * path)
PPCODE: PPCODE:
try { try {
Hash h = hashPath(parseHashType(algo), path).first; Hash h = hashPath(parseHashType(algo), path).first;
auto s = h.to_string(base32 ? Base32 : Base16, false); auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());
@ -216,7 +216,7 @@ SV * hashFile(char * algo, int base32, char * path)
PPCODE: PPCODE:
try { try {
Hash h = hashFile(parseHashType(algo), path); Hash h = hashFile(parseHashType(algo), path);
auto s = h.to_string(base32 ? Base32 : Base16, false); auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());
@ -227,7 +227,7 @@ SV * hashString(char * algo, int base32, char * s)
PPCODE: PPCODE:
try { try {
Hash h = hashString(parseHashType(algo), s); Hash h = hashString(parseHashType(algo), s);
auto s = h.to_string(base32 ? Base32 : Base16, false); auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());
@ -238,7 +238,7 @@ SV * convertHash(char * algo, char * s, int toBase32)
PPCODE: PPCODE:
try { try {
auto h = Hash::parseAny(s, parseHashType(algo)); auto h = Hash::parseAny(s, parseHashType(algo));
auto s = h.to_string(toBase32 ? Base32 : Base16, false); auto s = h.to_string(toBase32 ? Base::Base32 : Base::Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());

View file

@ -42,7 +42,7 @@ static std::string makeLockFilename(const std::string & storeUri) {
// This avoids issues with the escaped URI being very long and causing // This avoids issues with the escaped URI being very long and causing
// path too long errors, while also avoiding any possibility of collision // path too long errors, while also avoiding any possibility of collision
// caused by simple truncation. // caused by simple truncation.
auto hash = hashString(HashType::htSHA256, storeUri).to_string(Base::Base32, false); auto hash = hashString(HashType::SHA256, storeUri).to_string(Base::Base32, false);
return escapeUri(storeUri).substr(0, 48) + "-" + hash.substr(0, 16); return escapeUri(storeUri).substr(0, 48) + "-" + hash.substr(0, 16);
} }

View file

@ -246,7 +246,7 @@ StorePath ProfileManifest::build(ref<Store> store)
StringSink sink; StringSink sink;
sink << dumpPath(tempDir); sink << dumpPath(tempDir);
auto narHash = hashString(htSHA256, sink.s); auto narHash = hashString(HashType::SHA256, sink.s);
ValidPathInfo info{ ValidPathInfo info{
*store, *store,

View file

@ -96,7 +96,7 @@ static int listPossibleCallback(char * s, char *** avp)
return p; return p;
}; };
vp = check((char **) malloc(possible.size() * sizeof(char *))); vp = check(static_cast<char **>(malloc(possible.size() * sizeof(char *))));
for (auto & p : possible) for (auto & p : possible)
vp[ac++] = check(strdup(p.c_str())); vp[ac++] = check(strdup(p.c_str()));

View file

@ -50,7 +50,7 @@ struct AttrDb
Path cacheDir = getCacheDir() + "/nix/eval-cache-v5"; Path cacheDir = getCacheDir() + "/nix/eval-cache-v5";
createDirs(cacheDir); createDirs(cacheDir);
Path dbPath = cacheDir + "/" + fingerprint.to_string(Base16, false) + ".sqlite"; Path dbPath = cacheDir + "/" + fingerprint.to_string(Base::Base16, false) + ".sqlite";
state->db = SQLite(dbPath); state->db = SQLite(dbPath);
state->db.isCache(); state->db.isCache();

View file

@ -21,7 +21,6 @@
#include "flake/flakeref.hh" #include "flake/flakeref.hh"
#include <algorithm> #include <algorithm>
#include <chrono>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <cstring> #include <cstring>
@ -146,7 +145,7 @@ bool Value::isTrivial() const
&& internalType != tPrimOpApp && internalType != tPrimOpApp
&& (internalType != tThunk && (internalType != tThunk
|| (dynamic_cast<ExprAttrs *>(thunk.expr) || (dynamic_cast<ExprAttrs *>(thunk.expr)
&& ((ExprAttrs *) thunk.expr)->dynamicAttrs.empty()) && (static_cast<ExprAttrs *>(thunk.expr))->dynamicAttrs.empty())
|| dynamic_cast<ExprLambda *>(thunk.expr) || dynamic_cast<ExprLambda *>(thunk.expr)
|| dynamic_cast<ExprList *>(thunk.expr)); || dynamic_cast<ExprList *>(thunk.expr));
} }

View file

@ -937,7 +937,7 @@ Fingerprint LockedFlake::getFingerprint() const
// FIXME: as an optimization, if the flake contains a lock file // FIXME: as an optimization, if the flake contains a lock file
// and we haven't changed it, then it's sufficient to use // and we haven't changed it, then it's sufficient to use
// flake.sourceInfo.storePath for the fingerprint. // flake.sourceInfo.storePath for the fingerprint.
return hashString(htSHA256, return hashString(HashType::SHA256,
fmt("%s;%s;%d;%d;%s", fmt("%s;%s;%d;%d;%s",
flake.sourceInfo->storePath.to_string(), flake.sourceInfo->storePath.to_string(),
flake.lockedRef.subdir, flake.lockedRef.subdir,

View file

@ -346,7 +346,7 @@ void prim_importNative(EvalState & state, const PosIdx pos, Value * * args, Valu
state.error<EvalError>("could not open '%1%': %2%", path, dlerror()).debugThrow(); state.error<EvalError>("could not open '%1%': %2%", path, dlerror()).debugThrow();
dlerror(); dlerror();
ValueInitializer func = (ValueInitializer) dlsym(handle, sym.c_str()); ValueInitializer func = reinterpret_cast<ValueInitializer>(dlsym(handle, sym.c_str()));
if(!func) { if(!func) {
char *message = dlerror(); char *message = dlerror();
if (message) if (message)
@ -1336,7 +1336,7 @@ drvName, Bindings * attrs, Value & v)
state.error<EvalError>("derivation cannot be both content-addressed and impure") state.error<EvalError>("derivation cannot be both content-addressed and impure")
.atPos(v).debugThrow(); .atPos(v).debugThrow();
auto ht = parseHashTypeOpt(outputHashAlgo).value_or(htSHA256); auto ht = parseHashTypeOpt(outputHashAlgo).value_or(HashType::SHA256);
auto method = ingestionMethod.value_or(FileIngestionMethod::Recursive); auto method = ingestionMethod.value_or(FileIngestionMethod::Recursive);
for (auto & i : outputs) { for (auto & i : outputs) {
@ -1764,7 +1764,7 @@ static void prim_hashFile(EvalState & state, const PosIdx pos, Value * * args, V
auto path = realisePath(state, pos, *args[1]); auto path = realisePath(state, pos, *args[1]);
v.mkString(hashString(*ht, path.readFile()).to_string(Base16, false)); v.mkString(hashString(*ht, path.readFile()).to_string(Base::Base16, false));
} }
static RegisterPrimOp primop_hashFile({ static RegisterPrimOp primop_hashFile({
@ -2346,7 +2346,7 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
else if (n == "recursive") else if (n == "recursive")
method = FileIngestionMethod { state.forceBool(*attr.value, attr.pos, "while evaluating the `recursive` attribute passed to builtins.path") }; method = FileIngestionMethod { state.forceBool(*attr.value, attr.pos, "while evaluating the `recursive` attribute passed to builtins.path") };
else if (n == "sha256") else if (n == "sha256")
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `sha256` attribute passed to builtins.path"), htSHA256); expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `sha256` attribute passed to builtins.path"), HashType::SHA256);
else else
state.error<EvalError>( state.error<EvalError>(
"unsupported argument '%1%' to 'addPath'", "unsupported argument '%1%' to 'addPath'",
@ -2439,6 +2439,8 @@ static void prim_attrValues(EvalState & state, const PosIdx pos, Value * * args,
state.mkList(v, args[0]->attrs->size()); state.mkList(v, args[0]->attrs->size());
// FIXME: this is incredibly evil, *why*
// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
unsigned int n = 0; unsigned int n = 0;
for (auto & i : *args[0]->attrs) for (auto & i : *args[0]->attrs)
v.listElems()[n++] = (Value *) &i; v.listElems()[n++] = (Value *) &i;
@ -2452,6 +2454,7 @@ static void prim_attrValues(EvalState & state, const PosIdx pos, Value * * args,
for (unsigned int i = 0; i < n; ++i) for (unsigned int i = 0; i < n; ++i)
v.listElems()[i] = ((Attr *) v.listElems()[i])->value; v.listElems()[i] = ((Attr *) v.listElems()[i])->value;
// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
} }
static RegisterPrimOp primop_attrValues({ static RegisterPrimOp primop_attrValues({
@ -3861,7 +3864,7 @@ static void prim_hashString(EvalState & state, const PosIdx pos, Value * * args,
NixStringContext context; // discarded NixStringContext context; // discarded
auto s = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.hashString"); auto s = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.hashString");
v.mkString(hashString(*ht, s).to_string(Base16, false)); v.mkString(hashString(*ht, s).to_string(Base::Base16, false));
} }
static RegisterPrimOp primop_hashString({ static RegisterPrimOp primop_hashString({

View file

@ -31,7 +31,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
// be both a revision or a branch/tag name. // be both a revision or a branch/tag name.
auto value = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `rev` attribute passed to builtins.fetchMercurial"); auto value = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `rev` attribute passed to builtins.fetchMercurial");
if (std::regex_match(value.begin(), value.end(), revRegex)) if (std::regex_match(value.begin(), value.end(), revRegex))
rev = Hash::parseAny(value, htSHA1); rev = Hash::parseAny(value, HashType::SHA1);
else else
ref = value; ref = value;
} }
@ -73,7 +73,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
attrs2.alloc("branch").mkString(*input2.getRef()); attrs2.alloc("branch").mkString(*input2.getRef());
// Backward compatibility: set 'rev' to // Backward compatibility: set 'rev' to
// 0000000000000000000000000000000000000000 for a dirty tree. // 0000000000000000000000000000000000000000 for a dirty tree.
auto rev2 = input2.getRev().value_or(Hash(htSHA1)); auto rev2 = input2.getRev().value_or(Hash(HashType::SHA1));
attrs2.alloc("rev").mkString(rev2.gitRev()); attrs2.alloc("rev").mkString(rev2.gitRev());
attrs2.alloc("shortRev").mkString(rev2.gitRev().substr(0, 12)); attrs2.alloc("shortRev").mkString(rev2.gitRev().substr(0, 12));
if (auto revCount = input2.getRevCount()) if (auto revCount = input2.getRevCount())

View file

@ -32,7 +32,7 @@ void emitTreeAttrs(
auto narHash = input.getNarHash(); auto narHash = input.getNarHash();
assert(narHash); assert(narHash);
attrs.alloc("narHash").mkString(narHash->to_string(SRI, true)); attrs.alloc("narHash").mkString(narHash->to_string(Base::SRI, true));
if (input.getType() == "git") if (input.getType() == "git")
attrs.alloc("submodules").mkBool( attrs.alloc("submodules").mkBool(
@ -45,7 +45,7 @@ void emitTreeAttrs(
attrs.alloc("shortRev").mkString(rev->gitShortRev()); attrs.alloc("shortRev").mkString(rev->gitShortRev());
} else if (emptyRevFallback) { } else if (emptyRevFallback) {
// Backwards compat for `builtins.fetchGit`: dirty repos return an empty sha1 as rev // Backwards compat for `builtins.fetchGit`: dirty repos return an empty sha1 as rev
auto emptyHash = Hash(htSHA1); auto emptyHash = Hash(HashType::SHA1);
attrs.alloc("rev").mkString(emptyHash.gitRev()); attrs.alloc("rev").mkString(emptyHash.gitRev());
attrs.alloc("shortRev").mkString(emptyHash.gitShortRev()); attrs.alloc("shortRev").mkString(emptyHash.gitShortRev());
} }
@ -226,7 +226,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
if (n == "url") if (n == "url")
url = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the url we should fetch"); url = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the url we should fetch");
else if (n == "sha256") else if (n == "sha256")
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the sha256 of the content we should fetch"), htSHA256); expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the sha256 of the content we should fetch"), HashType::SHA256);
else if (n == "name") else if (n == "name")
name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the name of the content we should fetch"); name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the name of the content we should fetch");
else else
@ -252,7 +252,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
state.error<EvalError>("in pure evaluation mode, '%s' requires a 'sha256' argument", who).atPos(pos).debugThrow(); state.error<EvalError>("in pure evaluation mode, '%s' requires a 'sha256' argument", who).atPos(pos).debugThrow();
// early exit if pinned and already in the store // early exit if pinned and already in the store
if (expectedHash && expectedHash->type == htSHA256) { if (expectedHash && expectedHash->type == HashType::SHA256) {
auto expectedPath = state.store->makeFixedOutputPath( auto expectedPath = state.store->makeFixedOutputPath(
name, name,
FixedOutputInfo { FixedOutputInfo {
@ -277,13 +277,13 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
if (expectedHash) { if (expectedHash) {
auto hash = unpack auto hash = unpack
? state.store->queryPathInfo(storePath)->narHash ? state.store->queryPathInfo(storePath)->narHash
: hashFile(htSHA256, state.store->toRealPath(storePath)); : hashFile(HashType::SHA256, state.store->toRealPath(storePath));
if (hash != *expectedHash) { if (hash != *expectedHash) {
state.error<EvalError>( state.error<EvalError>(
"hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s", "hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s",
*url, *url,
expectedHash->to_string(Base32, true), expectedHash->to_string(Base::Base32, true),
hash.to_string(Base32, true) hash.to_string(Base::Base32, true)
).withExitStatus(102) ).withExitStatus(102)
.debugThrow(); .debugThrow();
} }

View file

@ -18,8 +18,8 @@ StorePath fetchToStore(
return return
settings.readOnlyMode settings.readOnlyMode
? store.computeStorePathForPath(name, path.path.abs(), method, htSHA256, filter2).first ? store.computeStorePathForPath(name, path.path.abs(), method, HashType::SHA256, filter2).first
: store.addToStore(name, path.path.abs(), method, htSHA256, filter2, repair); : store.addToStore(name, path.path.abs(), method, HashType::SHA256, filter2, repair);
} }

View file

@ -153,12 +153,12 @@ std::pair<Tree, Input> Input::fetch(ref<Store> store) const
}; };
auto narHash = store->queryPathInfo(tree.storePath)->narHash; auto narHash = store->queryPathInfo(tree.storePath)->narHash;
input.attrs.insert_or_assign("narHash", narHash.to_string(SRI, true)); input.attrs.insert_or_assign("narHash", narHash.to_string(Base::SRI, true));
if (auto prevNarHash = getNarHash()) { if (auto prevNarHash = getNarHash()) {
if (narHash != *prevNarHash) if (narHash != *prevNarHash)
throw Error((unsigned int) 102, "NAR hash mismatch in input '%s' (%s), expected '%s', got '%s'", throw Error((unsigned int) 102, "NAR hash mismatch in input '%s' (%s), expected '%s', got '%s'",
to_string(), tree.actualPath, prevNarHash->to_string(SRI, true), narHash.to_string(SRI, true)); to_string(), tree.actualPath, prevNarHash->to_string(Base::SRI, true), narHash.to_string(Base::SRI, true));
} }
if (auto prevLastModified = getLastModified()) { if (auto prevLastModified = getLastModified()) {
@ -240,8 +240,8 @@ std::string Input::getType() const
std::optional<Hash> Input::getNarHash() const std::optional<Hash> Input::getNarHash() const
{ {
if (auto s = maybeGetStrAttr(attrs, "narHash")) { if (auto s = maybeGetStrAttr(attrs, "narHash")) {
auto hash = s->empty() ? Hash(htSHA256) : Hash::parseSRI(*s); auto hash = s->empty() ? Hash(HashType::SHA256) : Hash::parseSRI(*s);
if (hash.type != htSHA256) if (hash.type != HashType::SHA256)
throw UsageError("narHash must use SHA-256"); throw UsageError("narHash must use SHA-256");
return hash; return hash;
} }
@ -264,7 +264,7 @@ std::optional<Hash> Input::getRev() const
hash = Hash::parseAnyPrefixed(*s); hash = Hash::parseAnyPrefixed(*s);
} catch (BadHash &e) { } catch (BadHash &e) {
// Default to sha1 for backwards compatibility with existing flakes // Default to sha1 for backwards compatibility with existing flakes
hash = Hash::parseAny(*s, htSHA1); hash = Hash::parseAny(*s, HashType::SHA1);
} }
} }

View file

@ -49,7 +49,7 @@ bool touchCacheFile(const Path & path, time_t touch_time)
Path getCachePath(std::string_view key) Path getCachePath(std::string_view key)
{ {
return getCacheDir() + "/nix/gitv3/" + return getCacheDir() + "/nix/gitv3/" +
hashString(htSHA256, key).to_string(Base32, false); hashString(HashType::SHA256, key).to_string(Base::Base32, false);
} }
// Returns the name of the HEAD branch. // Returns the name of the HEAD branch.
@ -238,7 +238,7 @@ std::pair<StorePath, Input> fetchFromWorkdir(ref<Store> store, Input & input, co
return files.count(file); return files.count(file);
}; };
auto storePath = store->addToStore(input.getName(), actualPath, FileIngestionMethod::Recursive, htSHA256, filter); auto storePath = store->addToStore(input.getName(), actualPath, FileIngestionMethod::Recursive, HashType::SHA256, filter);
// FIXME: maybe we should use the timestamp of the last // FIXME: maybe we should use the timestamp of the last
// modified dirty file? // modified dirty file?
@ -437,8 +437,8 @@ struct GitInputScheme : InputScheme
auto checkHashType = [&](const std::optional<Hash> & hash) auto checkHashType = [&](const std::optional<Hash> & hash)
{ {
if (hash.has_value() && !(hash->type == htSHA1 || hash->type == htSHA256)) 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(Base16, true)); throw Error("Hash '%s' is not supported by Git. Supported types are sha1 and sha256.", hash->to_string(Base::Base16, true));
}; };
auto getLockedAttrs = [&]() auto getLockedAttrs = [&]()
@ -501,7 +501,7 @@ struct GitInputScheme : InputScheme
if (!input.getRev()) if (!input.getRev())
input.attrs.insert_or_assign("rev", input.attrs.insert_or_assign("rev",
Hash::parseAny(chomp(runProgram("git", true, { "-C", actualUrl, "--git-dir", gitDir, "rev-parse", *input.getRef() })), htSHA1).gitRev()); Hash::parseAny(chomp(runProgram("git", true, { "-C", actualUrl, "--git-dir", gitDir, "rev-parse", *input.getRef() })), HashType::SHA1).gitRev());
repoDir = actualUrl; repoDir = actualUrl;
} else { } else {
@ -521,7 +521,7 @@ struct GitInputScheme : InputScheme
} }
if (auto res = getCache()->lookup(store, unlockedAttrs)) { if (auto res = getCache()->lookup(store, unlockedAttrs)) {
auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), htSHA1); auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), HashType::SHA1);
if (!input.getRev() || input.getRev() == rev2) { if (!input.getRev() || input.getRev() == rev2) {
input.attrs.insert_or_assign("rev", rev2.gitRev()); input.attrs.insert_or_assign("rev", rev2.gitRev());
return makeResult(res->first, std::move(res->second)); return makeResult(res->first, std::move(res->second));
@ -599,7 +599,7 @@ struct GitInputScheme : InputScheme
} }
if (!input.getRev()) if (!input.getRev())
input.attrs.insert_or_assign("rev", Hash::parseAny(chomp(readFile(localRefFile)), htSHA1).gitRev()); input.attrs.insert_or_assign("rev", Hash::parseAny(chomp(readFile(localRefFile)), HashType::SHA1).gitRev());
// cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in the remainder // cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in the remainder
} }
@ -695,7 +695,7 @@ struct GitInputScheme : InputScheme
unpackTarfile(*proc.getStdout(), tmpDir); unpackTarfile(*proc.getStdout(), tmpDir);
} }
auto storePath = store->addToStore(name, tmpDir, FileIngestionMethod::Recursive, htSHA256, filter); auto storePath = store->addToStore(name, tmpDir, FileIngestionMethod::Recursive, HashType::SHA256, filter);
auto lastModified = std::stoull(runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "log", "-1", "--format=%ct", "--no-show-signature", input.getRev()->gitRev() })); auto lastModified = std::stoull(runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "log", "-1", "--format=%ct", "--no-show-signature", input.getRev()->gitRev() }));

View file

@ -149,7 +149,7 @@ struct GitArchiveInputScheme : InputScheme
auto path = owner + "/" + repo; auto path = owner + "/" + repo;
assert(!(ref && rev)); assert(!(ref && rev));
if (ref) path += "/" + *ref; if (ref) path += "/" + *ref;
if (rev) path += "/" + rev->to_string(Base16, false); if (rev) path += "/" + rev->to_string(Base::Base16, false);
return ParsedURL { return ParsedURL {
.scheme = type(), .scheme = type(),
.path = path, .path = path,
@ -274,7 +274,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
readFile( readFile(
store->toRealPath( store->toRealPath(
downloadFile(store, url, "source", false, headers).storePath))); downloadFile(store, url, "source", false, headers).storePath)));
auto rev = Hash::parseAny(std::string { json["sha"] }, htSHA1); auto rev = Hash::parseAny(std::string { json["sha"] }, HashType::SHA1);
debug("HEAD revision for '%s' is %s", url, rev.gitRev()); debug("HEAD revision for '%s' is %s", url, rev.gitRev());
return rev; return rev;
} }
@ -295,7 +295,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
: "https://api.%s/repos/%s/%s/tarball/%s"; : "https://api.%s/repos/%s/%s/tarball/%s";
const auto url = fmt(urlFmt, host, getOwner(input), getRepo(input), const auto url = fmt(urlFmt, host, getOwner(input), getRepo(input),
input.getRev()->to_string(Base16, false)); input.getRev()->to_string(Base::Base16, false));
return DownloadUrl { url, headers }; return DownloadUrl { url, headers };
} }
@ -347,7 +347,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
store->toRealPath( store->toRealPath(
downloadFile(store, url, "source", false, headers).storePath))); downloadFile(store, url, "source", false, headers).storePath)));
if (json.is_array() && json.size() >= 1 && json[0]["id"] != nullptr) { if (json.is_array() && json.size() >= 1 && json[0]["id"] != nullptr) {
auto rev = Hash::parseAny(std::string(json[0]["id"]), htSHA1); auto rev = Hash::parseAny(std::string(json[0]["id"]), HashType::SHA1);
debug("HEAD revision for '%s' is %s", url, rev.gitRev()); debug("HEAD revision for '%s' is %s", url, rev.gitRev());
return rev; return rev;
} else if (json.is_array() && json.size() == 0) { } else if (json.is_array() && json.size() == 0) {
@ -367,7 +367,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com"); 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", 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"), host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(Base16, false)); input.getRev()->to_string(Base::Base16, false));
Headers headers = makeHeadersWithAuthTokens(host); Headers headers = makeHeadersWithAuthTokens(host);
return DownloadUrl { url, headers }; return DownloadUrl { url, headers };
@ -444,7 +444,7 @@ struct SourceHutInputScheme : GitArchiveInputScheme
if(!id) if(!id)
throw BadURL("in '%d', couldn't find ref '%d'", input.to_string(), ref); throw BadURL("in '%d', couldn't find ref '%d'", input.to_string(), ref);
auto rev = Hash::parseAny(*id, htSHA1); auto rev = Hash::parseAny(*id, HashType::SHA1);
debug("HEAD revision for '%s' is %s", fmt("%s/%s", base_url, ref), rev.gitRev()); debug("HEAD revision for '%s' is %s", fmt("%s/%s", base_url, ref), rev.gitRev());
return rev; return rev;
} }
@ -454,7 +454,7 @@ struct SourceHutInputScheme : GitArchiveInputScheme
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht"); auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
auto url = fmt("https://%s/%s/%s/archive/%s.tar.gz", auto url = fmt("https://%s/%s/%s/archive/%s.tar.gz",
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(Base16, false)); input.getRev()->to_string(Base::Base16, false));
Headers headers = makeHeadersWithAuthTokens(host); Headers headers = makeHeadersWithAuthTokens(host);
return DownloadUrl { url, headers }; return DownloadUrl { url, headers };

View file

@ -22,14 +22,14 @@ struct IndirectInputScheme : InputScheme
if (path.size() == 1) { if (path.size() == 1) {
} else if (path.size() == 2) { } else if (path.size() == 2) {
if (std::regex_match(path[1], revRegex)) if (std::regex_match(path[1], revRegex))
rev = Hash::parseAny(path[1], htSHA1); rev = Hash::parseAny(path[1], HashType::SHA1);
else if (std::regex_match(path[1], refRegex)) else if (std::regex_match(path[1], refRegex))
ref = path[1]; ref = path[1];
else else
throw BadURL("in flake URL '%s', '%s' is not a commit hash or branch/tag name", url.url, path[1]); throw BadURL("in flake URL '%s', '%s' is not a commit hash or branch/tag name", url.url, path[1]);
} else if (path.size() == 3) { } else if (path.size() == 3) {
ref = path[1]; ref = path[1];
rev = Hash::parseAny(path[2], htSHA1); rev = Hash::parseAny(path[2], HashType::SHA1);
} else } else
throw BadURL("GitHub URL '%s' is invalid", url.url); throw BadURL("GitHub URL '%s' is invalid", url.url);

View file

@ -198,7 +198,7 @@ struct MercurialInputScheme : InputScheme
return files.count(file); return files.count(file);
}; };
auto storePath = store->addToStore(input.getName(), actualPath, FileIngestionMethod::Recursive, htSHA256, filter); auto storePath = store->addToStore(input.getName(), actualPath, FileIngestionMethod::Recursive, HashType::SHA256, filter);
return {std::move(storePath), input}; return {std::move(storePath), input};
} }
@ -208,8 +208,8 @@ struct MercurialInputScheme : InputScheme
auto checkHashType = [&](const std::optional<Hash> & hash) auto checkHashType = [&](const std::optional<Hash> & hash)
{ {
if (hash.has_value() && hash->type != htSHA1) if (hash.has_value() && hash->type != HashType::SHA1)
throw Error("Hash '%s' is not supported by Mercurial. Only sha1 is supported.", hash->to_string(Base16, true)); throw Error("Hash '%s' is not supported by Mercurial. Only sha1 is supported.", hash->to_string(Base::Base16, true));
}; };
@ -248,14 +248,14 @@ struct MercurialInputScheme : InputScheme
}); });
if (auto res = getCache()->lookup(store, unlockedAttrs)) { if (auto res = getCache()->lookup(store, unlockedAttrs)) {
auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), htSHA1); auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), HashType::SHA1);
if (!input.getRev() || input.getRev() == rev2) { if (!input.getRev() || input.getRev() == rev2) {
input.attrs.insert_or_assign("rev", rev2.gitRev()); input.attrs.insert_or_assign("rev", rev2.gitRev());
return makeResult(res->first, std::move(res->second)); return makeResult(res->first, std::move(res->second));
} }
} }
Path cacheDir = fmt("%s/nix/hg/%s", getCacheDir(), hashString(htSHA256, actualUrl).to_string(Base32, false)); Path cacheDir = fmt("%s/nix/hg/%s", getCacheDir(), hashString(HashType::SHA256, actualUrl).to_string(Base::Base32, false));
/* If this is a commit hash that we already have, we don't /* If this is a commit hash that we already have, we don't
have to pull again. */ have to pull again. */
@ -289,7 +289,7 @@ struct MercurialInputScheme : InputScheme
runHg({ "log", "-R", cacheDir, "-r", revOrRef, "--template", "{node} {rev} {branch}" })); runHg({ "log", "-R", cacheDir, "-r", revOrRef, "--template", "{node} {rev} {branch}" }));
assert(tokens.size() == 3); assert(tokens.size() == 3);
input.attrs.insert_or_assign("rev", Hash::parseAny(tokens[0], htSHA1).gitRev()); input.attrs.insert_or_assign("rev", Hash::parseAny(tokens[0], HashType::SHA1).gitRev());
auto revCount = std::stoull(tokens[1]); auto revCount = std::stoull(tokens[1]);
input.attrs.insert_or_assign("ref", tokens[2]); input.attrs.insert_or_assign("ref", tokens[2]);

View file

@ -72,7 +72,7 @@ DownloadFileResult downloadFile(
} else { } else {
StringSink sink; StringSink sink;
sink << dumpString(res.data); sink << dumpString(res.data);
auto hash = hashString(htSHA256, res.data); auto hash = hashString(HashType::SHA256, res.data);
ValidPathInfo info { ValidPathInfo info {
*store, *store,
name, name,
@ -81,7 +81,7 @@ DownloadFileResult downloadFile(
.hash = hash, .hash = hash,
.references = {}, .references = {},
}, },
hashString(htSHA256, sink.s), hashString(HashType::SHA256, sink.s),
}; };
info.narSize = sink.s.size(); info.narSize = sink.s.size();
auto source = StringSource { sink.s }; auto source = StringSource { sink.s };
@ -155,7 +155,7 @@ DownloadTarballResult downloadTarball(
throw nix::Error("tarball '%s' contains an unexpected number of top-level files", url); throw nix::Error("tarball '%s' contains an unexpected number of top-level files", url);
auto topDir = tmpDir + "/" + members.begin()->name; auto topDir = tmpDir + "/" + members.begin()->name;
lastModified = lstat(topDir).st_mtime; lastModified = lstat(topDir).st_mtime;
unpackedStorePath = store->addToStore(name, topDir, FileIngestionMethod::Recursive, htSHA256, defaultPathFilter, NoRepair); unpackedStorePath = store->addToStore(name, topDir, FileIngestionMethod::Recursive, HashType::SHA256, defaultPathFilter, NoRepair);
} }
Attrs infoAttrs({ Attrs infoAttrs({
@ -238,7 +238,7 @@ struct CurlInputScheme : InputScheme
// NAR hashes are preferred over file hashes since tar/zip // NAR hashes are preferred over file hashes since tar/zip
// files don't have a canonical representation. // files don't have a canonical representation.
if (auto narHash = input.getNarHash()) if (auto narHash = input.getNarHash())
url.query.insert_or_assign("narHash", narHash->to_string(SRI, true)); url.query.insert_or_assign("narHash", narHash->to_string(Base::SRI, true));
return url; return url;
} }

View file

@ -2,8 +2,6 @@
#include "shared.hh" #include "shared.hh"
#include <cstring> #include <cstring>
#include <cstddef>
#include <cstdlib>
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
@ -17,17 +15,17 @@ static void sigsegvHandler(int signo, siginfo_t * info, void * ctx)
the stack pointer. Unfortunately, getting the stack pointer is the stack pointer. Unfortunately, getting the stack pointer is
not portable. */ not portable. */
bool haveSP = true; bool haveSP = true;
char * sp = 0; int64_t sp = 0;
#if defined(__x86_64__) && defined(REG_RSP) #if defined(__x86_64__) && defined(REG_RSP)
sp = (char *) ((ucontext_t *) ctx)->uc_mcontext.gregs[REG_RSP]; sp = static_cast<ucontext_t *>(ctx)->uc_mcontext.gregs[REG_RSP];
#elif defined(REG_ESP) #elif defined(REG_ESP)
sp = (char *) ((ucontext_t *) ctx)->uc_mcontext.gregs[REG_ESP]; sp = static_cast<ucontext_t *>(ctx)->uc_mcontext.gregs[REG_ESP];
#else #else
haveSP = false; haveSP = false;
#endif #endif
if (haveSP) { if (haveSP) {
ptrdiff_t diff = (char *) info->si_addr - sp; int64_t diff = int64_t(info->si_addr) - sp;
if (diff < 0) diff = -diff; if (diff < 0) diff = -diff;
if (diff < 4096) { if (diff < 4096) {
nix::stackOverflowHandler(info, ctx); nix::stackOverflowHandler(info, ctx);

View file

@ -3,17 +3,15 @@
#include "compression.hh" #include "compression.hh"
#include "derivations.hh" #include "derivations.hh"
#include "fs-accessor.hh" #include "fs-accessor.hh"
#include "globals.hh"
#include "nar-info.hh" #include "nar-info.hh"
#include "sync.hh" #include "sync.hh"
#include "remote-fs-accessor.hh" #include "remote-fs-accessor.hh"
#include "nar-info-disk-cache.hh" #include "nar-info-disk-cache.hh" // IWYU pragma: keep
#include "nar-accessor.hh" #include "nar-accessor.hh"
#include "thread-pool.hh" #include "thread-pool.hh"
#include "signals.hh" #include "signals.hh"
#include <chrono> #include <chrono>
#include <future>
#include <regex> #include <regex>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
@ -128,9 +126,9 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
/* Read the NAR simultaneously into a CompressionSink+FileSink (to /* Read the NAR simultaneously into a CompressionSink+FileSink (to
write the compressed NAR to disk), into a HashSink (to get the write the compressed NAR to disk), into a HashSink (to get the
NAR hash), and into a NarAccessor (to get the NAR listing). */ NAR hash), and into a NarAccessor (to get the NAR listing). */
HashSink fileHashSink { htSHA256 }; HashSink fileHashSink { HashType::SHA256 };
std::shared_ptr<FSAccessor> narAccessor; std::shared_ptr<FSAccessor> narAccessor;
HashSink narHashSink { htSHA256 }; HashSink narHashSink { HashType::SHA256 };
{ {
FdSink fileSink(fdTemp.get()); FdSink fileSink(fdTemp.get());
TeeSink teeSinkCompressed { fileSink, fileHashSink }; TeeSink teeSinkCompressed { fileSink, fileHashSink };
@ -150,7 +148,7 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
auto [fileHash, fileSize] = fileHashSink.finish(); auto [fileHash, fileSize] = fileHashSink.finish();
narInfo->fileHash = fileHash; narInfo->fileHash = fileHash;
narInfo->fileSize = fileSize; narInfo->fileSize = fileSize;
narInfo->url = "nar/" + narInfo->fileHash->to_string(Base32, false) + ".nar" narInfo->url = "nar/" + narInfo->fileHash->to_string(Base::Base32, false) + ".nar"
+ (compression == "xz" ? ".xz" : + (compression == "xz" ? ".xz" :
compression == "bzip2" ? ".bz2" : compression == "bzip2" ? ".bz2" :
compression == "zstd" ? ".zst" : compression == "zstd" ? ".zst" :
@ -288,7 +286,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSource
StorePath BinaryCacheStore::addToStoreFromDump(Source & dump, std::string_view name, StorePath BinaryCacheStore::addToStoreFromDump(Source & dump, std::string_view name,
FileIngestionMethod method, HashType hashAlgo, RepairFlag repair, const StorePathSet & references) FileIngestionMethod method, HashType hashAlgo, RepairFlag repair, const StorePathSet & references)
{ {
if (method != FileIngestionMethod::Recursive || hashAlgo != htSHA256) if (method != FileIngestionMethod::Recursive || hashAlgo != HashType::SHA256)
unsupported("addToStoreFromDump"); unsupported("addToStoreFromDump");
return addToStoreCommon(dump, repair, CheckSigs, [&](HashResult nar) { return addToStoreCommon(dump, repair, CheckSigs, [&](HashResult nar) {
ValidPathInfo info { ValidPathInfo info {
@ -425,7 +423,7 @@ StorePath BinaryCacheStore::addTextToStore(
const StorePathSet & references, const StorePathSet & references,
RepairFlag repair) RepairFlag repair)
{ {
auto textHash = hashString(htSHA256, s); auto textHash = hashString(HashType::SHA256, s);
auto path = makeTextPath(name, TextInfo { { textHash }, references }); auto path = makeTextPath(name, TextInfo { { textHash }, references });
if (!repair && isValidPath(path)) if (!repair && isValidPath(path))
@ -480,7 +478,8 @@ void BinaryCacheStore::addSignatures(const StorePath & storePath, const StringSe
when addSignatures() is called sequentially on a path, because when addSignatures() is called sequentially on a path, because
S3 might return an outdated cached version. */ S3 might return an outdated cached version. */
auto narInfo = make_ref<NarInfo>((NarInfo &) *queryPathInfo(storePath)); // downcast: BinaryCacheStore always returns NarInfo from queryPathInfoUncached, making it sound
auto narInfo = make_ref<NarInfo>(dynamic_cast<NarInfo const &>(*queryPathInfo(storePath)));
narInfo->sigs.insert(sigs.begin(), sigs.end()); narInfo->sigs.insert(sigs.begin(), sigs.end());

View file

@ -817,8 +817,8 @@ void LocalDerivationGoal::initTmpDir() {
if (passAsFile.find(i.first) == passAsFile.end()) { if (passAsFile.find(i.first) == passAsFile.end()) {
env[i.first] = i.second; env[i.first] = i.second;
} else { } else {
auto hash = hashString(htSHA256, i.first); auto hash = hashString(HashType::SHA256, i.first);
std::string fn = ".attr-" + hash.to_string(Base32, false); std::string fn = ".attr-" + hash.to_string(Base::Base32, false);
Path p = tmpDir + "/" + fn; Path p = tmpDir + "/" + fn;
writeFile(p, rewriteStrings(i.second, inputRewrites)); writeFile(p, rewriteStrings(i.second, inputRewrites));
chownToBuilder(p); chownToBuilder(p);
@ -1225,7 +1225,7 @@ void LocalDerivationGoal::startDaemon()
socklen_t remoteAddrLen = sizeof(remoteAddr); socklen_t remoteAddrLen = sizeof(remoteAddr);
AutoCloseFD remote{accept(daemonSocket.get(), AutoCloseFD remote{accept(daemonSocket.get(),
(struct sockaddr *) &remoteAddr, &remoteAddrLen)}; reinterpret_cast<struct sockaddr *>(&remoteAddr), &remoteAddrLen)};
if (!remote) { if (!remote) {
if (errno == EINTR || errno == EAGAIN) continue; if (errno == EINTR || errno == EAGAIN) continue;
if (errno == EINVAL || errno == ECONNABORTED) break; if (errno == EINVAL || errno == ECONNABORTED) break;
@ -2146,7 +2146,7 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
std::string(newInfo0.path.hashPart())}}); std::string(newInfo0.path.hashPart())}});
} }
HashResult narHashAndSize = hashPath(htSHA256, actualPath); HashResult narHashAndSize = hashPath(HashType::SHA256, actualPath);
newInfo0.narHash = narHashAndSize.first; newInfo0.narHash = narHashAndSize.first;
newInfo0.narSize = narHashAndSize.second; newInfo0.narSize = narHashAndSize.second;
@ -2166,7 +2166,7 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
std::string { scratchPath->hashPart() }, std::string { scratchPath->hashPart() },
std::string { requiredFinalPath.hashPart() }); std::string { requiredFinalPath.hashPart() });
rewriteOutput(outputRewrites); rewriteOutput(outputRewrites);
auto narHashAndSize = hashPath(htSHA256, actualPath); auto narHashAndSize = hashPath(HashType::SHA256, actualPath);
ValidPathInfo newInfo0 { requiredFinalPath, narHashAndSize.first }; ValidPathInfo newInfo0 { requiredFinalPath, narHashAndSize.first };
newInfo0.narSize = narHashAndSize.second; newInfo0.narSize = narHashAndSize.second;
auto refs = rewriteRefs(); auto refs = rewriteRefs();
@ -2203,8 +2203,8 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
BuildError("hash mismatch in fixed-output derivation '%s':\n likely URL: %s\n specified: %s\n got: %s", BuildError("hash mismatch in fixed-output derivation '%s':\n likely URL: %s\n specified: %s\n got: %s",
worker.store.printStorePath(drvPath), worker.store.printStorePath(drvPath),
guessedUrl, guessedUrl,
wanted.to_string(SRI, true), wanted.to_string(Base::SRI, true),
got.to_string(SRI, true))); got.to_string(Base::SRI, true)));
} }
if (!newInfo0.references.empty()) if (!newInfo0.references.empty())
delayedException = std::make_exception_ptr( delayedException = std::make_exception_ptr(
@ -2607,7 +2607,7 @@ StorePath LocalDerivationGoal::makeFallbackPath(OutputNameView outputName)
{ {
return worker.store.makeStorePath( return worker.store.makeStorePath(
"rewrite:" + std::string(drvPath.to_string()) + ":name:" + std::string(outputName), "rewrite:" + std::string(drvPath.to_string()) + ":name:" + std::string(outputName),
Hash(htSHA256), outputPathName(drv->name, outputName)); Hash(HashType::SHA256), outputPathName(drv->name, outputName));
} }
@ -2615,7 +2615,7 @@ StorePath LocalDerivationGoal::makeFallbackPath(const StorePath & path)
{ {
return worker.store.makeStorePath( return worker.store.makeStorePath(
"rewrite:" + std::string(drvPath.to_string()) + ":" + std::string(path.to_string()), "rewrite:" + std::string(drvPath.to_string()) + ":" + std::string(path.to_string()),
Hash(htSHA256), path.name()); Hash(HashType::SHA256), path.name());
} }

View file

@ -4,7 +4,7 @@
#include "drv-output-substitution-goal.hh" #include "drv-output-substitution-goal.hh"
#include "local-derivation-goal.hh" #include "local-derivation-goal.hh"
#include "signals.hh" #include "signals.hh"
#include "hook-instance.hh" #include "hook-instance.hh" // IWYU pragma: keep
#include <poll.h> #include <poll.h>
@ -539,7 +539,7 @@ void Worker::waitForInput()
} else { } else {
printMsg(lvlVomit, "%1%: read %2% bytes", printMsg(lvlVomit, "%1%: read %2% bytes",
goal->getName(), rd); goal->getName(), rd);
std::string_view data((char *) buffer.data(), rd); std::string_view data(reinterpret_cast<char *>(buffer.data()), rd);
j->lastOutput = after; j->lastOutput = after;
handleWorkResult(goal, goal->handleChildOutput(k, data)); handleWorkResult(goal, goal->handleChildOutput(k, data));
} }
@ -590,7 +590,7 @@ bool Worker::pathContentsGood(const StorePath & path)
res = false; res = false;
else { else {
HashResult current = hashPath(info->narHash.type, store.printStorePath(path)); HashResult current = hashPath(info->narHash.type, store.printStorePath(path));
Hash nullHash(htSHA256); Hash nullHash(HashType::SHA256);
res = info->narHash == nullHash || info->narHash == current.first; res = info->narHash == nullHash || info->narHash == current.first;
} }
pathContentsGoodCache.insert_or_assign(path, res); pathContentsGoodCache.insert_or_assign(path, res);

View file

@ -60,7 +60,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
if (!hashedMirror.ends_with("/")) hashedMirror += '/'; if (!hashedMirror.ends_with("/")) hashedMirror += '/';
std::optional<HashType> ht = parseHashTypeOpt(getAttr("outputHashAlgo")); std::optional<HashType> ht = parseHashTypeOpt(getAttr("outputHashAlgo"));
Hash h = newHashAllowEmpty(getAttr("outputHash"), ht); Hash h = newHashAllowEmpty(getAttr("outputHash"), ht);
fetch(hashedMirror + printHashType(h.type) + "/" + h.to_string(Base16, false)); fetch(hashedMirror + printHashType(h.type) + "/" + h.to_string(Base::Base16, false));
return; return;
} catch (Error & e) { } catch (Error & e) {
debug(e.what()); debug(e.what());

View file

@ -61,7 +61,7 @@ std::string ContentAddress::render() const
+ makeFileIngestionPrefix(method); + makeFileIngestionPrefix(method);
}, },
}, method.raw) }, method.raw)
+ this->hash.to_string(Base32, true); + this->hash.to_string(Base::Base32, true);
} }
/** /**

View file

@ -44,16 +44,16 @@ std::string SecretKey::signDetached(std::string_view data) const
{ {
unsigned char sig[crypto_sign_BYTES]; unsigned char sig[crypto_sign_BYTES];
unsigned long long sigLen; unsigned long long sigLen;
crypto_sign_detached(sig, &sigLen, (unsigned char *) data.data(), data.size(), crypto_sign_detached(sig, &sigLen, reinterpret_cast<const unsigned char *>(data.data()), data.size(),
(unsigned char *) key.data()); reinterpret_cast<const unsigned char *>(key.data()));
return name + ":" + base64Encode(std::string((char *) sig, sigLen)); return name + ":" + base64Encode(std::string(reinterpret_cast<char *>(sig), sigLen));
} }
PublicKey SecretKey::toPublicKey() const PublicKey SecretKey::toPublicKey() const
{ {
unsigned char pk[crypto_sign_PUBLICKEYBYTES]; unsigned char pk[crypto_sign_PUBLICKEYBYTES];
crypto_sign_ed25519_sk_to_pk(pk, (unsigned char *) key.data()); crypto_sign_ed25519_sk_to_pk(pk, reinterpret_cast<const unsigned char *>(key.data()));
return PublicKey(name, std::string((char *) pk, crypto_sign_PUBLICKEYBYTES)); return PublicKey(name, std::string(reinterpret_cast<char *>(pk), crypto_sign_PUBLICKEYBYTES));
} }
SecretKey SecretKey::generate(std::string_view name) SecretKey SecretKey::generate(std::string_view name)
@ -63,7 +63,7 @@ SecretKey SecretKey::generate(std::string_view name)
if (crypto_sign_keypair(pk, sk) != 0) if (crypto_sign_keypair(pk, sk) != 0)
throw Error("key generation failed"); throw Error("key generation failed");
return SecretKey(name, std::string((char *) sk, crypto_sign_SECRETKEYBYTES)); return SecretKey(name, std::string(reinterpret_cast<char *>(sk), crypto_sign_SECRETKEYBYTES));
} }
PublicKey::PublicKey(std::string_view s) PublicKey::PublicKey(std::string_view s)
@ -85,9 +85,9 @@ bool verifyDetached(const std::string & data, const std::string & sig,
if (sig2.size() != crypto_sign_BYTES) if (sig2.size() != crypto_sign_BYTES)
throw Error("signature is not valid"); throw Error("signature is not valid");
return crypto_sign_verify_detached((unsigned char *) sig2.data(), return crypto_sign_verify_detached(reinterpret_cast<unsigned char *>(sig2.data()),
(unsigned char *) data.data(), data.size(), reinterpret_cast<const unsigned char *>(data.data()), data.size(),
(unsigned char *) key->second.key.data()) == 0; reinterpret_cast<const unsigned char *>(key->second.key.data())) == 0;
} }
PublicKeys getDefaultPublicKeys() PublicKeys getDefaultPublicKeys()

View file

@ -416,7 +416,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
// TODO this is essentially RemoteStore::addCAToStore. Move it up to Store. // TODO this is essentially RemoteStore::addCAToStore. Move it up to Store.
return std::visit(overloaded { return std::visit(overloaded {
[&](const TextIngestionMethod &) { [&](const TextIngestionMethod &) {
if (hashType != htSHA256) if (hashType != HashType::SHA256)
throw UnimplementedError("When adding text-hashed data called '%s', only SHA-256 is supported but '%s' was given", throw UnimplementedError("When adding text-hashed data called '%s', only SHA-256 is supported but '%s' was given",
name, printHashType(hashType)); name, printHashType(hashType));
// We could stream this by changing Store // We could stream this by changing Store
@ -453,7 +453,11 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
hashAlgo = parseHashType(hashAlgoRaw); hashAlgo = parseHashType(hashAlgoRaw);
} }
GeneratorSource dumpSource{[&]() -> WireFormatGenerator { // Note to future maintainers: do *not* inline this into the
// generator statement as the lambda itself needs to live to the
// end of the generator's lifetime and is otherwise a UAF.
// NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines): does not outlive the outer function
auto g = [&]() -> WireFormatGenerator {
if (method == FileIngestionMethod::Recursive) { if (method == FileIngestionMethod::Recursive) {
/* We parse the NAR dump through into `saved` unmodified, /* We parse the NAR dump through into `saved` unmodified,
so why all this extra work? We still parse the NAR so so why all this extra work? We still parse the NAR so
@ -489,7 +493,8 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
} }
co_yield std::move(file->contents); co_yield std::move(file->contents);
} }
}()}; };
GeneratorSource dumpSource{g()};
logger->startWork(); logger->startWork();
auto path = store->addToStoreFromDump(dumpSource, baseName, method, hashAlgo); auto path = store->addToStoreFromDump(dumpSource, baseName, method, hashAlgo);
logger->stopWork(); logger->stopWork();
@ -875,7 +880,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
bool repair, dontCheckSigs; bool repair, dontCheckSigs;
auto path = store->parseStorePath(readString(from)); auto path = store->parseStorePath(readString(from));
auto deriver = readString(from); auto deriver = readString(from);
auto narHash = Hash::parseAny(readString(from), htSHA256); auto narHash = Hash::parseAny(readString(from), HashType::SHA256);
ValidPathInfo info { path, narHash }; ValidPathInfo info { path, narHash };
if (deriver != "") if (deriver != "")
info.deriver = store->parseStorePath(deriver); info.deriver = store->parseStorePath(deriver);

View file

@ -592,7 +592,7 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
[&](const DerivationOutput::CAFixed & dof) { [&](const DerivationOutput::CAFixed & dof) {
s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(dof.path(store, name, i.first))); s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(dof.path(store, name, i.first)));
s += ','; printUnquotedString(s, dof.ca.printMethodAlgo()); s += ','; printUnquotedString(s, dof.ca.printMethodAlgo());
s += ','; printUnquotedString(s, dof.ca.hash.to_string(Base16, false)); s += ','; printUnquotedString(s, dof.ca.hash.to_string(Base::Base16, false));
}, },
[&](const DerivationOutput::CAFloating & dof) { [&](const DerivationOutput::CAFloating & dof) {
s += ','; printUnquotedString(s, ""); s += ','; printUnquotedString(s, "");
@ -823,9 +823,9 @@ DrvHash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOut
std::map<std::string, Hash> outputHashes; std::map<std::string, Hash> outputHashes;
for (const auto & i : drv.outputs) { for (const auto & i : drv.outputs) {
auto & dof = std::get<DerivationOutput::CAFixed>(i.second.raw); auto & dof = std::get<DerivationOutput::CAFixed>(i.second.raw);
auto hash = hashString(htSHA256, "fixed:out:" auto hash = hashString(HashType::SHA256, "fixed:out:"
+ dof.ca.printMethodAlgo() + ":" + dof.ca.printMethodAlgo() + ":"
+ dof.ca.hash.to_string(Base16, false) + ":" + dof.ca.hash.to_string(Base::Base16, false) + ":"
+ store.printStorePath(dof.path(store, drv.name, i.first))); + store.printStorePath(dof.path(store, drv.name, i.first)));
outputHashes.insert_or_assign(i.first, std::move(hash)); outputHashes.insert_or_assign(i.first, std::move(hash));
} }
@ -870,11 +870,11 @@ DrvHash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOut
const auto h = get(res.hashes, outputName); const auto h = get(res.hashes, outputName);
if (!h) if (!h)
throw Error("no hash for output '%s' of derivation '%s'", outputName, drv.name); throw Error("no hash for output '%s' of derivation '%s'", outputName, drv.name);
inputs2[h->to_string(Base16, false)].value.insert(outputName); inputs2[h->to_string(Base::Base16, false)].value.insert(outputName);
} }
} }
auto hash = hashString(htSHA256, drv.unparse(store, maskOutputs, &inputs2)); auto hash = hashString(HashType::SHA256, drv.unparse(store, maskOutputs, &inputs2));
std::map<std::string, Hash> outputHashes; std::map<std::string, Hash> outputHashes;
for (const auto & [outputName, _] : drv.outputs) { for (const auto & [outputName, _] : drv.outputs) {
@ -975,7 +975,7 @@ void writeDerivation(Sink & out, const Store & store, const BasicDerivation & dr
[&](const DerivationOutput::CAFixed & dof) { [&](const DerivationOutput::CAFixed & dof) {
out << store.printStorePath(dof.path(store, drv.name, i.first)) out << store.printStorePath(dof.path(store, drv.name, i.first))
<< dof.ca.printMethodAlgo() << dof.ca.printMethodAlgo()
<< dof.ca.hash.to_string(Base16, false); << dof.ca.hash.to_string(Base::Base16, false);
}, },
[&](const DerivationOutput::CAFloating & dof) { [&](const DerivationOutput::CAFloating & dof) {
out << "" out << ""
@ -1007,7 +1007,7 @@ void writeDerivation(Sink & out, const Store & store, const BasicDerivation & dr
std::string hashPlaceholder(const OutputNameView outputName) std::string hashPlaceholder(const OutputNameView outputName)
{ {
// FIXME: memoize? // FIXME: memoize?
return "/" + hashString(htSHA256, concatStrings("nix-output:", outputName)).to_string(Base32, false); return "/" + hashString(HashType::SHA256, concatStrings("nix-output:", outputName)).to_string(Base::Base32, false);
} }
@ -1199,7 +1199,7 @@ void Derivation::checkInvariants(Store & store, const StorePath & drvPath) const
} }
const Hash impureOutputHash = hashString(htSHA256, "impure"); const Hash impureOutputHash = hashString(HashType::SHA256, "impure");
nlohmann::json DerivationOutput::toJSON( nlohmann::json DerivationOutput::toJSON(
const Store & store, std::string_view drvName, OutputNameView outputName) const const Store & store, std::string_view drvName, OutputNameView outputName) const
@ -1212,7 +1212,7 @@ nlohmann::json DerivationOutput::toJSON(
[&](const DerivationOutput::CAFixed & dof) { [&](const DerivationOutput::CAFixed & dof) {
res["path"] = store.printStorePath(dof.path(store, drvName, outputName)); res["path"] = store.printStorePath(dof.path(store, drvName, outputName));
res["hashAlgo"] = dof.ca.printMethodAlgo(); res["hashAlgo"] = dof.ca.printMethodAlgo();
res["hash"] = dof.ca.hash.to_string(Base16, false); res["hash"] = dof.ca.hash.to_string(Base::Base16, false);
// FIXME print refs? // FIXME print refs?
}, },
[&](const DerivationOutput::CAFloating & dof) { [&](const DerivationOutput::CAFloating & dof) {

View file

@ -5,7 +5,7 @@ namespace nix {
std::string DownstreamPlaceholder::render() const std::string DownstreamPlaceholder::render() const
{ {
return "/" + hash.to_string(Base32, false); return "/" + hash.to_string(Base::Base32, false);
} }
@ -19,7 +19,7 @@ DownstreamPlaceholder DownstreamPlaceholder::unknownCaOutput(
auto drvName = drvNameWithExtension.substr(0, drvNameWithExtension.size() - 4); auto drvName = drvNameWithExtension.substr(0, drvNameWithExtension.size() - 4);
auto clearText = "nix-upstream-output:" + std::string { drvPath.hashPart() } + ":" + outputPathName(drvName, outputName); auto clearText = "nix-upstream-output:" + std::string { drvPath.hashPart() } + ":" + outputPathName(drvName, outputName);
return DownstreamPlaceholder { return DownstreamPlaceholder {
hashString(htSHA256, clearText) hashString(HashType::SHA256, clearText)
}; };
} }
@ -31,10 +31,10 @@ DownstreamPlaceholder DownstreamPlaceholder::unknownDerivation(
xpSettings.require(Xp::DynamicDerivations); xpSettings.require(Xp::DynamicDerivations);
auto compressed = compressHash(placeholder.hash, 20); auto compressed = compressHash(placeholder.hash, 20);
auto clearText = "nix-computed-output:" auto clearText = "nix-computed-output:"
+ compressed.to_string(Base32, false) + compressed.to_string(Base::Base32, false)
+ ":" + std::string { outputName }; + ":" + std::string { outputName };
return DownstreamPlaceholder { return DownstreamPlaceholder {
hashString(htSHA256, clearText) hashString(HashType::SHA256, clearText)
}; };
} }

View file

@ -30,7 +30,7 @@ void Store::exportPath(const StorePath & path, Sink & sink)
{ {
auto info = queryPathInfo(path); auto info = queryPathInfo(path);
HashSink hashSink(htSHA256); HashSink hashSink(HashType::SHA256);
TeeSink teeSink(sink, hashSink); TeeSink teeSink(sink, hashSink);
teeSink << narFromPath(path); teeSink << narFromPath(path);
@ -41,7 +41,7 @@ void Store::exportPath(const StorePath & path, Sink & sink)
Hash hash = hashSink.currentHash().first; Hash hash = hashSink.currentHash().first;
if (hash != info->narHash && info->narHash != Hash(info->narHash.type)) if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
throw Error("hash of path '%s' has changed from '%s' to '%s'!", throw Error("hash of path '%s' has changed from '%s' to '%s'!",
printStorePath(path), info->narHash.to_string(Base32, true), hash.to_string(Base32, true)); printStorePath(path), info->narHash.to_string(Base::Base32, true), hash.to_string(Base::Base32, true));
teeSink teeSink
<< exportMagic << exportMagic
@ -77,7 +77,7 @@ StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs)
auto references = CommonProto::Serialise<StorePathSet>::read(*this, auto references = CommonProto::Serialise<StorePathSet>::read(*this,
CommonProto::ReadConn { .from = source }); CommonProto::ReadConn { .from = source });
auto deriver = readString(source); auto deriver = readString(source);
auto narHash = hashString(htSHA256, saved.s); auto narHash = hashString(HashType::SHA256, saved.s);
ValidPathInfo info { path, narHash }; ValidPathInfo info { path, narHash };
if (deriver != "") if (deriver != "")

View file

@ -5,7 +5,6 @@
#include "s3.hh" #include "s3.hh"
#include "signals.hh" #include "signals.hh"
#include "compression.hh" #include "compression.hh"
#include "finally.hh"
#if ENABLE_S3 #if ENABLE_S3
#include <aws/core/client/ClientConfiguration.h> #include <aws/core/client/ClientConfiguration.h>
@ -143,9 +142,9 @@ struct curlFileTransfer : public FileTransfer
if (successfulStatuses.count(getHTTPStatus()) && this->dataCallback) { if (successfulStatuses.count(getHTTPStatus()) && this->dataCallback) {
writtenToSink += realSize; writtenToSink += realSize;
dataCallback(*this, {(const char *) contents, realSize}); dataCallback(*this, {static_cast<const char *>(contents), realSize});
} else { } else {
this->result.data.append((const char *) contents, realSize); this->result.data.append(static_cast<const char *>(contents), realSize);
} }
return realSize; return realSize;
@ -157,13 +156,13 @@ struct curlFileTransfer : public FileTransfer
static size_t writeCallbackWrapper(void * contents, size_t size, size_t nmemb, void * userp) static size_t writeCallbackWrapper(void * contents, size_t size, size_t nmemb, void * userp)
{ {
return ((TransferItem *) userp)->writeCallback(contents, size, nmemb); return static_cast<TransferItem *>(userp)->writeCallback(contents, size, nmemb);
} }
size_t headerCallback(void * contents, size_t size, size_t nmemb) size_t headerCallback(void * contents, size_t size, size_t nmemb)
{ {
size_t realSize = size * nmemb; size_t realSize = size * nmemb;
std::string line((char *) contents, realSize); std::string line(static_cast<char *>(contents), realSize);
printMsg(lvlVomit, "got header for '%s': %s", request.uri, trim(line)); printMsg(lvlVomit, "got header for '%s': %s", request.uri, trim(line));
static std::regex statusLine("HTTP/[^ ]+ +[0-9]+(.*)", std::regex::extended | std::regex::icase); static std::regex statusLine("HTTP/[^ ]+ +[0-9]+(.*)", std::regex::extended | std::regex::icase);
@ -204,7 +203,7 @@ struct curlFileTransfer : public FileTransfer
static size_t headerCallbackWrapper(void * contents, size_t size, size_t nmemb, void * userp) static size_t headerCallbackWrapper(void * contents, size_t size, size_t nmemb, void * userp)
{ {
return ((TransferItem *) userp)->headerCallback(contents, size, nmemb); return static_cast<TransferItem *>(userp)->headerCallback(contents, size, nmemb);
} }
int progressCallback(double dltotal, double dlnow) int progressCallback(double dltotal, double dlnow)
@ -219,7 +218,7 @@ struct curlFileTransfer : public FileTransfer
static int progressCallbackWrapper(void * userp, double dltotal, double dlnow, double ultotal, double ulnow) static int progressCallbackWrapper(void * userp, double dltotal, double dlnow, double ultotal, double ulnow)
{ {
return ((TransferItem *) userp)->progressCallback(dltotal, dlnow); return static_cast<TransferItem *>(userp)->progressCallback(dltotal, dlnow);
} }
static int debugCallback(CURL * handle, curl_infotype type, char * data, size_t size, void * userptr) static int debugCallback(CURL * handle, curl_infotype type, char * data, size_t size, void * userptr)
@ -246,7 +245,7 @@ struct curlFileTransfer : public FileTransfer
static size_t readCallbackWrapper(char *buffer, size_t size, size_t nitems, void * userp) static size_t readCallbackWrapper(char *buffer, size_t size, size_t nitems, void * userp)
{ {
return ((TransferItem *) userp)->readCallback(buffer, size, nitems); return static_cast<TransferItem *>(userp)->readCallback(buffer, size, nitems);
} }
void init() void init()

View file

@ -42,7 +42,7 @@ static void makeSymlink(const Path & link, const Path & target)
void LocalStore::addIndirectRoot(const Path & path) void LocalStore::addIndirectRoot(const Path & path)
{ {
std::string hash = hashString(htSHA1, path).to_string(Base32, false); std::string hash = hashString(HashType::SHA1, path).to_string(Base::Base32, false);
Path realRoot = canonPath(fmt("%1%/%2%/auto/%3%", stateDir, gcRootsDir, hash)); Path realRoot = canonPath(fmt("%1%/%2%/auto/%3%", stateDir, gcRootsDir, hash));
makeSymlink(realRoot, path); makeSymlink(realRoot, path);
} }

View file

@ -183,7 +183,7 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
<< ServeProto::Command::AddToStoreNar << ServeProto::Command::AddToStoreNar
<< printStorePath(info.path) << printStorePath(info.path)
<< (info.deriver ? printStorePath(*info.deriver) : "") << (info.deriver ? printStorePath(*info.deriver) : "")
<< info.narHash.to_string(Base16, false); << info.narHash.to_string(Base::Base16, false);
conn->to << ServeProto::write(*this, *conn, info.references); conn->to << ServeProto::write(*this, *conn, info.references);
conn->to conn->to
<< info.registrationTime << info.registrationTime

View file

@ -11,7 +11,6 @@
#include "finally.hh" #include "finally.hh"
#include "compression.hh" #include "compression.hh"
#include <iostream>
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
@ -539,9 +538,10 @@ void LocalStore::openDB(State & state, bool create)
{ {
SQLiteStmt stmt; SQLiteStmt stmt;
stmt.create(db, "pragma main.journal_mode;"); stmt.create(db, "pragma main.journal_mode;");
if (sqlite3_step(stmt) != SQLITE_ROW) auto use = stmt.use();
if (use.step() != SQLITE_ROW)
SQLiteError::throw_(db, "querying journal mode"); SQLiteError::throw_(db, "querying journal mode");
prevMode = std::string((const char *) sqlite3_column_text(stmt, 0)); prevMode = use.getStr(0);
} }
if (prevMode != mode && if (prevMode != mode &&
sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0, 0, 0) != SQLITE_OK) sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0, 0, 0) != SQLITE_OK)
@ -842,7 +842,7 @@ uint64_t LocalStore::addValidPath(State & state,
state.stmts->RegisterValidPath.use() state.stmts->RegisterValidPath.use()
(printStorePath(info.path)) (printStorePath(info.path))
(info.narHash.to_string(Base16, true)) (info.narHash.to_string(Base::Base16, true))
(info.registrationTime == 0 ? time(0) : info.registrationTime) (info.registrationTime == 0 ? time(0) : info.registrationTime)
(info.deriver ? printStorePath(*info.deriver) : "", (bool) info.deriver) (info.deriver ? printStorePath(*info.deriver) : "", (bool) info.deriver)
(info.narSize, info.narSize != 0) (info.narSize, info.narSize != 0)
@ -916,19 +916,22 @@ std::shared_ptr<const ValidPathInfo> LocalStore::queryPathInfoInternal(State & s
info->registrationTime = useQueryPathInfo.getInt(2); info->registrationTime = useQueryPathInfo.getInt(2);
auto s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 3); if (auto deriver = useQueryPathInfo.getStrNullable(3); deriver.has_value()) {
if (s) info->deriver = parseStorePath(s); info->deriver = parseStorePath(*deriver);
}
/* Note that narSize = NULL yields 0. */ /* Note that narSize = NULL yields 0. */
info->narSize = useQueryPathInfo.getInt(4); info->narSize = useQueryPathInfo.getInt(4);
info->ultimate = useQueryPathInfo.getInt(5) == 1; info->ultimate = useQueryPathInfo.getInt(5) == 1;
s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 6); if (auto sigs = useQueryPathInfo.getStrNullable(6); sigs.has_value()) {
if (s) info->sigs = tokenizeString<StringSet>(s, " "); info->sigs = tokenizeString<StringSet>(*sigs, " ");
}
s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 7); if (auto ca = useQueryPathInfo.getStrNullable(7); ca.has_value()) {
if (s) info->ca = ContentAddress::parseOpt(s); info->ca = ContentAddress::parseOpt(*ca);
}
/* Get the references. */ /* Get the references. */
auto useQueryReferences(state.stmts->QueryReferences.use()(info->id)); auto useQueryReferences(state.stmts->QueryReferences.use()(info->id));
@ -945,7 +948,7 @@ void LocalStore::updatePathInfo(State & state, const ValidPathInfo & info)
{ {
state.stmts->UpdatePathInfo.use() state.stmts->UpdatePathInfo.use()
(info.narSize, info.narSize != 0) (info.narSize, info.narSize != 0)
(info.narHash.to_string(Base16, true)) (info.narHash.to_string(Base::Base16, true))
(info.ultimate ? 1 : 0, info.ultimate) (info.ultimate ? 1 : 0, info.ultimate)
(concatStringsSep(" ", info.sigs), !info.sigs.empty()) (concatStringsSep(" ", info.sigs), !info.sigs.empty())
(renderContentAddress(info.ca), (bool) info.ca) (renderContentAddress(info.ca), (bool) info.ca)
@ -1063,9 +1066,9 @@ std::optional<StorePath> LocalStore::queryPathFromHashPart(const std::string & h
if (!useQueryPathFromHashPart.next()) return {}; if (!useQueryPathFromHashPart.next()) return {};
const char * s = (const char *) sqlite3_column_text(state->stmts->QueryPathFromHashPart, 0); auto s = useQueryPathFromHashPart.getStrNullable(0);
if (s && prefix.compare(0, prefix.size(), s, prefix.size()) == 0) if (s.has_value() && s->starts_with(prefix))
return parseStorePath(s); return parseStorePath(*s);
return {}; return {};
}); });
} }
@ -1123,7 +1126,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
StorePathSet paths; StorePathSet paths;
for (auto & [_, i] : infos) { for (auto & [_, i] : infos) {
assert(i.narHash.type == htSHA256); assert(i.narHash.type == HashType::SHA256);
if (isValidPath_(*state, i.path)) if (isValidPath_(*state, i.path))
updatePathInfo(*state, i); updatePathInfo(*state, i);
else else
@ -1241,7 +1244,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
/* While restoring the path from the NAR, compute the hash /* While restoring the path from the NAR, compute the hash
of the NAR. */ of the NAR. */
HashSink hashSink(htSHA256); HashSink hashSink(HashType::SHA256);
TeeSource wrapperSource { source, hashSink }; TeeSource wrapperSource { source, hashSink };
@ -1252,7 +1255,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
if (hashResult.first != info.narHash) if (hashResult.first != info.narHash)
throw Error("hash mismatch importing path '%s';\n specified: %s\n got: %s", throw Error("hash mismatch importing path '%s';\n specified: %s\n got: %s",
printStorePath(info.path), info.narHash.to_string(Base32, true), hashResult.first.to_string(Base32, true)); printStorePath(info.path), info.narHash.to_string(Base::Base32, true), hashResult.first.to_string(Base::Base32, true));
if (hashResult.second != info.narSize) if (hashResult.second != info.narSize)
throw Error("size mismatch importing path '%s';\n specified: %s\n got: %s", throw Error("size mismatch importing path '%s';\n specified: %s\n got: %s",
@ -1268,8 +1271,8 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
if (specified.hash != actualHash.hash) { 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), printStorePath(info.path),
specified.hash.to_string(Base32, true), specified.hash.to_string(Base::Base32, true),
actualHash.hash.to_string(Base32, true)); actualHash.hash.to_string(Base::Base32, true));
} }
} }
@ -1318,7 +1321,7 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, std::string_view name
auto *toRealloc = dumpBuffer.release(); auto *toRealloc = dumpBuffer.release();
if (auto realloced = realloc(toRealloc, oldSize + want)) { if (auto realloced = realloc(toRealloc, oldSize + want)) {
dumpBuffer.reset((char*) realloced); dumpBuffer.reset(static_cast<char *>(realloced));
} else { } else {
free(toRealloc); free(toRealloc);
throw std::bad_alloc(); throw std::bad_alloc();
@ -1404,8 +1407,8 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, std::string_view name
/* For computing the nar hash. In recursive SHA-256 mode, this /* For computing the nar hash. In recursive SHA-256 mode, this
is the same as the store hash, so no need to do it again. */ is the same as the store hash, so no need to do it again. */
auto narHash = std::pair { hash, size }; auto narHash = std::pair { hash, size };
if (method != FileIngestionMethod::Recursive || hashAlgo != htSHA256) { if (method != FileIngestionMethod::Recursive || hashAlgo != HashType::SHA256) {
HashSink narSink { htSHA256 }; HashSink narSink { HashType::SHA256 };
narSink << dumpPath(realPath); narSink << dumpPath(realPath);
narHash = narSink.finish(); narHash = narSink.finish();
} }
@ -1436,7 +1439,7 @@ StorePath LocalStore::addTextToStore(
std::string_view s, std::string_view s,
const StorePathSet & references, RepairFlag repair) const StorePathSet & references, RepairFlag repair)
{ {
auto hash = hashString(htSHA256, s); auto hash = hashString(HashType::SHA256, s);
auto dstPath = makeTextPath(name, TextInfo { auto dstPath = makeTextPath(name, TextInfo {
.hash = hash, .hash = hash,
.references = references, .references = references,
@ -1462,7 +1465,7 @@ StorePath LocalStore::addTextToStore(
StringSink sink; StringSink sink;
sink << dumpString(s); sink << dumpString(s);
auto narHash = hashString(htSHA256, sink.s); auto narHash = hashString(HashType::SHA256, sink.s);
optimisePath(realPath, repair); optimisePath(realPath, repair);
@ -1573,7 +1576,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
for (auto & link : readDirectory(linksDir)) { for (auto & link : readDirectory(linksDir)) {
printMsg(lvlTalkative, "checking contents of '%s'", link.name); printMsg(lvlTalkative, "checking contents of '%s'", link.name);
Path linkPath = linksDir + "/" + link.name; Path linkPath = linksDir + "/" + link.name;
std::string hash = hashPath(htSHA256, linkPath).first.to_string(Base32, false); std::string hash = hashPath(HashType::SHA256, linkPath).first.to_string(Base::Base32, false);
if (hash != link.name) { if (hash != link.name) {
printError("link '%s' was modified! expected hash '%s', got '%s'", printError("link '%s' was modified! expected hash '%s', got '%s'",
linkPath, link.name, hash); linkPath, link.name, hash);
@ -1590,7 +1593,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
printInfo("checking store hashes..."); printInfo("checking store hashes...");
Hash nullHash(htSHA256); Hash nullHash(HashType::SHA256);
for (auto & i : validPaths) { for (auto & i : validPaths) {
try { try {
@ -1606,7 +1609,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
if (info->narHash != nullHash && info->narHash != current.first) { if (info->narHash != nullHash && info->narHash != current.first) {
printError("path '%s' was modified! expected hash '%s', got '%s'", printError("path '%s' was modified! expected hash '%s', got '%s'",
printStorePath(i), info->narHash.to_string(Base32, true), current.first.to_string(Base32, true)); printStorePath(i), info->narHash.to_string(Base::Base32, true), current.first.to_string(Base::Base32, true));
if (repair) repairPath(i); else errors = true; if (repair) repairPath(i); else errors = true;
} else { } else {

View file

@ -45,7 +45,7 @@ std::map<StorePath, StorePath> makeContentAddressed(
auto narModuloHash = [&] { auto narModuloHash = [&] {
StringSource source{sink.s}; StringSource source{sink.s};
return computeHashModulo(htSHA256, oldHashPart, source).first; return computeHashModulo(HashType::SHA256, oldHashPart, source).first;
}(); }();
ValidPathInfo info { ValidPathInfo info {
@ -63,7 +63,7 @@ std::map<StorePath, StorePath> makeContentAddressed(
const auto rewritten = rewriteStrings(sink.s, {{oldHashPart, std::string(info.path.hashPart())}}); const auto rewritten = rewriteStrings(sink.s, {{oldHashPart, std::string(info.path.hashPart())}});
info.narHash = hashString(htSHA256, rewritten); info.narHash = hashString(HashType::SHA256, rewritten);
info.narSize = sink.s.size(); info.narSize = sink.s.size();
StringSource source(rewritten); StringSource source(rewritten);

View file

@ -334,9 +334,9 @@ public:
(std::string(info->path.name())) (std::string(info->path.name()))
(narInfo ? narInfo->url : "", narInfo != 0) (narInfo ? narInfo->url : "", narInfo != 0)
(narInfo ? narInfo->compression : "", narInfo != 0) (narInfo ? narInfo->compression : "", narInfo != 0)
(narInfo && narInfo->fileHash ? narInfo->fileHash->to_string(Base32, true) : "", narInfo && narInfo->fileHash) (narInfo && narInfo->fileHash ? narInfo->fileHash->to_string(Base::Base32, true) : "", narInfo && narInfo->fileHash)
(narInfo ? narInfo->fileSize : 0, narInfo != 0 && narInfo->fileSize) (narInfo ? narInfo->fileSize : 0, narInfo != 0 && narInfo->fileSize)
(info->narHash.to_string(Base32, true)) (info->narHash.to_string(Base::Base32, true))
(info->narSize) (info->narSize)
(concatStringsSep(" ", info->shortRefs())) (concatStringsSep(" ", info->shortRefs()))
(info->deriver ? std::string(info->deriver->to_string()) : "", (bool) info->deriver) (info->deriver ? std::string(info->deriver->to_string()) : "", (bool) info->deriver)

View file

@ -104,11 +104,11 @@ std::string NarInfo::to_string(const Store & store) const
res += "URL: " + url + "\n"; res += "URL: " + url + "\n";
assert(compression != ""); assert(compression != "");
res += "Compression: " + compression + "\n"; res += "Compression: " + compression + "\n";
assert(fileHash && fileHash->type == htSHA256); assert(fileHash && fileHash->type == HashType::SHA256);
res += "FileHash: " + fileHash->to_string(Base32, true) + "\n"; res += "FileHash: " + fileHash->to_string(Base::Base32, true) + "\n";
res += "FileSize: " + std::to_string(fileSize) + "\n"; res += "FileSize: " + std::to_string(fileSize) + "\n";
assert(narHash.type == htSHA256); assert(narHash.type == HashType::SHA256);
res += "NarHash: " + narHash.to_string(Base32, true) + "\n"; res += "NarHash: " + narHash.to_string(Base::Base32, true) + "\n";
res += "NarSize: " + std::to_string(narSize) + "\n"; res += "NarSize: " + std::to_string(narSize) + "\n";
res += "References: " + concatStringsSep(" ", shortRefs()) + "\n"; res += "References: " + concatStringsSep(" ", shortRefs()) + "\n";

View file

@ -2,14 +2,11 @@
#include "globals.hh" #include "globals.hh"
#include "signals.hh" #include "signals.hh"
#include <cstdlib>
#include <cstring> #include <cstring>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <regex>
namespace nix { namespace nix {
@ -145,17 +142,17 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
Also note that if `path' is a symlink, then we're hashing the Also note that if `path' is a symlink, then we're hashing the
contents of the symlink (i.e. the result of readlink()), not contents of the symlink (i.e. the result of readlink()), not
the contents of the target (which may not even exist). */ the contents of the target (which may not even exist). */
Hash hash = hashPath(htSHA256, path).first; Hash hash = hashPath(HashType::SHA256, path).first;
debug("'%1%' has hash '%2%'", path, hash.to_string(Base32, true)); debug("'%1%' has hash '%2%'", path, hash.to_string(Base::Base32, true));
/* Check if this is a known hash. */ /* Check if this is a known hash. */
Path linkPath = linksDir + "/" + hash.to_string(Base32, false); Path linkPath = linksDir + "/" + hash.to_string(Base::Base32, false);
/* Maybe delete the link, if it has been corrupted. */ /* Maybe delete the link, if it has been corrupted. */
if (pathExists(linkPath)) { if (pathExists(linkPath)) {
auto stLink = lstat(linkPath); auto stLink = lstat(linkPath);
if (st.st_size != stLink.st_size if (st.st_size != stLink.st_size
|| (repair && hash != hashPath(htSHA256, linkPath).first)) || (repair && hash != hashPath(HashType::SHA256, linkPath).first))
{ {
// XXX: Consider overwriting linkPath with our valid version. // XXX: Consider overwriting linkPath with our valid version.
warn("removing corrupted link '%s'", linkPath); warn("removing corrupted link '%s'", linkPath);

View file

@ -29,7 +29,7 @@ std::string ValidPathInfo::fingerprint(const Store & store) const
store.printStorePath(path)); store.printStorePath(path));
return return
"1;" + store.printStorePath(path) + ";" "1;" + store.printStorePath(path) + ";"
+ narHash.to_string(Base32, true) + ";" + narHash.to_string(Base::Base32, true) + ";"
+ std::to_string(narSize) + ";" + std::to_string(narSize) + ";"
+ concatStringsSep(",", store.printStorePathSet(references)); + concatStringsSep(",", store.printStorePathSet(references));
} }

View file

@ -46,7 +46,7 @@ std::pair<StorePathSet, HashResult> scanForReferences(
const std::string & path, const std::string & path,
const StorePathSet & refs) const StorePathSet & refs)
{ {
HashSink hashSink { htSHA256 }; HashSink hashSink { HashType::SHA256 };
auto found = scanForReferences(hashSink, path, refs); auto found = scanForReferences(hashSink, path, refs);
auto hash = hashSink.finish(); auto hash = hashSink.finish();
return std::pair<StorePathSet, HashResult>(found, hash); return std::pair<StorePathSet, HashResult>(found, hash);

View file

@ -46,7 +46,7 @@ StorePath::StorePath(std::string_view _baseName)
} }
StorePath::StorePath(const Hash & hash, std::string_view _name) StorePath::StorePath(const Hash & hash, std::string_view _name)
: baseName((hash.to_string(Base32, false) + "-").append(std::string(_name))) : baseName((hash.to_string(Base::Base32, false) + "-").append(std::string(_name)))
{ {
checkName(baseName, name()); checkName(baseName, name());
} }
@ -60,7 +60,7 @@ StorePath StorePath::dummy("ffffffffffffffffffffffffffffffff-x");
StorePath StorePath::random(std::string_view name) StorePath StorePath::random(std::string_view name)
{ {
Hash hash(htSHA1); Hash hash(HashType::SHA1);
randombytes_buf(hash.hash, hash.hashSize); randombytes_buf(hash.hash, hash.hashSize);
return StorePath(hash, name); return StorePath(hash, name);
} }

View file

@ -39,7 +39,7 @@ struct DrvOutput {
std::string to_string() const; std::string to_string() const;
std::string strHash() const std::string strHash() const
{ return drvHash.to_string(Base16, true); } { return drvHash.to_string(Base::Base16, true); }
static DrvOutput parse(const std::string &); static DrvOutput parse(const std::string &);

View file

@ -397,7 +397,7 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
std::visit(overloaded { std::visit(overloaded {
[&](const TextIngestionMethod & thm) -> void { [&](const TextIngestionMethod & thm) -> void {
if (hashType != htSHA256) if (hashType != HashType::SHA256)
throw UnimplementedError("When adding text-hashed data called '%s', only SHA-256 is supported but '%s' was given", throw UnimplementedError("When adding text-hashed data called '%s', only SHA-256 is supported but '%s' was given",
name, printHashType(hashType)); name, printHashType(hashType));
std::string s = dump.drain(); std::string s = dump.drain();
@ -409,7 +409,7 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
conn->to conn->to
<< WorkerProto::Op::AddToStore << WorkerProto::Op::AddToStore
<< name << name
<< ((hashType == htSHA256 && fim == FileIngestionMethod::Recursive) ? 0 : 1) /* backwards compatibility hack */ << ((hashType == HashType::SHA256 && fim == FileIngestionMethod::Recursive) ? 0 : 1) /* backwards compatibility hack */
<< (fim == FileIngestionMethod::Recursive ? 1 : 0) << (fim == FileIngestionMethod::Recursive ? 1 : 0)
<< printHashType(hashType); << printHashType(hashType);
@ -461,7 +461,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
conn->to << WorkerProto::Op::AddToStoreNar conn->to << WorkerProto::Op::AddToStoreNar
<< printStorePath(info.path) << printStorePath(info.path)
<< (info.deriver ? printStorePath(*info.deriver) : "") << (info.deriver ? printStorePath(*info.deriver) : "")
<< info.narHash.to_string(Base16, false); << info.narHash.to_string(Base::Base16, false);
conn->to << WorkerProto::write(*this, *conn, info.references); conn->to << WorkerProto::write(*this, *conn, info.references);
conn->to << info.registrationTime << info.narSize conn->to << info.registrationTime << info.narSize
<< info.ultimate << info.sigs << renderContentAddress(info.ca) << info.ultimate << info.sigs << renderContentAddress(info.ca)
@ -533,7 +533,7 @@ StorePath RemoteStore::addTextToStore(
RepairFlag repair) RepairFlag repair)
{ {
StringSource source(s); StringSource source(s);
return addCAToStore(source, name, TextIngestionMethod {}, htSHA256, references, repair)->path; return addCAToStore(source, name, TextIngestionMethod {}, HashType::SHA256, references, repair)->path;
} }
void RemoteStore::registerDrvOutput(const Realisation & info) void RemoteStore::registerDrvOutput(const Realisation & info)

View file

@ -84,7 +84,7 @@ public:
* Add a content-addressable store path. Does not support references. `dump` will be drained. * Add a content-addressable store path. Does not support references. `dump` will be drained.
*/ */
StorePath addToStoreFromDump(Source & dump, std::string_view name, StorePath addToStoreFromDump(Source & dump, std::string_view name,
FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair, const StorePathSet & references = StorePathSet()) override; FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = HashType::SHA256, RepairFlag repair = NoRepair, const StorePathSet & references = StorePathSet()) override;
void addToStore(const ValidPathInfo & info, Source & nar, void addToStore(const ValidPathInfo & info, Source & nar,
RepairFlag repair, CheckSigsFlag checkSigs) override; RepairFlag repair, CheckSigsFlag checkSigs) override;

View file

@ -88,7 +88,7 @@ WireFormatGenerator ServeProto::Serialise<UnkeyedValidPathInfo>::write(const Sto
co_yield info.narSize; // downloadSize, lie a little co_yield info.narSize; // downloadSize, lie a little
co_yield info.narSize; co_yield info.narSize;
if (GET_PROTOCOL_MINOR(conn.version) >= 4) { if (GET_PROTOCOL_MINOR(conn.version) >= 4) {
co_yield info.narHash.to_string(Base32, true); co_yield info.narHash.to_string(Base::Base32, true);
co_yield renderContentAddress(info.ca); co_yield renderContentAddress(info.ca);
co_yield info.sigs; co_yield info.sigs;
} }

View file

@ -199,11 +199,20 @@ bool SQLiteStmt::Use::next()
return r == SQLITE_ROW; return r == SQLITE_ROW;
} }
std::optional<std::string> SQLiteStmt::Use::getStrNullable(int col)
{
auto s = reinterpret_cast<const char *>(sqlite3_column_text(stmt, col));
return s != nullptr ? std::make_optional<std::string>((s)) : std::nullopt;
}
std::string SQLiteStmt::Use::getStr(int col) std::string SQLiteStmt::Use::getStr(int col)
{ {
auto s = (const char *) sqlite3_column_text(stmt, col); if (auto res = getStrNullable(col); res.has_value()) {
assert(s); return *res;
return s; } else {
// FIXME: turn into fatal non-exception error with actual formatting when we have those
assert(false && "sqlite3 retrieved unexpected null");
}
} }
int64_t SQLiteStmt::Use::getInt(int col) int64_t SQLiteStmt::Use::getInt(int col)

View file

@ -107,6 +107,7 @@ struct SQLiteStmt
bool next(); bool next();
std::string getStr(int col); std::string getStr(int col);
std::optional<std::string> getStrNullable(int col);
int64_t getInt(int col); int64_t getInt(int col);
bool isNull(int col); bool isNull(int col);
}; };

View file

@ -156,7 +156,7 @@ StorePath Store::makeStorePath(std::string_view type,
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
auto s = std::string(type) + ":" + std::string(hash) auto s = std::string(type) + ":" + std::string(hash)
+ ":" + storeDir + ":" + std::string(name); + ":" + storeDir + ":" + std::string(name);
auto h = compressHash(hashString(htSHA256, s), 20); auto h = compressHash(hashString(HashType::SHA256, s), 20);
return StorePath(h, name); return StorePath(h, name);
} }
@ -164,7 +164,7 @@ StorePath Store::makeStorePath(std::string_view type,
StorePath Store::makeStorePath(std::string_view type, StorePath Store::makeStorePath(std::string_view type,
const Hash & hash, std::string_view name) const const Hash & hash, std::string_view name) const
{ {
return makeStorePath(type, hash.to_string(Base16, true), name); return makeStorePath(type, hash.to_string(Base::Base16, true), name);
} }
@ -194,7 +194,7 @@ static std::string makeType(
StorePath Store::makeFixedOutputPath(std::string_view name, const FixedOutputInfo & info) const StorePath Store::makeFixedOutputPath(std::string_view name, const FixedOutputInfo & info) const
{ {
if (info.hash.type == htSHA256 && info.method == FileIngestionMethod::Recursive) { if (info.hash.type == HashType::SHA256 && info.method == FileIngestionMethod::Recursive) {
return makeStorePath(makeType(*this, "source", info.references), info.hash, name); return makeStorePath(makeType(*this, "source", info.references), info.hash, name);
} else { } else {
if (!info.references.empty()) { if (!info.references.empty()) {
@ -202,10 +202,10 @@ StorePath Store::makeFixedOutputPath(std::string_view name, const FixedOutputInf
name); name);
} }
return makeStorePath("output:out", return makeStorePath("output:out",
hashString(htSHA256, hashString(HashType::SHA256,
"fixed:out:" "fixed:out:"
+ makeFileIngestionPrefix(info.method) + makeFileIngestionPrefix(info.method)
+ info.hash.to_string(Base16, true) + ":"), + info.hash.to_string(Base::Base16, true) + ":"),
name); name);
} }
} }
@ -213,7 +213,7 @@ StorePath Store::makeFixedOutputPath(std::string_view name, const FixedOutputInf
StorePath Store::makeTextPath(std::string_view name, const TextInfo & info) const StorePath Store::makeTextPath(std::string_view name, const TextInfo & info) const
{ {
assert(info.hash.type == htSHA256); assert(info.hash.type == HashType::SHA256);
return makeStorePath( return makeStorePath(
makeType(*this, "text", StoreReferences { makeType(*this, "text", StoreReferences {
.others = info.references, .others = info.references,
@ -259,7 +259,7 @@ StorePath Store::computeStorePathForText(
const StorePathSet & references) const const StorePathSet & references) const
{ {
return makeTextPath(name, TextInfo { return makeTextPath(name, TextInfo {
.hash = hashString(htSHA256, s), .hash = hashString(HashType::SHA256, s),
.references = references, .references = references,
}); });
} }
@ -407,7 +407,7 @@ ValidPathInfo Store::addToStoreSlow(std::string_view name, const Path & srcPath,
FileIngestionMethod method, HashType hashAlgo, FileIngestionMethod method, HashType hashAlgo,
std::optional<Hash> expectedCAHash) std::optional<Hash> expectedCAHash)
{ {
HashSink narHashSink { htSHA256 }; HashSink narHashSink { HashType::SHA256 };
HashSink caHashSink { hashAlgo }; HashSink caHashSink { hashAlgo };
/* Note that fileSink and unusualHashTee must be mutually exclusive, since /* Note that fileSink and unusualHashTee must be mutually exclusive, since
@ -416,7 +416,7 @@ ValidPathInfo Store::addToStoreSlow(std::string_view name, const Path & srcPath,
RetrieveRegularNARSink fileSink { caHashSink }; RetrieveRegularNARSink fileSink { caHashSink };
TeeSink unusualHashTee { narHashSink, caHashSink }; TeeSink unusualHashTee { narHashSink, caHashSink };
auto & narSink = method == FileIngestionMethod::Recursive && hashAlgo != htSHA256 auto & narSink = method == FileIngestionMethod::Recursive && hashAlgo != HashType::SHA256
? static_cast<Sink &>(unusualHashTee) ? static_cast<Sink &>(unusualHashTee)
: narHashSink; : narHashSink;
@ -442,7 +442,7 @@ ValidPathInfo Store::addToStoreSlow(std::string_view name, const Path & srcPath,
finish. */ finish. */
auto [narHash, narSize] = narHashSink.finish(); auto [narHash, narSize] = narHashSink.finish();
auto hash = method == FileIngestionMethod::Recursive && hashAlgo == htSHA256 auto hash = method == FileIngestionMethod::Recursive && hashAlgo == HashType::SHA256
? narHash ? narHash
: caHashSink.finish().first; : caHashSink.finish().first;
@ -854,7 +854,7 @@ std::string Store::makeValidityRegistration(const StorePathSet & paths,
auto info = queryPathInfo(i); auto info = queryPathInfo(i);
if (showHash) { if (showHash) {
s += info->narHash.to_string(Base16, false) + "\n"; s += info->narHash.to_string(Base::Base16, false) + "\n";
s += fmt("%1%\n", info->narSize); s += fmt("%1%\n", info->narSize);
} }
@ -1257,7 +1257,7 @@ std::optional<ValidPathInfo> decodeValidPathInfo(const Store & store, std::istre
if (!hashGiven) { if (!hashGiven) {
std::string s; std::string s;
getline(str, s); getline(str, s);
auto narHash = Hash::parseAny(s, htSHA256); auto narHash = Hash::parseAny(s, HashType::SHA256);
getline(str, s); getline(str, s);
auto narSize = string2Int<uint64_t>(s); auto narSize = string2Int<uint64_t>(s);
if (!narSize) throw Error("number expected"); if (!narSize) throw Error("number expected");

View file

@ -311,7 +311,7 @@ public:
*/ */
std::pair<StorePath, Hash> computeStorePathForPath(std::string_view name, std::pair<StorePath, Hash> computeStorePathForPath(std::string_view name,
const Path & srcPath, FileIngestionMethod method = FileIngestionMethod::Recursive, const Path & srcPath, FileIngestionMethod method = FileIngestionMethod::Recursive,
HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter) const; HashType hashAlgo = HashType::SHA256, PathFilter & filter = defaultPathFilter) const;
/** /**
* Preparatory part of addTextToStore(). * Preparatory part of addTextToStore().
@ -524,7 +524,7 @@ public:
std::string_view name, std::string_view name,
const Path & srcPath, const Path & srcPath,
FileIngestionMethod method = FileIngestionMethod::Recursive, FileIngestionMethod method = FileIngestionMethod::Recursive,
HashType hashAlgo = htSHA256, HashType hashAlgo = HashType::SHA256,
PathFilter & filter = defaultPathFilter, PathFilter & filter = defaultPathFilter,
RepairFlag repair = NoRepair, RepairFlag repair = NoRepair,
const StorePathSet & references = StorePathSet()); const StorePathSet & references = StorePathSet());
@ -535,7 +535,7 @@ public:
* memory. * memory.
*/ */
ValidPathInfo addToStoreSlow(std::string_view name, const Path & srcPath, ValidPathInfo addToStoreSlow(std::string_view name, const Path & srcPath,
FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256, FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = HashType::SHA256,
std::optional<Hash> expectedCAHash = {}); std::optional<Hash> expectedCAHash = {});
/** /**
@ -548,7 +548,7 @@ public:
* \todo remove? * \todo remove?
*/ */
virtual StorePath addToStoreFromDump(Source & dump, std::string_view name, virtual StorePath addToStoreFromDump(Source & dump, std::string_view name,
FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair, FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = HashType::SHA256, RepairFlag repair = NoRepair,
const StorePathSet & references = StorePathSet()) const StorePathSet & references = StorePathSet())
{ unsupported("addToStoreFromDump"); } { unsupported("addToStoreFromDump"); }
@ -679,7 +679,7 @@ public:
*/ */
nlohmann::json pathInfoToJSON(const StorePathSet & storePaths, nlohmann::json pathInfoToJSON(const StorePathSet & storePaths,
bool includeImpureInfo, bool showClosureSize, bool includeImpureInfo, bool showClosureSize,
Base hashBase = Base32, Base hashBase = Base::Base32,
AllowInvalidFlag allowInvalid = DisallowInvalid); AllowInvalidFlag allowInvalid = DisallowInvalid);
/** /**

View file

@ -158,7 +158,7 @@ WireFormatGenerator WorkerProto::Serialise<ValidPathInfo>::write(const Store & s
UnkeyedValidPathInfo WorkerProto::Serialise<UnkeyedValidPathInfo>::read(const Store & store, ReadConn conn) UnkeyedValidPathInfo WorkerProto::Serialise<UnkeyedValidPathInfo>::read(const Store & store, ReadConn conn)
{ {
auto deriver = readString(conn.from); auto deriver = readString(conn.from);
auto narHash = Hash::parseAny(readString(conn.from), htSHA256); auto narHash = Hash::parseAny(readString(conn.from), HashType::SHA256);
UnkeyedValidPathInfo info(narHash); UnkeyedValidPathInfo info(narHash);
if (deriver != "") info.deriver = store.parseStorePath(deriver); if (deriver != "") info.deriver = store.parseStorePath(deriver);
info.references = WorkerProto::Serialise<StorePathSet>::read(store, conn); info.references = WorkerProto::Serialise<StorePathSet>::read(store, conn);
@ -174,7 +174,7 @@ UnkeyedValidPathInfo WorkerProto::Serialise<UnkeyedValidPathInfo>::read(const St
WireFormatGenerator WorkerProto::Serialise<UnkeyedValidPathInfo>::write(const Store & store, WriteConn conn, const UnkeyedValidPathInfo & pathInfo) WireFormatGenerator WorkerProto::Serialise<UnkeyedValidPathInfo>::write(const Store & store, WriteConn conn, const UnkeyedValidPathInfo & pathInfo)
{ {
co_yield (pathInfo.deriver ? store.printStorePath(*pathInfo.deriver) : ""); co_yield (pathInfo.deriver ? store.printStorePath(*pathInfo.deriver) : "");
co_yield pathInfo.narHash.to_string(Base16, false); co_yield pathInfo.narHash.to_string(Base::Base16, false);
co_yield WorkerProto::write(store, conn, pathInfo.references); co_yield WorkerProto::write(store, conn, pathInfo.references);
co_yield pathInfo.registrationTime; co_yield pathInfo.registrationTime;
co_yield pathInfo.narSize; co_yield pathInfo.narSize;

View file

@ -15,7 +15,7 @@
namespace nix { namespace nix {
enum HashType : char; enum class HashType : char;
class MultiCommand; class MultiCommand;

140
src/libutil/charptr-cast.hh Normal file
View file

@ -0,0 +1,140 @@
#pragma once
/** @file Safe casts between character pointer types. */
#include <concepts> // IWYU pragma: keep
#include <type_traits>
namespace nix {
namespace charptr_cast_detail {
/** Custom version of std::decay that does not eat CV qualifiers on \c {char * const}. */
template<typename T>
struct DecayArrayInternal
{
using type = T;
};
template <typename T>
struct DecayArrayInternal<T[]>
{
using type = T *;
};
template <typename T, std::size_t N>
struct DecayArrayInternal<T[N]>
{
using type = T *;
};
template <typename T>
using DecayArray = DecayArrayInternal<T>::type;
/** Is a character type for the purposes of safe reinterpret_cast. */
template<typename T>
concept IsChar = std::same_as<T, char> || std::same_as<T, unsigned char>;
template<typename T>
concept IsConvertibleToChar = std::same_as<T, char8_t> || std::same_as<T, void> || IsChar<T>;
template<typename T>
concept IsDecayOrPointer = std::is_pointer_v<T> || std::is_pointer_v<DecayArray<T>>;
template<typename From, typename To>
concept ValidQualifiers = requires {
// Does not discard const
requires !std::is_const_v<From> || std::is_const_v<To>;
// Don't deal with volatile
requires !std::is_volatile_v<From> && !std::is_volatile_v<To>;
};
template<typename From, typename To>
concept BaseCase = requires {
// Cannot cast away const
requires ValidQualifiers<From, To>;
// At base case, neither should be pointers
requires !std::is_pointer_v<From> && !std::is_pointer_v<To>;
// Finally are the types compatible?
requires IsConvertibleToChar<std::remove_cv_t<From>>;
requires IsChar<std::remove_cv_t<To>>;
};
static_assert(BaseCase<char, char>);
static_assert(BaseCase<unsigned char, char>);
static_assert(BaseCase<char8_t, char>);
static_assert(!BaseCase<const char8_t, char>);
static_assert(!BaseCase<const char8_t, unsigned char>);
static_assert(BaseCase<void, unsigned char>);
// Not legal to cast to char8_t
static_assert(!BaseCase<void, char8_t>);
// No pointers
static_assert(!BaseCase<void *, char8_t>);
static_assert(!BaseCase<char *, char *>);
// Required to be written in the old style because recursion in concepts is not
// allowed. Personally I think the committee hates fun.
template<typename From, typename To, typename = void>
struct RecursionHelper : std::false_type
{};
template<typename From, typename To>
struct RecursionHelper<From, To, std::enable_if_t<BaseCase<From, To>>> : std::true_type
{};
template<typename From, typename To>
struct RecursionHelper<
From,
To,
std::enable_if_t<std::is_pointer_v<From> && std::is_pointer_v<To> && ValidQualifiers<From, To>>>
: RecursionHelper<std::remove_pointer_t<From>, std::remove_pointer_t<To>>
{};
template<typename From, typename To>
concept IsCharCastable = requires {
// We only decay arrays in From for safety reasons. There is almost no reason
// to cast *into* an array and such code probably needs closer inspection
// anyway.
requires RecursionHelper<DecayArray<From>, To>::value;
requires IsDecayOrPointer<From> && std::is_pointer_v<To>;
};
static_assert(!IsCharCastable<char **, char *>);
static_assert(IsCharCastable<char *, char *>);
static_assert(!IsCharCastable<const char *, char *>);
static_assert(!IsCharCastable<volatile char *, char *>);
static_assert(!IsCharCastable<char *, volatile char *>);
static_assert(IsCharCastable<char *, const char *>);
static_assert(IsCharCastable<char **, const char **>);
static_assert(IsCharCastable<char **, const char * const *>);
static_assert(!IsCharCastable<char * const *, const char **>);
static_assert(!IsCharCastable<char, char>);
static_assert(IsCharCastable<const char *, const unsigned char *>);
static_assert(!IsCharCastable<char [64][64], char **>);
static_assert(IsCharCastable<char [64], char *>);
}
/** Casts between character pointers with guaranteed safety. If this compiles,
* it is at least a sound conversion per C++23 §7.2.1 line 11.
*
* This will not let you:
* - Turn things into void *
* - Turn things that are not char into char
* - Turn things into things that are not char
* - Cast away const
*
* At every level in the pointer indirections, \c To must as const or more
* const than \c From.
*
* \c From may be any character pointer or void pointer or an array of characters.
*
* N.B. Be careful, the template args are in the possibly-surprising
* order To, From due to deduction.
*/
template<typename To, typename From>
requires charptr_cast_detail::IsCharCastable<From, To>
inline To charptr_cast(From p)
{
return reinterpret_cast<To>(p);
}
}

View file

@ -119,8 +119,8 @@ private:
static ssize_t callback_write(struct archive * archive, void * _self, const void * buffer, size_t length) static ssize_t callback_write(struct archive * archive, void * _self, const void * buffer, size_t length)
{ {
auto self = (ArchiveCompressionSink *) _self; auto self = static_cast<ArchiveCompressionSink *>(_self);
self->nextSink({(const char *) buffer, length}); self->nextSink({static_cast<const char *>(buffer), length});
return length; return length;
} }
}; };
@ -160,7 +160,7 @@ struct BrotliDecompressionSource : Source
size_t read(char * data, size_t len) override size_t read(char * data, size_t len) override
{ {
uint8_t * out = (uint8_t *) data; uint8_t * out = reinterpret_cast<uint8_t *>(data);
const auto * begin = out; const auto * begin = out;
while (len && !BrotliDecoderIsFinished(state.get())) { while (len && !BrotliDecoderIsFinished(state.get())) {
@ -172,7 +172,7 @@ struct BrotliDecompressionSource : Source
} catch (EndOfFile &) { } catch (EndOfFile &) {
break; break;
} }
next_in = (const uint8_t *) buf.get(); next_in = reinterpret_cast<const uint8_t *>(buf.get());
} }
if (!BrotliDecoderDecompressStream( if (!BrotliDecoderDecompressStream(
@ -238,7 +238,7 @@ struct BrotliCompressionSink : ChunkedCompressionSink
void writeInternal(std::string_view data) override void writeInternal(std::string_view data) override
{ {
auto next_in = (const uint8_t *) data.data(); auto next_in = reinterpret_cast<const uint8_t *>(data.data());
size_t avail_in = data.size(); size_t avail_in = data.size();
uint8_t * next_out = outbuf; uint8_t * next_out = outbuf;
size_t avail_out = sizeof(outbuf); size_t avail_out = sizeof(outbuf);
@ -254,7 +254,7 @@ struct BrotliCompressionSink : ChunkedCompressionSink
throw CompressionError("error while compressing brotli compression"); throw CompressionError("error while compressing brotli compression");
if (avail_out < sizeof(outbuf) || avail_in == 0) { if (avail_out < sizeof(outbuf) || avail_in == 0) {
nextSink({(const char *) outbuf, sizeof(outbuf) - avail_out}); nextSink({reinterpret_cast<const char *>(outbuf), sizeof(outbuf) - avail_out});
next_out = outbuf; next_out = outbuf;
avail_out = sizeof(outbuf); avail_out = sizeof(outbuf);
} }

View file

@ -115,7 +115,7 @@ Generator<Bytes> drainFDSource(int fd, bool block)
throw SysError("reading from file"); throw SysError("reading from file");
} }
else if (rd == 0) break; else if (rd == 0) break;
else co_yield std::span{(char *) buf.data(), (size_t) rd}; else co_yield std::span{reinterpret_cast<char *>(buf.data()), (size_t) rd};
} }
} }

View file

@ -567,9 +567,8 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix) std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
{ {
Path tmpl(defaultTempDir() + "/" + prefix + ".XXXXXX"); Path tmpl(defaultTempDir() + "/" + prefix + ".XXXXXX");
// Strictly speaking, this is UB, but who cares...
// FIXME: use O_TMPFILE. // FIXME: use O_TMPFILE.
AutoCloseFD fd(mkstemp((char *) tmpl.c_str())); AutoCloseFD fd(mkstemp(tmpl.data()));
if (!fd) if (!fd)
throw SysError("creating temporary file '%s'", tmpl); throw SysError("creating temporary file '%s'", tmpl);
closeOnExec(fd.get()); closeOnExec(fd.get());

View file

@ -22,7 +22,7 @@ public:
Finally(Finally &&other) : fun(std::move(other.fun)) { Finally(Finally &&other) : fun(std::move(other.fun)) {
other.movedFrom = true; other.movedFrom = true;
} }
~Finally() noexcept(false) ~Finally() noexcept(noexcept(fun()))
{ {
try { try {
if (!movedFrom) if (!movedFrom)

View file

@ -18,10 +18,10 @@ namespace nix {
static size_t regularHashSize(HashType type) { static size_t regularHashSize(HashType type) {
switch (type) { switch (type) {
case htMD5: return md5HashSize; case HashType::MD5: return md5HashSize;
case htSHA1: return sha1HashSize; case HashType::SHA1: return sha1HashSize;
case htSHA256: return sha256HashSize; case HashType::SHA256: return sha256HashSize;
case htSHA512: return sha512HashSize; case HashType::SHA512: return sha512HashSize;
} }
abort(); abort();
} }
@ -109,34 +109,33 @@ static std::string printHash32(const Hash & hash)
std::string printHash16or32(const Hash & hash) std::string printHash16or32(const Hash & hash)
{ {
assert(hash.type); return hash.to_string(hash.type == HashType::MD5 ? Base::Base16 : Base::Base32, false);
return hash.to_string(hash.type == htMD5 ? Base16 : Base32, false);
} }
std::string Hash::to_string(Base base, bool includeType) const std::string Hash::to_string(Base base, bool includeType) const
{ {
std::string s; std::string s;
if (base == SRI || includeType) { if (base == Base::SRI || includeType) {
s += printHashType(type); s += printHashType(type);
s += base == SRI ? '-' : ':'; s += base == Base::SRI ? '-' : ':';
} }
switch (base) { switch (base) {
case Base16: case Base::Base16:
s += printHash16(*this); s += printHash16(*this);
break; break;
case Base32: case Base::Base32:
s += printHash32(*this); s += printHash32(*this);
break; break;
case Base64: case Base::Base64:
case SRI: case Base::SRI:
s += base64Encode(std::string_view((const char *) hash, hashSize)); s += base64Encode(std::string_view(reinterpret_cast<const char *>(hash), hashSize));
break; break;
} }
return s; return s;
} }
Hash Hash::dummy(htSHA256); Hash Hash::dummy(HashType::SHA256);
Hash Hash::parseSRI(std::string_view original) { Hash Hash::parseSRI(std::string_view original) {
auto rest = original; auto rest = original;
@ -266,7 +265,7 @@ Hash newHashAllowEmpty(std::string_view hashStr, std::optional<HashType> ht)
if (!ht) if (!ht)
throw BadHash("empty hash requires explicit hash type"); throw BadHash("empty hash requires explicit hash type");
Hash h(*ht); Hash h(*ht);
warn("found empty hash, assuming '%s'", h.to_string(SRI, true)); warn("found empty hash, assuming '%s'", h.to_string(Base::SRI, true));
return h; return h;
} else } else
return Hash::parseAny(hashStr, ht); return Hash::parseAny(hashStr, ht);
@ -284,29 +283,29 @@ union Ctx
static void start(HashType ht, Ctx & ctx) static void start(HashType ht, Ctx & ctx)
{ {
if (ht == htMD5) MD5_Init(&ctx.md5); if (ht == HashType::MD5) MD5_Init(&ctx.md5);
else if (ht == htSHA1) SHA1_Init(&ctx.sha1); else if (ht == HashType::SHA1) SHA1_Init(&ctx.sha1);
else if (ht == htSHA256) SHA256_Init(&ctx.sha256); else if (ht == HashType::SHA256) SHA256_Init(&ctx.sha256);
else if (ht == htSHA512) SHA512_Init(&ctx.sha512); else if (ht == HashType::SHA512) SHA512_Init(&ctx.sha512);
} }
static void update(HashType ht, Ctx & ctx, static void update(HashType ht, Ctx & ctx,
std::string_view data) std::string_view data)
{ {
if (ht == htMD5) MD5_Update(&ctx.md5, data.data(), data.size()); if (ht == HashType::MD5) MD5_Update(&ctx.md5, data.data(), data.size());
else if (ht == htSHA1) SHA1_Update(&ctx.sha1, data.data(), data.size()); else if (ht == HashType::SHA1) SHA1_Update(&ctx.sha1, data.data(), data.size());
else if (ht == htSHA256) SHA256_Update(&ctx.sha256, data.data(), data.size()); else if (ht == HashType::SHA256) SHA256_Update(&ctx.sha256, data.data(), data.size());
else if (ht == htSHA512) SHA512_Update(&ctx.sha512, data.data(), data.size()); else if (ht == HashType::SHA512) SHA512_Update(&ctx.sha512, data.data(), data.size());
} }
static void finish(HashType ht, Ctx & ctx, unsigned char * hash) static void finish(HashType ht, Ctx & ctx, unsigned char * hash)
{ {
if (ht == htMD5) MD5_Final(hash, &ctx.md5); if (ht == HashType::MD5) MD5_Final(hash, &ctx.md5);
else if (ht == htSHA1) SHA1_Final(hash, &ctx.sha1); else if (ht == HashType::SHA1) SHA1_Final(hash, &ctx.sha1);
else if (ht == htSHA256) SHA256_Final(hash, &ctx.sha256); else if (ht == HashType::SHA256) SHA256_Final(hash, &ctx.sha256);
else if (ht == htSHA512) SHA512_Final(hash, &ctx.sha512); else if (ht == HashType::SHA512) SHA512_Final(hash, &ctx.sha512);
} }
@ -387,10 +386,10 @@ Hash compressHash(const Hash & hash, unsigned int newSize)
std::optional<HashType> parseHashTypeOpt(std::string_view s) std::optional<HashType> parseHashTypeOpt(std::string_view s)
{ {
if (s == "md5") return htMD5; if (s == "md5") return HashType::MD5;
else if (s == "sha1") return htSHA1; else if (s == "sha1") return HashType::SHA1;
else if (s == "sha256") return htSHA256; else if (s == "sha256") return HashType::SHA256;
else if (s == "sha512") return htSHA512; else if (s == "sha512") return HashType::SHA512;
else return std::optional<HashType> {}; else return std::optional<HashType> {};
} }
@ -406,10 +405,10 @@ HashType parseHashType(std::string_view s)
std::string_view printHashType(HashType ht) std::string_view printHashType(HashType ht)
{ {
switch (ht) { switch (ht) {
case htMD5: return "md5"; case HashType::MD5: return "md5";
case htSHA1: return "sha1"; case HashType::SHA1: return "sha1";
case htSHA256: return "sha256"; case HashType::SHA256: return "sha256";
case htSHA512: return "sha512"; case HashType::SHA512: return "sha512";
default: default:
// illegal hash type enum value internally, as opposed to external input // illegal hash type enum value internally, as opposed to external input
// which should be validated with nice error message. // which should be validated with nice error message.

View file

@ -12,7 +12,7 @@ namespace nix {
MakeError(BadHash, Error); MakeError(BadHash, Error);
enum HashType : char { htMD5 = 42, htSHA1, htSHA256, htSHA512 }; enum class HashType : char { MD5 = 42, SHA1, SHA256, SHA512 };
const int md5HashSize = 16; const int md5HashSize = 16;
@ -24,7 +24,7 @@ extern std::set<std::string> hashTypes;
extern const std::string base32Chars; extern const std::string base32Chars;
enum Base : int { Base64, Base32, Base16, SRI }; enum class Base : int { Base64, Base32, Base16, SRI };
struct Hash struct Hash
@ -119,12 +119,12 @@ public:
std::string gitRev() const std::string gitRev() const
{ {
return to_string(Base16, false); return to_string(Base::Base16, false);
} }
std::string gitShortRev() const std::string gitShortRev() const
{ {
return std::string(to_string(Base16, false), 0, 7); return std::string(to_string(Base::Base16, false), 0, 7);
} }
static Hash dummy; static Hash dummy;

View file

@ -52,6 +52,7 @@ libutil_headers = files(
'box_ptr.hh', 'box_ptr.hh',
'canon-path.hh', 'canon-path.hh',
'cgroup.hh', 'cgroup.hh',
'charptr-cast.hh',
'checked-arithmetic.hh', 'checked-arithmetic.hh',
'chunked-vector.hh', 'chunked-vector.hh',
'closure.hh', 'closure.hh',

View file

@ -9,9 +9,7 @@
#include <cerrno> #include <cerrno>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <future>
#include <iostream> #include <iostream>
#include <thread>
#include <grp.h> #include <grp.h>
#include <sys/types.h> #include <sys/types.h>
@ -176,7 +174,7 @@ static pid_t doFork(std::function<void()> fun)
#if __linux__ #if __linux__
static int childEntry(void * arg) static int childEntry(void * arg)
{ {
auto main = (std::function<void()> *) arg; auto main = static_cast<std::function<void()> *>(arg);
(*main)(); (*main)();
return 1; return 1;
} }
@ -212,8 +210,8 @@ Pid startProcess(std::function<void()> fun, const ProcessOptions & options)
assert(!(options.cloneFlags & CLONE_VM)); assert(!(options.cloneFlags & CLONE_VM));
size_t stackSize = 1 * 1024 * 1024; size_t stackSize = 1 * 1024 * 1024;
auto stack = (char *) mmap(0, stackSize, auto stack = static_cast<char *>(mmap(0, stackSize,
PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0));
if (stack == MAP_FAILED) throw SysError("allocating stack"); if (stack == MAP_FAILED) throw SysError("allocating stack");
Finally freeStack([&]() { munmap(stack, stackSize); }); Finally freeStack([&]() { munmap(stack, stackSize); });

View file

@ -8,7 +8,8 @@ namespace nix {
std::vector<char *> stringsToCharPtrs(const Strings & ss) std::vector<char *> stringsToCharPtrs(const Strings & ss)
{ {
std::vector<char *> res; std::vector<char *> res;
for (auto & s : ss) res.push_back((char *) s.c_str()); // This is const cast since this exists for OS APIs that want char *
for (auto & s : ss) res.push_back(const_cast<char *>(s.data()));
res.push_back(0); res.push_back(0);
return res; return res;
} }

View file

@ -20,6 +20,8 @@ constexpr char treeNull[] = " ";
* Convert a list of strings to a null-terminated vector of `char * Convert a list of strings to a null-terminated vector of `char
* *`s. The result must not be accessed beyond the lifetime of the * *`s. The result must not be accessed beyond the lifetime of the
* list of strings. * list of strings.
*
* Modifying the resulting array elements violates the constness of ss.
*/ */
std::vector<char *> stringsToCharPtrs(const Strings & ss); std::vector<char *> stringsToCharPtrs(const Strings & ss);

View file

@ -15,11 +15,11 @@ static int callback_open(struct archive *, void * self)
static ssize_t callback_read(struct archive * archive, void * _self, const void * * buffer) static ssize_t callback_read(struct archive * archive, void * _self, const void * * buffer)
{ {
auto self = (TarArchive *) _self; auto self = static_cast<TarArchive *>(_self);
*buffer = self->buffer.data(); *buffer = self->buffer.data();
try { try {
return self->source->read((char *) self->buffer.data(), self->buffer.size()); return self->source->read(reinterpret_cast<char *>(self->buffer.data()), self->buffer.size());
} catch (EndOfFile &) { } catch (EndOfFile &) {
return 0; return 0;
} catch (std::exception & err) { } catch (std::exception & err) {

View file

@ -404,8 +404,8 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) { for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) {
auto info = store->queryPathInfo(j); auto info = store->queryPathInfo(j);
if (query == qHash) { if (query == qHash) {
assert(info->narHash.type == htSHA256); assert(info->narHash.type == HashType::SHA256);
cout << fmt("%s\n", info->narHash.to_string(Base32, true)); cout << fmt("%s\n", info->narHash.to_string(Base::Base32, true));
} else if (query == qSize) } else if (query == qSize)
cout << fmt("%d\n", info->narSize); cout << fmt("%d\n", info->narSize);
} }
@ -540,7 +540,7 @@ static void registerValidity(bool reregister, bool hashGiven, bool canonicalise)
if (canonicalise) if (canonicalise)
canonicalisePathMetaData(store->printStorePath(info->path), {}); canonicalisePathMetaData(store->printStorePath(info->path), {});
if (!hashGiven) { if (!hashGiven) {
HashResult hash = hashPath(htSHA256, store->printStorePath(info->path)); HashResult hash = hashPath(HashType::SHA256, store->printStorePath(info->path));
info->narHash = hash.first; info->narHash = hash.first;
info->narSize = hash.second; info->narSize = hash.second;
} }
@ -768,8 +768,8 @@ static void opVerifyPath(Strings opFlags, Strings opArgs)
if (current.first != info->narHash) { 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), store->printStorePath(path),
info->narHash.to_string(Base32, true), info->narHash.to_string(Base::Base32, true),
current.first.to_string(Base32, true)); current.first.to_string(Base::Base32, true));
status = 1; status = 1;
} }
} }
@ -970,7 +970,7 @@ static void opServe(Strings opFlags, Strings opArgs)
auto deriver = readString(in); auto deriver = readString(in);
ValidPathInfo info { ValidPathInfo info {
store->parseStorePath(path), store->parseStorePath(path),
Hash::parseAny(readString(in), htSHA256), Hash::parseAny(readString(in), HashType::SHA256),
}; };
if (deriver != "") if (deriver != "")
info.deriver = store->parseStorePath(deriver); info.deriver = store->parseStorePath(deriver);

View file

@ -32,11 +32,11 @@ struct CmdAddToStore : MixDryRun, StoreCommand
StringSink sink; StringSink sink;
sink << dumpPath(path); sink << dumpPath(path);
auto narHash = hashString(htSHA256, sink.s); auto narHash = hashString(HashType::SHA256, sink.s);
Hash hash = narHash; Hash hash = narHash;
if (ingestionMethod == FileIngestionMethod::Flat) { if (ingestionMethod == FileIngestionMethod::Flat) {
HashSink hsink(htSHA256); HashSink hsink(HashType::SHA256);
hsink << readFileSource(path); hsink << readFileSource(path);
hash = hsink.finish().first; hash = hsink.finish().first;
} }

View file

@ -316,7 +316,7 @@ static void daemonLoop(std::optional<TrustedFlag> forceTrustClientOpt)
socklen_t remoteAddrLen = sizeof(remoteAddr); socklen_t remoteAddrLen = sizeof(remoteAddr);
AutoCloseFD remote{accept(fdSocket.get(), AutoCloseFD remote{accept(fdSocket.get(),
(struct sockaddr *) &remoteAddr, &remoteAddrLen)}; reinterpret_cast<struct sockaddr *>(&remoteAddr), &remoteAddrLen)};
checkInterrupt(); checkInterrupt();
if (!remote) { if (!remote) {
if (errno == EINTR) continue; if (errno == EINTR) continue;

View file

@ -226,7 +226,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
j["url"] = flake.lockedRef.to_string(); // FIXME: rename to lockedUrl j["url"] = flake.lockedRef.to_string(); // FIXME: rename to lockedUrl
j["locked"] = fetchers::attrsToJSON(flake.lockedRef.toAttrs()); j["locked"] = fetchers::attrsToJSON(flake.lockedRef.toAttrs());
if (auto rev = flake.lockedRef.input.getRev()) if (auto rev = flake.lockedRef.input.getRev())
j["revision"] = rev->to_string(Base16, false); j["revision"] = rev->to_string(Base::Base16, false);
if (auto dirtyRev = fetchers::maybeGetStrAttr(flake.lockedRef.toAttrs(), "dirtyRev")) if (auto dirtyRev = fetchers::maybeGetStrAttr(flake.lockedRef.toAttrs(), "dirtyRev"))
j["dirtyRevision"] = *dirtyRev; j["dirtyRevision"] = *dirtyRev;
if (auto revCount = flake.lockedRef.input.getRevCount()) if (auto revCount = flake.lockedRef.input.getRevCount())
@ -253,7 +253,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
if (auto rev = flake.lockedRef.input.getRev()) if (auto rev = flake.lockedRef.input.getRev())
logger->cout( logger->cout(
ANSI_BOLD "Revision:" ANSI_NORMAL " %s", ANSI_BOLD "Revision:" ANSI_NORMAL " %s",
rev->to_string(Base16, false)); rev->to_string(Base::Base16, false));
if (auto dirtyRev = fetchers::maybeGetStrAttr(flake.lockedRef.toAttrs(), "dirtyRev")) if (auto dirtyRev = fetchers::maybeGetStrAttr(flake.lockedRef.toAttrs(), "dirtyRev"))
logger->cout( logger->cout(
ANSI_BOLD "Revision:" ANSI_NORMAL " %s", ANSI_BOLD "Revision:" ANSI_NORMAL " %s",
@ -1434,13 +1434,13 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON
if (json) { if (json) {
auto res = nlohmann::json::object(); auto res = nlohmann::json::object();
res["storePath"] = store->printStorePath(tree.storePath); res["storePath"] = store->printStorePath(tree.storePath);
res["hash"] = hash.to_string(SRI, true); res["hash"] = hash.to_string(Base::SRI, true);
logger->cout(res.dump()); logger->cout(res.dump());
} else { } else {
notice("Downloaded '%s' to '%s' (hash '%s').", notice("Downloaded '%s' to '%s' (hash '%s').",
lockedRef.to_string(), lockedRef.to_string(),
store->printStorePath(tree.storePath), store->printStorePath(tree.storePath),
hash.to_string(SRI, true)); hash.to_string(Base::SRI, true));
} }
} }
}; };

View file

@ -11,9 +11,9 @@ using namespace nix;
struct CmdHashBase : Command struct CmdHashBase : Command
{ {
FileIngestionMethod mode; FileIngestionMethod mode;
Base base = SRI; Base base = Base::SRI;
bool truncate = false; bool truncate = false;
HashType ht = htSHA256; HashType ht = HashType::SHA256;
std::vector<std::string> paths; std::vector<std::string> paths;
std::optional<std::string> modulus; std::optional<std::string> modulus;
@ -22,25 +22,25 @@ struct CmdHashBase : Command
addFlag({ addFlag({
.longName = "sri", .longName = "sri",
.description = "Print the hash in SRI format.", .description = "Print the hash in SRI format.",
.handler = {&base, SRI}, .handler = {&base, Base::SRI},
}); });
addFlag({ addFlag({
.longName = "base64", .longName = "base64",
.description = "Print the hash in base-64 format.", .description = "Print the hash in base-64 format.",
.handler = {&base, Base64}, .handler = {&base, Base::Base64},
}); });
addFlag({ addFlag({
.longName = "base32", .longName = "base32",
.description = "Print the hash in base-32 (Nix-specific) format.", .description = "Print the hash in base-32 (Nix-specific) format.",
.handler = {&base, Base32}, .handler = {&base, Base::Base32},
}); });
addFlag({ addFlag({
.longName = "base16", .longName = "base16",
.description = "Print the hash in base-16 format.", .description = "Print the hash in base-16 format.",
.handler = {&base, Base16}, .handler = {&base, Base::Base16},
}); });
addFlag(Flag::mkHashTypeFlag("type", &ht)); addFlag(Flag::mkHashTypeFlag("type", &ht));
@ -90,7 +90,7 @@ struct CmdHashBase : Command
? computeHashModulo(ht, *modulus, source).first ? computeHashModulo(ht, *modulus, source).first
: hashSource(ht, source).first; : hashSource(ht, source).first;
if (truncate && h.hashSize > 20) h = compressHash(h, 20); if (truncate && h.hashSize > 20) h = compressHash(h, 20);
logger->cout(h.to_string(base, base == SRI)); logger->cout(h.to_string(base, base == Base::SRI));
} }
} }
}; };
@ -110,16 +110,16 @@ struct CmdToBase : Command
std::string description() override std::string description() override
{ {
return fmt("convert a hash to %s representation", return fmt("convert a hash to %s representation",
base == Base16 ? "base-16" : base == Base::Base16 ? "base-16" :
base == Base32 ? "base-32" : base == Base::Base32 ? "base-32" :
base == Base64 ? "base-64" : base == Base::Base64 ? "base-64" :
"SRI"); "SRI");
} }
void run() override void run() override
{ {
for (auto s : args) for (auto s : args)
logger->cout(Hash::parseAny(s, ht).to_string(base, base == SRI)); logger->cout(Hash::parseAny(s, ht).to_string(base, base == Base::SRI));
} }
}; };
@ -129,10 +129,10 @@ struct CmdHash : NixMultiCommand
: MultiCommand({ : MultiCommand({
{"file", []() { return make_ref<CmdHashBase>(FileIngestionMethod::Flat);; }}, {"file", []() { return make_ref<CmdHashBase>(FileIngestionMethod::Flat);; }},
{"path", []() { return make_ref<CmdHashBase>(FileIngestionMethod::Recursive); }}, {"path", []() { return make_ref<CmdHashBase>(FileIngestionMethod::Recursive); }},
{"to-base16", []() { return make_ref<CmdToBase>(Base16); }}, {"to-base16", []() { return make_ref<CmdToBase>(Base::Base16); }},
{"to-base32", []() { return make_ref<CmdToBase>(Base32); }}, {"to-base32", []() { return make_ref<CmdToBase>(Base::Base32); }},
{"to-base64", []() { return make_ref<CmdToBase>(Base64); }}, {"to-base64", []() { return make_ref<CmdToBase>(Base::Base64); }},
{"to-sri", []() { return make_ref<CmdToBase>(SRI); }}, {"to-sri", []() { return make_ref<CmdToBase>(Base::SRI); }},
}) })
{ } { }
@ -158,7 +158,7 @@ static int compatNixHash(int argc, char * * argv)
{ {
std::optional<HashType> ht; std::optional<HashType> ht;
bool flat = false; bool flat = false;
Base base = Base16; Base base = Base::Base16;
bool truncate = false; bool truncate = false;
enum { opHash, opTo } op = opHash; enum { opHash, opTo } op = opHash;
std::vector<std::string> ss; std::vector<std::string> ss;
@ -169,10 +169,10 @@ static int compatNixHash(int argc, char * * argv)
else if (*arg == "--version") else if (*arg == "--version")
printVersion("nix-hash"); printVersion("nix-hash");
else if (*arg == "--flat") flat = true; else if (*arg == "--flat") flat = true;
else if (*arg == "--base16") base = Base16; else if (*arg == "--base16") base = Base::Base16;
else if (*arg == "--base32") base = Base32; else if (*arg == "--base32") base = Base::Base32;
else if (*arg == "--base64") base = Base64; else if (*arg == "--base64") base = Base::Base64;
else if (*arg == "--sri") base = SRI; else if (*arg == "--sri") base = Base::SRI;
else if (*arg == "--truncate") truncate = true; else if (*arg == "--truncate") truncate = true;
else if (*arg == "--type") { else if (*arg == "--type") {
std::string s = getArg(*arg, arg, end); std::string s = getArg(*arg, arg, end);
@ -180,19 +180,19 @@ static int compatNixHash(int argc, char * * argv)
} }
else if (*arg == "--to-base16") { else if (*arg == "--to-base16") {
op = opTo; op = opTo;
base = Base16; base = Base::Base16;
} }
else if (*arg == "--to-base32") { else if (*arg == "--to-base32") {
op = opTo; op = opTo;
base = Base32; base = Base::Base32;
} }
else if (*arg == "--to-base64") { else if (*arg == "--to-base64") {
op = opTo; op = opTo;
base = Base64; base = Base::Base64;
} }
else if (*arg == "--to-sri") { else if (*arg == "--to-sri") {
op = opTo; op = opTo;
base = SRI; base = Base::SRI;
} }
else if (*arg != "" && arg->at(0) == '-') else if (*arg != "" && arg->at(0) == '-')
return false; return false;
@ -203,7 +203,7 @@ static int compatNixHash(int argc, char * * argv)
if (op == opHash) { if (op == opHash) {
CmdHashBase cmd(flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive); CmdHashBase cmd(flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive);
if (!ht.has_value()) ht = htMD5; if (!ht.has_value()) ht = HashType::MD5;
cmd.ht = ht.value(); cmd.ht = ht.value();
cmd.base = base; cmd.base = base;
cmd.truncate = truncate; cmd.truncate = truncate;

View file

@ -1,5 +1,3 @@
#include <algorithm>
#include "args/root.hh" #include "args/root.hh"
#include "command.hh" #include "command.hh"
#include "common-args.hh" #include "common-args.hh"
@ -62,12 +60,12 @@ static bool haveInternet()
for (auto i = addrs; i; i = i->ifa_next) { for (auto i = addrs; i; i = i->ifa_next) {
if (!i->ifa_addr) continue; if (!i->ifa_addr) continue;
if (i->ifa_addr->sa_family == AF_INET) { if (i->ifa_addr->sa_family == AF_INET) {
if (ntohl(((sockaddr_in *) i->ifa_addr)->sin_addr.s_addr) != INADDR_LOOPBACK) { if (ntohl(reinterpret_cast<sockaddr_in *>(i->ifa_addr)->sin_addr.s_addr) != INADDR_LOOPBACK) {
return true; return true;
} }
} else if (i->ifa_addr->sa_family == AF_INET6) { } else if (i->ifa_addr->sa_family == AF_INET6) {
if (!IN6_IS_ADDR_LOOPBACK(&((sockaddr_in6 *) i->ifa_addr)->sin6_addr) && if (!IN6_IS_ADDR_LOOPBACK(&reinterpret_cast<sockaddr_in6 *>(i->ifa_addr)->sin6_addr) &&
!IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6 *) i->ifa_addr)->sin6_addr)) !IN6_IS_ADDR_LINKLOCAL(&reinterpret_cast<sockaddr_in6 *>(i->ifa_addr)->sin6_addr))
return true; return true;
} }
} }

View file

@ -90,7 +90,7 @@ struct CmdPathInfo : StorePathsCommand, MixJSON
std::cout << store->pathInfoToJSON( std::cout << store->pathInfoToJSON(
// FIXME: preserve order? // FIXME: preserve order?
StorePathSet(storePaths.begin(), storePaths.end()), StorePathSet(storePaths.begin(), storePaths.end()),
true, showClosureSize, SRI, AllowInvalid).dump(); true, showClosureSize, Base::SRI, AllowInvalid).dump();
} }
else { else {

View file

@ -133,7 +133,7 @@ std::tuple<StorePath, Hash> prefetchFile(
static int main_nix_prefetch_url(int argc, char * * argv) static int main_nix_prefetch_url(int argc, char * * argv)
{ {
{ {
HashType ht = htSHA256; HashType ht = HashType::SHA256;
std::vector<std::string> args; std::vector<std::string> args;
bool printPath = getEnv("PRINT_PATH") == "1"; bool printPath = getEnv("PRINT_PATH") == "1";
bool fromExpr = false; bool fromExpr = false;
@ -256,7 +256,7 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON
bool executable = false; bool executable = false;
bool unpack = false; bool unpack = false;
std::optional<std::string> name; std::optional<std::string> name;
HashType hashType = htSHA256; HashType hashType = HashType::SHA256;
std::optional<Hash> expectedHash; std::optional<Hash> expectedHash;
CmdStorePrefetchFile() CmdStorePrefetchFile()
@ -316,13 +316,13 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON
if (json) { if (json) {
auto res = nlohmann::json::object(); auto res = nlohmann::json::object();
res["storePath"] = store->printStorePath(storePath); res["storePath"] = store->printStorePath(storePath);
res["hash"] = hash.to_string(SRI, true); res["hash"] = hash.to_string(Base::SRI, true);
logger->cout(res.dump()); logger->cout(res.dump());
} else { } else {
notice("Downloaded '%s' to '%s' (hash '%s').", notice("Downloaded '%s' to '%s' (hash '%s').",
url, url,
store->printStorePath(storePath), store->printStorePath(storePath),
hash.to_string(SRI, true)); hash.to_string(Base::SRI, true));
} }
} }
}; };

View file

@ -109,8 +109,8 @@ struct CmdVerify : StorePathsCommand
act2.result(resCorruptedPath, store->printStorePath(info->path)); act2.result(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), store->printStorePath(info->path),
info->narHash.to_string(Base32, true), info->narHash.to_string(Base::Base32, true),
hash.first.to_string(Base32, true)); hash.first.to_string(Base::Base32, true));
} }
} }

View file

@ -171,7 +171,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
and `dependency`. */ and `dependency`. */
std::function<void(Node &, const std::string &, const std::string &)> printNode; std::function<void(Node &, const std::string &, const std::string &)> printNode;
struct BailOut { }; struct BailOut : std::exception { };
printNode = [&](Node & node, const std::string & firstPad, const std::string & tailPad) { printNode = [&](Node & node, const std::string & firstPad, const std::string & tailPad) {
auto pathS = store->printStorePath(node.path); auto pathS = store->printStorePath(node.path);

View file

@ -102,15 +102,15 @@ CHARACTERIZATION_TEST(
(std::tuple<ContentAddress, ContentAddress, ContentAddress> { (std::tuple<ContentAddress, ContentAddress, ContentAddress> {
ContentAddress { ContentAddress {
.method = TextIngestionMethod {}, .method = TextIngestionMethod {},
.hash = hashString(HashType::htSHA256, "Derive(...)"), .hash = hashString(HashType::SHA256, "Derive(...)"),
}, },
ContentAddress { ContentAddress {
.method = FileIngestionMethod::Flat, .method = FileIngestionMethod::Flat,
.hash = hashString(HashType::htSHA1, "blob blob..."), .hash = hashString(HashType::SHA1, "blob blob..."),
}, },
ContentAddress { ContentAddress {
.method = FileIngestionMethod::Recursive, .method = FileIngestionMethod::Recursive,
.hash = hashString(HashType::htSHA256, "(...)"), .hash = hashString(HashType::SHA256, "(...)"),
}, },
})) }))
@ -197,7 +197,7 @@ CHARACTERIZATION_TEST(
std::optional { std::optional {
ContentAddress { ContentAddress {
.method = FileIngestionMethod::Flat, .method = FileIngestionMethod::Flat,
.hash = hashString(HashType::htSHA1, "blob blob..."), .hash = hashString(HashType::SHA1, "blob blob..."),
}, },
}, },
})) }))

View file

@ -148,7 +148,7 @@ TEST_JSON(DynDerivationTest, caFixedText,
TEST_JSON(CaDerivationTest, caFloating, TEST_JSON(CaDerivationTest, caFloating,
(DerivationOutput::CAFloating { (DerivationOutput::CAFloating {
.method = FileIngestionMethod::Recursive, .method = FileIngestionMethod::Recursive,
.hashType = htSHA256, .hashType = HashType::SHA256,
}), }),
"drv-name", "output-name") "drv-name", "output-name")
@ -159,7 +159,7 @@ TEST_JSON(DerivationTest, deferred,
TEST_JSON(ImpureDerivationTest, impure, TEST_JSON(ImpureDerivationTest, impure,
(DerivationOutput::Impure { (DerivationOutput::Impure {
.method = FileIngestionMethod::Recursive, .method = FileIngestionMethod::Recursive,
.hashType = htSHA256, .hashType = HashType::SHA256,
}), }),
"drv-name", "output-name") "drv-name", "output-name")

View file

@ -6,7 +6,6 @@
#include <future> #include <future>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <stdexcept>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <sys/poll.h> #include <sys/poll.h>
@ -130,7 +129,7 @@ serveHTTP(std::string status, std::string headers, std::function<std::string()>
TEST(FileTransfer, exceptionAbortsDownload) TEST(FileTransfer, exceptionAbortsDownload)
{ {
struct Done struct Done : std::exception
{}; {};
auto ft = makeFileTransfer(); auto ft = makeFileTransfer();

View file

@ -53,15 +53,15 @@ VERSIONED_CHARACTERIZATION_TEST(
(std::tuple<ContentAddress, ContentAddress, ContentAddress> { (std::tuple<ContentAddress, ContentAddress, ContentAddress> {
ContentAddress { ContentAddress {
.method = TextIngestionMethod {}, .method = TextIngestionMethod {},
.hash = hashString(HashType::htSHA256, "Derive(...)"), .hash = hashString(HashType::SHA256, "Derive(...)"),
}, },
ContentAddress { ContentAddress {
.method = FileIngestionMethod::Flat, .method = FileIngestionMethod::Flat,
.hash = hashString(HashType::htSHA1, "blob blob..."), .hash = hashString(HashType::SHA1, "blob blob..."),
}, },
ContentAddress { ContentAddress {
.method = FileIngestionMethod::Recursive, .method = FileIngestionMethod::Recursive,
.hash = hashString(HashType::htSHA256, "(...)"), .hash = hashString(HashType::SHA256, "(...)"),
}, },
})) }))
@ -278,7 +278,7 @@ VERSIONED_CHARACTERIZATION_TEST(
"foo", "foo",
FixedOutputInfo { FixedOutputInfo {
.method = FileIngestionMethod::Recursive, .method = FileIngestionMethod::Recursive,
.hash = hashString(HashType::htSHA256, "(...)"), .hash = hashString(HashType::SHA256, "(...)"),
.references = { .references = {
.others = { .others = {
StorePath { StorePath {
@ -348,7 +348,7 @@ VERSIONED_CHARACTERIZATION_TEST(
std::optional { std::optional {
ContentAddress { ContentAddress {
.method = FileIngestionMethod::Flat, .method = FileIngestionMethod::Flat,
.hash = hashString(HashType::htSHA1, "blob blob..."), .hash = hashString(HashType::SHA1, "blob blob..."),
}, },
}, },
})) }))

View file

@ -55,15 +55,15 @@ VERSIONED_CHARACTERIZATION_TEST(
(std::tuple<ContentAddress, ContentAddress, ContentAddress> { (std::tuple<ContentAddress, ContentAddress, ContentAddress> {
ContentAddress { ContentAddress {
.method = TextIngestionMethod {}, .method = TextIngestionMethod {},
.hash = hashString(HashType::htSHA256, "Derive(...)"), .hash = hashString(HashType::SHA256, "Derive(...)"),
}, },
ContentAddress { ContentAddress {
.method = FileIngestionMethod::Flat, .method = FileIngestionMethod::Flat,
.hash = hashString(HashType::htSHA1, "blob blob..."), .hash = hashString(HashType::SHA1, "blob blob..."),
}, },
ContentAddress { ContentAddress {
.method = FileIngestionMethod::Recursive, .method = FileIngestionMethod::Recursive,
.hash = hashString(HashType::htSHA256, "(...)"), .hash = hashString(HashType::SHA256, "(...)"),
}, },
})) }))
@ -417,7 +417,7 @@ VERSIONED_CHARACTERIZATION_TEST(
"foo", "foo",
FixedOutputInfo { FixedOutputInfo {
.method = FileIngestionMethod::Recursive, .method = FileIngestionMethod::Recursive,
.hash = hashString(HashType::htSHA256, "(...)"), .hash = hashString(HashType::SHA256, "(...)"),
.references = { .references = {
.others = { .others = {
StorePath { StorePath {
@ -492,7 +492,7 @@ VERSIONED_CHARACTERIZATION_TEST(
std::optional { std::optional {
ContentAddress { ContentAddress {
.method = FileIngestionMethod::Flat, .method = FileIngestionMethod::Flat,
.hash = hashString(HashType::htSHA1, "blob blob..."), .hash = hashString(HashType::SHA1, "blob blob..."),
}, },
}, },
})) }))

View file

@ -11,11 +11,11 @@ using namespace nix;
Gen<Hash> Arbitrary<Hash>::arbitrary() Gen<Hash> Arbitrary<Hash>::arbitrary()
{ {
Hash prototype(htSHA1); Hash prototype(HashType::SHA1);
return return
gen::apply( gen::apply(
[](const std::vector<uint8_t> & v) { [](const std::vector<uint8_t> & v) {
Hash hash(htSHA1); Hash hash(HashType::SHA1);
assert(v.size() == hash.hashSize); assert(v.size() == hash.hashSize);
std::copy(v.begin(), v.end(), hash.hash); std::copy(v.begin(), v.end(), hash.hash);
return hash; return hash;

View file

@ -28,7 +28,7 @@ TEST(closure, correctClosure) {
} }
TEST(closure, properlyHandlesDirectExceptions) { TEST(closure, properlyHandlesDirectExceptions) {
struct TestExn {}; struct TestExn : std::exception {};
EXPECT_THROW( EXPECT_THROW(
computeClosure<string>( computeClosure<string>(
{"A"}, {"A"},

View file

@ -85,6 +85,7 @@ TEST(Generator, nestsExceptions)
co_yield 1; co_yield 1;
co_yield []() -> Generator<int> { co_yield []() -> Generator<int> {
co_yield 9; co_yield 9;
// NOLINTNEXTLINE(hicpp-exception-baseclass)
throw 1; throw 1;
co_yield 10; co_yield 10;
}(); }();
@ -101,6 +102,7 @@ TEST(Generator, exception)
{ {
auto g = []() -> Generator<int> { auto g = []() -> Generator<int> {
co_yield 1; co_yield 1;
// NOLINTNEXTLINE(hicpp-exception-baseclass)
throw 1; throw 1;
}(); }();
@ -110,6 +112,7 @@ TEST(Generator, exception)
} }
{ {
auto g = []() -> Generator<int> { auto g = []() -> Generator<int> {
// NOLINTNEXTLINE(hicpp-exception-baseclass)
throw 1; throw 1;
co_return; co_return;
}(); }();
@ -173,11 +176,13 @@ struct ThrowTransform
int operator()(bool) int operator()(bool)
{ {
// NOLINTNEXTLINE(hicpp-exception-baseclass)
throw 2; throw 2;
} }
Generator<int, void> operator()(Generator<int> && inner) Generator<int, void> operator()(Generator<int> && inner)
{ {
// NOLINTNEXTLINE(hicpp-exception-baseclass)
throw false; throw false;
} }
}; };

View file

@ -13,28 +13,28 @@ namespace nix {
TEST(hashString, testKnownMD5Hashes1) { TEST(hashString, testKnownMD5Hashes1) {
// values taken from: https://tools.ietf.org/html/rfc1321 // values taken from: https://tools.ietf.org/html/rfc1321
auto s1 = ""; auto s1 = "";
auto hash = hashString(HashType::htMD5, s1); auto hash = hashString(HashType::MD5, s1);
ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e"); ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e");
} }
TEST(hashString, testKnownMD5Hashes2) { TEST(hashString, testKnownMD5Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc1321 // values taken from: https://tools.ietf.org/html/rfc1321
auto s2 = "abc"; auto s2 = "abc";
auto hash = hashString(HashType::htMD5, s2); auto hash = hashString(HashType::MD5, s2);
ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72"); ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72");
} }
TEST(hashString, testKnownSHA1Hashes1) { TEST(hashString, testKnownSHA1Hashes1) {
// values taken from: https://tools.ietf.org/html/rfc3174 // values taken from: https://tools.ietf.org/html/rfc3174
auto s = "abc"; auto s = "abc";
auto hash = hashString(HashType::htSHA1, s); auto hash = hashString(HashType::SHA1, s);
ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d"); ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d");
} }
TEST(hashString, testKnownSHA1Hashes2) { TEST(hashString, testKnownSHA1Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc3174 // values taken from: https://tools.ietf.org/html/rfc3174
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
auto hash = hashString(HashType::htSHA1, s); auto hash = hashString(HashType::SHA1, s);
ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1"); ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
} }
@ -42,7 +42,7 @@ namespace nix {
// values taken from: https://tools.ietf.org/html/rfc4634 // values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abc"; auto s = "abc";
auto hash = hashString(HashType::htSHA256, s); auto hash = hashString(HashType::SHA256, s);
ASSERT_EQ(hash.to_string(Base::Base16, true), ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); "sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
} }
@ -50,7 +50,7 @@ namespace nix {
TEST(hashString, testKnownSHA256Hashes2) { TEST(hashString, testKnownSHA256Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc4634 // values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
auto hash = hashString(HashType::htSHA256, s); auto hash = hashString(HashType::SHA256, s);
ASSERT_EQ(hash.to_string(Base::Base16, true), ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); "sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
} }
@ -58,7 +58,7 @@ namespace nix {
TEST(hashString, testKnownSHA512Hashes1) { TEST(hashString, testKnownSHA512Hashes1) {
// values taken from: https://tools.ietf.org/html/rfc4634 // values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abc"; auto s = "abc";
auto hash = hashString(HashType::htSHA512, s); auto hash = hashString(HashType::SHA512, s);
ASSERT_EQ(hash.to_string(Base::Base16, true), ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9" "sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9"
"7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd" "7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd"
@ -68,7 +68,7 @@ namespace nix {
// values taken from: https://tools.ietf.org/html/rfc4634 // values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; auto s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
auto hash = hashString(HashType::htSHA512, s); auto hash = hashString(HashType::SHA512, s);
ASSERT_EQ(hash.to_string(Base::Base16, true), ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1" "sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1"
"7299aeadb6889018501d289e4900f7e4331b99dec4b5433a" "7299aeadb6889018501d289e4900f7e4331b99dec4b5433a"

View file

@ -29,12 +29,12 @@ namespace nix {
char cwd[PATH_MAX+1]; char cwd[PATH_MAX+1];
auto p = absPath(""); auto p = absPath("");
ASSERT_EQ(p, getcwd((char*)&cwd, PATH_MAX)); ASSERT_EQ(p, getcwd(cwd, PATH_MAX));
} }
TEST(absPath, usesOptionalBasePathWhenGiven) { TEST(absPath, usesOptionalBasePathWhenGiven) {
char _cwd[PATH_MAX+1]; char _cwd[PATH_MAX+1];
char* cwd = getcwd((char*)&_cwd, PATH_MAX); char* cwd = getcwd(_cwd, PATH_MAX);
auto p = absPath("", cwd); auto p = absPath("", cwd);
@ -43,7 +43,7 @@ namespace nix {
TEST(absPath, isIdempotent) { TEST(absPath, isIdempotent) {
char _cwd[PATH_MAX+1]; char _cwd[PATH_MAX+1];
char* cwd = getcwd((char*)&_cwd, PATH_MAX); char* cwd = getcwd(_cwd, PATH_MAX);
auto p1 = absPath(cwd); auto p1 = absPath(cwd);
auto p2 = absPath(p1); auto p2 = absPath(p1);