Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1/** 2 Some functions for manipulating meta attributes, as well as the 3 name attribute. 4*/ 5 6{ lib }: 7 8let 9 inherit (lib) 10 matchAttrs 11 any 12 all 13 isDerivation 14 getBin 15 assertMsg 16 ; 17 inherit (lib.attrsets) mapAttrs' filterAttrs; 18 inherit (builtins) isString match typeOf; 19 20in 21rec { 22 23 /** 24 Add to or override the meta attributes of the given 25 derivation. 26 27 # Inputs 28 29 `newAttrs` 30 31 : 1\. Function argument 32 33 `drv` 34 35 : 2\. Function argument 36 37 # Examples 38 :::{.example} 39 ## `lib.meta.addMetaAttrs` usage example 40 41 ```nix 42 addMetaAttrs {description = "Bla blah";} somePkg 43 ``` 44 45 ::: 46 */ 47 addMetaAttrs = newAttrs: drv: drv // { meta = (drv.meta or { }) // newAttrs; }; 48 49 /** 50 Disable Hydra builds of given derivation. 51 52 # Inputs 53 54 `drv` 55 56 : 1\. Function argument 57 */ 58 dontDistribute = drv: addMetaAttrs { hydraPlatforms = [ ]; } drv; 59 60 /** 61 Change the [symbolic name of a derivation](https://nixos.org/manual/nix/stable/language/derivations.html#attr-name). 62 63 :::{.warning} 64 Dependent derivations will be rebuilt when the symbolic name is changed. 65 ::: 66 67 # Inputs 68 69 `name` 70 71 : 1\. Function argument 72 73 `drv` 74 75 : 2\. Function argument 76 */ 77 setName = name: drv: drv // { inherit name; }; 78 79 /** 80 Like `setName`, but takes the previous name as an argument. 81 82 # Inputs 83 84 `updater` 85 86 : 1\. Function argument 87 88 `drv` 89 90 : 2\. Function argument 91 92 # Examples 93 :::{.example} 94 ## `lib.meta.updateName` usage example 95 96 ```nix 97 updateName (oldName: oldName + "-experimental") somePkg 98 ``` 99 100 ::: 101 */ 102 updateName = updater: drv: drv // { name = updater (drv.name); }; 103 104 /** 105 Append a suffix to the name of a package (before the version 106 part). 107 108 # Inputs 109 110 `suffix` 111 112 : 1\. Function argument 113 */ 114 appendToName = 115 suffix: 116 updateName ( 117 name: 118 let 119 x = builtins.parseDrvName name; 120 in 121 "${x.name}-${suffix}-${x.version}" 122 ); 123 124 /** 125 Apply a function to each derivation and only to derivations in an attrset. 126 127 # Inputs 128 129 `f` 130 131 : 1\. Function argument 132 133 `set` 134 135 : 2\. Function argument 136 */ 137 mapDerivationAttrset = 138 f: set: lib.mapAttrs (name: pkg: if lib.isDerivation pkg then (f pkg) else pkg) set; 139 140 /** 141 The default priority of packages in Nix. See `defaultPriority` in [`src/nix/profile.cc`](https://github.com/NixOS/nix/blob/master/src/nix/profile.cc#L47). 142 */ 143 defaultPriority = 5; 144 145 /** 146 Set the nix-env priority of the package. Note that higher values are lower priority, and vice versa. 147 148 # Inputs 149 150 `priority` 151 : 1\. The priority to set. 152 153 `drv` 154 : 2\. Function argument 155 */ 156 setPrio = priority: addMetaAttrs { inherit priority; }; 157 158 /** 159 Decrease the nix-env priority of the package, i.e., other 160 versions/variants of the package will be preferred. 161 162 # Inputs 163 164 `drv` 165 166 : 1\. Function argument 167 */ 168 lowPrio = setPrio 10; 169 170 /** 171 Apply lowPrio to an attrset with derivations. 172 173 # Inputs 174 175 `set` 176 177 : 1\. Function argument 178 */ 179 lowPrioSet = set: mapDerivationAttrset lowPrio set; 180 181 /** 182 Increase the nix-env priority of the package, i.e., this 183 version/variant of the package will be preferred. 184 185 # Inputs 186 187 `drv` 188 189 : 1\. Function argument 190 */ 191 hiPrio = setPrio (-10); 192 193 /** 194 Apply hiPrio to an attrset with derivations. 195 196 # Inputs 197 198 `set` 199 200 : 1\. Function argument 201 */ 202 hiPrioSet = set: mapDerivationAttrset hiPrio set; 203 204 /** 205 Check to see if a platform is matched by the given `meta.platforms` 206 element. 207 208 A `meta.platform` pattern is either 209 210 1. (legacy) a system string. 211 212 2. (modern) a pattern for the entire platform structure (see `lib.systems.inspect.platformPatterns`). 213 214 3. (modern) a pattern for the platform `parsed` field (see `lib.systems.inspect.patterns`). 215 216 We can inject these into a pattern for the whole of a structured platform, 217 and then match that. 218 219 # Inputs 220 221 `platform` 222 223 : 1\. Function argument 224 225 `elem` 226 227 : 2\. Function argument 228 229 # Examples 230 :::{.example} 231 ## `lib.meta.platformMatch` usage example 232 233 ```nix 234 lib.meta.platformMatch { system = "aarch64-darwin"; } "aarch64-darwin" 235 => true 236 ``` 237 238 ::: 239 */ 240 platformMatch = 241 platform: elem: 242 ( 243 # Check with simple string comparison if elem was a string. 244 # 245 # The majority of comparisons done with this function will be against meta.platforms 246 # which contains a simple platform string. 247 # 248 # Avoiding an attrset allocation results in significant performance gains (~2-30) across the board in OfBorg 249 # because this is a hot path for nixpkgs. 250 if isString elem then 251 platform ? system && elem == platform.system 252 else 253 matchAttrs ( 254 # Normalize platform attrset. 255 if elem ? parsed then elem else { parsed = elem; } 256 ) platform 257 ); 258 259 /** 260 Check if a package is available on a given platform. 261 262 A package is available on a platform if both 263 264 1. One of `meta.platforms` pattern matches the given 265 platform, or `meta.platforms` is not present. 266 267 2. None of `meta.badPlatforms` pattern matches the given platform. 268 269 # Inputs 270 271 `platform` 272 273 : 1\. Function argument 274 275 `pkg` 276 277 : 2\. Function argument 278 279 # Examples 280 :::{.example} 281 ## `lib.meta.availableOn` usage example 282 283 ```nix 284 lib.meta.availableOn { system = "aarch64-darwin"; } pkg.zsh 285 => true 286 ``` 287 288 ::: 289 */ 290 availableOn = 291 platform: pkg: 292 ((!pkg ? meta.platforms) || any (platformMatch platform) pkg.meta.platforms) 293 && all (elem: !platformMatch platform elem) (pkg.meta.badPlatforms or [ ]); 294 295 /** 296 Mapping of SPDX ID to the attributes in lib.licenses. 297 298 For SPDX IDs, see https://spdx.org/licenses. 299 Note that some SPDX licenses might be missing. 300 301 # Examples 302 :::{.example} 303 ## `lib.meta.licensesSpdx` usage example 304 305 ```nix 306 lib.licensesSpdx.MIT == lib.licenses.mit 307 => true 308 lib.licensesSpdx."MY LICENSE" 309 => error: attribute 'MY LICENSE' missing 310 ``` 311 312 ::: 313 */ 314 licensesSpdx = mapAttrs' (_key: license: { 315 name = license.spdxId; 316 value = license; 317 }) (filterAttrs (_key: license: license ? spdxId) lib.licenses); 318 319 /** 320 Get the corresponding attribute in lib.licenses from the SPDX ID 321 or warn and fallback to `{ shortName = <license string>; }`. 322 323 For SPDX IDs, see https://spdx.org/licenses. 324 Note that some SPDX licenses might be missing. 325 326 # Type 327 328 ``` 329 getLicenseFromSpdxId :: str -> AttrSet 330 ``` 331 332 # Examples 333 :::{.example} 334 ## `lib.meta.getLicenseFromSpdxId` usage example 335 336 ```nix 337 lib.getLicenseFromSpdxId "MIT" == lib.licenses.mit 338 => true 339 lib.getLicenseFromSpdxId "mIt" == lib.licenses.mit 340 => true 341 lib.getLicenseFromSpdxId "MY LICENSE" 342 => trace: warning: getLicenseFromSpdxId: No license matches the given SPDX ID: MY LICENSE 343 => { shortName = "MY LICENSE"; } 344 ``` 345 346 ::: 347 */ 348 getLicenseFromSpdxId = 349 licstr: 350 getLicenseFromSpdxIdOr licstr ( 351 lib.warn "getLicenseFromSpdxId: No license matches the given SPDX ID: ${licstr}" { 352 shortName = licstr; 353 } 354 ); 355 356 /** 357 Get the corresponding attribute in lib.licenses from the SPDX ID 358 or fallback to the given default value. 359 360 For SPDX IDs, see https://spdx.org/licenses. 361 Note that some SPDX licenses might be missing. 362 363 # Inputs 364 365 `licstr` 366 : 1\. SPDX ID string to find a matching license 367 368 `default` 369 : 2\. Fallback value when a match is not found 370 371 # Type 372 373 ``` 374 getLicenseFromSpdxIdOr :: str -> Any -> Any 375 ``` 376 377 # Examples 378 :::{.example} 379 ## `lib.meta.getLicenseFromSpdxIdOr` usage example 380 381 ```nix 382 lib.getLicenseFromSpdxIdOr "MIT" null == lib.licenses.mit 383 => true 384 lib.getLicenseFromSpdxId "mIt" null == lib.licenses.mit 385 => true 386 lib.getLicenseFromSpdxIdOr "MY LICENSE" lib.licenses.free == lib.licenses.free 387 => true 388 lib.getLicenseFromSpdxIdOr "MY LICENSE" null 389 => null 390 lib.getLicenseFromSpdxIdOr "MY LICENSE" (builtins.throw "No SPDX ID matches MY LICENSE") 391 => error: No SPDX ID matches MY LICENSE 392 ``` 393 ::: 394 */ 395 getLicenseFromSpdxIdOr = 396 let 397 lowercaseLicenses = lib.mapAttrs' (name: value: { 398 name = lib.toLower name; 399 inherit value; 400 }) licensesSpdx; 401 in 402 licstr: default: lowercaseLicenses.${lib.toLower licstr} or default; 403 404 /** 405 Get the path to the main program of a package based on meta.mainProgram 406 407 # Inputs 408 409 `x` 410 411 : 1\. Function argument 412 413 # Type 414 415 ``` 416 getExe :: package -> string 417 ``` 418 419 # Examples 420 :::{.example} 421 ## `lib.meta.getExe` usage example 422 423 ```nix 424 getExe pkgs.hello 425 => "/nix/store/g124820p9hlv4lj8qplzxw1c44dxaw1k-hello-2.12/bin/hello" 426 getExe pkgs.mustache-go 427 => "/nix/store/am9ml4f4ywvivxnkiaqwr0hyxka1xjsf-mustache-go-1.3.0/bin/mustache" 428 ``` 429 430 ::: 431 */ 432 getExe = 433 x: 434 getExe' x ( 435 x.meta.mainProgram or ( 436 # This could be turned into an error when 23.05 is at end of life 437 lib.warn 438 "getExe: Package ${ 439 lib.strings.escapeNixIdentifier x.meta.name or x.pname or x.name 440 } does not have the meta.mainProgram attribute. We'll assume that the main program has the same name for now, but this behavior is deprecated, because it leads to surprising errors when the assumption does not hold. If the package has a main program, please set `meta.mainProgram` in its definition to make this warning go away. Otherwise, if the package does not have a main program, or if you don't control its definition, use getExe' to specify the name to the program, such as lib.getExe' foo \"bar\"." 441 lib.getName 442 x 443 ) 444 ); 445 446 /** 447 Get the path of a program of a derivation. 448 449 # Inputs 450 451 `x` 452 453 : 1\. Function argument 454 455 `y` 456 457 : 2\. Function argument 458 459 # Type 460 461 ``` 462 getExe' :: derivation -> string -> string 463 ``` 464 465 # Examples 466 :::{.example} 467 ## `lib.meta.getExe'` usage example 468 469 ```nix 470 getExe' pkgs.hello "hello" 471 => "/nix/store/g124820p9hlv4lj8qplzxw1c44dxaw1k-hello-2.12/bin/hello" 472 getExe' pkgs.imagemagick "convert" 473 => "/nix/store/5rs48jamq7k6sal98ymj9l4k2bnwq515-imagemagick-7.1.1-15/bin/convert" 474 ``` 475 476 ::: 477 */ 478 getExe' = 479 x: y: 480 assert assertMsg (isDerivation x) 481 "lib.meta.getExe': The first argument is of type ${typeOf x}, but it should be a derivation instead."; 482 assert assertMsg (isString y) 483 "lib.meta.getExe': The second argument is of type ${typeOf y}, but it should be a string instead."; 484 assert assertMsg (match ".*/.*" y == null) 485 "lib.meta.getExe': The second argument \"${y}\" is a nested path with a \"/\" character, but it should just be the name of the executable instead."; 486 "${getBin x}/bin/${y}"; 487}