diff --git a/src/libexpr/meson.build b/src/libexpr/meson.build index 9f0f84d33..3c942a5d1 100644 --- a/src/libexpr/meson.build +++ b/src/libexpr/meson.build @@ -89,6 +89,7 @@ libexpr_sources = files( 'primops/attrset.cc', 'primops/context.cc', 'primops/control.cc', + 'primops/hash.cc', 'primops/fetchClosure.cc', 'primops/fetchMercurial.cc', 'primops/fetchTree.cc', diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 07132408a..d8dcb43f2 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -115,12 +115,7 @@ StringMap EvalState::realiseContext(const NixStringContext & context) return res; } -struct RealisePathFlags { - // Whether to check that the path is allowed in pure eval mode - bool checkForPureEval = true; -}; - -static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, const RealisePathFlags flags = {}) +SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, const RealisePathFlags flags) { NixStringContext context; @@ -1585,30 +1580,6 @@ static RegisterPrimOp primop_findFile(PrimOp { .fun = prim_findFile, }); -/* Return the cryptographic hash of a file in base-16. */ -static void prim_hashFile(EvalState & state, const PosIdx pos, Value * * args, Value & v) -{ - auto type = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hashFile"); - std::optional ht = parseHashType(type); - if (!ht) - state.error("unknown hash type '%1%'", type).atPos(pos).debugThrow(); - - auto path = realisePath(state, pos, *args[1]); - - v.mkString(hashString(*ht, path.readFile()).to_string(Base16, false)); -} - -static RegisterPrimOp primop_hashFile({ - .name = "__hashFile", - .args = {"type", "p"}, - .doc = R"( - Return a base-16 representation of the cryptographic hash of the - file at path *p*. The hash algorithm specified by *type* must be one - of `"md5"`, `"sha1"`, `"sha256"` or `"sha512"`. - )", - .fun = prim_hashFile, -}); - static std::string_view fileTypeToString(InputAccessor::Type type) { return @@ -3103,31 +3074,6 @@ static RegisterPrimOp primop_lessThan({ *************************************************************/ -/* Return the cryptographic hash of a string in base-16. */ -static void prim_hashString(EvalState & state, const PosIdx pos, Value * * args, Value & v) -{ - auto type = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hashString"); - std::optional ht = parseHashType(type); - if (!ht) - state.error("unknown hash algorithm '%1%'", type).atPos(pos).debugThrow(); - - NixStringContext context; // discarded - 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)); -} - -static RegisterPrimOp primop_hashString({ - .name = "__hashString", - .args = {"type", "s"}, - .doc = R"( - Return a base-16 representation of the cryptographic hash of string - *s*. The hash algorithm specified by *type* must be one of `"md5"`, - `"sha1"`, `"sha256"` or `"sha512"`. - )", - .fun = prim_hashString, -}); - /************************************************************* * Versions *************************************************************/ diff --git a/src/libexpr/primops.hh b/src/libexpr/primops.hh index 0b9763e29..00ffb019a 100644 --- a/src/libexpr/primops.hh +++ b/src/libexpr/primops.hh @@ -86,4 +86,11 @@ struct RegexCache } }; +struct RealisePathFlags { + // Whether to check that the path is allowed in pure eval mode + bool checkForPureEval = true; +}; + +SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, const RealisePathFlags flags = {}); + } diff --git a/src/libexpr/primops/hash.cc b/src/libexpr/primops/hash.cc new file mode 100644 index 000000000..be73fa30a --- /dev/null +++ b/src/libexpr/primops/hash.cc @@ -0,0 +1,69 @@ +#include "hash.hh" +#include "primops.hh" + +namespace nix { + +/** + * builtins.hashFile + */ + +static void prim_hashFile(EvalState & state, const PosIdx pos, Value ** args, Value & v) +{ + auto type = state.forceStringNoCtx( + *args[0], pos, "while evaluating the first argument passed to builtins.hashFile" + ); + std::optional ht = parseHashType(type); + if (!ht) { + state.error("unknown hash type '%1%'", type).atPos(pos).debugThrow(); + } + + auto path = realisePath(state, pos, *args[1]); + + v.mkString(hashString(*ht, path.readFile()).to_string(Base16, false)); +} + +static RegisterPrimOp primop_hashFile({ + .name = "__hashFile", + .args = {"type", "p"}, + .doc = R"( + Return a base-16 representation of the cryptographic hash of the + file at path *p*. The hash algorithm specified by *type* must be one + of `"md5"`, `"sha1"`, `"sha256"` or `"sha512"`. + )", + .fun = prim_hashFile, +}); + +/** + * builtins.hashString + */ + +static void prim_hashString(EvalState & state, const PosIdx pos, Value ** args, Value & v) +{ + auto type = state.forceStringNoCtx( + *args[0], pos, "while evaluating the first argument passed to builtins.hashString" + ); + std::optional ht = parseHashType(type); + if (!ht) { + state.error("unknown hash algorithm '%1%'", type).atPos(pos).debugThrow(); + } + + NixStringContext context; // discarded + 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)); +} + +static RegisterPrimOp primop_hashString({ + .name = "__hashString", + .args = {"type", "s"}, + .doc = R"( + Return a base-16 representation of the cryptographic hash of string + *s*. The hash algorithm specified by *type* must be one of `"md5"`, + `"sha1"`, `"sha256"` or `"sha512"`. + )", + .fun = prim_hashString, +}); + +}