From ca1262a4832b290d9f35c4b9c5f67f93144c7f2a Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Tue, 30 Jan 2024 17:29:47 -0500 Subject: [PATCH] lib: Add optionalDrvAttr to conditionally set drv attributes. This allows for adding new, conditionally set, derivation attributes to an existing derivation without changing any output paths in the case where the condition is not met. --- doc/default.nix | 1 + lib/default.nix | 2 +- lib/derivations.nix | 26 ++++++++++++++++++++++++++ lib/tests/misc.nix | 20 +++++++++++++++++++- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/doc/default.nix b/doc/default.nix index 26aae9efa573..bcbc20b9f983 100644 --- a/doc/default.nix +++ b/doc/default.nix @@ -25,6 +25,7 @@ let { name = "gvariant"; description = "GVariant formatted string serialization functions"; } { name = "customisation"; description = "Functions to customise (derivation-related) functions, derivatons, or attribute sets"; } { name = "meta"; description = "functions for derivation metadata"; } + { name = "derivations"; description = "miscellaneous derivation-specific functions"; } ]; }; diff --git a/lib/default.nix b/lib/default.nix index f6c94ae91634..a17307be6e07 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -116,7 +116,7 @@ let inherit (self.customisation) overrideDerivation makeOverridable callPackageWith callPackagesWith extendDerivation hydraJob makeScope makeScopeWithSplicing makeScopeWithSplicing'; - inherit (self.derivations) lazyDerivation; + inherit (self.derivations) lazyDerivation optionalDrvAttr; inherit (self.meta) addMetaAttrs dontDistribute setName updateName appendToName mapDerivationAttrset setPrio lowPrio lowPrioSet hiPrio hiPrioSet getLicenseFromSpdxId getExe getExe'; diff --git a/lib/derivations.nix b/lib/derivations.nix index 5b7ed1868e86..44b727ee31cc 100644 --- a/lib/derivations.nix +++ b/lib/derivations.nix @@ -98,4 +98,30 @@ in # `lazyDerivation` caller knew a shortcut, be taken from there. meta = args.meta or checked.meta; } // passthru; + + /* Conditionally set a derivation attribute. + + Because `mkDerivation` sets `__ignoreNulls = true`, a derivation + attribute set to `null` will not impact the derivation output hash. + Thus, this function passes through its `value` argument if the `cond` + is `true`, but returns `null` if not. + + Type: optionalDrvAttr :: Bool -> a -> a | Null + + Example: + (stdenv.mkDerivation { + name = "foo"; + x = optionalDrvAttr true 1; + y = optionalDrvAttr false 1; + }).drvPath == (stdenv.mkDerivation { + name = "foo"; + x = 1; + }).drvPath + => true + */ + optionalDrvAttr = + # Condition + cond: + # Attribute value + value: if cond then value else null; } diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 3059878ba069..193e68a96933 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -1902,7 +1902,7 @@ runTests { expected = true; }; - # lazyDerivation + # DERIVATIONS testLazyDerivationIsLazyInDerivationForAttrNames = { expr = attrNames (lazyDerivation { @@ -1955,6 +1955,24 @@ runTests { expected = derivation; }; + testOptionalDrvAttr = let + mkDerivation = args: derivation (args // { + builder = "builder"; + system = "system"; + __ignoreNulls = true; + }); + in { + expr = (mkDerivation { + name = "foo"; + x = optionalDrvAttr true 1; + y = optionalDrvAttr false 1; + }).drvPath; + expected = (mkDerivation { + name = "foo"; + x = 1; + }).drvPath; + }; + testTypeDescriptionInt = { expr = (with types; int).description; expected = "signed integer";