about summary refs log tree commit diff
path: root/nixpkgs/lib
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-10-19 14:40:23 +0000
committerAlyssa Ross <hi@alyssa.is>2022-01-07 10:22:32 +0000
commitcc62bcb55359ba8c5e0fe3a48e778444c89060d8 (patch)
treeca0e21d44eaf8837b687395e614445f7761d7bbd /nixpkgs/lib
parentd6625e8d25efd829c3cfa227d025ca4e606ae4b7 (diff)
parenta323570a264da96a0b0bcc1c9aa017794acdc752 (diff)
downloadnixlib-cc62bcb55359ba8c5e0fe3a48e778444c89060d8.tar
nixlib-cc62bcb55359ba8c5e0fe3a48e778444c89060d8.tar.gz
nixlib-cc62bcb55359ba8c5e0fe3a48e778444c89060d8.tar.bz2
nixlib-cc62bcb55359ba8c5e0fe3a48e778444c89060d8.tar.lz
nixlib-cc62bcb55359ba8c5e0fe3a48e778444c89060d8.tar.xz
nixlib-cc62bcb55359ba8c5e0fe3a48e778444c89060d8.tar.zst
nixlib-cc62bcb55359ba8c5e0fe3a48e778444c89060d8.zip
Merge commit 'a323570a264da96a0b0bcc1c9aa017794acdc752'
Diffstat (limited to 'nixpkgs/lib')
-rw-r--r--nixpkgs/lib/customisation.nix3
-rw-r--r--nixpkgs/lib/default.nix6
-rw-r--r--nixpkgs/lib/generators.nix27
-rw-r--r--nixpkgs/lib/licenses.nix10
-rw-r--r--nixpkgs/lib/modules.nix25
-rw-r--r--nixpkgs/lib/options.nix28
-rw-r--r--nixpkgs/lib/strings.nix13
-rw-r--r--nixpkgs/lib/systems/default.nix1
-rw-r--r--nixpkgs/lib/systems/supported.nix25
-rw-r--r--nixpkgs/lib/tests/maintainers.nix4
-rw-r--r--nixpkgs/lib/tests/misc.nix24
-rwxr-xr-xnixpkgs/lib/tests/modules.sh4
-rw-r--r--nixpkgs/lib/tests/modules/types-anything/functions.nix12
-rw-r--r--nixpkgs/lib/trivial.nix21
-rw-r--r--nixpkgs/lib/types.nix6
15 files changed, 186 insertions, 23 deletions
diff --git a/nixpkgs/lib/customisation.nix b/nixpkgs/lib/customisation.nix
index c17cb0d0f8e5..a794b673d70c 100644
--- a/nixpkgs/lib/customisation.nix
+++ b/nixpkgs/lib/customisation.nix
@@ -145,7 +145,8 @@ rec {
     let
       outputs = drv.outputs or [ "out" ];
 
-      commonAttrs = drv // (builtins.listToAttrs outputsList) //
+      commonAttrs = (removeAttrs drv [ "outputUnspecified" ]) //
+        (builtins.listToAttrs outputsList) //
         ({ all = map (x: x.value) outputsList; }) // passthru;
 
       outputToAttrListElement = outputName:
diff --git a/nixpkgs/lib/default.nix b/nixpkgs/lib/default.nix
index bb99a1be8a8c..5a85c5421172 100644
--- a/nixpkgs/lib/default.nix
+++ b/nixpkgs/lib/default.nix
@@ -91,7 +91,7 @@ let
       concatImapStringsSep makeSearchPath makeSearchPathOutput
       makeLibraryPath makeBinPath optionalString
       hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
-      escapeShellArg escapeShellArgs escapeRegex replaceChars lowerChars
+      escapeShellArg escapeShellArgs escapeRegex escapeXML replaceChars lowerChars
       upperChars toLower toUpper addContextFrom splitString
       removePrefix removeSuffix versionOlder versionAtLeast
       getName getVersion
@@ -123,8 +123,8 @@ let
     inherit (self.options) isOption mkEnableOption mkSinkUndeclaredOptions
       mergeDefaultOption mergeOneOption mergeEqualOption getValues
       getFiles optionAttrSetToDocList optionAttrSetToDocList'
-      scrubOptionValue literalExample showOption showFiles
-      unknownModule mkOption;
+      scrubOptionValue literalExpression literalExample literalDocBook
+      showOption showFiles unknownModule mkOption;
     inherit (self.types) isType setType defaultTypeMerge defaultFunctor
       isOptionType mkOptionType;
     inherit (self.asserts)
diff --git a/nixpkgs/lib/generators.nix b/nixpkgs/lib/generators.nix
index 0cec4d2dd620..79ae9055ce3d 100644
--- a/nixpkgs/lib/generators.nix
+++ b/nixpkgs/lib/generators.nix
@@ -197,6 +197,30 @@ rec {
     */
   toYAML = {}@args: toJSON args;
 
+  withRecursion =
+    args@{
+      /* If this option is not null, the given value will stop evaluating at a certain depth */
+      depthLimit
+      /* If this option is true, an error will be thrown, if a certain given depth is exceeded */
+    , throwOnDepthLimit ? true
+    }:
+      assert builtins.isInt depthLimit;
+      let
+        transform = depth:
+          if depthLimit != null && depth > depthLimit then
+            if throwOnDepthLimit
+              then throw "Exceeded maximum eval-depth limit of ${toString depthLimit} while trying to evaluate with `generators.withRecursion'!"
+              else const "<unevaluated>"
+          else id;
+        mapAny = with builtins; depth: v:
+          let
+            evalNext = x: mapAny (depth + 1) (transform (depth + 1) x);
+          in
+            if isAttrs v then mapAttrs (const evalNext) v
+            else if isList v then map evalNext v
+            else transform (depth + 1) v;
+      in
+        mapAny 0;
 
   /* Pretty print a value, akin to `builtins.trace`.
     * Should probably be a builtin as well.
@@ -208,7 +232,8 @@ rec {
     allowPrettyValues ? false,
     /* If this option is true, the output is indented with newlines for attribute sets and lists */
     multiline ? true
-  }@args: let
+  }@args:
+    let
     go = indent: v: with builtins;
     let     isPath   = v: typeOf v == "path";
             introSpace = if multiline then "\n${indent}  " else " ";
