summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/debug.nix184
-rw-r--r--lib/default.nix11
-rw-r--r--lib/modules.nix4
-rw-r--r--lib/trivial.nix11
4 files changed, 143 insertions, 67 deletions
diff --git a/lib/debug.nix b/lib/debug.nix
index d163e60b6957..91a9265a6b5e 100644
--- a/lib/debug.nix
+++ b/lib/debug.nix
@@ -1,34 +1,67 @@
+/* Collection of functions useful for debugging
+ broken nix expressions.
+
+ * `trace`-like functions take two values, print
+ the first to stderr and return the second.
+ * `traceVal`-like functions take one argument
+ which both printed and returned.
+ * `traceSeq`-like functions fully evaluate their
+ traced value before printing (not just to “weak
+ head normal form” like trace does by default).
+ * Functions that end in `-Fn` take an additional
+ function as their first argument, which is applied
+ to the traced value before it is printed.
+*/
{ lib }:
-
let
-
-inherit (builtins) trace attrNamesToStr isAttrs isList isInt
- isString isBool head substring attrNames;
-
-inherit (lib) all id mapAttrsFlatten elem isFunction;
-
+ inherit (builtins) trace isAttrs isList isInt
+ head substring attrNames;
+ inherit (lib) id elem isFunction;
in
rec {
- inherit (builtins) addErrorContext;
-
- addErrorContextToAttrs = lib.mapAttrs (a: v: lib.addErrorContext "while evaluating ${a}" v);
+ # -- TRACING --
- traceIf = p: msg: x: if p then trace msg x else x;
+ /* Trace msg, but only if pred is true.
- traceVal = x: trace x x;
- traceXMLVal = x: trace (builtins.toXML x) x;
- traceXMLValMarked = str: x: trace (str + builtins.toXML x) x;
+ Example:
+ traceIf true "hello" 3
+ trace: hello
+ => 3
+ */
+ traceIf = pred: msg: x: if pred then trace msg x else x;
- # strict trace functions (traced structure is fully evaluated and printed)
+ /* Trace the value and also return it.
- /* `builtins.trace`, but the value is `builtins.deepSeq`ed first. */
+ Example:
+ traceValFn (v: "mystring ${v}") "foo"
+ trace: mystring foo
+ => "foo"
+ */
+ traceValFn = f: x: trace (f x) x;
+ traceVal = traceValFn id;
+
+ /* `builtins.trace`, but the value is `builtins.deepSeq`ed first.
+
+ Example:
+ trace { a.b.c = 3; } null
+ trace: { a = <CODE>; }
+ => null
+ traceSeq { a.b.c = 3; } null
+ trace: { a = { b = { c = 3; }; }; }
+ => null
+ */
traceSeq = x: y: trace (builtins.deepSeq x x) y;
- /* Like `traceSeq`, but only down to depth n.
- * This is very useful because lots of `traceSeq` usages
- * lead to an infinite recursion.
+ /* Like `traceSeq`, but only evaluate down to depth n.
+ This is very useful because lots of `traceSeq` usages
+ lead to an infinite recursion.
+
+ Example:
+ traceSeqN 2 { a.b.c = 3; } null
+ trace: { a = { b = {…}; }; }
+ => null
*/
traceSeqN = depth: x: y: with lib;
let snip = v: if isList v then noQuotes "[…]" v
@@ -43,39 +76,16 @@ rec {
in trace (generators.toPretty { allowPrettyValues = true; }
(modify depth snip x)) y;
- /* `traceSeq`, but the same value is traced and returned */
- traceValSeq = v: traceVal (builtins.deepSeq v v);
- /* `traceValSeq` but with fixed depth */
- traceValSeqN = depth: v: traceSeqN depth v v;
+ /* A combination of `traceVal` and `traceSeq` */
+ traceValSeqFn = f: v: traceVal f (builtins.deepSeq v v);
+ traceValSeq = traceValSeqFn id;
+ /* A combination of `traceVal` and `traceSeqN`. */
+ traceValSeqNFn = f: depth: v: traceSeqN depth (f v) v;
+ traceValSeqN = traceValSeqNFn id;
- # this can help debug your code as well - designed to not produce thousands of lines
- traceShowVal = x: trace (showVal x) x;
- traceShowValMarked = str: x: trace (str + showVal x) x;
- attrNamesToStr = a: lib.concatStringsSep "; " (map (x: "${x}=") (attrNames a));
- showVal = x:
- if isAttrs x then
- if x ? outPath then "x is a derivation, name ${if x ? name then x.name else "<no name>"}, { ${attrNamesToStr x} }"
- else "x is attr set { ${attrNamesToStr x} }"
- else if isFunction x then "x is a function"
- else if x == [] then "x is an empty list"
- else if isList x then "x is a list, first element is: ${showVal (head x)}"
- else if x == true then "x is boolean true"
- else if x == false then "x is boolean false"
- else if x == null then "x is null"
- else if isInt x then "x is an integer `${toString x}'"
- else if isString x then "x is a string `${substring 0 50 x}...'"
- else "x is probably a path `${substring 0 50 (toString x)}...'";
- # trace the arguments passed to function and its result
- # maybe rewrite these functions in a traceCallXml like style. Then one function is enough
- traceCall = n: f: a: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
- traceCall2 = n: f: a: b: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
- traceCall3 = n: f: a: b: c: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
-
- # FIXME: rename this?
- traceValIfNot = c: x:
- if c x then true else trace (showVal x) false;
+ # -- TESTING --
/* Evaluate a set of tests. A test is an attribute set {expr,
expected}, denoting an expression and its expected result. The
@@ -99,9 +109,68 @@ rec {
# usage: { testX = allTrue [ true ]; }
testAllTrue = expr: { inherit expr; expected = map (x: true) expr; };
- strict = v:
- trace "Warning: strict is deprecated and will be removed in the next release"
- (builtins.seq v v);
+
+ # -- DEPRECATED --
+
+ traceShowVal = x: trace (showVal x) x;
+ traceShowValMarked = str: x: trace (str + showVal x) x;
+
+ attrNamesToStr = a:
+ trace ( "Warning: `attrNamesToStr` is deprecated "
+ + "and will be removed in the next release. "
+ + "Please use more specific concatenation "
+ + "for your uses (`lib.concat(Map)StringsSep`)." )
+ (lib.concatStringsSep "; " (map (x: "${x}=") (attrNames a)));
+
+ showVal = with lib;
+ trace ( "Warning: `showVal` is deprecated "
+ + "and will be removed in the next release, "
+ + "please use `traceSeqN`" )
+ (let
+ modify = v:
+ let pr = f: { __pretty = f; val = v; };
+ in if isDerivation v then pr
+ (drv: "<δ:${drv.name}:${concatStringsSep ","
+ (attrNames drv)}>")
+ else if [] == v then pr (const "[]")
+ else if isList v then pr (l: "[ ${go (head l)}, … ]")
+ else if isAttrs v then pr
+ (a: "{ ${ concatStringsSep ", " (attrNames a)} }")
+ else v;
+ go = x: generators.toPretty
+ { allowPrettyValues = true; }
+ (modify x);
+ in go);
+
+ traceXMLVal = x:
+ trace ( "Warning: `traceXMLVal` is deprecated "
+ + "and will be removed in the next release. "
+ + "Please use `traceValFn builtins.toXML`." )
+ (trace (builtins.toXML x) x);
+ traceXMLValMarked = str: x:
+ trace ( "Warning: `traceXMLValMarked` is deprecated "
+ + "and will be removed in the next release. "
+ + "Please use `traceValFn (x: str + builtins.toXML x)`." )
+ (trace (str + builtins.toXML x) x);
+
+ # trace the arguments passed to function and its result
+ # maybe rewrite these functions in a traceCallXml like style. Then one function is enough
+ traceCall = n: f: a: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
+ traceCall2 = n: f: a: b: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
+ traceCall3 = n: f: a: b: c: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
+
+ traceValIfNot = c: x:
+ trace ( "Warning: `traceValIfNot` is deprecated "
+ + "and will be removed in the next release. "
+ + "Please use `if/then/else` and `traceValSeq 1`.")
+ (if c x then true else traceSeq (showVal x) false);
+
+
+ addErrorContextToAttrs = attrs:
+ trace ( "Warning: `addErrorContextToAttrs` is deprecated "
+ + "and will be removed in the next release. "
+ + "Please use `builtins.addErrorContext` directly." )
+ (lib.mapAttrs (a: v: lib.addErrorContext "while evaluating ${a}" v) attrs);
# example: (traceCallXml "myfun" id 3) will output something like
# calling myfun arg 1: 3 result: 3
@@ -109,17 +178,20 @@ rec {
# note: if result doesn't evaluate you'll get no trace at all (FIXME)
# args should be printed in any case
traceCallXml = a:
- if !isInt a then
+ trace ( "Warning: `traceCallXml` is deprecated "
+ + "and will be removed in the next release. "
+ + "Please complain if you use the function regularly." )
+ (if !isInt a then
traceCallXml 1 "calling ${a}\n"
else
let nr = a;
in (str: expr:
if isFunction expr then
(arg:
- traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (strict arg)}" (expr arg)
+ traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (builtins.seq arg arg)}" (expr arg)
)
else
- let r = strict expr;
+ let r = builtins.seq expr expr;
in trace "${str}\n result:\n${builtins.toXML r}" r
- );
+ ));
}
diff --git a/lib/default.nix b/lib/default.nix
index c292ed33e1da..60ce01a93cd2 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -58,7 +58,7 @@ let
replaceStrings seq stringLength sub substring tail;
inherit (trivial) id const concat or and boolToString mergeAttrs
flip mapNullable inNixShell min max importJSON warn info
- nixpkgsVersion mod compare splitByAndCompare
+ nixpkgsVersion version mod compare splitByAndCompare
functionArgs setFunctionArgs isFunction;
inherit (fixedPoints) fix fix' extends composeExtensions
@@ -115,11 +115,12 @@ let
unknownModule mkOption;
inherit (types) isType setType defaultTypeMerge defaultFunctor
isOptionType mkOptionType;
- inherit (debug) addErrorContextToAttrs traceIf traceVal
+ inherit (debug) addErrorContextToAttrs traceIf traceVal traceValFn
traceXMLVal traceXMLValMarked traceSeq traceSeqN traceValSeq
- traceValSeqN traceShowVal traceShowValMarked
- showVal traceCall traceCall2 traceCall3 traceValIfNot runTests
- testAllTrue strict traceCallXml attrNamesToStr;
+ traceValSeqFn traceValSeqN traceValSeqNFn traceShowVal
+ traceShowValMarked showVal traceCall traceCall2 traceCall3
+ traceValIfNot runTests testAllTrue traceCallXml
+ attrNamesToStr;
inherit (misc) maybeEnv defaultMergeArg defaultMerge foldArgs
defaultOverridableDelayableArgs composedArgsAndFun
maybeAttrNullable maybeAttr ifEnable checkFlag getValue
diff --git a/lib/modules.nix b/lib/modules.nix
index 4ef982c7ec96..6c8033322a54 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -159,7 +159,7 @@ rec {
context = name: ''while evaluating the module argument `${name}' in "${key}":'';
extraArgs = builtins.listToAttrs (map (name: {
inherit name;
- value = addErrorContext (context name)
+ value = builtins.addErrorContext (context name)
(args.${name} or config._module.args.${name});
}) requiredArgs);
@@ -309,7 +309,7 @@ rec {
res.mergedValue;
in opt //
- { value = addErrorContext "while evaluating the option `${showOption loc}':" value;
+ { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
definitions = map (def: def.value) res.defsFinal;
files = map (def: def.file) res.defsFinal;
inherit (res) isDefined;
diff --git a/lib/trivial.nix b/lib/trivial.nix
index a928e1dbca98..251cb796db0e 100644
--- a/lib/trivial.nix
+++ b/lib/trivial.nix
@@ -58,11 +58,14 @@ rec {
inherit (lib.strings) fileContents;
+ release = fileContents ../.version;
+ versionSuffix = let suffixFile = ../.version-suffix; in
+ if pathExists suffixFile then fileContents suffixFile else "pre-git";
+
# Return the Nixpkgs version number.
- nixpkgsVersion =
- let suffixFile = ../.version-suffix; in
- fileContents ../.version
- + (if pathExists suffixFile then fileContents suffixFile else "pre-git");
+ version = release + versionSuffix;
+
+ nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version;
# Whether we're being called by nix-shell.
inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";