Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 93 additions & 1 deletion lib/customisation.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
let
inherit (builtins)
intersectAttrs
unsafeGetAttrPos
;
inherit (lib)
functionArgs
Expand Down Expand Up @@ -33,6 +34,7 @@ let
extends
toFunction
id
defaultTo
;
inherit (lib.strings) levenshtein levenshteinAtMost;

Expand Down Expand Up @@ -303,7 +305,7 @@ rec {
errorForArg =
arg:
let
loc = builtins.unsafeGetAttrPos arg fargs;
loc = unsafeGetAttrPos arg fargs;
in
"Function called without required argument \"${arg}\" at "
+ "${loc.file}:${toString loc.line}${prettySuggestions (getSuggestions arg)}";
Expand Down Expand Up @@ -863,4 +865,94 @@ rec {
transformDrv
;
};

/**
Get informative message string about attribute missing under `finalAttrs.passthru`
due to accidental overriting `passthru` when calling `<pkg>.overrideAttrs`.

# Inputs

`getFinalPassthruMissingMessage`-specific configurations
: `attrName`: the missing attribute name.
: `finalAttrs`: the final state of the [fixed-point arguments](#chap-build-helpers-finalAttrs), to get possible possition of incorrect overriding.
: `prefix`: Additional prefix to the message for the name of the package and/or the build helper.

# Type

```
getFinalPassthruMissingMessage ::
{
attrName :: String,
finalAttrs :: null or { passthru :: AttrSet, ... },
prefix :: String,
}
-> String
```
*/
getFinalPassthruMissingMessage =
{
attrName,
finalAttrs ? null,
prefix ? "",
}:
let
pos = unsafeGetAttrPos "passthru" finalAttrs;
in
"${prefix}passthru.${attrName} missing after overrideAttrs overriding."
+ optionalString (
finalAttrs != null && pos != null
) " Last overridden at ${pos.file}:${toString pos.line}";

/**
Get attribute from finalAttrs.passthru, falling back to a custom default and an optional message.

`getFinalPassthruWith` roughly resembles

```nix
finalAttrs.passthru.${attrName} or (handler "message" default)
```

Where [`getFinalPassthruMissingMessage`](#function-library-lib.customisation.getFinalPassthruMissingMessage) provides the message.

# Inputs

`getFinalPassthruWith`-specific configurations
: `handler`: Function to take the message and the default value in case the attribute is missing. Typical values include `throw`, `lib.warn` and `null`, where `null` means silently using the default value.
: `prefix`: Additional prefix to the message for the name of the package and/or the build helper.

`finalAttrs`
: The final state of the [fixed-point arguments](#chap-build-helpers-finalAttrs).

`attrName`
: The attribute name to get from `finalAttrs.passthru`.

# Type

```
getFinalPassthruWith ::
{
handler :: String -> a -> a,
prefix :: String,
}
-> { passthru :: AttrSet, ... }
-> String
-> a
```
*/
getFinalPassthruWith =
{
handler ? throw,
prefix ? "",
}:
finalAttrs: attrName:
if finalAttrs.passthru ? ${attrName} then
default: finalAttrs.passthru.${attrName}
else
(defaultTo (m: d: d) handler) (getFinalPassthruMissingMessage {
inherit
prefix
finalAttrs
attrName
;
});
}
2 changes: 2 additions & 0 deletions lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ let
makeScopeWithSplicing
makeScopeWithSplicing'
extendMkDerivation
getFinalPassthruMissingMessage
getFinalPassthruWith
;
inherit (self.derivations) lazyDerivation optionalDrvAttr warnOnInstantiate;
inherit (self.generators) mkLuaInline;
Expand Down
45 changes: 45 additions & 0 deletions lib/tests/misc.nix
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ let
genList
getExe
getExe'
getFinalPassthruWith
getLicenseFromSpdxIdOr
groupBy
groupBy'
Expand Down Expand Up @@ -118,6 +119,7 @@ let
uniqueStrings
updateManyAttrsByPath
versions
warn
xor
;

Expand Down Expand Up @@ -239,6 +241,49 @@ runTests {
expected = functionArgs f;
};

testGetFinalPassthruFallback =
let
finalAttrs = {
passthru = { };
};
in
{
expr = {
nullWithDefault = getFinalPassthruWith { handler = null; } finalAttrs "foo" "myDefaultValue";
throwWithDefault =
(builtins.tryEval (getFinalPassthruWith { handler = throw; } finalAttrs "foo" "myDefaultValue"))
.success;
throwWithoutDefault =
(builtins.tryEval (getFinalPassthruWith { handler = throw; } finalAttrs "foo")).success;
};
expected = {
nullWithDefault = "myDefaultValue";
throwWithDefault = false;
throwWithoutDefault = false;
};
};

testGetFinalPassthruSuccess =
let
finalAttrs = {
passthru = {
foo = "bar";
};
};
in
{
expr = {
nullWithDefault = getFinalPassthruWith { handler = null; } finalAttrs "foo" "myDefaultValue";
warnWithDefault = getFinalPassthruWith { handler = warn; } finalAttrs "foo" "myDefaultValue";
throwWithDefault = getFinalPassthruWith { handler = throw; } finalAttrs "foo" "myDefaultValue";
};
expected = {
nullWithDefault = "bar";
warnWithDefault = "bar";
throwWithDefault = "bar";
};
};

# TRIVIAL

testId = {
Expand Down
16 changes: 7 additions & 9 deletions pkgs/build-support/go/module.nix
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ lib.extendMkDerivation {

...
}@args:
let
getFinalPassthruOr = lib.getFinalPassthruWith {
prefix = "buildGoModule: ${finalAttrs.name or finalAttrs.pname}: ";
handler = lib.warn;
} finalAttrs;
in
{
inherit
modRoot
Expand Down Expand Up @@ -205,15 +211,7 @@ lib.extendMkDerivation {
outputHashAlgo = if finalAttrs.vendorHash == "" then "sha256" else null;
# in case an overlay clears passthru by accident, don't fail evaluation
}).overrideAttrs
(
let
pos = builtins.unsafeGetAttrPos "passthru" finalAttrs;
posString =
if pos == null then "unknown" else "${pos.file}:${toString pos.line}:${toString pos.column}";
in
finalAttrs.passthru.overrideModAttrs
or (lib.warn "buildGoModule: ${finalAttrs.name or finalAttrs.pname}: passthru.overrideModAttrs missing after overrideAttrs. Last overridden at ${posString}." overrideModAttrs)
);
(getFinalPassthruOr "overrideModAttrs" overrideModAttrs);

nativeBuildInputs = [ go ] ++ nativeBuildInputs;

Expand Down
Loading