diff --git a/nixpkgs/lib/licenses.nix b/nixpkgs/lib/licenses.nix
index 772985f9509d..d305001a5c19 100644
--- a/nixpkgs/lib/licenses.nix
+++ b/nixpkgs/lib/licenses.nix
@@ -153,6 +153,11 @@ in mkLicense lset) ({
     free = false;
   };
 
+  capec = {
+    fullName = "Common Attack Pattern Enumeration and Classification";
+    url = "https://capec.mitre.org/about/termsofuse.html";
+  };
+
   clArtistic = {
     spdxId = "ClArtistic";
     fullName = "Clarified Artistic License";
@@ -240,6 +245,11 @@ in mkLicense lset) ({
     fullName = "CeCILL Free Software License Agreement v2.0";
   };
 
+  cecill21 = {
+    spdxId = "CECILL-2.1";
+    fullName = "CeCILL Free Software License Agreement v2.1";
+  };
+
   cecill-b = {
     spdxId = "CECILL-B";
     fullName  = "CeCILL-B Free Software License Agreement";
diff --git a/nixpkgs/lib/modules.nix b/nixpkgs/lib/modules.nix
index b124ea000a2e..46ae3f136310 100644
--- a/nixpkgs/lib/modules.nix
+++ b/nixpkgs/lib/modules.nix
@@ -162,13 +162,24 @@ rec {
             baseMsg = "The option `${showOption (prefix ++ firstDef.prefix)}' does not exist. Definition values:${showDefs [ firstDef ]}";
           in
             if attrNames options == [ "_module" ]
-              then throw ''
-                ${baseMsg}
-
-                However there are no options defined in `${showOption prefix}'. Are you sure you've
-                declared your options properly? This can happen if you e.g. declared your options in `types.submodule'
-                under `config' rather than `options'.
-              ''
+              then
+                let
+                  optionName = showOption prefix;
+                in
+                  if optionName == ""
+                    then throw ''
+                      ${baseMsg}
+
+                      It seems as if you're trying to declare an option by placing it into `config' rather than `options'!
+                    ''
+                  else
+                    throw ''
+                      ${baseMsg}
+
+                      However there are no options defined in `${showOption prefix}'. Are you sure you've
+                      declared your options properly? This can happen if you e.g. declared your options in `types.submodule'
+                      under `config' rather than `options'.
+                    ''
             else throw baseMsg
         else null;
 
diff --git a/nixpkgs/lib/options.nix b/nixpkgs/lib/options.nix
index 204c86df9f51..b3164181312e 100644
--- a/nixpkgs/lib/options.nix
+++ b/nixpkgs/lib/options.nix
@@ -54,7 +54,7 @@ rec {
 
      Example:
        mkOption { }  // => { _type = "option"; }
-       mkOption { defaultText = "foo"; } // => { _type = "option"; defaultText = "foo"; }
+       mkOption { default = "foo"; } // => { _type = "option"; default = "foo"; }
   */
   mkOption =
     {
@@ -212,11 +212,25 @@ rec {
     else x;
 
 
-  /* For use in the `example` option attribute. It causes the given
-     text to be included verbatim in documentation. This is necessary
-     for example values that are not simple values, e.g., functions.
+  /* For use in the `defaultText` and `example` option attributes. Causes the
+     given string to be rendered verbatim in the documentation as Nix code. This
+     is necessary for complex values, e.g. functions, or values that depend on
+     other values or packages.
   */
-  literalExample = text: { _type = "literalExample"; inherit text; };
+  literalExpression = text:
+    if ! isString text then throw "literalExpression expects a string."
+    else { _type = "literalExpression"; inherit text; };
+
+  literalExample = lib.warn "literalExample is deprecated, use literalExpression instead, or use literalDocBook for a non-Nix description." literalExpression;
+
+
+  /* For use in the `defaultText` and `example` option attributes. Causes the
+     given DocBook text to be inserted verbatim in the documentation, for when
+     a `literalExpression` would be too hard to read.
+  */
+  literalDocBook = text:
+    if ! isString text then throw "literalDocBook expects a string."
+    else { _type = "literalDocBook"; inherit text; };
 
   # Helper functions.
 
@@ -247,7 +261,9 @@ rec {
   showDefs = defs: concatMapStrings (def:
     let
       # Pretty print the value for display, if successful
-      prettyEval = builtins.tryEval (lib.generators.toPretty {} def.value);
+      prettyEval = builtins.tryEval
+        (lib.generators.toPretty { }
+          (lib.generators.withRecursion { depthLimit = 10; throwOnDepthLimit = false; } def.value));
       # Split it into its lines
       lines = filter (v: ! isList v) (builtins.split "\n" prettyEval.value);
       # Only display the first 5 lines, and indent them for better visibility
diff --git a/nixpkgs/lib/strings.nix b/nixpkgs/lib/strings.nix
index a111e1e2597b..de135d1c2746 100644
--- a/nixpkgs/lib/strings.nix
+++ b/nixpkgs/lib/strings.nix
@@ -362,6 +362,19 @@ rec {
     if match "[a-zA-Z_][a-zA-Z0-9_'-]*" s != null
     then s else escapeNixString s;
 
+  /* Escapes a string such that it is safe to include verbatim in an XML
+     document.
+
+     Type: string -> string
+
+     Example:
+       escapeXML ''"test" 'test' < & >''
+       => "\\[\\^a-z]\\*"
+  */
+  escapeXML = builtins.replaceStrings
+    ["\"" "'" "<" ">" "&"]
+    ["&quot;" "&apos;" "&lt;" "&gt;" "&amp;"];
+
   # Obsolete - use replaceStrings instead.
   replaceChars = builtins.replaceStrings or (
     del: new: s:
diff --git a/nixpkgs/lib/systems/default.nix b/nixpkgs/lib/systems/default.nix
index ef609859abbf..529eeb6514b9 100644
--- a/nixpkgs/lib/systems/default.nix
+++ b/nixpkgs/lib/systems/default.nix
@@ -8,6 +8,7 @@ rec {
   platforms = import ./platforms.nix { inherit lib; };
   examples = import ./examples.nix { inherit lib; };
   architectures = import ./architectures.nix { inherit lib; };
+  supported = import ./supported.nix { inherit lib; };
 
   # Elaborate a `localSystem` or `crossSystem` so that it contains everything
   # necessary.
diff --git a/nixpkgs/lib/systems/supported.nix b/nixpkgs/lib/systems/supported.nix
new file mode 100644
index 000000000000..ef429454f046
--- /dev/null
+++ b/nixpkgs/lib/systems/supported.nix
@@ -0,0 +1,25 @@
+# Supported systems according to RFC0046's definition.
+#
+# https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md
+{ lib }:
+rec {
+  # List of systems that are built by Hydra.
+  hydra = tier1 ++ tier2 ++ tier3;
+
+  tier1 = [
+    "x86_64-linux"
+  ];
+
+  tier2 = [
+    "aarch64-linux"
+    "x86_64-darwin"
+  ];
+
+  tier3 = [
+    "aarch64-darwin"
+    "armv6l-linux"
+    "armv7l-linux"
+    "i686-linux"
+    "mipsel-linux"
+  ];
+}
diff --git a/nixpkgs/lib/tests/maintainers.nix b/nixpkgs/lib/tests/maintainers.nix
index 2408a20af4b7..3cbfba569481 100644
--- a/nixpkgs/lib/tests/maintainers.nix
+++ b/nixpkgs/lib/tests/maintainers.nix
@@ -16,6 +16,10 @@ let
       email = lib.mkOption {
         type = types.str;
       };
+      matrix = lib.mkOption {
+        type = types.nullOr types.str;
+        default = null;
+      };
       github = lib.mkOption {
         type = types.nullOr types.str;
         default = null;
diff --git a/nixpkgs/lib/tests/misc.nix b/nixpkgs/lib/tests/misc.nix
index 4b2e5afc1d60..7b3a6b4e60b8 100644
--- a/nixpkgs/lib/tests/misc.nix
+++ b/nixpkgs/lib/tests/misc.nix
@@ -246,6 +246,11 @@ runTests {
     };
   };
 
+  testEscapeXML = {
+    expr = escapeXML ''"test" 'test' < & >'';
+    expected = "&quot;test&quot; &apos;test&apos; &lt; &amp; &gt;";
+  };
+
 # LISTS
 
   testFilter = {
@@ -529,6 +534,25 @@ runTests {
     };
   };
 
+  testToPrettyLimit =
+    let
+      a.b = 1;
+      a.c = a;
+    in {
+      expr = generators.toPretty { } (generators.withRecursion { throwOnDepthLimit = false; depthLimit = 2; } a);
+      expected = "{\n  b = 1;\n  c = {\n    b = \"<unevaluated>\";\n    c = {\n      b = \"<unevaluated>\";\n      c = \"<unevaluated>\";\n    };\n  };\n}";
+    };
+
+  testToPrettyLimitThrow =
+    let
+      a.b = 1;
+      a.c = a;
+    in {
+      expr = (builtins.tryEval
+        (generators.toPretty { } (generators.withRecursion { depthLimit = 2; } a))).success;
+      expected = false;
+    };
+
   testToPrettyMultiline = {
     expr = mapAttrs (const (generators.toPretty { })) rec {
       list = [ 3 4 [ false ] ];
diff --git a/nixpkgs/lib/tests/modules.sh b/nixpkgs/lib/tests/modules.sh
index 2e57c2f8e2a1..b51db91f6b07 100755
--- a/nixpkgs/lib/tests/modules.sh
+++ b/nixpkgs/lib/tests/modules.sh
@@ -254,8 +254,10 @@ checkConfigOutput / config.value.path ./types-anything/equal-atoms.nix
 checkConfigOutput null config.value.null ./types-anything/equal-atoms.nix
 checkConfigOutput 0.1 config.value.float ./types-anything/equal-atoms.nix
 # Functions can't be merged together
-checkConfigError "The option .* has conflicting definition values" config.value.multiple-lambdas ./types-anything/functions.nix
+checkConfigError "The option .value.multiple-lambdas.<function body>. has conflicting option types" config.applied.multiple-lambdas ./types-anything/functions.nix
 checkConfigOutput '<LAMBDA>' config.value.single-lambda ./types-anything/functions.nix
+checkConfigOutput 'null' config.applied.merging-lambdas.x ./types-anything/functions.nix
+checkConfigOutput 'null' config.applied.merging-lambdas.y ./types-anything/functions.nix
 # Check that all mk* modifiers are applied
 checkConfigError 'attribute .* not found' config.value.mkiffalse ./types-anything/mk-mods.nix
 checkConfigOutput '{ }' config.value.mkiftrue ./types-anything/mk-mods.nix
diff --git a/nixpkgs/lib/tests/modules/types-anything/functions.nix b/nixpkgs/lib/tests/modules/types-anything/functions.nix
index 079518913918..21edd4aff9c4 100644
--- a/nixpkgs/lib/tests/modules/types-anything/functions.nix
+++ b/nixpkgs/lib/tests/modules/types-anything/functions.nix
@@ -1,16 +1,22 @@
-{ lib, ... }: {
+{ lib, config, ... }: {
 
   options.value = lib.mkOption {
     type = lib.types.anything;
   };
 
+  options.applied = lib.mkOption {
+    default = lib.mapAttrs (name: fun: fun null) config.value;
+  };
+
   config = lib.mkMerge [
     {
       value.single-lambda = x: x;
-      value.multiple-lambdas = x: x;
+      value.multiple-lambdas = x: { inherit x; };
+      value.merging-lambdas = x: { inherit x; };
     }
     {
-      value.multiple-lambdas = x: x;
+      value.multiple-lambdas = x: [ x ];
+      value.merging-lambdas = y: { inherit y; };
     }
   ];
 
diff --git a/nixpkgs/lib/trivial.nix b/nixpkgs/lib/trivial.nix
index 7956ba4bde6f..a389c7cdfacb 100644
--- a/nixpkgs/lib/trivial.nix
+++ b/nixpkgs/lib/trivial.nix
@@ -303,7 +303,26 @@ rec {
   # TODO: figure out a clever way to integrate location information from
   # something like __unsafeGetAttrPos.
 
-  warn = msg: builtins.trace "warning: ${msg}";
+  /*
+    Print a warning before returning the second argument. This function behaves
+    like `builtins.trace`, but requires a string message and formats it as a
+    warning, including the `warning: ` prefix.
+
+    To get a call stack trace and abort evaluation, set the environment variable
+    `NIX_ABORT_ON_WARN=true` and set the Nix options `--option pure-eval false --show-trace`
+
+    Type: string -> a -> a
+  */
+  warn =
+    if lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") ["1" "true" "yes"]
+    then msg: builtins.trace "warning: ${msg}" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
+    else msg: builtins.trace "warning: ${msg}";
+
+  /*
+    Like warn, but only warn when the first argument is `true`.
+
+    Type: bool -> string -> a -> a
+  */
   warnIf = cond: msg: if cond then warn msg else id;
 
   info = msg: builtins.trace "INFO: ${msg}";
diff --git a/nixpkgs/lib/types.nix b/nixpkgs/lib/types.nix
index a0be2ff3a452..c2532065d7ea 100644
--- a/nixpkgs/lib/types.nix
+++ b/nixpkgs/lib/types.nix
@@ -192,6 +192,12 @@ rec {
               else (listOf anything).merge;
             # This is the type of packages, only accept a single definition
             stringCoercibleSet = mergeOneOption;
+            lambda = loc: defs: arg: anything.merge
+              (loc ++ [ "<function body>" ])
+              (map (def: {
+                file = def.file;
+                value = def.value arg;
+              }) defs);
             # Otherwise fall back to only allowing all equal definitions
           }.${commonType} or mergeEqualOption;
         in mergeFunction loc defs;