lib/customisation.nix: format with nixfmt-rfc-style

This commit is contained in:
Yueh-Shun Li 2024-12-20 20:57:46 +08:00
parent 7071342c52
commit 8788c4bff9

View file

@ -2,19 +2,43 @@
let let
inherit (builtins) inherit (builtins)
intersectAttrs; intersectAttrs
;
inherit (lib) inherit (lib)
functionArgs isFunction mirrorFunctionArgs isAttrs setFunctionArgs functionArgs
optionalAttrs attrNames filter elemAt concatStringsSep sortOn take length isFunction
filterAttrs optionalString flip pathIsDirectory head pipe isDerivation listToAttrs mirrorFunctionArgs
mapAttrs seq flatten deepSeq warnIf isInOldestRelease extends isAttrs
setFunctionArgs
optionalAttrs
attrNames
filter
elemAt
concatStringsSep
sortOn
take
length
filterAttrs
optionalString
flip
pathIsDirectory
head
pipe
isDerivation
listToAttrs
mapAttrs
seq
flatten
deepSeq
warnIf
isInOldestRelease
extends
; ;
inherit (lib.strings) levenshtein levenshteinAtMost; inherit (lib.strings) levenshtein levenshteinAtMost;
in in
rec { rec {
/** /**
`overrideDerivation drv f` takes a derivation (i.e., the result `overrideDerivation drv f` takes a derivation (i.e., the result
of a call to the builtin function `derivation`) and returns a new of a call to the builtin function `derivation`) and returns a new
@ -40,7 +64,6 @@ rec {
You should in general prefer `drv.overrideAttrs` over this function; You should in general prefer `drv.overrideAttrs` over this function;
see the nixpkgs manual for more information on overriding. see the nixpkgs manual for more information on overriding.
# Inputs # Inputs
`drv` `drv`
@ -74,20 +97,21 @@ rec {
::: :::
*/ */
overrideDerivation = drv: f: overrideDerivation =
drv: f:
let let
newDrv = derivation (drv.drvAttrs // (f drv)); newDrv = derivation (drv.drvAttrs // (f drv));
in flip (extendDerivation (seq drv.drvPath true)) newDrv ( in
{ meta = drv.meta or {}; flip (extendDerivation (seq drv.drvPath true)) newDrv (
passthru = if drv ? passthru then drv.passthru else {}; {
meta = drv.meta or { };
passthru = if drv ? passthru then drv.passthru else { };
} }
// // (drv.passthru or { })
(drv.passthru or {}) // optionalAttrs (drv ? __spliced) {
// __spliced = { } // (mapAttrs (_: sDrv: overrideDerivation sDrv f) drv.__spliced);
optionalAttrs (drv ? __spliced) { }
__spliced = {} // (mapAttrs (_: sDrv: overrideDerivation sDrv f) drv.__spliced); );
});
/** /**
`makeOverridable` takes a function from attribute set to attribute set and `makeOverridable` takes a function from attribute set to attribute set and
@ -97,7 +121,6 @@ rec {
Please refer to documentation on [`<pkg>.overrideDerivation`](#sec-pkg-overrideDerivation) to learn about `overrideDerivation` and caveats Please refer to documentation on [`<pkg>.overrideDerivation`](#sec-pkg-overrideDerivation) to learn about `overrideDerivation` and caveats
related to its use. related to its use.
# Inputs # Inputs
`f` `f`
@ -128,12 +151,14 @@ rec {
::: :::
*/ */
makeOverridable = f: makeOverridable =
f:
let let
# Creates a functor with the same arguments as f # Creates a functor with the same arguments as f
mirrorArgs = mirrorFunctionArgs f; mirrorArgs = mirrorFunctionArgs f;
in in
mirrorArgs (origArgs: mirrorArgs (
origArgs:
let let
result = f origArgs; result = f origArgs;
@ -146,19 +171,22 @@ rec {
overrideResult = g: makeOverridable (mirrorArgs (args: g (f args))) origArgs; overrideResult = g: makeOverridable (mirrorArgs (args: g (f args))) origArgs;
in in
if isAttrs result then if isAttrs result then
result // { result
// {
override = overrideArgs; override = overrideArgs;
overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv); overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv);
${if result ? overrideAttrs then "overrideAttrs" else null} = fdrv: ${if result ? overrideAttrs then "overrideAttrs" else null} =
overrideResult (x: x.overrideAttrs fdrv); fdrv: overrideResult (x: x.overrideAttrs fdrv);
} }
else if isFunction result then else if isFunction result then
# Transform the result into a functor while propagating its arguments # Transform the result into a functor while propagating its arguments
setFunctionArgs result (functionArgs result) // { setFunctionArgs result (functionArgs result)
// {
override = overrideArgs; override = overrideArgs;
} }
else result); else
result
);
/** /**
Call the package function in the file `fn` with the required Call the package function in the file `fn` with the required
@ -188,7 +216,6 @@ rec {
<!-- TODO: Apply "Example:" tag to the examples above --> <!-- TODO: Apply "Example:" tag to the examples above -->
# Inputs # Inputs
`autoArgs` `autoArgs`
@ -209,7 +236,8 @@ rec {
callPackageWith :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a callPackageWith :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
``` ```
*/ */
callPackageWith = autoArgs: fn: args: callPackageWith =
autoArgs: fn: args:
let let
f = if isFunction fn then fn else import fn; f = if isFunction fn then fn else import fn;
fargs = functionArgs f; fargs = functionArgs f;
@ -222,12 +250,16 @@ rec {
# wouldn't be passed to it # wouldn't be passed to it
missingArgs = missingArgs =
# Filter out arguments that have a default value # Filter out arguments that have a default value
(filterAttrs (name: value: ! value) (
filterAttrs (name: value: !value)
# Filter out arguments that would be passed # Filter out arguments that would be passed
(removeAttrs fargs (attrNames allArgs))); (removeAttrs fargs (attrNames allArgs))
);
# Get a list of suggested argument names for a given missing one # Get a list of suggested argument names for a given missing one
getSuggestions = arg: pipe (autoArgs // args) [ getSuggestions =
arg:
pipe (autoArgs // args) [
attrNames attrNames
# Only use ones that are at most 2 edits away. While mork would work, # Only use ones that are at most 2 edits away. While mork would work,
# levenshteinAtMost is only fast for 2 or less. # levenshteinAtMost is only fast for 2 or less.
@ -240,41 +272,50 @@ rec {
(map (x: "\"" + x + "\"")) (map (x: "\"" + x + "\""))
]; ];
prettySuggestions = suggestions: prettySuggestions =
if suggestions == [] then "" suggestions:
else if length suggestions == 1 then ", did you mean ${elemAt suggestions 0}?" if suggestions == [ ] then
else ", did you mean ${concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?"; ""
else if length suggestions == 1 then
", did you mean ${elemAt suggestions 0}?"
else
", did you mean ${concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?";
errorForArg = arg: errorForArg =
arg:
let let
loc = builtins.unsafeGetAttrPos arg fargs; loc = builtins.unsafeGetAttrPos arg fargs;
# loc' can be removed once lib/minver.nix is >2.3.4, since that includes # loc' can be removed once lib/minver.nix is >2.3.4, since that includes
# https://github.com/NixOS/nix/pull/3468 which makes loc be non-null # https://github.com/NixOS/nix/pull/3468 which makes loc be non-null
loc' = if loc != null then loc.file + ":" + toString loc.line loc' =
else if ! isFunction fn then if loc != null then
loc.file + ":" + toString loc.line
else if !isFunction fn then
toString fn + optionalString (pathIsDirectory fn) "/default.nix" toString fn + optionalString (pathIsDirectory fn) "/default.nix"
else "<unknown location>"; else
in "Function called without required argument \"${arg}\" at " "<unknown location>";
in
"Function called without required argument \"${arg}\" at "
+ "${loc'}${prettySuggestions (getSuggestions arg)}"; + "${loc'}${prettySuggestions (getSuggestions arg)}";
# Only show the error for the first missing argument # Only show the error for the first missing argument
error = errorForArg (head (attrNames missingArgs)); error = errorForArg (head (attrNames missingArgs));
in if missingArgs == {} in
then makeOverridable f allArgs if missingArgs == { } then
makeOverridable f allArgs
# This needs to be an abort so it can't be caught with `builtins.tryEval`, # This needs to be an abort so it can't be caught with `builtins.tryEval`,
# which is used by nix-env and ofborg to filter out packages that don't evaluate. # which is used by nix-env and ofborg to filter out packages that don't evaluate.
# This way we're forced to fix such errors in Nixpkgs, # This way we're forced to fix such errors in Nixpkgs,
# which is especially relevant with allowAliases = false # which is especially relevant with allowAliases = false
else abort "lib.customisation.callPackageWith: ${error}"; else
abort "lib.customisation.callPackageWith: ${error}";
/** /**
Like callPackage, but for a function that returns an attribute Like callPackage, but for a function that returns an attribute
set of derivations. The override function is added to the set of derivations. The override function is added to the
individual attributes. individual attributes.
# Inputs # Inputs
`autoArgs` `autoArgs`
@ -295,7 +336,8 @@ rec {
callPackagesWith :: AttrSet -> ((AttrSet -> AttrSet) | Path) -> AttrSet -> AttrSet callPackagesWith :: AttrSet -> ((AttrSet -> AttrSet) | Path) -> AttrSet -> AttrSet
``` ```
*/ */
callPackagesWith = autoArgs: fn: args: callPackagesWith =
autoArgs: fn: args:
let let
f = if isFunction fn then fn else import fn; f = if isFunction fn then fn else import fn;
auto = intersectAttrs (functionArgs f) autoArgs; auto = intersectAttrs (functionArgs f) autoArgs;
@ -304,18 +346,19 @@ rec {
pkgs = f origArgs; pkgs = f origArgs;
mkAttrOverridable = name: _: makeOverridable (mirrorArgs (newArgs: (f newArgs).${name})) origArgs; mkAttrOverridable = name: _: makeOverridable (mirrorArgs (newArgs: (f newArgs).${name})) origArgs;
in in
if isDerivation pkgs then throw if isDerivation pkgs then
("function `callPackages` was called on a *single* derivation " throw (
"function `callPackages` was called on a *single* derivation "
+ ''"${pkgs.name or "<unknown-name>"}";'' + ''"${pkgs.name or "<unknown-name>"}";''
+ " did you mean to use `callPackage` instead?") + " did you mean to use `callPackage` instead?"
else mapAttrs mkAttrOverridable pkgs; )
else
mapAttrs mkAttrOverridable pkgs;
/** /**
Add attributes to each output of a derivation without changing Add attributes to each output of a derivation without changing
the derivation itself and check a given condition when evaluating. the derivation itself and check a given condition when evaluating.
# Inputs # Inputs
`condition` `condition`
@ -336,34 +379,48 @@ rec {
extendDerivation :: Bool -> Any -> Derivation -> Derivation extendDerivation :: Bool -> Any -> Derivation -> Derivation
``` ```
*/ */
extendDerivation = condition: passthru: drv: extendDerivation =
condition: passthru: drv:
let let
outputs = drv.outputs or [ "out" ]; outputs = drv.outputs or [ "out" ];
commonAttrs = drv // (listToAttrs outputsList) // commonAttrs =
({ all = map (x: x.value) outputsList; }) // passthru; drv // (listToAttrs outputsList) // ({ all = map (x: x.value) outputsList; }) // passthru;
outputToAttrListElement = outputName: outputToAttrListElement = outputName: {
{ name = outputName; name = outputName;
value = commonAttrs // { value =
commonAttrs
// {
inherit (drv.${outputName}) type outputName; inherit (drv.${outputName}) type outputName;
outputSpecified = true; outputSpecified = true;
drvPath = assert condition; drv.${outputName}.drvPath; drvPath =
outPath = assert condition; drv.${outputName}.outPath; assert condition;
} // drv.${outputName}.drvPath;
outPath =
assert condition;
drv.${outputName}.outPath;
}
//
# TODO: give the derivation control over the outputs. # TODO: give the derivation control over the outputs.
# `overrideAttrs` may not be the only attribute that needs # `overrideAttrs` may not be the only attribute that needs
# updating when switching outputs. # updating when switching outputs.
optionalAttrs (passthru?overrideAttrs) { optionalAttrs (passthru ? overrideAttrs) {
# TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing. # TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing.
overrideAttrs = f: (passthru.overrideAttrs f).${outputName}; overrideAttrs = f: (passthru.overrideAttrs f).${outputName};
}; };
}; };
outputsList = map outputToAttrListElement outputs; outputsList = map outputToAttrListElement outputs;
in commonAttrs // { in
drvPath = assert condition; drv.drvPath; commonAttrs
outPath = assert condition; drv.outPath; // {
drvPath =
assert condition;
drv.drvPath;
outPath =
assert condition;
drv.outPath;
}; };
/** /**
@ -372,7 +429,6 @@ rec {
result to ensure that there are no thunks kept alive to prevent result to ensure that there are no thunks kept alive to prevent
garbage collection. garbage collection.
# Inputs # Inputs
`drv` `drv`
@ -385,21 +441,29 @@ rec {
hydraJob :: (Derivation | Null) -> (Derivation | Null) hydraJob :: (Derivation | Null) -> (Derivation | Null)
``` ```
*/ */
hydraJob = drv: hydraJob =
drv:
let let
outputs = drv.outputs or ["out"]; outputs = drv.outputs or [ "out" ];
commonAttrs = commonAttrs =
{ inherit (drv) name system meta; inherit outputs; } {
inherit (drv) name system meta;
inherit outputs;
}
// optionalAttrs (drv._hydraAggregate or false) { // optionalAttrs (drv._hydraAggregate or false) {
_hydraAggregate = true; _hydraAggregate = true;
constituents = map hydraJob (flatten drv.constituents); constituents = map hydraJob (flatten drv.constituents);
} }
// (listToAttrs outputsList); // (listToAttrs outputsList);
makeOutput = outputName: makeOutput =
let output = drv.${outputName}; in outputName:
{ name = outputName; let
output = drv.${outputName};
in
{
name = outputName;
value = commonAttrs // { value = commonAttrs // {
outPath = output.outPath; outPath = output.outPath;
drvPath = output.drvPath; drvPath = output.drvPath;
@ -411,8 +475,8 @@ rec {
outputsList = map makeOutput outputs; outputsList = map makeOutput outputs;
drv' = (head outputsList).value; drv' = (head outputsList).value;
in if drv == null then null else in
deepSeq drv' drv'; if drv == null then null else deepSeq drv' drv';
/** /**
Make an attribute set (a "scope") from functions that take arguments from that same attribute set. Make an attribute set (a "scope") from functions that take arguments from that same attribute set.
@ -538,19 +602,21 @@ rec {
makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> scope makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> scope
``` ```
*/ */
makeScope = newScope: f: makeScope =
let self = f self // { newScope: f:
let
self = f self // {
newScope = scope: newScope (self // scope); newScope = scope: newScope (self // scope);
callPackage = self.newScope {}; callPackage = self.newScope { };
overrideScope = g: makeScope newScope (extends g f); overrideScope = g: makeScope newScope (extends g f);
packages = f; packages = f;
}; };
in self; in
self;
/** /**
backward compatibility with old uncurried form; deprecated backward compatibility with old uncurried form; deprecated
# Inputs # Inputs
`splicePackages` `splicePackages`
@ -579,9 +645,14 @@ rec {
*/ */
makeScopeWithSplicing = makeScopeWithSplicing =
splicePackages: newScope: otherSplices: keep: extra: f: splicePackages: newScope: otherSplices: keep: extra: f:
makeScopeWithSplicing' makeScopeWithSplicing' { inherit splicePackages newScope; } {
{ inherit splicePackages newScope; } inherit
{ inherit otherSplices keep extra f; }; otherSplices
keep
extra
f
;
};
/** /**
Like makeScope, but aims to support cross compilation. It's still ugly, but Like makeScope, but aims to support cross compilation. It's still ugly, but
@ -608,14 +679,16 @@ rec {
``` ```
*/ */
makeScopeWithSplicing' = makeScopeWithSplicing' =
{ splicePackages {
, newScope splicePackages,
newScope,
}: }:
{ otherSplices {
otherSplices,
# Attrs from `self` which won't be spliced. # Attrs from `self` which won't be spliced.
# Avoid using keep, it's only used for a python hook workaround, added in PR #104201. # Avoid using keep, it's only used for a python hook workaround, added in PR #104201.
# ex: `keep = (self: { inherit (self) aAttr; })` # ex: `keep = (self: { inherit (self) aAttr; })`
, keep ? (_self: {}) keep ? (_self: { }),
# Additional attrs to add to the sets `callPackage`. # Additional attrs to add to the sets `callPackage`.
# When the package is from a subset (but not a subset within a package IS #211340) # When the package is from a subset (but not a subset within a package IS #211340)
# within `spliced0` it will be spliced. # within `spliced0` it will be spliced.
@ -630,8 +703,8 @@ rec {
# nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { } # nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { }
# «derivation ...CoreFoundation-11.0.0.drv» # «derivation ...CoreFoundation-11.0.0.drv»
# ``` # ```
, extra ? (_spliced0: {}) extra ? (_spliced0: { }),
, f f,
}: }:
let let
spliced0 = splicePackages { spliced0 = splicePackages {
@ -648,13 +721,15 @@ rec {
callPackage = newScope spliced; # == self.newScope {}; callPackage = newScope spliced; # == self.newScope {};
# N.B. the other stages of the package set spliced in are *not* # N.B. the other stages of the package set spliced in are *not*
# overridden. # overridden.
overrideScope = g: (makeScopeWithSplicing' overrideScope =
{ inherit splicePackages newScope; } g:
{ inherit otherSplices keep extra; (makeScopeWithSplicing' { inherit splicePackages newScope; } {
inherit otherSplices keep extra;
f = extends g f; f = extends g f;
}); });
packages = f; packages = f;
}; };
in self; in
self;
} }