summary refs log tree commit diff
path: root/lib/options.nix
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2013-10-28 19:48:30 +0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2013-10-28 22:45:57 +0100
commit73f32d03758a53ad1baac31795cfd99e325032f3 (patch)
tree8df21c7319e758a85a4916890714b0d90c631a67 /lib/options.nix
parentdbefab9cf42c09444dd2554380104096969c0728 (diff)
downloadnixpkgs-73f32d03758a53ad1baac31795cfd99e325032f3.tar
nixpkgs-73f32d03758a53ad1baac31795cfd99e325032f3.tar.gz
nixpkgs-73f32d03758a53ad1baac31795cfd99e325032f3.tar.bz2
nixpkgs-73f32d03758a53ad1baac31795cfd99e325032f3.tar.lz
nixpkgs-73f32d03758a53ad1baac31795cfd99e325032f3.tar.xz
nixpkgs-73f32d03758a53ad1baac31795cfd99e325032f3.tar.zst
nixpkgs-73f32d03758a53ad1baac31795cfd99e325032f3.zip
Show precise error messages in option merge failures
For instance, if time.timeZone is defined multiple times, you now get
the error message:

  error: user-thrown exception: The unique option `time.timeZone' is defined multiple times, in `/etc/nixos/configurations/misc/eelco/x11vnc.nix' and `/etc/nixos/configuration.nix'.

while previously you got:

  error: user-thrown exception: Multiple definitions of string. Only one is allowed for this option.

and only an inspection of the stack trace gave a clue as to what
option caused the problem.
Diffstat (limited to 'lib/options.nix')
-rw-r--r--lib/options.nix21
1 files changed, 11 insertions, 10 deletions
diff --git a/lib/options.nix b/lib/options.nix
index d649d1160a0..66957bc7f15 100644
--- a/lib/options.nix
+++ b/lib/options.nix
@@ -35,7 +35,7 @@ rec {
   addDefaultOptionValues = defs: opts: opts //
     builtins.listToAttrs (map (defName:
       { name = defName;
-        value = 
+        value =
           let
             defValue = builtins.getAttr defName defs;
             optValue = builtins.getAttr defName opts;
@@ -49,27 +49,26 @@ rec {
           else
             # `defValue' is an attribute set containing options.
             # So recurse.
-            if hasAttr defName opts && isAttrs optValue 
+            if hasAttr defName opts && isAttrs optValue
             then addDefaultOptionValues defValue optValue
             else addDefaultOptionValues defValue {};
       }
     ) (attrNames defs));
 
-  mergeDefaultOption = list:
+  mergeDefaultOption = args: list:
     if length list == 1 then head list
-    else if all builtins.isFunction list then x: mergeDefaultOption (map (f: f x) list)
+    else if all builtins.isFunction list then x: mergeDefaultOption args (map (f: f x) list)
     else if all isList list then concatLists list
     else if all isAttrs list then fold lib.mergeAttrs {} list
     else if all builtins.isBool list then fold lib.or false list
     else if all builtins.isString list then lib.concatStrings list
-    else if all builtins.isInt list && all (x: x == head list) list
-         then head list
-    else throw "Cannot merge values.";
+    else if all builtins.isInt list && all (x: x == head list) list then head list
+    else throw "Cannot merge definitions of `${showOption args.prefix}' given in ${showFiles args.files}.";
 
 
   /* Obsolete, will remove soon.  Specify an option type or apply
      function instead.  */
-  mergeTypedOption = typeName: predicate: merge: list:
+  mergeTypedOption = typeName: predicate: merge: args: list:
     if all predicate list then merge list
     else throw "Expect a ${typeName}.";
 
@@ -82,9 +81,10 @@ rec {
     (x: if builtins ? isString then builtins.isString x else x + "")
     lib.concatStrings;
 
-  mergeOneOption = list:
+  mergeOneOption = args: list:
     if list == [] then abort "This case should never happen."
-    else if length list != 1 then throw "Multiple definitions. Only one is allowed for this option."
+    else if length list != 1 then
+      throw "The unique option `${showOption args.prefix}' is defined multiple times, in ${showFiles args.files}."
     else head list;
 
 
@@ -135,6 +135,7 @@ rec {
 
   /* Helper functions. */
   showOption = concatStringsSep ".";
+  showFiles = files: concatStringsSep " and " (map (f: "`${f}'") files);
   unknownModule = "<unknown-file>";
 
 }