@ -16,23 +16,23 @@ rec {
defaultMergeArg = x : y : if builtins . isAttrs y then
y
else
else
( y x ) ;
defaultMerge = x : y : x // ( defaultMergeArg x y ) ;
foldArgs = merger : f : init : x :
let arg = ( merger init ( defaultMergeArg init x ) ) ;
# now add the function with composed args already applied to the final attrs
base = ( setAttrMerge " p a s s t h r u " { } ( f arg )
( z : z // rec {
function = foldArgs merger f arg ;
args = ( lib . attrByPath [ " p a s s t h r u " " a r g s " ] { } z ) // x ;
foldArgs = merger : f : init : x :
let arg = ( merger init ( defaultMergeArg init x ) ) ;
# now add the function with composed args already applied to the final attrs
base = ( setAttrMerge " p a s s t h r u " { } ( f arg )
( z : z // rec {
function = foldArgs merger f arg ;
args = ( lib . attrByPath [ " p a s s t h r u " " a r g s " ] { } z ) // x ;
} ) ) ;
withStdOverrides = base // {
override = base . passthru . function ;
} ;
withStdOverrides = base // {
override = base . passthru . function ;
} ;
in
withStdOverrides ;
withStdOverrides ;
# predecessors: proposed replacement for applyAndFun (which has a bug cause it merges twice)
# the naming "overridableDelayableArgs" tries to express that you can
@ -49,35 +49,35 @@ rec {
#
# examples: see test cases "res" below;
overridableDelayableArgs =
f : # the function applied to the arguments
initial : # you pass attrs, the functions below are passing a function taking the fix argument
f : # the function applied to the arguments
initial : # you pass attrs, the functions below are passing a function taking the fix argument
let
takeFixed = if isFunction initial then initial else ( fixed : initial ) ; # transform initial to an expression always taking the fixed argument
tidy = args :
tidy = args :
let # apply all functions given in "applyPreTidy" in sequence
applyPreTidyFun = fold ( n : a : x : n ( a x ) ) lib . id ( maybeAttr " a p p l y P r e T i d y " [ ] args ) ;
applyPreTidyFun = fold ( n : a : x : n ( a x ) ) lib . id ( maybeAttr " a p p l y P r e T i d y " [ ] args ) ;
in removeAttrs ( applyPreTidyFun args ) ( [ " a p p l y P r e T i d y " ] ++ ( maybeAttr " r e m o v e A t t r s " [ ] args ) ) ; # tidy up args before applying them
fun = n : x :
let newArgs = fixed :
let args = takeFixed fixed ;
mergeFun = args . ${ n } ;
in if isAttrs x then ( mergeFun args x )
else assert isFunction x ;
mergeFun args ( x ( args // { inherit fixed ; } ) ) ;
in overridableDelayableArgs f newArgs ;
fun = n : x :
let newArgs = fixed :
let args = takeFixed fixed ;
mergeFun = args . ${ n } ;
in if isAttrs x then ( mergeFun args x )
else assert isFunction x ;
mergeFun args ( x ( args // { inherit fixed ; } ) ) ;
in overridableDelayableArgs f newArgs ;
in
( f ( tidy ( lib . fix takeFixed ) ) ) // {
merge = fun " m e r g e F u n " ;
replace = fun " k e e p F u n " ;
} ;
defaultOverridableDelayableArgs = f :
defaultOverridableDelayableArgs = f :
let defaults = {
mergeFun = mergeAttrByFunc ; # default merge function. merge strategie (concatenate lists, strings) is given by mergeAttrBy
keepFun = a : b : { inherit ( a ) removeAttrs mergeFun keepFun mergeAttrBy ; } // b ; # even when using replace preserve these values
keepFun = a : b : { inherit ( a ) removeAttrs mergeFun keepFun mergeAttrBy ; } // b ; # even when using replace preserve these values
applyPreTidy = [ ] ; # list of functions applied to args before args are tidied up (usage case : prepareDerivationArgs)
mergeAttrBy = mergeAttrBy // {
applyPreTidy = a : b : a ++ b ;
removeAttrs = a : b : a ++ b ;
applyPreTidy = a : b : a ++ b ;
removeAttrs = a : b : a ++ b ;
} ;
removeAttrs = [ " m e r g e F u n " " k e e p F u n " " m e r g e A t t r B y " " r e m o v e A t t r s " " f i x e d " ] ; # before applying the arguments to the function make sure these names are gone
} ;
@ -86,7 +86,7 @@ rec {
# rec { # an example of how composedArgsAndFun can be used
# a = composedArgsAndFun (x : x) { a = ["2"]; meta = { d = "bar";}; };
# a = composedArgsAndFun (x: x) { a = ["2"]; meta = { d = "bar";}; };
# # meta.d will be lost ! It's your task to preserve it (eg using a merge function)
# b = a.passthru.function { a = [ "3" ]; meta = { d2 = "bar2";}; };
# # instead of passing/ overriding values you can use a merge function:
@ -119,7 +119,7 @@ rec {
else if val == true || val == false then false
else null ;
# Return true only if there is an attribute and it is true.
checkFlag = attrSet : name :
if name == " t r u e " then true else
@ -134,29 +134,29 @@ rec {
( attrByPath [ name ] ( if checkFlag attrSet name then true else
if argList == [ ] then null else
let x = builtins . head argList ; in
if ( head x ) == name then
if ( head x ) == name then
( head ( tail x ) )
else ( getValue attrSet
else ( getValue attrSet
( tail argList ) name ) ) attrSet ) ;
# Input : attrSet, [[name default] ...], [ [flagname reqs..] ... ]
# Output : are reqs satisfied? It's asserted.
checkReqs = attrSet : argList : condList :
checkReqs = attrSet : argList : condList :
(
fold lib . and true
( map ( x : let name = ( head x ) ; in
( ( checkFlag attrSet name ) ->
fold lib . and true
( map ( x : let name = ( head x ) ; in
( ( checkFlag attrSet name ) ->
( fold lib . and true
( map ( y : let val = ( getValue attrSet argList y ) ; in
( val != null ) && ( val != false ) )
( tail x ) ) ) ) ) condList ) ) ;
( val != null ) && ( val != false ) )
( tail x ) ) ) ) ) condList ) ) ;
# This function has O(n^2) performance.
uniqList = { inputList , acc ? [ ] } :
let go = xs : acc :
uniqList = { inputList , acc ? [ ] }:
let go = xs : acc :
if xs == [ ]
then [ ]
else let x = head xs ;
@ -164,26 +164,26 @@ rec {
in y ++ go ( tail xs ) ( y ++ acc ) ;
in go inputList acc ;
uniqListExt = { inputList , outputList ? [ ] ,
getter ? ( x : x ) , compare ? ( x : y : x == y ) } :
uniqListExt = { inputList ,
outputList ? [ ] ,
getter ? ( x : x ) ,
compare ? ( x : y : x == y ) } :
if inputList == [ ] then outputList else
let x = head inputList ;
isX = y : ( compare ( getter y ) ( getter x ) ) ;
newOutputList = outputList ++
( if any isX outputList then [ ] else [ x ] ) ;
in uniqListExt { outputList = newOutputList ;
inputList = ( tail inputList ) ;
inherit getter compare ;
} ;
let x = head inputList ;
isX = y : ( compare ( getter y ) ( getter x ) ) ;
newOutputList = outputList ++
( if any isX outputList then [ ] else [ x ] ) ;
in uniqListExt { outputList = newOutputList ;
inputList = ( tail inputList ) ;
inherit getter compare ;
} ;
condConcat = name : list : checker :
if list == [ ] then name else
if checker ( head list ) then
condConcat
( name + ( head ( tail list ) ) )
( tail ( tail list ) )
if checker ( head list ) then
condConcat
( name + ( head ( tail list ) ) )
( tail ( tail list ) )
checker
else condConcat
name ( tail ( tail list ) ) checker ;
@ -202,12 +202,12 @@ rec {
in
work startSet [ ] [ ] ;
innerModifySumArgs = f : x : a : b : if b == null then ( f a b ) // x else
innerModifySumArgs = f : x : a : b : if b == null then ( f a b ) // x else
innerModifySumArgs f x ( a // b ) ;
modifySumArgs = f : x : innerModifySumArgs f x { } ;
innerClosePropagation = acc : xs :
innerClosePropagation = acc : xs :
if xs == [ ]
then acc
else let y = head xs ;
@ -227,31 +227,31 @@ rec {
closePropagation = list : ( uniqList { inputList = ( innerClosePropagation [ ] list ) ; } ) ;
# calls a function (f attr value ) for each record item. returns a list
mapAttrsFlatten = f : r : map ( attr : f attr r . ${ attr } ) ( attrNames r ) ;
mapAttrsFlatten = f : r : map ( attr : f attr r . ${ attr } ) ( attrNames r ) ;
# attribute set containing one attribute
nvs = name : value : listToAttrs [ ( nameValuePair name value ) ] ;
nvs = name : value : listToAttrs [ ( nameValuePair name value ) ] ;
# adds / replaces an attribute of an attribute set
setAttr = set : name : v : set // ( nvs name v ) ;
setAttr = set : name : v : set // ( nvs name v ) ;
# setAttrMerge (similar to mergeAttrsWithFunc but only merges the values of a particular name)
# setAttrMerge "a" [] { a = [2];} (x : x ++ [3]) -> { a = [2 3]; }
# setAttrMerge "a" [] { } (x : x ++ [3]) -> { a = [ 3]; }
setAttrMerge = name : default : attrs : f :
# setAttrMerge "a" [] { a = [2];} (x: x ++ [3]) -> { a = [2 3]; }
# setAttrMerge "a" [] { } (x: x ++ [3]) -> { a = [ 3]; }
setAttrMerge = name : default : attrs : f :
setAttr attrs name ( f ( maybeAttr name default attrs ) ) ;
# Using f = a : b = b the result is similar to //
# Using f = a: b = b the result is similar to //
# merge attributes with custom function handling the case that the attribute
# exists in both sets
mergeAttrsWithFunc = f : set1 : set2 :
fold ( n : set : if set ? ${ n }
mergeAttrsWithFunc = f : set1 : set2 :
fold ( n : set : if set ? ${ n }
then setAttr set n ( f set . ${ n } set2 . ${ n } )
else set )
( set2 // set1 ) ( attrNames set2 ) ;
# merging two attribute set concatenating the values of same attribute names
# eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
mergeAttrsConcatenateValues = mergeAttrsWithFunc ( a : b : ( toList a ) ++ ( toList b ) ) ;
mergeAttrsConcatenateValues = mergeAttrsWithFunc ( a : b : ( toList a ) ++ ( toList b ) ) ;
# merges attributes using //, if a name exisits in both attributes
# an error will be triggered unless its listed in mergeLists
@ -262,10 +262,10 @@ rec {
# ! deprecated, use mergeAttrByFunc instead
mergeAttrsNoOverride = { mergeLists ? [ " b u i l d I n p u t s " " p r o p a g a t e d B u i l d I n p u t s " ] ,
overrideSnd ? [ " b u i l d P h a s e " ]
} : attrs1 : attrs2 :
fold ( n : set :
} : attrs1 : attrs2 :
fold ( n : set :
setAttr set n ( if set ? ${ n }
then # merge
then # merge
if elem n mergeLists # attribute contains list, merge them by concatenating
then attrs2 . ${ n } ++ attrs1 . ${ n }
else if elem n overrideSnd
@ -286,14 +286,14 @@ rec {
# { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
# is used by prepareDerivationArgs, defaultOverridableDelayableArgs and can be used when composing using
# foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
mergeAttrByFunc = x : y :
mergeAttrByFunc = x : y :
let
mergeAttrBy2 = { mergeAttrBy = lib . mergeAttrs ; }
mergeAttrBy2 = { mergeAttrBy = lib . mergeAttrs ; }
// ( maybeAttr " m e r g e A t t r B y " { } x )
// ( maybeAttr " m e r g e A t t r B y " { } y ) ; in
fold lib . mergeAttrs { } [
x y
( mapAttrs ( a : v : # merge special names using given functions
( mapAttrs ( a : v : # merge special names using given functions
if x ? ${ a }
then if y ? ${ a }
then v x . ${ a } y . ${ a } # both have attr, use merge func
@ -313,9 +313,9 @@ rec {
#
# This function is best explained by an example:
#
# {version ? "2.x"} :
# {version ? "2.x"}:
#
# mkDerivation (mergeAttrsByVersion "package-name" version
# mkDerivation (mergeAttrsByVersion "package-name" version
# { # version specific settings
# "git" = { src = ..; preConfigre = "autogen.sh"; buildInputs = [automake autoconf libtool]; };
# "2.x" = { src = ..; };
@ -346,21 +346,24 @@ rec {
# See misc.nix -> versionedDerivation
# discussion: nixpkgs: pull/310
mergeAttrsByVersion = name : version : attrsByVersion : base :
mergeAttrsByFuncDefaultsClean [ { name = " ${ name } - ${ version } " ; } base ( maybeAttr version ( throw " b a d v e r s i o n ${ version } f o r ${ name } " ) attrsByVersion ) ] ;
mergeAttrsByFuncDefaultsClean [ { name = " ${ name } - ${ version } " ; }
base
( maybeAttr version ( throw " b a d v e r s i o n ${ version } f o r ${ name } " ) attrsByVersion )
] ;
# sane defaults (same name as attr name so that inherit can be used)
mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
listToAttrs ( map ( n : nameValuePair n lib . concat )
listToAttrs ( map ( n : nameValuePair n lib . concat )
[ " n a t i v e B u i l d I n p u t s " " b u i l d I n p u t s " " p r o p a g a t e d B u i l d I n p u t s " " c o n f i g u r e F l a g s " " p r e P h a s e s " " p o s t A l l " " p a t c h e s " ] )
// listToAttrs ( map ( n : nameValuePair n lib . mergeAttrs ) [ " p a s s t h r u " " m e t a " " c f g " " f l a g s " ] )
// listToAttrs ( map ( n : nameValuePair n ( a : b : " ${ a } \n ${ b } " ) ) [ " p r e C o n f i g u r e " " p o s t I n s t a l l " ] )
// listToAttrs ( map ( n : nameValuePair n lib . mergeAttrs ) [ " p a s s t h r u " " m e t a " " c f g " " f l a g s " ] )
// listToAttrs ( map ( n : nameValuePair n ( a : b : " ${ a } \n ${ b } " ) ) [ " p r e C o n f i g u r e " " p o s t I n s t a l l " ] )
;
# prepareDerivationArgs tries to make writing configurable derivations easier
# example:
# prepareDerivationArgs {
# mergeAttrBy = {
# myScript = x : y : x ++ "\n" ++ y;
# myScript = x: y: x ++ "\n" ++ y;
# };
# cfg = {
# readlineSupport = true;
@ -392,10 +395,10 @@ rec {
# TODO use args.mergeFun here as well?
prepareDerivationArgs = args :
let args2 = { cfg = { } ; flags = { } ; } // args ;
flagName = name : " ${ name } S u p p o r t " ;
cfgWithDefaults = ( listToAttrs ( map ( n : nameValuePair ( flagName n ) false ) ( attrNames args2 . flags ) ) )
flagName = name : " ${ name } S u p p o r t " ;
cfgWithDefaults = ( listToAttrs ( map ( n : nameValuePair ( flagName n ) false ) ( attrNames args2 . flags ) ) )
// args2 . cfg ;
opts = attrValues ( mapAttrs ( a : v :
opts = attrValues ( mapAttrs ( a : v :
let v2 = if v ? set || v ? unset then v else { set = v ; } ;
n = if cfgWithDefaults . ${ flagName a } then " s e t " else " u n s e t " ;
attr = maybeAttr n { } v2 ; in