at 21.11-pre 10 kB view raw
1{ lib }: 2 3rec { 4 5 ## Simple (higher order) functions 6 7 /* The identity function 8 For when you need a function that does nothing. 9 10 Type: id :: a -> a 11 */ 12 id = 13 # The value to return 14 x: x; 15 16 /* The constant function 17 18 Ignores the second argument. If called with only one argument, 19 constructs a function that always returns a static value. 20 21 Type: const :: a -> b -> a 22 Example: 23 let f = const 5; in f 10 24 => 5 25 */ 26 const = 27 # Value to return 28 x: 29 # Value to ignore 30 y: x; 31 32 /* Pipes a value through a list of functions, left to right. 33 34 Type: pipe :: a -> [<functions>] -> <return type of last function> 35 Example: 36 pipe 2 [ 37 (x: x + 2) # 2 + 2 = 4 38 (x: x * 2) # 4 * 2 = 8 39 ] 40 => 8 41 42 # ideal to do text transformations 43 pipe [ "a/b" "a/c" ] [ 44 45 # create the cp command 46 (map (file: ''cp "${src}/${file}" $out\n'')) 47 48 # concatenate all commands into one string 49 lib.concatStrings 50 51 # make that string into a nix derivation 52 (pkgs.runCommand "copy-to-out" {}) 53 54 ] 55 => <drv which copies all files to $out> 56 57 The output type of each function has to be the input type 58 of the next function, and the last function returns the 59 final value. 60 */ 61 pipe = val: functions: 62 let reverseApply = x: f: f x; 63 in builtins.foldl' reverseApply val functions; 64 /* note please dont add a function like `compose = flip pipe`. 65 This would confuse users, because the order of the functions 66 in the list is not clear. With pipe, its obvious that it 67 goes first-to-last. With `compose`, not so much. 68 */ 69 70 ## Named versions corresponding to some builtin operators. 71 72 /* Concatenate two lists 73 74 Type: concat :: [a] -> [a] -> [a] 75 76 Example: 77 concat [ 1 2 ] [ 3 4 ] 78 => [ 1 2 3 4 ] 79 */ 80 concat = x: y: x ++ y; 81 82 /* boolean or */ 83 or = x: y: x || y; 84 85 /* boolean and */ 86 and = x: y: x && y; 87 88 /* bitwise and */ 89 bitAnd = builtins.bitAnd 90 or (import ./zip-int-bits.nix 91 (a: b: if a==1 && b==1 then 1 else 0)); 92 93 /* bitwise or */ 94 bitOr = builtins.bitOr 95 or (import ./zip-int-bits.nix 96 (a: b: if a==1 || b==1 then 1 else 0)); 97 98 /* bitwise xor */ 99 bitXor = builtins.bitXor 100 or (import ./zip-int-bits.nix 101 (a: b: if a!=b then 1 else 0)); 102 103 /* bitwise not */ 104 bitNot = builtins.sub (-1); 105 106 /* Convert a boolean to a string. 107 108 This function uses the strings "true" and "false" to represent 109 boolean values. Calling `toString` on a bool instead returns "1" 110 and "" (sic!). 111 112 Type: boolToString :: bool -> string 113 */ 114 boolToString = b: if b then "true" else "false"; 115 116 /* Merge two attribute sets shallowly, right side trumps left 117 118 mergeAttrs :: attrs -> attrs -> attrs 119 120 Example: 121 mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; } 122 => { a = 1; b = 3; c = 4; } 123 */ 124 mergeAttrs = 125 # Left attribute set 126 x: 127 # Right attribute set (higher precedence for equal keys) 128 y: x // y; 129 130 /* Flip the order of the arguments of a binary function. 131 132 Type: flip :: (a -> b -> c) -> (b -> a -> c) 133 134 Example: 135 flip concat [1] [2] 136 => [ 2 1 ] 137 */ 138 flip = f: a: b: f b a; 139 140 /* Apply function if the supplied argument is non-null. 141 142 Example: 143 mapNullable (x: x+1) null 144 => null 145 mapNullable (x: x+1) 22 146 => 23 147 */ 148 mapNullable = 149 # Function to call 150 f: 151 # Argument to check for null before passing it to `f` 152 a: if a == null then a else f a; 153 154 # Pull in some builtins not included elsewhere. 155 inherit (builtins) 156 pathExists readFile isBool 157 isInt isFloat add sub lessThan 158 seq deepSeq genericClosure; 159 160 161 ## nixpkgs version strings 162 163 /* Returns the current full nixpkgs version number. */ 164 version = release + versionSuffix; 165 166 /* Returns the current nixpkgs release number as string. */ 167 release = lib.strings.fileContents ../.version; 168 169 /* Returns the current nixpkgs release code name. 170 171 On each release the first letter is bumped and a new animal is chosen 172 starting with that new letter. 173 */ 174 codeName = "Porcupine"; 175 176 /* Returns the current nixpkgs version suffix as string. */ 177 versionSuffix = 178 let suffixFile = ../.version-suffix; 179 in if pathExists suffixFile 180 then lib.strings.fileContents suffixFile 181 else "pre-git"; 182 183 /* Attempts to return the the current revision of nixpkgs and 184 returns the supplied default value otherwise. 185 186 Type: revisionWithDefault :: string -> string 187 */ 188 revisionWithDefault = 189 # Default value to return if revision can not be determined 190 default: 191 let 192 revisionFile = "${toString ./..}/.git-revision"; 193 gitRepo = "${toString ./..}/.git"; 194 in if lib.pathIsGitRepo gitRepo 195 then lib.commitIdFromGitRepo gitRepo 196 else if lib.pathExists revisionFile then lib.fileContents revisionFile 197 else default; 198 199 nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version; 200 201 /* Determine whether the function is being called from inside a Nix 202 shell. 203 204 Type: inNixShell :: bool 205 */ 206 inNixShell = builtins.getEnv "IN_NIX_SHELL" != ""; 207 208 209 ## Integer operations 210 211 /* Return minimum of two numbers. */ 212 min = x: y: if x < y then x else y; 213 214 /* Return maximum of two numbers. */ 215 max = x: y: if x > y then x else y; 216 217 /* Integer modulus 218 219 Example: 220 mod 11 10 221 => 1 222 mod 1 10 223 => 1 224 */ 225 mod = base: int: base - (int * (builtins.div base int)); 226 227 228 ## Comparisons 229 230 /* C-style comparisons 231 232 a < b, compare a b => -1 233 a == b, compare a b => 0 234 a > b, compare a b => 1 235 */ 236 compare = a: b: 237 if a < b 238 then -1 239 else if a > b 240 then 1 241 else 0; 242 243 /* Split type into two subtypes by predicate `p`, take all elements 244 of the first subtype to be less than all the elements of the 245 second subtype, compare elements of a single subtype with `yes` 246 and `no` respectively. 247 248 Type: (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int) 249 250 Example: 251 let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in 252 253 cmp "a" "z" => -1 254 cmp "fooa" "fooz" => -1 255 256 cmp "f" "a" => 1 257 cmp "fooa" "a" => -1 258 # while 259 compare "fooa" "a" => 1 260 */ 261 splitByAndCompare = 262 # Predicate 263 p: 264 # Comparison function if predicate holds for both values 265 yes: 266 # Comparison function if predicate holds for neither value 267 no: 268 # First value to compare 269 a: 270 # Second value to compare 271 b: 272 if p a 273 then if p b then yes a b else -1 274 else if p b then 1 else no a b; 275 276 277 /* Reads a JSON file. 278 279 Type :: path -> any 280 */ 281 importJSON = path: 282 builtins.fromJSON (builtins.readFile path); 283 284 /* Reads a TOML file. 285 286 Type :: path -> any 287 */ 288 importTOML = path: 289 builtins.fromTOML (builtins.readFile path); 290 291 ## Warnings 292 293 # See https://github.com/NixOS/nix/issues/749. Eventually we'd like these 294 # to expand to Nix builtins that carry metadata so that Nix can filter out 295 # the INFO messages without parsing the message string. 296 # 297 # Usage: 298 # { 299 # foo = lib.warn "foo is deprecated" oldFoo; 300 # bar = lib.warnIf (bar == "") "Empty bar is deprecated" bar; 301 # } 302 # 303 # TODO: figure out a clever way to integrate location information from 304 # something like __unsafeGetAttrPos. 305 306 warn = msg: builtins.trace "warning: ${msg}"; 307 warnIf = cond: msg: if cond then warn msg else id; 308 309 info = msg: builtins.trace "INFO: ${msg}"; 310 311 showWarnings = warnings: res: lib.fold (w: x: warn w x) res warnings; 312 313 ## Function annotations 314 315 /* Add metadata about expected function arguments to a function. 316 The metadata should match the format given by 317 builtins.functionArgs, i.e. a set from expected argument to a bool 318 representing whether that argument has a default or not. 319 setFunctionArgs : (a b) Map String Bool (a b) 320 321 This function is necessary because you can't dynamically create a 322 function of the { a, b ? foo, ... }: format, but some facilities 323 like callPackage expect to be able to query expected arguments. 324 */ 325 setFunctionArgs = f: args: 326 { # TODO: Should we add call-time "type" checking like built in? 327 __functor = self: f; 328 __functionArgs = args; 329 }; 330 331 /* Extract the expected function arguments from a function. 332 This works both with nix-native { a, b ? foo, ... }: style 333 functions and functions with args set with 'setFunctionArgs'. It 334 has the same return type and semantics as builtins.functionArgs. 335 setFunctionArgs : (a b) Map String Bool. 336 */ 337 functionArgs = f: f.__functionArgs or (builtins.functionArgs f); 338 339 /* Check whether something is a function or something 340 annotated with function args. 341 */ 342 isFunction = f: builtins.isFunction f || 343 (f ? __functor && isFunction (f.__functor f)); 344 345 /* Convert the given positive integer to a string of its hexadecimal 346 representation. For example: 347 348 toHexString 0 => "0" 349 350 toHexString 16 => "10" 351 352 toHexString 250 => "FA" 353 */ 354 toHexString = i: 355 let 356 toHexDigit = d: 357 if d < 10 358 then toString d 359 else 360 { 361 "10" = "A"; 362 "11" = "B"; 363 "12" = "C"; 364 "13" = "D"; 365 "14" = "E"; 366 "15" = "F"; 367 }.${toString d}; 368 in 369 lib.concatMapStrings toHexDigit (toBaseDigits 16 i); 370 371 /* `toBaseDigits base i` converts the positive integer i to a list of its 372 digits in the given base. For example: 373 374 toBaseDigits 10 123 => [ 1 2 3 ] 375 376 toBaseDigits 2 6 => [ 1 1 0 ] 377 378 toBaseDigits 16 250 => [ 15 10 ] 379 */ 380 toBaseDigits = base: i: 381 let 382 go = i: 383 if i < base 384 then [i] 385 else 386 let 387 r = i - ((i / base) * base); 388 q = (i - r) / base; 389 in 390 [r] ++ go q; 391 in 392 assert (base >= 2); 393 assert (i >= 0); 394 lib.reverseList (go i); 395}