libexpr: add builtins.warn
Added builtins.warn` which takes two arguments: a message that is displayed as a warning during evaluation which must be a string and a value that is returned from the expression. The next commits add new settings to control the behavior of the new builtin: `debugger-on-warn` allows the user to start the debugger and `abort-on-warn` aborts evaluation with an error. Unlike upstream, I chose not to mark evaluation warnings from `builtins.warn` as distinct from other warnings because that breaks the commonly expected logging format `level: message`. Co-authored-by: Qyriad <qyriad@qyriad.me> Upstream-PR: https://github.com/NixOS/nix/pull/10592 Fixes: https://git.lix.systems/lix-project/lix/issues/579 Change-Id: I8658c88e5c27952b65e8b9f5525a572e0680cc1f
This commit is contained in:
committed by
Qyriad
co-authored by
Qyriad
parent
dd3ba39384
commit
0ade82d23a
@@ -176,6 +176,11 @@ midnightveil:
|
||||
forgejo: midnightveil
|
||||
github: midnightveil
|
||||
|
||||
milibopp:
|
||||
display_name: Emilia Bopp
|
||||
forgejo: milibopp
|
||||
github: milibopp
|
||||
|
||||
nan-git:
|
||||
display_name: NaN-git
|
||||
github: NaN-git
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
synopsis: "Add `builtins.warn` for emitting warnings from Nix code"
|
||||
cls: [2248]
|
||||
category: "Features"
|
||||
credits: [milibopp, Qyriad]
|
||||
---
|
||||
|
||||
Lix now has a builtin function for emitting warnings.
|
||||
Like `builtins.trace`, it takes two arguments: the message to emit, and the expression to return.
|
||||
_Unlike_ `builtins.trace`, `builtins.warn` requires the first argument — the message — to be a string.
|
||||
In the future we may extend `builtins.warn` to accept a more structured API.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
name: warn
|
||||
args: [msg, e2]
|
||||
---
|
||||
Evaluate string *msg* and print it on standard error. Then return *e2*.
|
||||
This function is useful for warning about unexpected conditions without aborting evaluation.
|
||||
@@ -148,6 +148,7 @@ builtin_definitions = files(
|
||||
'builtins/typeOf.md',
|
||||
'builtins/unsafeDiscardOutputDependency.md',
|
||||
'builtins/unsafeGetAttrPos.md',
|
||||
'builtins/warn.md',
|
||||
'builtins/zipAttrsWith.md',
|
||||
# keep-sorted end
|
||||
)
|
||||
|
||||
@@ -768,6 +768,19 @@ static void prim_trace(EvalState & state, Value * * args, Value & v)
|
||||
v = *args[1];
|
||||
}
|
||||
|
||||
static void prim_warn(EvalState & state, Value ** args, Value & v)
|
||||
{
|
||||
// We only accept a string argument for now. The use case for pretty printing a value is covered
|
||||
// by `trace`. By rejecting non-strings we allow future versions to add more features without
|
||||
// breaking existing code.
|
||||
auto const msg =
|
||||
state.forceString(*args[0], noPos, "while evaluating message for builtins.warn");
|
||||
|
||||
printTaggedWarning("%s", Uncolored(msg));
|
||||
|
||||
state.forceValue(*args[1], noPos);
|
||||
v = *args[1];
|
||||
}
|
||||
|
||||
/* Takes two arguments and evaluates to the second one. Used as the
|
||||
* builtins.traceVerbose implementation when --trace-verbose is not enabled
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
error:
|
||||
… while calling the 'warn' builtin
|
||||
at /pwd/in.nix:1:1:
|
||||
1| builtins.warn { cat = "girl"; } 1337
|
||||
| ^
|
||||
2|
|
||||
|
||||
… while evaluating message for builtins.warn
|
||||
|
||||
error: expected a string but found a set: { cat = "girl"; }
|
||||
@@ -0,0 +1 @@
|
||||
warning: meow
|
||||
@@ -0,0 +1 @@
|
||||
1337
|
||||
@@ -0,0 +1 @@
|
||||
builtins.warn { cat = "girl"; } 1337
|
||||
@@ -0,0 +1 @@
|
||||
builtins.warn "meow" 1337
|
||||
@@ -0,0 +1,6 @@
|
||||
[[test]]
|
||||
runner = "eval-okay"
|
||||
|
||||
[[test]]
|
||||
runner = "eval-fail"
|
||||
in = "in-reject-non-string.nix"
|
||||
@@ -121,6 +121,14 @@ namespace nix {
|
||||
ASSERT_NE(text.find("test string 123"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PrimOpTest, warn) {
|
||||
CaptureLogging l;
|
||||
auto const v = eval("builtins.warn \"test string 123\" 123");
|
||||
ASSERT_THAT(v, IsIntEq(123));
|
||||
auto const text = l.get();
|
||||
ASSERT_NE(text.find("test string 123"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PrimOpTest, placeholder) {
|
||||
auto v = eval("builtins.placeholder \"out\"");
|
||||
ASSERT_THAT(v, IsStringEq("/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9"));
|
||||
|
||||
Reference in New Issue
Block a user