65 lines
2.4 KiB
Diff
65 lines
2.4 KiB
Diff
From 3aa73c21e3afc91522a6121b0d591af6925b4ba6 Mon Sep 17 00:00:00 2001
|
|
From: Rodrigo Arias Mallo <rodarima@gmail.com>
|
|
Date: Mon, 13 Oct 2025 16:05:30 +0200
|
|
Subject: [PATCH] Add builtins.catchAll to catch all types of errors
|
|
|
|
Allows fetching multiple Git repositories with builtin.fetchGit and
|
|
catching any errors thrown by the builtin, in opposition to the builtin
|
|
tryEval.
|
|
---
|
|
src/libexpr/primops.cc | 38 ++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 38 insertions(+)
|
|
|
|
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
|
|
index 36a67a39d..3b26f9f43 100644
|
|
--- a/src/libexpr/primops.cc
|
|
+++ b/src/libexpr/primops.cc
|
|
@@ -849,6 +849,44 @@ static RegisterPrimOp primop_tryEval({
|
|
.fun = prim_tryEval,
|
|
});
|
|
|
|
+/* Like tryEval but catch all errors. Success => {success=true; value=something;},
|
|
+ * else => {success=false; value=false;} */
|
|
+static void prim_catchAll(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
|
+{
|
|
+ auto attrs = state.buildBindings(3);
|
|
+ try {
|
|
+ state.forceValue(*args[0], pos);
|
|
+ attrs.insert(state.sValue, args[0]);
|
|
+ attrs.alloc("success").mkBool(true);
|
|
+ attrs.alloc("msg").mkNull();
|
|
+ } catch (Error & e) {
|
|
+ attrs.alloc(state.sValue).mkBool(false);
|
|
+ attrs.alloc("success").mkBool(false);
|
|
+ attrs.alloc("msg").mkString(e.msg());
|
|
+ }
|
|
+ v.mkAttrs(attrs);
|
|
+}
|
|
+
|
|
+static RegisterPrimOp primop_catchAll({
|
|
+ .name = "__catchAll",
|
|
+ .args = {"e"},
|
|
+ .doc = R"(
|
|
+ Try to shallowly evaluate *e*. Return a set containing the
|
|
+ attributes `success` (`true` if *e* evaluated successfully,
|
|
+ `false` if an error was thrown) and `value`, equalling *e* if
|
|
+ successful and `false` otherwise. In contrast with `tryEval`,
|
|
+ `catchAll` will prevent all errors from being thrown, including
|
|
+ for those created by `abort` and type errors generated by
|
|
+ builtins. Also note that this doesn't evaluate *e* deeply, so
|
|
+ `let e = { x = throw ""; }; in (builtins.catchAll e).success`
|
|
+ will be `true`. Using `builtins.deepSeq` one can get the expected
|
|
+ result: `let e = { x = throw ""; }; in
|
|
+ (builtins.catchAll (builtins.deepSeq e e)).success` will be
|
|
+ `false`.
|
|
+ )",
|
|
+ .fun = prim_catchAll,
|
|
+});
|
|
+
|
|
/* Return an environment variable. Use with care. */
|
|
static void prim_getEnv(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
|
{
|
|
--
|
|
2.51.0
|
|
|