Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

336 lignes
8.6 KiB

  1. { lib }:
  2. rec {
  3. ## Simple (higher order) functions
  4. /* The identity function
  5. For when you need a function that does “nothing”.
  6. Type: id :: a -> a
  7. */
  8. id =
  9. # The value to return
  10. x: x;
  11. /* The constant function
  12. Ignores the second argument. If called with only one argument,
  13. constructs a function that always returns a static value.
  14. Type: const :: a -> b -> a
  15. Example:
  16. let f = const 5; in f 10
  17. => 5
  18. */
  19. const =
  20. # Value to return
  21. x:
  22. # Value to ignore
  23. y: x;
  24. /* Pipes a value through a list of functions, left to right.
  25. Type: pipe :: a -> [<functions>] -> <return type of last function>
  26. Example:
  27. pipe 2 [
  28. (x: x + 2) # 2 + 2 = 4
  29. (x: x * 2) # 4 * 2 = 8
  30. ]
  31. => 8
  32. # ideal to do text transformations
  33. pipe [ "a/b" "a/c" ] [
  34. # create the cp command
  35. (map (file: ''cp "${src}/${file}" $out\n''))
  36. # concatenate all commands into one string
  37. lib.concatStrings
  38. # make that string into a nix derivation
  39. (pkgs.runCommand "copy-to-out" {})
  40. ]
  41. => <drv which copies all files to $out>
  42. The output type of each function has to be the input type
  43. of the next function, and the last function returns the
  44. final value.
  45. */
  46. pipe = val: functions:
  47. let reverseApply = x: f: f x;
  48. in builtins.foldl' reverseApply val functions;
  49. /* note please don’t add a function like `compose = flip pipe`.
  50. This would confuse users, because the order of the functions
  51. in the list is not clear. With pipe, it’s obvious that it
  52. goes first-to-last. With `compose`, not so much.
  53. */
  54. ## Named versions corresponding to some builtin operators.
  55. /* Concatenate two lists
  56. Type: concat :: [a] -> [a] -> [a]
  57. Example:
  58. concat [ 1 2 ] [ 3 4 ]
  59. => [ 1 2 3 4 ]
  60. */
  61. concat = x: y: x ++ y;
  62. /* boolean “or” */
  63. or = x: y: x || y;
  64. /* boolean “and” */
  65. and = x: y: x && y;
  66. /* bitwise “and” */
  67. bitAnd = builtins.bitAnd
  68. or (import ./zip-int-bits.nix
  69. (a: b: if a==1 && b==1 then 1 else 0));
  70. /* bitwise “or” */
  71. bitOr = builtins.bitOr
  72. or (import ./zip-int-bits.nix
  73. (a: b: if a==1 || b==1 then 1 else 0));
  74. /* bitwise “xor” */
  75. bitXor = builtins.bitXor
  76. or (import ./zip-int-bits.nix
  77. (a: b: if a!=b then 1 else 0));
  78. /* bitwise “not” */
  79. bitNot = builtins.sub (-1);
  80. /* Convert a boolean to a string.
  81. This function uses the strings "true" and "false" to represent
  82. boolean values. Calling `toString` on a bool instead returns "1"
  83. and "" (sic!).
  84. Type: boolToString :: bool -> string
  85. */
  86. boolToString = b: if b then "true" else "false";
  87. /* Merge two attribute sets shallowly, right side trumps left
  88. mergeAttrs :: attrs -> attrs -> attrs
  89. Example:
  90. mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
  91. => { a = 1; b = 3; c = 4; }
  92. */
  93. mergeAttrs =
  94. # Left attribute set
  95. x:
  96. # Right attribute set (higher precedence for equal keys)
  97. y: x // y;
  98. /* Flip the order of the arguments of a binary function.
  99. Type: flip :: (a -> b -> c) -> (b -> a -> c)
  100. Example:
  101. flip concat [1] [2]
  102. => [ 2 1 ]
  103. */
  104. flip = f: a: b: f b a;
  105. /* Apply function if the supplied argument is non-null.
  106. Example:
  107. mapNullable (x: x+1) null
  108. => null
  109. mapNullable (x: x+1) 22
  110. => 23
  111. */
  112. mapNullable =
  113. # Function to call
  114. f:
  115. # Argument to check for null before passing it to `f`
  116. a: if a == null then a else f a;
  117. # Pull in some builtins not included elsewhere.
  118. inherit (builtins)
  119. pathExists readFile isBool
  120. isInt isFloat add sub lessThan
  121. seq deepSeq genericClosure;
  122. ## nixpks version strings
  123. /* Returns the current full nixpkgs version number. */
  124. version = release + versionSuffix;
  125. /* Returns the current nixpkgs release number as string. */
  126. release = lib.strings.fileContents ../.version;
  127. /* Returns the current nixpkgs release code name.
  128. On each release the first letter is bumped and a new animal is chosen
  129. starting with that new letter.
  130. */
  131. codeName = "Nightingale";
  132. /* Returns the current nixpkgs version suffix as string. */
  133. versionSuffix =
  134. let suffixFile = ../.version-suffix;
  135. in if pathExists suffixFile
  136. then lib.strings.fileContents suffixFile
  137. else "pre-git";
  138. /* Attempts to return the the current revision of nixpkgs and
  139. returns the supplied default value otherwise.
  140. Type: revisionWithDefault :: string -> string
  141. */
  142. revisionWithDefault =
  143. # Default value to return if revision can not be determined
  144. default:
  145. let
  146. revisionFile = "${toString ./..}/.git-revision";
  147. gitRepo = "${toString ./..}/.git";
  148. in if lib.pathIsGitRepo gitRepo
  149. then lib.commitIdFromGitRepo gitRepo
  150. else if lib.pathExists revisionFile then lib.fileContents revisionFile
  151. else default;
  152. nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version;
  153. /* Determine whether the function is being called from inside a Nix
  154. shell.
  155. Type: inNixShell :: bool
  156. */
  157. inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
  158. ## Integer operations
  159. /* Return minimum of two numbers. */
  160. min = x: y: if x < y then x else y;
  161. /* Return maximum of two numbers. */
  162. max = x: y: if x > y then x else y;
  163. /* Integer modulus
  164. Example:
  165. mod 11 10
  166. => 1
  167. mod 1 10
  168. => 1
  169. */
  170. mod = base: int: base - (int * (builtins.div base int));
  171. ## Comparisons
  172. /* C-style comparisons
  173. a < b, compare a b => -1
  174. a == b, compare a b => 0
  175. a > b, compare a b => 1
  176. */
  177. compare = a: b:
  178. if a < b
  179. then -1
  180. else if a > b
  181. then 1
  182. else 0;
  183. /* Split type into two subtypes by predicate `p`, take all elements
  184. of the first subtype to be less than all the elements of the
  185. second subtype, compare elements of a single subtype with `yes`
  186. and `no` respectively.
  187. Type: (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
  188. Example:
  189. let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
  190. cmp "a" "z" => -1
  191. cmp "fooa" "fooz" => -1
  192. cmp "f" "a" => 1
  193. cmp "fooa" "a" => -1
  194. # while
  195. compare "fooa" "a" => 1
  196. */
  197. splitByAndCompare =
  198. # Predicate
  199. p:
  200. # Comparison function if predicate holds for both values
  201. yes:
  202. # Comparison function if predicate holds for neither value
  203. no:
  204. # First value to compare
  205. a:
  206. # Second value to compare
  207. b:
  208. if p a
  209. then if p b then yes a b else -1
  210. else if p b then 1 else no a b;
  211. /* Reads a JSON file.
  212. Type :: path -> any
  213. */
  214. importJSON = path:
  215. builtins.fromJSON (builtins.readFile path);
  216. ## Warnings
  217. # See https://github.com/NixOS/nix/issues/749. Eventually we'd like these
  218. # to expand to Nix builtins that carry metadata so that Nix can filter out
  219. # the INFO messages without parsing the message string.
  220. #
  221. # Usage:
  222. # {
  223. # foo = lib.warn "foo is deprecated" oldFoo;
  224. # }
  225. #
  226. # TODO: figure out a clever way to integrate location information from
  227. # something like __unsafeGetAttrPos.
  228. warn = msg: builtins.trace "warning: ${msg}";
  229. info = msg: builtins.trace "INFO: ${msg}";
  230. showWarnings = warnings: res: lib.fold (w: x: warn w x) res warnings;
  231. ## Function annotations
  232. /* Add metadata about expected function arguments to a function.
  233. The metadata should match the format given by
  234. builtins.functionArgs, i.e. a set from expected argument to a bool
  235. representing whether that argument has a default or not.
  236. setFunctionArgs : (a → b) → Map String Bool → (a → b)
  237. This function is necessary because you can't dynamically create a
  238. function of the { a, b ? foo, ... }: format, but some facilities
  239. like callPackage expect to be able to query expected arguments.
  240. */
  241. setFunctionArgs = f: args:
  242. { # TODO: Should we add call-time "type" checking like built in?
  243. __functor = self: f;
  244. __functionArgs = args;
  245. };
  246. /* Extract the expected function arguments from a function.
  247. This works both with nix-native { a, b ? foo, ... }: style
  248. functions and functions with args set with 'setFunctionArgs'. It
  249. has the same return type and semantics as builtins.functionArgs.
  250. setFunctionArgs : (a → b) → Map String Bool.
  251. */
  252. functionArgs = f: f.__functionArgs or (builtins.functionArgs f);
  253. /* Check whether something is a function or something
  254. annotated with function args.
  255. */
  256. isFunction = f: builtins.isFunction f ||
  257. (f ? __functor && isFunction (f.__functor f));
  258. }