diff --git a/lib/customisation.nix b/lib/customisation.nix index 08fc5db0614de..a9eadc456bf8d 100644 --- a/lib/customisation.nix +++ b/lib/customisation.nix @@ -107,6 +107,61 @@ rec { } else result); + /* + Apply arbitrary customization to an overridable attribute set and its overriding results. + + This function apply the specified customization *modify* + to an [overridable](#chap-overrides) attribute set *overridable* + and update common attributes that perform overriding + to automatically re-apply the customization to future overriding results. + + Attributes [`override`](#sec-pkg-override), + [`overrideAttributes`](#sec-pkg-overrideAttrs) and + [`overrideDerivation`](#sec-pkg-overrideDerivation) are chosen + to cover most of the use cases. + + Example: + helloWithAns1 = lib.extendDerivation true { ans = 42; } pkgs.hello + + helloWithAns1.ans + => 42 + (helloWithAns1.override { }).ans + => error: attribute 'ans' missing + + helloWithAns2 = lib.applyToOverridable (lib.extendDerivation true { ans = 42; }) pkgs.hello + + helloWithAns2.ans + => 42 + (helloWithAns2.override { }).ans + => 42 + + helloFive1 = lib.extendDerivation (2 + 2 == 5) { } pkgs.hello + + helloFive1 + => error: assertion 'condition' failed + helloFive1.override { } + => «derivation /nix/store/4f4rwzm6s707ify0yqgib2lckp4dw8as-hello-2.12.1.drv» + + helloFive2 = lib.applyToOverridable (lib.extendDerivation (2 + 2 == 5) { }) pkgs.hello + + helloFive2 + => error: assertion 'condition' failed + helloFive2.override { } + => error: assertion 'condition' failed + + Type: + applyToOverridable :: (AttrSet -> AttrSet) -> AttrSet -> AttrSet + */ + applyToOverridable = modify: overridable: + let + r = modify overridable; + in + r // { + ${if r ? override then "override" else null} = lib.mirrorFunctionArgs r.override (fdrv: applyToOverridable modify (r.override fdrv)); + ${if r ? overrideAttrs then "overrideAttrs" else null} = fdrv: applyToOverridable modify (r.overrideAttrs fdrv); + ${if r ? overrideDerivation then "overrideDerivation" else null} = fdrv: applyToOverridable modify (r.overrideDerivation fdrv); + }; + /* Call the package function in the file `fn` with the required arguments automatically. The function is called with the diff --git a/lib/default.nix b/lib/default.nix index 0dac50a08caa0..2772d11e006c7 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -114,6 +114,7 @@ let inherit (self.stringsWithDeps) textClosureList textClosureMap noDepEntry fullDepEntry packEntry stringAfter; inherit (self.customisation) overrideDerivation makeOverridable + applyToOverridable callPackageWith callPackagesWith extendDerivation hydraJob makeScope makeScopeWithSplicing makeScopeWithSplicing'; inherit (self.derivations) lazyDerivation; diff --git a/pkgs/development/compilers/cudatoolkit/stdenv.nix b/pkgs/development/compilers/cudatoolkit/stdenv.nix index 95e783a682bff..0fee67fa9ea4d 100644 --- a/pkgs/development/compilers/cudatoolkit/stdenv.nix +++ b/pkgs/development/compilers/cudatoolkit/stdenv.nix @@ -26,8 +26,10 @@ let }; assertCondition = true; in -lib.extendDerivation - assertCondition - passthruExtra +lib.applyToOverridable + (lib.extendDerivation + assertCondition + passthruExtra + ) cudaStdenv diff --git a/pkgs/test/overriding.nix b/pkgs/test/overriding.nix index f2519088f138a..ebb1b39a42cb3 100644 --- a/pkgs/test/overriding.nix +++ b/pkgs/test/overriding.nix @@ -31,6 +31,43 @@ let expr = ((stdenvNoCC.mkDerivation { pname = "hello-no-final-attrs"; }).overrideAttrs { pname = "hello-no-final-attrs-overridden"; }).pname == "hello-no-final-attrs-overridden"; expected = true; }) + ({ + name = "extendDerivation-passthru"; + expr = helloWithAns.ans == 42; + expected = true; + }) + ] + ++ getTestsApplyToOverridable { } + ; + + getTestsApplyToOverridable = + { applyToOverridable ? lib.applyToOverridable + , fname ? "applyToOverridable" + }: + let + helloWithAnsOverridable = applyToOverridable (lib.extendDerivation true { ans = 42; }) pkgs.hello; + in + [ + ({ + name = fname + "-self"; + expr = helloWithAnsOverridable.ans == 42; + expected = true; + }) + ({ + name = fname + "-override"; + expr = (helloWithAnsOverridable.override { stdenv = pkgs.clangStdenv; }).ans == 42; + expected = true; + }) + ({ + name = fname + "-overrideAttrs"; + expr = (helloWithAnsOverridable.overrideAttrs (previousAttrs: { FOO = "bar"; })).ans == 42; + expected = true; + }) + ({ + name = fname + "-overrideDerivation"; + expr = (helloWithAnsOverridable.overrideDerivation (previousDrv: { FOO = "bar"; })).ans == 42; + expected = true; + }) ]; addEntangled = origOverrideAttrs: f: @@ -55,6 +92,8 @@ let overrides1 = example.overrideAttrs (_: super: { pname = "a-better-${super.pname}"; }); repeatedOverrides = overrides1.overrideAttrs (_: super: { pname = "${super.pname}-with-blackjack"; }); + + helloWithAns = lib.extendDerivation true { ans = 42; } pkgs.hello; in stdenvNoCC.mkDerivation {