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,37 +151,42 @@ 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 (
let origArgs:
result = f origArgs; let
result = f origArgs;
# Changes the original arguments with (potentially a function that returns) a set of new attributes # Changes the original arguments with (potentially a function that returns) a set of new attributes
overrideWith = newArgs: origArgs // (if isFunction newArgs then newArgs origArgs else newArgs); overrideWith = newArgs: origArgs // (if isFunction newArgs then newArgs origArgs else newArgs);
# Re-call the function but with different arguments # Re-call the function but with different arguments
overrideArgs = mirrorArgs (newArgs: makeOverridable f (overrideWith newArgs)); overrideArgs = mirrorArgs (newArgs: makeOverridable f (overrideWith newArgs));
# Change the result of the function call by applying g to it # Change the result of the function call by applying g to it
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,59 +250,72 @@ 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) (
# Filter out arguments that would be passed filterAttrs (name: value: !value)
(removeAttrs fargs (attrNames allArgs))); # Filter out arguments that would be passed
(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 =
attrNames arg:
# Only use ones that are at most 2 edits away. While mork would work, pipe (autoArgs // args) [
# levenshteinAtMost is only fast for 2 or less. attrNames
(filter (levenshteinAtMost 2 arg)) # Only use ones that are at most 2 edits away. While mork would work,
# Put strings with shorter distance first # levenshteinAtMost is only fast for 2 or less.
(sortOn (levenshtein arg)) (filter (levenshteinAtMost 2 arg))
# Only take the first couple results # Put strings with shorter distance first
(take 3) (sortOn (levenshtein arg))
# Quote all entries # Only take the first couple results
(map (x: "\"" + x + "\"")) (take 3)
]; # Quote all entries
(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
# This needs to be an abort so it can't be caught with `builtins.tryEval`, makeOverridable f allArgs
# which is used by nix-env and ofborg to filter out packages that don't evaluate. # This needs to be an abort so it can't be caught with `builtins.tryEval`,
# This way we're forced to fix such errors in Nixpkgs, # which is used by nix-env and ofborg to filter out packages that don't evaluate.
# which is especially relevant with allowAliases = false # This way we're forced to fix such errors in Nixpkgs,
else abort "lib.customisation.callPackageWith: ${error}"; # which is especially relevant with allowAliases = false
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 (
+ ''"${pkgs.name or "<unknown-name>"}";'' "function `callPackages` was called on a *single* derivation "
+ " did you mean to use `callPackage` instead?") + ''"${pkgs.name or "<unknown-name>"}";''
else mapAttrs mkAttrOverridable pkgs; + " did you mean to use `callPackage` instead?"
)
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:
newScope = scope: newScope (self // scope); let
callPackage = self.newScope {}; self = f self // {
overrideScope = g: makeScope newScope (extends g f); newScope = scope: newScope (self // scope);
packages = f; callPackage = self.newScope { };
}; overrideScope = g: makeScope newScope (extends g f);
in self; packages = f;
};
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,30 +679,32 @@ rec {
``` ```
*/ */
makeScopeWithSplicing' = makeScopeWithSplicing' =
{ splicePackages {
, newScope splicePackages,
newScope,
}: }:
{ otherSplices {
# Attrs from `self` which won't be spliced. otherSplices,
# Avoid using keep, it's only used for a python hook workaround, added in PR #104201. # Attrs from `self` which won't be spliced.
# ex: `keep = (self: { inherit (self) aAttr; })` # Avoid using keep, it's only used for a python hook workaround, added in PR #104201.
, keep ? (_self: {}) # ex: `keep = (self: { inherit (self) aAttr; })`
# Additional attrs to add to the sets `callPackage`. keep ? (_self: { }),
# When the package is from a subset (but not a subset within a package IS #211340) # Additional attrs to add to the sets `callPackage`.
# within `spliced0` it will be spliced. # When the package is from a subset (but not a subset within a package IS #211340)
# When using an package outside the set but it's available from `pkgs`, use the package from `pkgs.__splicedPackages`. # within `spliced0` it will be spliced.
# If the package is not available within the set or in `pkgs`, such as a package in a let binding, it will not be spliced # When using an package outside the set but it's available from `pkgs`, use the package from `pkgs.__splicedPackages`.
# ex: # If the package is not available within the set or in `pkgs`, such as a package in a let binding, it will not be spliced
# ``` # ex:
# nix-repl> darwin.apple_sdk.frameworks.CoreFoundation # ```
# «derivation ...CoreFoundation-11.0.0.drv» # nix-repl> darwin.apple_sdk.frameworks.CoreFoundation
# nix-repl> darwin.CoreFoundation # «derivation ...CoreFoundation-11.0.0.drv»
# error: attribute 'CoreFoundation' missing # nix-repl> darwin.CoreFoundation
# nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { } # error: attribute 'CoreFoundation' missing
# «derivation ...CoreFoundation-11.0.0.drv» # nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { }
# ``` # «derivation ...CoreFoundation-11.0.0.drv»
, extra ? (_spliced0: {}) # ```
, f extra ? (_spliced0: { }),
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;
} }