Compare commits

...

38 commits

Author SHA1 Message Date
Jeff Hykin dd6d59a04d improve test script 2024-05-26 10:31:46 -04:00
Jeff Hykin cac07bdeee get check-eval.nix working 2024-05-26 10:27:28 -04:00
Jeff Hykin 3b9a7b9277 temove tests that depend on pkgs 2024-05-26 10:27:11 -04:00
Jeff Hykin 5fc6685efe add basic test script 2024-05-26 10:26:37 -04:00
Jeff Hykin 7916f50847 remove top level nix inherits 2024-05-26 10:20:23 -04:00
Jeff Hykin 63c79d1b48 simplify top of lib 2024-05-26 10:05:03 -04:00
Jeff Hykin 590b181303 add note 2024-05-26 09:59:56 -04:00
Jeff Hykin a38922846e reduce indirection 2024-05-26 09:57:20 -04:00
Jeff Hykin 6ce2f22854 add WIP trivial 2024-05-25 13:19:19 -04:00
Jeff Hykin 0911efe6d2 add other static info 2024-05-25 13:17:55 -04:00
Jeff Hykin 06688e3ab8 fix logical or 2024-05-25 13:17:47 -04:00
Jeff Hykin 01b6beb111 add id, const, pipe, concat, or, and, xor, bitNot, boolToString, mergeAttrs, flip, mapNullable 2024-05-25 13:04:22 -04:00
Jeff Hykin 427ad23000 add throwIfNot 2024-05-25 12:58:35 -04:00
Jeff Hykin 2ca5e185ce - 2024-05-25 12:55:53 -04:00
Jeff Hykin e0f04630de change how static is handled 2024-05-25 12:55:31 -04:00
Jeff Hykin 9e3062a5d8 - 2024-05-25 12:33:24 -04:00
Jeff Hykin df3269bfeb add reverseList 2024-05-25 12:29:12 -04:00
Jeff Hykin 1462db9587 add setFunctionArgs 2024-05-25 12:26:31 -04:00
Jeff Hykin 2613fed53e add functionArgs 2024-05-25 12:22:03 -04:00
Jeff Hykin 415acdce94 improve foundation 2024-05-25 12:20:22 -04:00
Jeff Hykin a4c9fde3e9 start detangling lib 2024-05-25 12:14:33 -04:00
Jeff Hykin 9cb4ed1ffc - 2024-05-25 12:13:51 -04:00
Jeff Hykin 11c40a8dcf add release to setup.toml 2024-05-25 11:44:27 -04:00
Jeff Hykin 97466d7f6d start to untangle lib 2024-05-25 11:44:17 -04:00
Jeff Hykin ab9110a43b move minNixVersion into meta.toml 2024-05-25 11:32:17 -04:00
Jeff Hykin 68d28c7f95 add teams for backwards compat (intentional duplicated entries) 2024-05-25 11:29:14 -04:00
Jeff Hykin f144947b81 add maintainers for backwards compatibility 2024-05-25 11:26:35 -04:00
Jeff Hykin e987e7b28b switch everything to toml 2024-05-25 11:18:25 -04:00
Jeff Hykin 7dc5f8db8e clean unused 2024-05-25 11:02:20 -04:00
Jeff Hykin 8f0b52892c make sourceTypes json 2024-05-25 11:02:11 -04:00
Jeff Hykin 735f118b90 add todo 2024-05-25 10:59:28 -04:00
Jeff Hykin adff8800eb make licenses static 2024-05-25 10:39:23 -04:00
Jeff Hykin ff9633d02b clean up lib 2024-05-25 10:31:17 -04:00
Jeff Hykin acb415f94f add WIP stage0_darwin 2024-05-25 10:30:52 -04:00
Jeff Hykin 040494bb21 new bootTools is working 2024-05-21 23:53:33 -04:00
Jeff Hykin 3864986c18 git subrepo clone (merge) git@github.com:nix-community/nixpkgs.lib.git lib
subrepo:
  subdir:   "lib"
  merged:   "0df131b5"
upstream:
  origin:   "git@github.com:nix-community/nixpkgs.lib.git"
  branch:   "master"
  commit:   "0df131b5"
git-subrepo:
  version:  "0.4.5"
  origin:   "???"
  commit:   "???"
2024-05-21 22:12:54 -04:00
Jeff Hykin 91911cb438 WIP bootstrap tools 2024-05-21 22:12:38 -04:00
Jeff Hykin 4e14b7b16c clear out everything 2024-05-21 21:36:48 -04:00
2676 changed files with 31430 additions and 305887 deletions

View file

@ -1,28 +0,0 @@
let requiredVersion = import ./lib/minver.nix; in
if ! builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.nixVersion == 1 then
abort ''
This version of Nixpkgs requires Nix >= ${requiredVersion}, please upgrade:
- If you are running NixOS, `nixos-rebuild' can be used to upgrade your system.
- Alternatively, with Nix > 2.0 `nix upgrade-nix' can be used to imperatively
upgrade Nix. You may use `nix-env --version' to check which version you have.
- If you installed Nix using the install script (https://nixos.org/nix/install),
it is safe to upgrade by running it again:
curl -L https://nixos.org/nix/install | sh
For more information, please see the NixOS release notes at
https://nixos.org/nixos/manual or locally at
${toString ./nixos/doc/manual/release-notes}.
If you need further help, see https://nixos.org/nixos/support.html
''
else
import ./pkgs/top-level/impure.nix

View file

@ -1,46 +1,5 @@
{
outputs = { self, ... }:
let
forAllSystems = self.lib.genAttrs self.lib.systems.flakeExposed;
in
{
lib = import ./lib;
auxPackages = forAllSystems (system:
(
let requiredVersion = import ./lib/minver.nix; in
if ! builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.nixVersion == 1 then
abort ''
This version of Nixpkgs requires Nix >= ${requiredVersion}, please upgrade:
- If you are running NixOS, `nixos-rebuild' can be used to upgrade your system.
- Alternatively, with Nix > 2.0 `nix upgrade-nix' can be used to imperatively
upgrade Nix. You may use `nix-env --version' to check which version you have.
- If you installed Nix using the install script (https://nixos.org/nix/install),
it is safe to upgrade by running it again:
curl -L https://nixos.org/nix/install | sh
For more information, please see the NixOS release notes at
https://nixos.org/nixos/manual or locally at
${toString ./nixos/doc/manual/release-notes}.
If you need further help, see https://nixos.org/nixos/support.html
''
else
import ./pkgs/top-level/default.nix { localSystem = system; }
)
);
legacyPackages = forAllSystems (system: import ./. { inherit system; });
# To test, run nix build .#tests.x86_64-linux.release
tests = forAllSystems (system: {
systems = import ./lib/tests/systems.nix;
release = import ./lib/tests/release.nix { pkgs = self.auxPackages.${system}; };
});
};
{}
;
}

View file

@ -1,171 +0,0 @@
/* Library of low-level helper functions for nix expressions.
*
* Please implement (mostly) exhaustive unit tests
* for new functions in `./tests.nix`.
*/
let
inherit (import ./fixed-points.nix { inherit lib; }) makeExtensible;
lib = makeExtensible (self: let
callLibs = file: import file { lib = self; };
in {
# often used, or depending on very little
trivial = callLibs ./trivial.nix;
fixedPoints = callLibs ./fixed-points.nix;
# datatypes
attrsets = callLibs ./attrsets.nix;
lists = callLibs ./lists.nix;
strings = callLibs ./strings.nix;
stringsWithDeps = callLibs ./strings-with-deps.nix;
# packaging
customisation = callLibs ./customisation.nix;
derivations = callLibs ./derivations.nix;
maintainers = import ../maintainers/maintainer-list.nix;
teams = callLibs ../maintainers/team-list.nix;
meta = callLibs ./meta.nix;
versions = callLibs ./versions.nix;
# module system
modules = callLibs ./modules.nix;
options = callLibs ./options.nix;
types = callLibs ./types.nix;
# constants
licenses = callLibs ./licenses.nix;
sourceTypes = callLibs ./source-types.nix;
systems = callLibs ./systems;
# serialization
cli = callLibs ./cli.nix;
gvariant = callLibs ./gvariant.nix;
generators = callLibs ./generators.nix;
# misc
asserts = callLibs ./asserts.nix;
debug = callLibs ./debug.nix;
misc = callLibs ./deprecated/misc.nix;
# domain-specific
fetchers = callLibs ./fetchers.nix;
# Eval-time filesystem handling
path = callLibs ./path;
filesystem = callLibs ./filesystem.nix;
fileset = callLibs ./fileset;
sources = callLibs ./sources.nix;
# back-compat aliases
platforms = self.systems.doubles;
# linux kernel configuration
kernel = callLibs ./kernel.nix;
inherit (builtins) add addErrorContext attrNames concatLists
deepSeq elem elemAt filter genericClosure genList getAttr
hasAttr head isAttrs isBool isInt isList isPath isString length
lessThan listToAttrs pathExists readFile replaceStrings seq
stringLength sub substring tail trace;
inherit (self.trivial) id const pipe concat or and xor bitAnd bitOr bitXor
bitNot boolToString mergeAttrs flip mapNullable inNixShell isFloat min max
importJSON importTOML warn warnIf warnIfNot throwIf throwIfNot checkListOfEnum
info showWarnings nixpkgsVersion version isInOldestRelease
mod compare splitByAndCompare
functionArgs setFunctionArgs isFunction toFunction mirrorFunctionArgs
toHexString toBaseDigits inPureEvalMode;
inherit (self.fixedPoints) fix fix' converge extends composeExtensions
composeManyExtensions makeExtensible makeExtensibleWithCustomName;
inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath
getAttrFromPath attrVals attrValues getAttrs catAttrs filterAttrs
filterAttrsRecursive foldlAttrs foldAttrs collect nameValuePair mapAttrs
mapAttrs' mapAttrsToList attrsToList concatMapAttrs mapAttrsRecursive
mapAttrsRecursiveCond genAttrs isDerivation toDerivation optionalAttrs
zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
recursiveUpdate matchAttrs mergeAttrsList overrideExisting showAttrPath getOutput
getBin getLib getDev getMan chooseDevOutputs zipWithNames zip
recurseIntoAttrs dontRecurseIntoAttrs cartesianProduct cartesianProductOfSets
mapCartesianProduct updateManyAttrsByPath;
inherit (self.lists) singleton forEach foldr fold foldl foldl' imap0 imap1
ifilter0 concatMap flatten remove findSingle findFirst any all count
optional optionals toList range replicate partition zipListsWith zipLists
reverseList listDfs toposort sort sortOn naturalSort compareLists take
drop sublist last init crossLists unique allUnique intersectLists
subtractLists mutuallyExclusive groupBy groupBy';
inherit (self.strings) concatStrings concatMapStrings concatImapStrings
intersperse concatStringsSep concatMapStringsSep
concatImapStringsSep concatLines makeSearchPath makeSearchPathOutput
makeLibraryPath makeIncludePath makeBinPath optionalString
hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
escapeShellArg escapeShellArgs
isStorePath isStringLike
isValidPosixName toShellVar toShellVars
escapeRegex escapeURL escapeXML replaceChars lowerChars
upperChars toLower toUpper addContextFrom splitString
removePrefix removeSuffix versionOlder versionAtLeast
getName getVersion
cmakeOptionType cmakeBool cmakeFeature
mesonOption mesonBool mesonEnable
nameFromURL enableFeature enableFeatureAs withFeature
withFeatureAs fixedWidthString fixedWidthNumber
toInt toIntBase10 readPathsFromFile fileContents;
inherit (self.stringsWithDeps) textClosureList textClosureMap
noDepEntry fullDepEntry packEntry stringAfter;
inherit (self.customisation) overrideDerivation makeOverridable
callPackageWith callPackagesWith extendDerivation hydraJob
makeScope makeScopeWithSplicing makeScopeWithSplicing';
inherit (self.derivations) lazyDerivation optionalDrvAttr;
inherit (self.meta) addMetaAttrs dontDistribute setName updateName
appendToName mapDerivationAttrset setPrio lowPrio lowPrioSet hiPrio
hiPrioSet getLicenseFromSpdxId getExe getExe';
inherit (self.filesystem) pathType pathIsDirectory pathIsRegularFile
packagesFromDirectoryRecursive;
inherit (self.sources) cleanSourceFilter
cleanSource sourceByRegex sourceFilesBySuffices
commitIdFromGitRepo cleanSourceWith pathHasContext
canCleanSource pathIsGitRepo;
inherit (self.modules) evalModules setDefaultModuleLocation
unifyModuleSyntax applyModuleArgsIfFunction mergeModules
mergeModules' mergeOptionDecls mergeDefinitions
pushDownProperties dischargeProperties filterOverrides
sortProperties fixupOptionType mkIf mkAssert mkMerge mkOverride
mkOptionDefault mkDefault mkImageMediaOverride mkForce mkVMOverride
mkFixStrictness mkOrder mkBefore mkAfter mkAliasDefinitions
mkAliasAndWrapDefinitions fixMergeModules mkRemovedOptionModule
mkRenamedOptionModule mkRenamedOptionModuleWith
mkMergedOptionModule mkChangedOptionModule
mkAliasOptionModule mkDerivedConfig doRename
mkAliasOptionModuleMD;
evalOptionValue = lib.warn "External use of `lib.evalOptionValue` is deprecated. If your use case isn't covered by non-deprecated functions, we'd like to know more and perhaps support your use case well, instead of providing access to these low level functions. In this case please open an issue in https://github.com/nixos/nixpkgs/issues/." self.modules.evalOptionValue;
inherit (self.options) isOption mkEnableOption mkSinkUndeclaredOptions
mergeDefaultOption mergeOneOption mergeEqualOption mergeUniqueOption
getValues getFiles
optionAttrSetToDocList optionAttrSetToDocList'
scrubOptionValue literalExpression literalExample
showOption showOptionWithDefLocs showFiles
unknownModule mkOption mkPackageOption mkPackageOptionMD
mdDoc literalMD;
inherit (self.types) isType setType defaultTypeMerge defaultFunctor
isOptionType mkOptionType;
inherit (self.asserts)
assertMsg assertOneOf;
inherit (self.debug) traceIf traceVal traceValFn
traceSeq traceSeqN traceValSeq
traceValSeqFn traceValSeqN traceValSeqNFn traceFnSeqN
runTests testAllTrue;
inherit (self.misc) maybeEnv defaultMergeArg defaultMerge foldArgs
maybeAttrNullable maybeAttr ifEnable checkFlag getValue
checkReqs uniqList uniqListExt condConcat lazyGenericClosure
innerModifySumArgs modifySumArgs innerClosePropagation
closePropagation mapAttrsFlatten nvs setAttr setAttrMerge
mergeAttrsWithFunc mergeAttrsConcatenateValues
mergeAttrsNoOverride mergeAttrByFunc mergeAttrsByFuncDefaults
mergeAttrsByFuncDefaultsClean mergeAttrBy
fakeHash fakeSha256 fakeSha512
nixType imap;
inherit (self.versions)
splitVersion;
});
in lib

View file

@ -1,309 +0,0 @@
{ lib, ... }:
rec {
/*
`fix f` computes the fixed point of the given function `f`. In other words, the return value is `x` in `x = f x`.
`f` must be a lazy function.
This means that `x` must be a value that can be partially evaluated,
such as an attribute set, a list, or a function.
This way, `f` can use one part of `x` to compute another part.
**Relation to syntactic recursion**
This section explains `fix` by refactoring from syntactic recursion to a call of `fix` instead.
For context, Nix lets you define attributes in terms of other attributes syntactically using the [`rec { }` syntax](https://nixos.org/manual/nix/stable/language/constructs.html#recursive-sets).
```nix
nix-repl> rec {
foo = "foo";
bar = "bar";
foobar = foo + bar;
}
{ bar = "bar"; foo = "foo"; foobar = "foobar"; }
```
This is convenient when constructing a value to pass to a function for example,
but an equivalent effect can be achieved with the `let` binding syntax:
```nix
nix-repl> let self = {
foo = "foo";
bar = "bar";
foobar = self.foo + self.bar;
}; in self
{ bar = "bar"; foo = "foo"; foobar = "foobar"; }
```
But in general you can get more reuse out of `let` bindings by refactoring them to a function.
```nix
nix-repl> f = self: {
foo = "foo";
bar = "bar";
foobar = self.foo + self.bar;
}
```
This is where `fix` comes in, it contains the syntactic recursion that's not in `f` anymore.
```nix
nix-repl> fix = f:
let self = f self; in self;
```
By applying `fix` we get the final result.
```nix
nix-repl> fix f
{ bar = "bar"; foo = "foo"; foobar = "foobar"; }
```
Such a refactored `f` using `fix` is not useful by itself.
See [`extends`](#function-library-lib.fixedPoints.extends) for an example use case.
There `self` is also often called `final`.
Type: fix :: (a -> a) -> a
Example:
fix (self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; })
=> { bar = "bar"; foo = "foo"; foobar = "foobar"; }
fix (self: [ 1 2 (elemAt self 0 + elemAt self 1) ])
=> [ 1 2 3 ]
*/
fix = f: let x = f x; in x;
/*
A variant of `fix` that records the original recursive attribute set in the
result, in an attribute named `__unfix__`.
This is useful in combination with the `extends` function to
implement deep overriding.
*/
fix' = f: let x = f x // { __unfix__ = f; }; in x;
/*
Return the fixpoint that `f` converges to when called iteratively, starting
with the input `x`.
```
nix-repl> converge (x: x / 2) 16
0
```
Type: (a -> a) -> a -> a
*/
converge = f: x:
let
x' = f x;
in
if x' == x
then x
else converge f x';
/*
Extend a function using an overlay.
Overlays allow modifying and extending fixed-point functions, specifically ones returning attribute sets.
A fixed-point function is a function which is intended to be evaluated by passing the result of itself as the argument.
This is possible due to Nix's lazy evaluation.
A fixed-point function returning an attribute set has the form
```nix
final: { # attributes }
```
where `final` refers to the lazily evaluated attribute set returned by the fixed-point function.
An overlay to such a fixed-point function has the form
```nix
final: prev: { # attributes }
```
where `prev` refers to the result of the original function to `final`, and `final` is the result of the composition of the overlay and the original function.
Applying an overlay is done with `extends`:
```nix
let
f = final: { # attributes };
overlay = final: prev: { # attributes };
in extends overlay f;
```
To get the value of `final`, use `lib.fix`:
```nix
let
f = final: { # attributes };
overlay = final: prev: { # attributes };
g = extends overlay f;
in fix g
```
:::{.note}
The argument to the given fixed-point function after applying an overlay will *not* refer to its own return value, but rather to the value after evaluating the overlay function.
The given fixed-point function is called with a separate argument than if it was evaluated with `lib.fix`.
:::
:::{.example}
# Extend a fixed-point function with an overlay
Define a fixed-point function `f` that expects its own output as the argument `final`:
```nix-repl
f = final: {
# Constant value a
a = 1;
# b depends on the final value of a, available as final.a
b = final.a + 2;
}
```
Evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) to get the final result:
```nix-repl
fix f
=> { a = 1; b = 3; }
```
An overlay represents a modification or extension of such a fixed-point function.
Here's an example of an overlay:
```nix-repl
overlay = final: prev: {
# Modify the previous value of a, available as prev.a
a = prev.a + 10;
# Extend the attribute set with c, letting it depend on the final values of a and b
c = final.a + final.b;
}
```
Use `extends overlay f` to apply the overlay to the fixed-point function `f`.
This produces a new fixed-point function `g` with the combined behavior of `f` and `overlay`:
```nix-repl
g = extends overlay f
```
The result is a function, so we can't print it directly, but it's the same as:
```nix-repl
g' = final: {
# The constant from f, but changed with the overlay
a = 1 + 10;
# Unchanged from f
b = final.a + 2;
# Extended in the overlay
c = final.a + final.b;
}
```
Evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) again to get the final result:
```nix-repl
fix g
=> { a = 11; b = 13; c = 24; }
```
:::
Type:
extends :: (Attrs -> Attrs -> Attrs) # The overlay to apply to the fixed-point function
-> (Attrs -> Attrs) # A fixed-point function
-> (Attrs -> Attrs) # The resulting fixed-point function
Example:
f = final: { a = 1; b = final.a + 2; }
fix f
=> { a = 1; b = 3; }
fix (extends (final: prev: { a = prev.a + 10; }) f)
=> { a = 11; b = 13; }
fix (extends (final: prev: { b = final.a + 5; }) f)
=> { a = 1; b = 6; }
fix (extends (final: prev: { c = final.a + final.b; }) f)
=> { a = 1; b = 3; c = 4; }
*/
extends =
# The overlay to apply to the fixed-point function
overlay:
# The fixed-point function
f:
# Wrap with parenthesis to prevent nixdoc from rendering the `final` argument in the documentation
# The result should be thought of as a function, the argument of that function is not an argument to `extends` itself
(
final:
let
prev = f final;
in
prev // overlay final prev
);
/*
Compose two extending functions of the type expected by 'extends'
into one where changes made in the first are available in the
'super' of the second
*/
composeExtensions =
f: g: final: prev:
let fApplied = f final prev;
prev' = prev // fApplied;
in fApplied // g final prev';
/*
Compose several extending functions of the type expected by 'extends' into
one where changes made in preceding functions are made available to
subsequent ones.
```
composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
^final ^prev ^overrides ^final ^prev ^overrides
```
*/
composeManyExtensions =
lib.foldr (x: y: composeExtensions x y) (final: prev: {});
/*
Create an overridable, recursive attribute set. For example:
```
nix-repl> obj = makeExtensible (self: { })
nix-repl> obj
{ __unfix__ = «lambda»; extend = «lambda»; }
nix-repl> obj = obj.extend (self: super: { foo = "foo"; })
nix-repl> obj
{ __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; }
nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; })
nix-repl> obj
{ __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
```
*/
makeExtensible = makeExtensibleWithCustomName "extend";
/*
Same as `makeExtensible` but the name of the extending attribute is
customized.
*/
makeExtensibleWithCustomName = extenderName: rattrs:
fix' (self: (rattrs self) // {
${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);
});
}

File diff suppressed because it is too large Load diff

View file

@ -1,2 +0,0 @@
# Expose the minimum required version for evaluating Nixpkgs
"2.3"

View file

@ -1,19 +0,0 @@
{ lib }:
let
defaultSourceType = tname: {
shortName = tname;
isSource = false;
};
in lib.mapAttrs (tname: tset: defaultSourceType tname // tset) {
fromSource = {
isSource = true;
};
binaryNativeCode = {};
binaryBytecode = {};
binaryFirmware = {};
}

View file

@ -1,68 +0,0 @@
/* List of NixOS maintainers.
```nix
handle = {
# Required
name = "Your name";
# Optional, but at least one of email, matrix or githubId must be given
email = "address@example.org";
matrix = "@user:example.org";
github = "GithubUsername";
githubId = your-github-id;
keys = [{
fingerprint = "AAAA BBBB CCCC DDDD EEEE FFFF 0000 1111 2222 3333";
}];
};
```
where
- `handle` is the handle you are going to use in nixpkgs expressions,
- `name` is a name that people would know and recognize you by,
- `email` is your maintainer email address,
- `matrix` is your Matrix user ID,
- `github` is your GitHub handle (as it appears in the URL of your profile page, `https://github.com/<userhandle>`),
- `githubId` is your GitHub user ID, which can be found at `https://api.github.com/users/<userhandle>`,
- `keys` is a list of your PGP/GPG key fingerprints.
Specifying a GitHub account ensures that you automatically:
- get invited to the @NixOS/nixpkgs-maintainers team ;
- once you are part of the @NixOS org, OfBorg will request you review
pull requests that modify a package for which you are a maintainer.
`handle == github` is strongly preferred whenever `github` is an acceptable attribute name and is short and convenient.
If `github` begins with a numeral, `handle` should be prefixed with an underscore.
```nix
_1example = {
github = "1example";
};
```
Add PGP/GPG keys only if you actually use them to sign commits and/or mail.
To get the required PGP/GPG values for a key run
```shell
gpg --fingerprint <email> | head -n 2
```
!!! Note that PGP/GPG values stored here are for informational purposes only, don't use this file as a source of truth.
More fields may be added in the future, however, in order to comply with GDPR this file should stay as minimal as possible.
When editing this file:
* keep the list alphabetically sorted, check with:
nix-instantiate --eval maintainers/scripts/check-maintainers-sorted.nix
* test the validity of the format with:
nix-build lib/tests/maintainers.nix
See `./scripts/check-maintainer-github-handles.sh` for an example on how to work with this data.
When adding a new maintainer, be aware of the current commit conventions
documented at [CONTRIBUTING.md](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#commit-conventions)
file located in the root of the Nixpkgs repo.
*/
{
}

View file

@ -1,48 +0,0 @@
/* List of maintainer teams.
name = {
# Required
members = [ maintainer1 maintainer2 ];
scope = "Maintain foo packages.";
shortName = "foo";
# Optional
enableFeatureFreezePing = true;
githubTeams = [ "my-subsystem" ];
};
where
- `members` is the list of maintainers belonging to the group,
- `scope` describes the scope of the group.
- `shortName` short human-readable name
- `enableFeatureFreezePing` will ping this team during the Feature Freeze announcements on releases
- There is limited mention capacity in a single post, so this should be reserved for critical components
or larger ecosystems within nixpkgs.
- `githubTeams` will ping specified GitHub teams as well
More fields may be added in the future.
When editing this file:
* keep the list alphabetically sorted
* test the validity of the format with:
nix-build lib/tests/teams.nix
*/
{ lib }:
with lib.maintainers; {
llvm = {
members = [];
scope = "Maintain LLVM package sets and related packages";
shortName = "LLVM";
enableFeatureFreezePing = true;
};
lix = {
members = [];
};
python = {
members = [];
};
rust = {
members = [];
};
}

459
nodes/1_lib/default.nix Normal file
View file

@ -0,0 +1,459 @@
let
# no "external"dependencies
in
let # internal dependencies
foundation = import ./source/detangled/1_foundation.nix;
static = import ./source/detangled/2_static.nix;
fixedPoints = import ./source/detangled/3_fixed-points.nix;
in
let
untangledBase = {
# constants
sourceTypes = static.setup.sourceTypes;
licenses = static.setup.licenses;
maintainers = static.setup.maintainers;
teams = static.setup.teams;
# just to be overridable
builtins = builtins;
# top level helpers
loadStatic = foundation.loadStatic;
foldr = foundation.foldr;
# namespaces
fixedPoints = fixedPoints;
};
#
# legacy lib
#
lib = fixedPoints.makeExtensible (
self:
untangledBase // {
trivial = import ./source/trivial.nix { lib = self; };
attrsets = import ./source/attrsets.nix { lib = self; };
lists = import ./source/lists.nix { lib = self; };
strings = import ./source/strings.nix { lib = self; };
stringsWithDeps = import ./source/strings-with-deps.nix { lib = self; };
customisation = import ./source/customisation.nix { lib = self; };
derivations = import ./source/derivations.nix { lib = self; };
meta = import ./source/meta.nix { lib = self; };
versions = import ./source/versions.nix { lib = self; };
modules = import ./source/modules.nix { lib = self; };
options = import ./source/options.nix { lib = self; };
types = import ./source/types.nix { lib = self; };
systems = import ./source/systems { lib = self; };
cli = import ./source/cli.nix { lib = self; };
gvariant = import ./source/gvariant.nix { lib = self; };
generators = import ./source/generators.nix { lib = self; };
asserts = import ./source/asserts.nix { lib = self; };
debug = import ./source/debug.nix { lib = self; };
fetchers = import ./source/fetchers.nix { lib = self; };
path = import ./source/path { lib = self; };
filesystem = import ./source/filesystem.nix { lib = self; };
fileset = import ./source/fileset { lib = self; };
sources = import ./source/sources.nix { lib = self; };
kernel = import ./source/kernel.nix { lib = self; };
platforms = self.systems.doubles; # back-compat aliases # TODO: these are not the same as system.platform, we should probably try and unify them
# builtin aliases
add = builtins.add;
addErrorContext = builtins.addErrorContext;
attrNames = builtins.attrNames;
concatLists = builtins.concatLists;
deepSeq = builtins.deepSeq;
elem = builtins.elem;
elemAt = builtins.elemAt;
filter = builtins.filter;
genericClosure = builtins.genericClosure;
genList = builtins.genList;
getAttr = builtins.getAttr;
hasAttr = builtins.hasAttr;
head = builtins.head;
isAttrs = builtins.isAttrs;
isBool = builtins.isBool;
isInt = builtins.isInt;
isList = builtins.isList;
isPath = builtins.isPath;
isString = builtins.isString;
length = builtins.length;
lessThan = builtins.lessThan;
listToAttrs = builtins.listToAttrs;
pathExists = builtins.pathExists;
readFile = builtins.readFile;
replaceStrings = builtins.replaceStrings;
seq = builtins.seq;
stringLength = builtins.stringLength;
sub = builtins.sub;
substring = builtins.substring;
tail = builtins.tail;
trace = builtins.trace;
# trivial to top level
id = self.trivial.id;
const = self.trivial.const;
pipe = self.trivial.pipe;
concat = self.trivial.concat;
or = self.trivial.or;
and = self.trivial.and;
xor = self.trivial.xor;
bitAnd = self.trivial.bitAnd;
bitOr = self.trivial.bitOr;
bitXor = self.trivial.bitXor;
bitNot = self.trivial.bitNot;
boolToString = self.trivial.boolToString;
mergeAttrs = self.trivial.mergeAttrs;
flip = self.trivial.flip;
mapNullable = self.trivial.mapNullable;
inNixShell = self.trivial.inNixShell;
isFloat = self.trivial.isFloat;
min = self.trivial.min;
max = self.trivial.max;
importJSON = self.trivial.importJSON;
importTOML = self.trivial.importTOML;
warn = self.trivial.warn;
warnIf = self.trivial.warnIf;
warnIfNot = self.trivial.warnIfNot;
throwIf = self.trivial.throwIf;
throwIfNot = self.trivial.throwIfNot;
checkListOfEnum = self.trivial.checkListOfEnum;
info = self.trivial.info;
showWarnings = self.trivial.showWarnings;
nixpkgsVersion = self.trivial.nixpkgsVersion;
version = self.trivial.version;
isInOldestRelease = self.trivial.isInOldestRelease;
mod = self.trivial.mod;
compare = self.trivial.compare;
splitByAndCompare = self.trivial.splitByAndCompare;
functionArgs = self.trivial.functionArgs;
setFunctionArgs = self.trivial.setFunctionArgs;
isFunction = self.trivial.isFunction;
toFunction = self.trivial.toFunction;
mirrorFunctionArgs = self.trivial.mirrorFunctionArgs;
toHexString = self.trivial.toHexString;
toBaseDigits = self.trivial.toBaseDigits;
inPureEvalMode = self.trivial.inPureEvalMode;
# fixed points to top level
fix = self.fixedPoints.fix;
fix' = self.fixedPoints.fix';
converge = self.fixedPoints.converge;
extends = self.fixedPoints.extends;
composeExtensions = self.fixedPoints.composeExtensions;
composeManyExtensions = self.fixedPoints.composeManyExtensions;
makeExtensible = self.fixedPoints.makeExtensible;
makeExtensibleWithCustomName = self.fixedPoints.makeExtensibleWithCustomName;
# attrsets to top level
attrByPath = self.attrsets.attrByPath;
hasAttrByPath = self.attrsets.hasAttrByPath;
setAttrByPath = self.attrsets.setAttrByPath;
getAttrFromPath = self.attrsets.getAttrFromPath;
attrVals = self.attrsets.attrVals;
attrValues = self.attrsets.attrValues;
getAttrs = self.attrsets.getAttrs;
catAttrs = self.attrsets.catAttrs;
filterAttrs = self.attrsets.filterAttrs;
filterAttrsRecursive = self.attrsets.filterAttrsRecursive;
foldlAttrs = self.attrsets.foldlAttrs;
foldAttrs = self.attrsets.foldAttrs;
collect = self.attrsets.collect;
nameValuePair = self.attrsets.nameValuePair;
mapAttrs = self.attrsets.mapAttrs;
mapAttrs' = self.attrsets.mapAttrs';
mapAttrsToList = self.attrsets.mapAttrsToList;
attrsToList = self.attrsets.attrsToList;
concatMapAttrs = self.attrsets.concatMapAttrs;
mapAttrsRecursive = self.attrsets.mapAttrsRecursive;
mapAttrsRecursiveCond = self.attrsets.mapAttrsRecursiveCond;
genAttrs = self.attrsets.genAttrs;
isDerivation = self.attrsets.isDerivation;
toDerivation = self.attrsets.toDerivation;
optionalAttrs = self.attrsets.optionalAttrs;
zipAttrsWithNames = self.attrsets.zipAttrsWithNames;
zipAttrsWith = self.attrsets.zipAttrsWith;
zipAttrs = self.attrsets.zipAttrs;
recursiveUpdateUntil = self.attrsets.recursiveUpdateUntil;
recursiveUpdate = self.attrsets.recursiveUpdate;
matchAttrs = self.attrsets.matchAttrs;
mergeAttrsList = self.attrsets.mergeAttrsList;
overrideExisting = self.attrsets.overrideExisting;
showAttrPath = self.attrsets.showAttrPath;
getOutput = self.attrsets.getOutput;
getBin = self.attrsets.getBin;
getLib = self.attrsets.getLib;
getDev = self.attrsets.getDev;
getMan = self.attrsets.getMan;
chooseDevOutputs = self.attrsets.chooseDevOutputs;
zipWithNames = self.attrsets.zipWithNames;
zip = self.attrsets.zip;
recurseIntoAttrs = self.attrsets.recurseIntoAttrs;
dontRecurseIntoAttrs = self.attrsets.dontRecurseIntoAttrs;
cartesianProduct = self.attrsets.cartesianProduct;
cartesianProductOfSets = self.attrsets.cartesianProductOfSets;
mapCartesianProduct = self.attrsets.mapCartesianProduct;
updateManyAttrsByPath = self.attrsets.updateManyAttrsByPath;
# lists to top level
singleton = self.lists.singleton;
forEach = self.lists.forEach;
foldr = self.lists.foldr;
fold = self.lists.fold;
foldl = self.lists.foldl;
foldl' = self.lists.foldl';
imap0 = self.lists.imap0;
imap1 = self.lists.imap1;
ifilter0 = self.lists.ifilter0;
concatMap = self.lists.concatMap;
flatten = self.lists.flatten;
remove = self.lists.remove;
findSingle = self.lists.findSingle;
findFirst = self.lists.findFirst;
any = self.lists.any;
all = self.lists.all;
count = self.lists.count;
optional = self.lists.optional;
optionals = self.lists.optionals;
toList = self.lists.toList;
range = self.lists.range;
replicate = self.lists.replicate;
partition = self.lists.partition;
zipListsWith = self.lists.zipListsWith;
zipLists = self.lists.zipLists;
reverseList = self.lists.reverseList;
listDfs = self.lists.listDfs;
toposort = self.lists.toposort;
sort = self.lists.sort;
sortOn = self.lists.sortOn;
naturalSort = self.lists.naturalSort;
compareLists = self.lists.compareLists;
take = self.lists.take;
drop = self.lists.drop;
sublist = self.lists.sublist;
last = self.lists.last;
init = self.lists.init;
crossLists = self.lists.crossLists;
unique = self.lists.unique;
allUnique = self.lists.allUnique;
intersectLists = self.lists.intersectLists;
subtractLists = self.lists.subtractLists;
mutuallyExclusive = self.lists.mutuallyExclusive;
groupBy = self.lists.groupBy;
groupBy' = self.lists.groupBy';
# strings to top level
concatStrings = self.strings.concatStrings;
concatMapStrings = self.strings.concatMapStrings;
concatImapStrings = self.strings.concatImapStrings;
intersperse = self.strings.intersperse;
concatStringsSep = self.strings.concatStringsSep;
concatMapStringsSep = self.strings.concatMapStringsSep;
concatImapStringsSep = self.strings.concatImapStringsSep;
concatLines = self.strings.concatLines;
makeSearchPath = self.strings.makeSearchPath;
makeSearchPathOutput = self.strings.makeSearchPathOutput;
makeLibraryPath = self.strings.makeLibraryPath;
makeIncludePath = self.strings.makeIncludePath;
makeBinPath = self.strings.makeBinPath;
optionalString = self.strings.optionalString;
hasInfix = self.strings.hasInfix;
hasPrefix = self.strings.hasPrefix;
hasSuffix = self.strings.hasSuffix;
stringToCharacters = self.strings.stringToCharacters;
stringAsChars = self.strings.stringAsChars;
escape = self.strings.escape;
escapeShellArg = self.strings.escapeShellArg;
escapeShellArgs = self.strings.escapeShellArgs;
isStorePath = self.strings.isStorePath;
isStringLike = self.strings.isStringLike;
isValidPosixName = self.strings.isValidPosixName;
toShellVar = self.strings.toShellVar;
toShellVars = self.strings.toShellVars;
escapeRegex = self.strings.escapeRegex;
escapeURL = self.strings.escapeURL;
escapeXML = self.strings.escapeXML;
replaceChars = self.strings.replaceChars;
lowerChars = self.strings.lowerChars;
upperChars = self.strings.upperChars;
toLower = self.strings.toLower;
toUpper = self.strings.toUpper;
addContextFrom = self.strings.addContextFrom;
splitString = self.strings.splitString;
removePrefix = self.strings.removePrefix;
removeSuffix = self.strings.removeSuffix;
versionOlder = self.strings.versionOlder;
versionAtLeast = self.strings.versionAtLeast;
getName = self.strings.getName;
getVersion = self.strings.getVersion;
cmakeOptionType = self.strings.cmakeOptionType;
cmakeBool = self.strings.cmakeBool;
cmakeFeature = self.strings.cmakeFeature;
mesonOption = self.strings.mesonOption;
mesonBool = self.strings.mesonBool;
mesonEnable = self.strings.mesonEnable;
nameFromURL = self.strings.nameFromURL;
enableFeature = self.strings.enableFeature;
enableFeatureAs = self.strings.enableFeatureAs;
withFeature = self.strings.withFeature;
withFeatureAs = self.strings.withFeatureAs;
fixedWidthString = self.strings.fixedWidthString;
fixedWidthNumber = self.strings.fixedWidthNumber;
toInt = self.strings.toInt;
toIntBase10 = self.strings.toIntBase10;
readPathsFromFile = self.strings.readPathsFromFile;
fileContents = self.strings.fileContents;
# stringsWithDeps to top level
textClosureList = self.stringsWithDeps.textClosureList;
textClosureMap = self.stringsWithDeps.textClosureMap;
noDepEntry = self.stringsWithDeps.noDepEntry;
fullDepEntry = self.stringsWithDeps.fullDepEntry;
packEntry = self.stringsWithDeps.packEntry;
stringAfter = self.stringsWithDeps.stringAfter;
# customisation to top level
overrideDerivation = self.customisation.overrideDerivation;
makeOverridable = self.customisation.makeOverridable;
callPackageWith = self.customisation.callPackageWith;
callPackagesWith = self.customisation.callPackagesWith;
extendDerivation = self.customisation.extendDerivation;
hydraJob = self.customisation.hydraJob;
makeScope = self.customisation.makeScope;
makeScopeWithSplicing = self.customisation.makeScopeWithSplicing;
makeScopeWithSplicing' = self.customisation.makeScopeWithSplicing';
# derivations to top level
lazyDerivation = self.derivations.lazyDerivation;
optionalDrvAttr = self.derivations.optionalDrvAttr;
# meta to top level
addMetaAttrs = self.meta.addMetaAttrs;
dontDistribute = self.meta.dontDistribute;
setName = self.meta.setName;
updateName = self.meta.updateName;
appendToName = self.meta.appendToName;
mapDerivationAttrset = self.meta.mapDerivationAttrset;
setPrio = self.meta.setPrio;
lowPrio = self.meta.lowPrio;
lowPrioSet = self.meta.lowPrioSet;
hiPrio = self.meta.hiPrio;
hiPrioSet = self.meta.hiPrioSet;
getLicenseFromSpdxId = self.meta.getLicenseFromSpdxId;
getExe = self.meta.getExe;
getExe' = self.meta.getExe';
# filesystem to top level
pathType = self.filesystem.pathType;
pathIsDirectory = self.filesystem.pathIsDirectory;
pathIsRegularFile = self.filesystem.pathIsRegularFile;
packagesFromDirectoryRecursive = self.filesystem.packagesFromDirectoryRecursive;
# sources to top level
cleanSourceFilter = self.sources.cleanSourceFilter;
cleanSource = self.sources.cleanSource;
sourceByRegex = self.sources.sourceByRegex;
sourceFilesBySuffices = self.sources.sourceFilesBySuffices;
commitIdFromGitRepo = self.sources.commitIdFromGitRepo;
cleanSourceWith = self.sources.cleanSourceWith;
pathHasContext = self.sources.pathHasContext;
canCleanSource = self.sources.canCleanSource;
pathIsGitRepo = self.sources.pathIsGitRepo;
# modules to top level
evalModules = self.modules.evalModules;
setDefaultModuleLocation = self.modules.setDefaultModuleLocation;
unifyModuleSyntax = self.modules.unifyModuleSyntax;
applyModuleArgsIfFunction = self.modules.applyModuleArgsIfFunction;
mergeModules = self.modules.mergeModules;
mergeModules' = self.modules.mergeModules';
mergeOptionDecls = self.modules.mergeOptionDecls;
mergeDefinitions = self.modules.mergeDefinitions;
pushDownProperties = self.modules.pushDownProperties;
dischargeProperties = self.modules.dischargeProperties;
filterOverrides = self.modules.filterOverrides;
sortProperties = self.modules.sortProperties;
fixupOptionType = self.modules.fixupOptionType;
mkIf = self.modules.mkIf;
mkAssert = self.modules.mkAssert;
mkMerge = self.modules.mkMerge;
mkOverride = self.modules.mkOverride;
mkOptionDefault = self.modules.mkOptionDefault;
mkDefault = self.modules.mkDefault;
mkImageMediaOverride = self.modules.mkImageMediaOverride;
mkForce = self.modules.mkForce;
mkVMOverride = self.modules.mkVMOverride;
mkFixStrictness = self.modules.mkFixStrictness;
mkOrder = self.modules.mkOrder;
mkBefore = self.modules.mkBefore;
mkAfter = self.modules.mkAfter;
mkAliasDefinitions = self.modules.mkAliasDefinitions;
mkAliasAndWrapDefinitions = self.modules.mkAliasAndWrapDefinitions;
fixMergeModules = self.modules.fixMergeModules;
mkRemovedOptionModule = self.modules.mkRemovedOptionModule;
mkRenamedOptionModule = self.modules.mkRenamedOptionModule;
mkRenamedOptionModuleWith = self.modules.mkRenamedOptionModuleWith;
mkMergedOptionModule = self.modules.mkMergedOptionModule;
mkChangedOptionModule = self.modules.mkChangedOptionModule;
mkAliasOptionModule = self.modules.mkAliasOptionModule;
mkDerivedConfig = self.modules.mkDerivedConfig;
doRename = self.modules.doRename;
mkAliasOptionModuleMD = self.modules.mkAliasOptionModuleMD;
# options to top level
isOption = self.options.isOption;
mkEnableOption = self.options.mkEnableOption;
mkSinkUndeclaredOptions = self.options.mkSinkUndeclaredOptions;
mergeDefaultOption = self.options.mergeDefaultOption;
mergeOneOption = self.options.mergeOneOption;
mergeEqualOption = self.options.mergeEqualOption;
mergeUniqueOption = self.options.mergeUniqueOption;
getValues = self.options.getValues;
getFiles = self.options.getFiles;
optionAttrSetToDocList = self.options.optionAttrSetToDocList;
optionAttrSetToDocList' = self.options.optionAttrSetToDocList';
scrubOptionValue = self.options.scrubOptionValue;
literalExpression = self.options.literalExpression;
literalExample = self.options.literalExample;
showOption = self.options.showOption;
showOptionWithDefLocs = self.options.showOptionWithDefLocs;
showFiles = self.options.showFiles;
unknownModule = self.options.unknownModule;
mkOption = self.options.mkOption;
mkPackageOption = self.options.mkPackageOption;
mkPackageOptionMD = self.options.mkPackageOptionMD;
mdDoc = self.options.mdDoc;
literalMD = self.options.literalMD;
# types to top level
isType = self.types.isType;
setType = self.types.setType;
defaultTypeMerge = self.types.defaultTypeMerge;
defaultFunctor = self.types.defaultFunctor;
isOptionType = self.types.isOptionType;
mkOptionType = self.types.mkOptionType;
# asserts to top level
assertMsg = self.asserts.assertMsg;
assertOneOf = self.asserts.assertOneOf;
# debug to top level
traceIf = self.debug.traceIf;
traceVal = self.debug.traceVal;
traceValFn = self.debug.traceValFn;
traceSeq = self.debug.traceSeq;
traceSeqN = self.debug.traceSeqN;
traceValSeq = self.debug.traceValSeq;
traceValSeqFn = self.debug.traceValSeqFn;
traceValSeqN = self.debug.traceValSeqN;
traceValSeqNFn = self.debug.traceValSeqNFn;
traceFnSeqN = self.debug.traceFnSeqN;
runTests = self.debug.runTests;
testAllTrue = self.debug.testAllTrue;
# versions to top level
splitVersion = self.versions.splitVersion;
}
);
in lib

19
nodes/1_lib/scripts/test Executable file
View file

@ -0,0 +1,19 @@
#!/usr/bin/env bash
#
# this just runs tests/check-eval.nix
#
result="$(
echo 'import ./nodes/1_lib/source/tests/check-eval.nix' | nix repl --show-trace 2>&1 | grep -v 'Inappropriate ioctl for device'
)"
expected='Welcome to Nix 2.18.1. Type :? for help.
null'
if [ "$(echo "$result")" = "$expected" ]
then
echo test passed
else
echo "test failed"
echo "$result"
fi

View file

@ -19,7 +19,6 @@ This file evaluates to an attribute set containing two separate kinds of attribu
Example: `lib.take` is an alias for `lib.lists.take`.
Most files in this directory are definitions of sub-libraries, but there are a few others:
- [`minver.nix`](minver.nix): A string of the minimum version of Nix that is required to evaluate Nixpkgs.
- [`tests`](tests): Tests, see [Running tests](#running-tests)
- [`release.nix`](tests/release.nix): A derivation aggregating all tests
- [`misc.nix`](tests/misc.nix): Evaluation unit tests for most sub-libraries

View file

@ -2025,16 +2025,4 @@ rec {
intersection;
in
(x // y) // mask;
# DEPRECATED
zipWithNames = warn
"lib.zipWithNames is a deprecated alias of lib.zipAttrsWithNames." zipAttrsWithNames;
# DEPRECATED
zip = warn
"lib.zip is a deprecated alias of lib.zipAttrsWith." zipAttrsWith;
# DEPRECATED
cartesianProductOfSets = warnIf (isInOldestRelease 2405)
"lib.cartesianProductOfSets is a deprecated alias of lib.cartesianProduct." cartesianProduct;
}

View file

@ -0,0 +1 @@
import ../. # just to help tests pass, evetually remove this file

View file

@ -0,0 +1,374 @@
{ lib }:
let
inherit (lib)
and
any
attrByPath
attrNames
compare
concat
concatMap
elem
filter
foldl
foldr
genericClosure
head
imap1
init
isAttrs
isFunction
isInt
isList
lists
listToAttrs
mapAttrs
mergeAttrs
meta
nameValuePair
tail
toList
;
inherit (lib.attrsets) removeAttrs;
# returns default if env var is not set
maybeEnv = name: default:
let value = builtins.getEnv name; in
if value == "" then default else value;
defaultMergeArg = x : y: if builtins.isAttrs y then
y
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 "passthru" {} (f arg)
( z: z // {
function = foldArgs merger f arg;
args = (attrByPath ["passthru" "args"] {} z) // x;
} ));
withStdOverrides = base // {
override = base.passthru.function;
};
in
withStdOverrides;
# shortcut for attrByPath ["name"] default attrs
maybeAttrNullable = maybeAttr;
# shortcut for attrByPath ["name"] default attrs
maybeAttr = name: default: attrs: attrs.${name} or default;
# Return the second argument if the first one is true or the empty version
# of the second argument.
ifEnable = cond: val:
if cond then val
else if builtins.isList val then []
else if builtins.isAttrs val then {}
# else if builtins.isString val then ""
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 == "true" then true else
if name == "false" then false else
if (elem name (attrByPath ["flags"] [] attrSet)) then true else
attrByPath [name] false attrSet ;
# Input : attrSet, [ [name default] ... ], name
# Output : its value or default.
getValue = attrSet: argList: name:
( 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
(head (tail x))
else (getValue attrSet
(tail argList) name)) attrSet );
# Input : attrSet, [[name default] ...], [ [flagname reqs..] ... ]
# Output : are reqs satisfied? It's asserted.
checkReqs = attrSet: argList: condList:
(
foldr and true
(map (x: let name = (head x); in
((checkFlag attrSet name) ->
(foldr and true
(map (y: let val=(getValue attrSet argList y); in
(val!=null) && (val!=false))
(tail x))))) condList));
# This function has O(n^2) performance.
uniqList = { inputList, acc ? [] }:
let go = xs: acc:
if xs == []
then []
else let x = head xs;
y = if elem x acc then [] else [x];
in y ++ go (tail xs) (y ++ acc);
in go inputList acc;
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;
};
condConcat = name: list: checker:
if list == [] then name else
if checker (head list) then
condConcat
(name + (head (tail list)))
(tail (tail list))
checker
else condConcat
name (tail (tail list)) checker;
lazyGenericClosure = {startSet, operator}:
let
work = list: doneKeys: result:
if list == [] then
result
else
let x = head list; key = x.key; in
if elem key doneKeys then
work (tail list) doneKeys result
else
work (tail list ++ operator x) ([key] ++ doneKeys) ([x] ++ result);
in
work startSet [] [];
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:
if xs == []
then acc
else let y = head xs;
ys = tail xs;
in if ! isAttrs y
then innerClosePropagation acc ys
else let acc' = [y] ++ acc;
in innerClosePropagation
acc'
(uniqList { inputList = (maybeAttrNullable "propagatedBuildInputs" [] y)
++ (maybeAttrNullable "propagatedNativeBuildInputs" [] y)
++ ys;
acc = acc';
}
);
closePropagationSlow = list: (uniqList {inputList = (innerClosePropagation [] list);});
# This is an optimisation of closePropagation which avoids the O(n^2) behavior
# Using a list of derivations, it generates the full closure of the propagatedXXXBuildInputs
# The ordering / sorting / comparison is done based on the `outPath`
# attribute of each derivation.
# On some benchmarks, it performs up to 15 times faster than closePropagation.
# See https://github.com/NixOS/nixpkgs/pull/194391 for details.
closePropagationFast = list:
builtins.map (x: x.val) (builtins.genericClosure {
startSet = builtins.map (x: {
key = x.outPath;
val = x;
}) (builtins.filter (x: x != null) list);
operator = item:
if !builtins.isAttrs item.val then
[ ]
else
builtins.concatMap (x:
if x != null then [{
key = x.outPath;
val = x;
}] else
[ ]) ((item.val.propagatedBuildInputs or [ ])
++ (item.val.propagatedNativeBuildInputs or [ ]));
});
closePropagation = if builtins ? genericClosure
then closePropagationFast
else closePropagationSlow;
# calls a function (f attr value ) for each record item. returns a list
mapAttrsFlatten = f: r: map (attr: f attr r.${attr}) (attrNames r);
# attribute set containing one attribute
nvs = name: value: listToAttrs [ (nameValuePair name value) ];
# adds / replaces an attribute of an attribute set
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:
setAttr attrs name (f (maybeAttr name default attrs));
# 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:
foldr (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) );
# merges attributes using //, if a name exists in both attributes
# an error will be triggered unless its listed in mergeLists
# so you can mergeAttrsNoOverride { buildInputs = [a]; } { buildInputs = [a]; } {} to get
# { buildInputs = [a b]; }
# merging buildPhase doesn't really make sense. The cases will be rare where appending /prefixing will fit your needs?
# in these cases the first buildPhase will override the second one
# ! deprecated, use mergeAttrByFunc instead
mergeAttrsNoOverride = { mergeLists ? ["buildInputs" "propagatedBuildInputs"],
overrideSnd ? [ "buildPhase" ]
}: attrs1: attrs2:
foldr (n: set:
setAttr set n ( if set ? ${n}
then # merge
if elem n mergeLists # attribute contains list, merge them by concatenating
then attrs2.${n} ++ attrs1.${n}
else if elem n overrideSnd
then attrs1.${n}
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
else attrs2.${n} # add attribute not existing in attr1
)) attrs1 (attrNames attrs2);
# example usage:
# mergeAttrByFunc {
# inherit mergeAttrBy; # defined below
# buildInputs = [ a b ];
# } {
# buildInputs = [ c d ];
# };
# will result in
# { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
# is used by defaultOverridableDelayableArgs and can be used when composing using
# foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
mergeAttrByFunc = x: y:
let
mergeAttrBy2 = { mergeAttrBy = mergeAttrs; }
// (maybeAttr "mergeAttrBy" {} x)
// (maybeAttr "mergeAttrBy" {} y); in
foldr mergeAttrs {} [
x y
(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
else x.${a} # only x has attr
else y.${a} # only y has attr)
) (removeAttrs mergeAttrBy2
# don't merge attrs which are neither in x nor y
(filter (a: ! x ? ${a} && ! y ? ${a})
(attrNames mergeAttrBy2))
)
)
];
mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { inherit mergeAttrBy; };
mergeAttrsByFuncDefaultsClean = list: removeAttrs (mergeAttrsByFuncDefaults list) ["mergeAttrBy"];
# sane defaults (same name as attr name so that inherit can be used)
mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
listToAttrs (map (n: nameValuePair n concat)
[ "nativeBuildInputs" "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" "patches" ])
// listToAttrs (map (n: nameValuePair n mergeAttrs) [ "passthru" "meta" "cfg" "flags" ])
// listToAttrs (map (n: nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ])
;
nixType = x:
if isAttrs x then
if x ? outPath then "derivation"
else "attrs"
else if isFunction x then "function"
else if isList x then "list"
else if x == true then "bool"
else if x == false then "bool"
else if x == null then "null"
else if isInt x then "int"
else "string";
/**
# Deprecated
For historical reasons, imap has an index starting at 1.
But for consistency with the rest of the library we want an index
starting at zero.
*/
imap = imap1;
# Fake hashes. Can be used as hash placeholders, when computing hash ahead isn't trivial
fakeHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
fakeSha256 = "0000000000000000000000000000000000000000000000000000000000000000";
fakeSha512 = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
in
# Everything in this attrset is the public interface of the file.
{
inherit
checkFlag
checkReqs
closePropagation
closePropagationFast
closePropagationSlow
condConcat
defaultMerge
defaultMergeArg
fakeHash
fakeSha256
fakeSha512
foldArgs
getValue
ifEnable
imap
innerClosePropagation
innerModifySumArgs
lazyGenericClosure
mapAttrsFlatten
maybeAttr
maybeAttrNullable
maybeEnv
mergeAttrBy
mergeAttrByFunc
mergeAttrsByFuncDefaults
mergeAttrsByFuncDefaultsClean
mergeAttrsConcatenateValues
mergeAttrsNoOverride
mergeAttrsWithFunc
modifySumArgs
nixType
nvs
setAttr
setAttrMerge
uniqList
uniqListExt
;
}

View file

@ -0,0 +1,591 @@
#
# foundation contains functions that only depend on builtins or themself (no inter-dependence or ordering)
#
let
loadStatic = (folder:
{
setup = builtins.fromTOML ( builtins.readFile "${folder}/static/setup.toml" );
meta = builtins.fromTOML ( builtins.readFile "${folder}/static/meta.toml" );
}
);
/**
right fold a binary function `op` between successive elements of
`list` with `nul` as the starting value, i.e.,
`foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))`.
# Inputs
`op`
: 1\. Function argument
`nul`
: 2\. Function argument
`list`
: 3\. Function argument
# Type
```
foldr :: (a -> b -> b) -> b -> [a] -> b
```
# Examples
:::{.example}
## `lib.lists.foldr` usage example
```nix
concat = foldr (a: b: a + b) "z"
concat [ "a" "b" "c" ]
=> "abcz"
# different types
strange = foldr (int: str: toString (int + 1) + str) "a"
strange [ 1 2 3 4 ]
=> "2345a"
```
:::
*/
foldr = (
op: nul: list:
let
len = builtins.length list;
fold' = n:
if n == len
then nul
else op (builtins.elemAt list n) (fold' (n + 1));
in
fold' 0
);
/**
Reverse the order of the elements of a list.
# Inputs
`xs`
: 1\. Function argument
# Type
```
reverseList :: [a] -> [a]
```
# Examples
:::{.example}
## `lib.lists.reverseList` usage example
```nix
reverseList [ "b" "o" "j" ]
=> [ "j" "o" "b" ]
```
:::
*/
reverseList = xs:
let l = builtins.length xs; in builtins.genList (n: builtins.elemAt xs (l - n - 1)) l;
/**
Check whether something is a function or something
annotated with function args.
# Inputs
`f`
: 1\. Function argument
*/
isFunction = f: builtins.isFunction f ||
(f ? __functor && isFunction (f.__functor f));
/**
Extract the expected function arguments from a function.
This works both with nix-native { a, b ? foo, ... }: style
functions and functions with args set with 'setFunctionArgs'. It
has the same return type and semantics as builtins.functionArgs.
setFunctionArgs : (a b) Map String Bool.
# Inputs
`f`
: 1\. Function argument
*/
functionArgs = f:
if f ? __functor
then f.__functionArgs or (functionArgs (f.__functor f))
else builtins.functionArgs f;
/**
Add metadata about expected function arguments to a function.
The metadata should match the format given by
builtins.functionArgs, i.e. a set from expected argument to a bool
representing whether that argument has a default or not.
setFunctionArgs : (a b) Map String Bool (a b)
This function is necessary because you can't dynamically create a
function of the { a, b ? foo, ... }: format, but some facilities
like callPackage expect to be able to query expected arguments.
# Inputs
`f`
: 1\. Function argument
`args`
: 2\. Function argument
*/
setFunctionArgs = f: args:
{
__functor = self: f;
__functionArgs = args;
};
# See https://github.com/NixOS/nix/issues/749. Eventually we'd like these
# to expand to Nix builtins that carry metadata so that Nix can filter out
# the INFO messages without parsing the message string.
#
# Usage:
# {
# foo = lib.warn "foo is deprecated" oldFoo;
# bar = lib.warnIf (bar == "") "Empty bar is deprecated" bar;
# }
#
# TODO: figure out a clever way to integrate location information from
# something like __unsafeGetAttrPos.
/**
Print a warning before returning the second argument. This function behaves
like `builtins.trace`, but requires a string message and formats it as a
warning, including the `warning: ` prefix.
To get a call stack trace and abort evaluation, set the environment variable
`NIX_ABORT_ON_WARN=true` and set the Nix options `--option pure-eval false --show-trace`
# Inputs
`msg`
: Warning message to print.
`val`
: Value to return as-is.
# Type
```
string -> a -> a
```
*/
warn =
if builtins.elem (builtins.getEnv "NIX_ABORT_ON_WARN") ["1" "true" "yes"]
then msg: builtins.trace "warning: ${msg}" (builtins.abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
else msg: builtins.trace "warning: ${msg}";
/**
Like the `assert b; e` expression, but with a custom error message and
without the semicolon.
If true, return the identity function, `r: r`.
If false, throw the error message.
Calls can be juxtaposed using function application, as `(r: r) a = a`, so
`(r: r) (r: r) a = a`, and so forth.
# Inputs
`cond`
: 1\. Function argument
`msg`
: 2\. Function argument
# Type
```
bool -> string -> a -> a
```
# Examples
:::{.example}
## `lib.trivial.throwIfNot` usage example
```nix
throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list."
lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays
pkgs
```
:::
*/
throwIfNot = cond: msg: if cond then x: x else builtins.throw msg;
/**
The identity function
For when you need a function that does nothing.
# Inputs
`x`
: The value to return
# Type
```
id :: a -> a
```
*/
id = x: x;
/**
The constant function
Ignores the second argument. If called with only one argument,
constructs a function that always returns a static value.
# Inputs
`x`
: Value to return
`y`
: Value to ignore
# Type
```
const :: a -> b -> a
```
# Examples
:::{.example}
## `lib.trivial.const` usage example
```nix
let f = const 5; in f 10
=> 5
```
:::
*/
const =
x:
y: x;
/**
Pipes a value through a list of functions, left to right.
# Inputs
`value`
: Value to start piping.
`fns`
: List of functions to apply sequentially.
# Type
```
pipe :: a -> [<functions>] -> <return type of last function>
```
# Examples
:::{.example}
## `lib.trivial.pipe` usage example
```nix
pipe 2 [
(x: x + 2) # 2 + 2 = 4
(x: x * 2) # 4 * 2 = 8
]
=> 8
# ideal to do text transformations
pipe [ "a/b" "a/c" ] [
# create the cp command
(map (file: ''cp "${src}/${file}" $out\n''))
# concatenate all commands into one string
lib.concatStrings
# make that string into a nix derivation
(pkgs.runCommand "copy-to-out" {})
]
=> <drv which copies all files to $out>
The output type of each function has to be the input type
of the next function, and the last function returns the
final value.
```
:::
*/
pipe = builtins.foldl' (x: f: f x);
# note please dont add a function like `compose = flip pipe`.
# This would confuse users, because the order of the functions
# in the list is not clear. With pipe, its obvious that it
# goes first-to-last. With `compose`, not so much.
## Named versions corresponding to some builtin operators.
/**
Concatenate two lists
# Inputs
`x`
: 1\. Function argument
`y`
: 2\. Function argument
# Type
```
concat :: [a] -> [a] -> [a]
```
# Examples
:::{.example}
## `lib.trivial.concat` usage example
```nix
concat [ 1 2 ] [ 3 4 ]
=> [ 1 2 3 4 ]
```
:::
*/
concat = x: y: x ++ y;
/**
boolean or
# Inputs
`x`
: 1\. Function argument
`y`
: 2\. Function argument
*/
logicalOr = x: y: x || y;
/**
boolean and
# Inputs
`x`
: 1\. Function argument
`y`
: 2\. Function argument
*/
and = x: y: x && y;
/**
boolean exclusive or
# Inputs
`x`
: 1\. Function argument
`y`
: 2\. Function argument
*/
# We explicitly invert the arguments purely as a type assertion.
# This is invariant under XOR, so it does not affect the result.
xor = x: y: (!x) != (!y);
/**
bitwise not
*/
bitNot = builtins.sub (-1);
/**
Convert a boolean to a string.
This function uses the strings "true" and "false" to represent
boolean values. Calling `toString` on a bool instead returns "1"
and "" (sic!).
# Inputs
`b`
: 1\. Function argument
# Type
```
boolToString :: bool -> string
```
*/
boolToString = b: if b then "true" else "false";
/**
Merge two attribute sets shallowly, right side trumps left
mergeAttrs :: attrs -> attrs -> attrs
# Inputs
`x`
: Left attribute set
`y`
: Right attribute set (higher precedence for equal keys)
# Examples
:::{.example}
## `lib.trivial.mergeAttrs` usage example
```nix
mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
=> { a = 1; b = 3; c = 4; }
```
:::
*/
mergeAttrs =
x:
y: x // y;
/**
Flip the order of the arguments of a binary function.
# Inputs
`f`
: 1\. Function argument
`a`
: 2\. Function argument
`b`
: 3\. Function argument
# Type
```
flip :: (a -> b -> c) -> (b -> a -> c)
```
# Examples
:::{.example}
## `lib.trivial.flip` usage example
```nix
flip concat [1] [2]
=> [ 2 1 ]
```
:::
*/
flip = f: a: b: f b a;
/**
Apply function if the supplied argument is non-null.
# Inputs
`f`
: Function to call
`a`
: Argument to check for null before passing it to `f`
# Examples
:::{.example}
## `lib.trivial.mapNullable` usage example
```nix
mapNullable (x: x+1) null
=> null
mapNullable (x: x+1) 22
=> 23
```
:::
*/
mapNullable =
f:
a: if a == null then a else f a;
in
{
loadStatic = loadStatic;
foldr = foldr;
reverseList = reverseList;
isFunction = isFunction;
functionArgs = functionArgs;
setFunctionArgs = setFunctionArgs;
warn = warn;
throwIfNot = throwIfNot;
id = id;
const = const;
pipe = pipe;
concat = concat;
logicalOr = logicalOr; # cant use "or" directly because it's a keyword
and = and;
xor = xor;
bitNot = bitNot;
boolToString = boolToString;
mergeAttrs = mergeAttrs;
flip = flip;
mapNullable = mapNullable;
}

View file

@ -0,0 +1,19 @@
let # internal lib dependencies
foundation = import ./1_foundation.nix;
in
# e.g. the root of the node
foundation.loadStatic ../../.
# will end up being an object like this:
# {
# setup = {
# release = "";
# sourceTypes = { ...};
# licenses = { ... };
# maintainers = [ ... ];
# teams = { ... };
# };
# meta = {
# minNixVersion = "2.3";
# generatedBy = "";
# };
# }

View file

@ -0,0 +1,321 @@
let # internal lib dependencies
foundation = import ./1_foundation.nix;
in
let
/*
`fix f` computes the fixed point of the given function `f`. In other words, the return value is `x` in `x = f x`.
`f` must be a lazy function.
This means that `x` must be a value that can be partially evaluated,
such as an attribute set, a list, or a function.
This way, `f` can use one part of `x` to compute another part.
**Relation to syntactic recursion**
This section explains `fix` by refactoring from syntactic recursion to a call of `fix` instead.
For context, Nix lets you define attributes in terms of other attributes syntactically using the [`rec { }` syntax](https://nixos.org/manual/nix/stable/language/constructs.html#recursive-sets).
```nix
nix-repl> rec {
foo = "foo";
bar = "bar";
foobar = foo + bar;
}
{ bar = "bar"; foo = "foo"; foobar = "foobar"; }
```
This is convenient when constructing a value to pass to a function for example,
but an equivalent effect can be achieved with the `let` binding syntax:
```nix
nix-repl> let self = {
foo = "foo";
bar = "bar";
foobar = self.foo + self.bar;
}; in self
{ bar = "bar"; foo = "foo"; foobar = "foobar"; }
```
But in general you can get more reuse out of `let` bindings by refactoring them to a function.
```nix
nix-repl> f = self: {
foo = "foo";
bar = "bar";
foobar = self.foo + self.bar;
}
```
This is where `fix` comes in, it contains the syntactic recursion that's not in `f` anymore.
```nix
nix-repl> fix = f:
let self = f self; in self;
```
By applying `fix` we get the final result.
```nix
nix-repl> fix f
{ bar = "bar"; foo = "foo"; foobar = "foobar"; }
```
Such a refactored `f` using `fix` is not useful by itself.
See [`extends`](#function-library-lib.fixedPoints.extends) for an example use case.
There `self` is also often called `final`.
Type: fix :: (a -> a) -> a
Example:
fix (self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; })
=> { bar = "bar"; foo = "foo"; foobar = "foobar"; }
fix (self: [ 1 2 (elemAt self 0 + elemAt self 1) ])
=> [ 1 2 3 ]
*/
fix = f: let x = f x; in x;
/*
A variant of `fix` that records the original recursive attribute set in the
result, in an attribute named `__unfix__`.
This is useful in combination with the `extends` function to
implement deep overriding.
*/
fix' = f: let x = f x // { __unfix__ = f; }; in x;
/*
Return the fixpoint that `f` converges to when called iteratively, starting
with the input `x`.
```
nix-repl> converge (x: x / 2) 16
0
```
Type: (a -> a) -> a -> a
*/
converge = f: x:
let
x' = f x;
in
if x' == x
then x
else converge f x';
/*
Extend a function using an overlay.
Overlays allow modifying and extending fixed-point functions, specifically ones returning attribute sets.
A fixed-point function is a function which is intended to be evaluated by passing the result of itself as the argument.
This is possible due to Nix's lazy evaluation.
A fixed-point function returning an attribute set has the form
```nix
final: { # attributes }
```
where `final` refers to the lazily evaluated attribute set returned by the fixed-point function.
An overlay to such a fixed-point function has the form
```nix
final: prev: { # attributes }
```
where `prev` refers to the result of the original function to `final`, and `final` is the result of the composition of the overlay and the original function.
Applying an overlay is done with `extends`:
```nix
let
f = final: { # attributes };
overlay = final: prev: { # attributes };
in extends overlay f;
```
To get the value of `final`, use `lib.fix`:
```nix
let
f = final: { # attributes };
overlay = final: prev: { # attributes };
g = extends overlay f;
in fix g
```
:::{.note}
The argument to the given fixed-point function after applying an overlay will *not* refer to its own return value, but rather to the value after evaluating the overlay function.
The given fixed-point function is called with a separate argument than if it was evaluated with `lib.fix`.
:::
:::{.example}
# Extend a fixed-point function with an overlay
Define a fixed-point function `f` that expects its own output as the argument `final`:
```nix-repl
f = final: {
# Constant value a
a = 1;
# b depends on the final value of a, available as final.a
b = final.a + 2;
}
```
Evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) to get the final result:
```nix-repl
fix f
=> { a = 1; b = 3; }
```
An overlay represents a modification or extension of such a fixed-point function.
Here's an example of an overlay:
```nix-repl
overlay = final: prev: {
# Modify the previous value of a, available as prev.a
a = prev.a + 10;
# Extend the attribute set with c, letting it depend on the final values of a and b
c = final.a + final.b;
}
```
Use `extends overlay f` to apply the overlay to the fixed-point function `f`.
This produces a new fixed-point function `g` with the combined behavior of `f` and `overlay`:
```nix-repl
g = extends overlay f
```
The result is a function, so we can't print it directly, but it's the same as:
```nix-repl
g' = final: {
# The constant from f, but changed with the overlay
a = 1 + 10;
# Unchanged from f
b = final.a + 2;
# Extended in the overlay
c = final.a + final.b;
}
```
Evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) again to get the final result:
```nix-repl
fix g
=> { a = 11; b = 13; c = 24; }
```
:::
Type:
extends :: (Attrs -> Attrs -> Attrs) # The overlay to apply to the fixed-point function
-> (Attrs -> Attrs) # A fixed-point function
-> (Attrs -> Attrs) # The resulting fixed-point function
Example:
f = final: { a = 1; b = final.a + 2; }
fix f
=> { a = 1; b = 3; }
fix (extends (final: prev: { a = prev.a + 10; }) f)
=> { a = 11; b = 13; }
fix (extends (final: prev: { b = final.a + 5; }) f)
=> { a = 1; b = 6; }
fix (extends (final: prev: { c = final.a + final.b; }) f)
=> { a = 1; b = 3; c = 4; }
*/
extends =
# The overlay to apply to the fixed-point function
overlay:
# The fixed-point function
f:
# Wrap with parenthesis to prevent nixdoc from rendering the `final` argument in the documentation
# The result should be thought of as a function, the argument of that function is not an argument to `extends` itself
(
final:
let
prev = f final;
in
prev // overlay final prev
);
/*
Compose two extending functions of the type expected by 'extends'
into one where changes made in the first are available in the
'super' of the second
*/
composeExtensions =
f: g: final: prev:
let fApplied = f final prev;
prev' = prev // fApplied;
in fApplied // g final prev';
/*
Compose several extending functions of the type expected by 'extends' into
one where changes made in preceding functions are made available to
subsequent ones.
```
composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
^final ^prev ^overrides ^final ^prev ^overrides
```
*/
composeManyExtensions =
foundation.foldr (x: y: composeExtensions x y) (final: prev: {});
/*
Same as `makeExtensible` but the name of the extending attribute is
customized.
*/
makeExtensibleWithCustomName = extenderName: rattrs:
fix' (self: (rattrs self) // {
${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);
});
/*
Create an overridable, recursive attribute set. For example:
```
nix-repl> obj = makeExtensible (self: { })
nix-repl> obj
{ __unfix__ = «lambda»; extend = «lambda»; }
nix-repl> obj = obj.extend (self: super: { foo = "foo"; })
nix-repl> obj
{ __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; }
nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; })
nix-repl> obj
{ __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
```
*/
makeExtensible = makeExtensibleWithCustomName "extend";
in
{
fix = fix;
fix' = fix';
converge = converge;
extends = extends;
composeExtensions = composeExtensions;
composeManyExtensions = composeManyExtensions;
makeExtensibleWithCustomName = makeExtensibleWithCustomName;
makeExtensible = makeExtensible;
}

View file

@ -0,0 +1,593 @@
let
foundation = import ./detangled/1_foundation.nix;
static = import ./detangled/2_static.nix;
# FIXME: this file is currently broken because it depends on the following:
# lib.pathIsGitRepo
# lib.commitIdFromGitRepo
# lib.fileContents
# lib.subtractLists
# lib.concatMapStrings
in
let
isFunction = foundation.isFunction;
functionArgs = foundation.functionArgs;
in {
# Pull in some builtins for backwards compatibility (ideally would be deprecated and people would use lib.builtins.THING)
pathExists = builtins.pathExists;
readFile = builtins.readFile;
isBool = builtins.isBool;
isInt = builtins.isInt;
isFloat = builtins.isFloat;
add = builtins.add;
sub = builtins.sub;
lessThan = builtins.lessThan;
seq = builtins.seq;
deepSeq = builtins.deepSeq;
genericClosure = builtins.genericClosure;
bitAnd = builtins.bitAnd;
bitOr = builtins.bitOr;
bitXor = builtins.bitXor;
# static stuff
release = static.setup.release;
codeName = static.setup.codeName;
versionSuffix = static.setup.versionSuffix;
oldestSupportedRelease = static.setup.oldestSupportedRelease;
version = static.setup.release + static.setup.versionSuffix;
# helpers that are from foundation
functionArgs = foundation.functionArgs;
isFunction = foundation.isFunction;
setFunctionArgs = foundation.setFunctionArgs;
warn = foundation.warn;
throwIfNot = foundation.throwIfNot;
id = foundation.id;
const = foundation.const;
pipe = foundation.pipe;
concat = foundation.concat;
and = foundation.and;
xor = foundation.xor;
bitNot = foundation.bitNot;
boolToString = foundation.boolToString;
mergeAttrs = foundation.mergeAttrs;
flip = foundation.flip;
mapNullable = foundation.mapNullable;
or = foundation.logicalOr; # different name mapping because of "or" being a keyword
/**
Whether a feature is supported in all supported releases (at the time of
release branch-off, if applicable). See `oldestSupportedRelease`.
# Inputs
`release`
: Release number of feature introduction as an integer, e.g. 2111 for 21.11.
Set it to the upcoming release, matching the nixpkgs/.version file.
*/
isInOldestRelease =
release:
release <= static.setup.oldestSupportedRelease;
/**
Attempts to return the the current revision of nixpkgs and
returns the supplied default value otherwise.
# Inputs
`default`
: Default value to return if revision can not be determined
# Type
```
revisionWithDefault :: string -> string
```
*/
revisionWithDefault =
default:
let
revisionFile = "${toString ./..}/.git-revision";
gitRepo = "${toString ./..}/.git";
in if lib.pathIsGitRepo gitRepo
then lib.commitIdFromGitRepo gitRepo
else if builtins.pathExists revisionFile then lib.fileContents revisionFile
else default;
nixpkgsVersion = foundation.warn "lib.nixpkgsVersion is a deprecated alias of lib.version." (static.setup.release + static.setup.versionSuffix);
/**
Determine whether the function is being called from inside a Nix
shell.
# Type
```
inNixShell :: bool
```
*/
inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
/**
Determine whether the function is being called from inside pure-eval mode
by seeing whether `builtins` contains `currentSystem`. If not, we must be in
pure-eval mode.
# Type
```
inPureEvalMode :: bool
```
*/
inPureEvalMode = ! builtins ? currentSystem;
## Integer operations
/**
Return minimum of two numbers.
# Inputs
`x`
: 1\. Function argument
`y`
: 2\. Function argument
*/
min = x: y: if x < y then x else y;
/**
Return maximum of two numbers.
# Inputs
`x`
: 1\. Function argument
`y`
: 2\. Function argument
*/
max = x: y: if x > y then x else y;
/**
Integer modulus
# Inputs
`base`
: 1\. Function argument
`int`
: 2\. Function argument
# Examples
:::{.example}
## `lib.trivial.mod` usage example
```nix
mod 11 10
=> 1
mod 1 10
=> 1
```
:::
*/
mod = base: int: base - (int * (builtins.div base int));
## Comparisons
/**
C-style comparisons
a < b, compare a b => -1
a == b, compare a b => 0
a > b, compare a b => 1
# Inputs
`a`
: 1\. Function argument
`b`
: 2\. Function argument
*/
compare = a: b:
if a < b
then -1
else if a > b
then 1
else 0;
/**
Split type into two subtypes by predicate `p`, take all elements
of the first subtype to be less than all the elements of the
second subtype, compare elements of a single subtype with `yes`
and `no` respectively.
# Inputs
`p`
: Predicate
`yes`
: Comparison function if predicate holds for both values
`no`
: Comparison function if predicate holds for neither value
`a`
: First value to compare
`b`
: Second value to compare
# Type
```
(a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
```
# Examples
:::{.example}
## `lib.trivial.splitByAndCompare` usage example
```nix
let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
cmp "a" "z" => -1
cmp "fooa" "fooz" => -1
cmp "f" "a" => 1
cmp "fooa" "a" => -1
# while
compare "fooa" "a" => 1
```
:::
*/
splitByAndCompare =
p: yes: no: a: b:
if p a
then if p b then yes a b else -1
else if p b then 1 else no a b;
/**
Reads a JSON file.
# Inputs
`path`
: 1\. Function argument
# Type
```
importJSON :: path -> any
```
*/
importJSON = path:
builtins.fromJSON (builtins.readFile path);
/**
Reads a TOML file.
# Inputs
`path`
: 1\. Function argument
# Type
```
importTOML :: path -> any
```
*/
importTOML = path:
builtins.fromTOML (builtins.readFile path);
## Warnings
/**
Like warn, but only warn when the first argument is `true`.
# Inputs
`cond`
: 1\. Function argument
`msg`
: 2\. Function argument
`val`
: Value to return as-is.
# Type
```
bool -> string -> a -> a
```
*/
warnIf = cond: msg: if cond then warn msg else x: x;
/**
Like warnIf, but negated (warn if the first argument is `false`).
# Inputs
`cond`
: 1\. Function argument
`msg`
: 2\. Function argument
`val`
: Value to return as-is.
# Type
```
bool -> string -> a -> a
```
*/
warnIfNot = cond: msg: if cond then x: x else warn msg;
/**
Like throwIfNot, but negated (throw if the first argument is `true`).
# Inputs
`cond`
: 1\. Function argument
`msg`
: 2\. Function argument
# Type
```
bool -> string -> a -> a
```
*/
throwIf = cond: msg: if cond then throw msg else x: x;
/**
Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
# Inputs
`msg`
: 1\. Function argument
`valid`
: 2\. Function argument
`given`
: 3\. Function argument
# Type
```
String -> List ComparableVal -> List ComparableVal -> a -> a
```
# Examples
:::{.example}
## `lib.trivial.checkListOfEnum` usage example
```nix
let colorVariants = ["bright" "dark" "black"]
in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants;
=>
error: color variants: bright, black unexpected; valid ones: standard, light, dark
```
:::
*/
checkListOfEnum = msg: valid: given:
let
unexpected = lib.subtractLists valid given;
in
foundation.throwIfNot (unexpected == [])
"${msg}: ${builtins.concatStringsSep ", " (builtins.map builtins.toString unexpected)} unexpected; valid ones: ${builtins.concatStringsSep ", " (builtins.map builtins.toString valid)}";
info = msg: builtins.trace "INFO: ${msg}";
showWarnings = warnings: res: foundation.foldr (w: x: warn w x) res warnings;
## Function annotations
/**
`mirrorFunctionArgs f g` creates a new function `g'` with the same behavior as `g` (`g' x == g x`)
but its function arguments mirroring `f` (`lib.functionArgs g' == lib.functionArgs f`).
# Inputs
`f`
: Function to provide the argument metadata
`g`
: Function to set the argument metadata to
# Type
```
mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c)
```
# Examples
:::{.example}
## `lib.trivial.mirrorFunctionArgs` usage example
```nix
addab = {a, b}: a + b
addab { a = 2; b = 4; }
=> 6
lib.functionArgs addab
=> { a = false; b = false; }
addab1 = attrs: addab attrs + 1
addab1 { a = 2; b = 4; }
=> 7
lib.functionArgs addab1
=> { }
addab1' = lib.mirrorFunctionArgs addab addab1
addab1' { a = 2; b = 4; }
=> 7
lib.functionArgs addab1'
=> { a = false; b = false; }
```
:::
*/
mirrorFunctionArgs =
f:
let
fArgs = foundation.functionArgs f;
in
g:
foundation.setFunctionArgs g fArgs;
/**
Turns any non-callable values into constant functions.
Returns callable values as is.
# Inputs
`v`
: Any value
# Examples
:::{.example}
## `lib.trivial.toFunction` usage example
```nix
nix-repl> lib.toFunction 1 2
1
nix-repl> lib.toFunction (x: x + 1) 2
3
```
:::
*/
toFunction =
v:
if foundation.isFunction v
then v
else k: v;
/**
`toBaseDigits base i` converts the positive integer i to a list of its
digits in the given base. For example:
toBaseDigits 10 123 => [ 1 2 3 ]
toBaseDigits 2 6 => [ 1 1 0 ]
toBaseDigits 16 250 => [ 15 10 ]
# Inputs
`base`
: 1\. Function argument
`i`
: 2\. Function argument
*/
toBaseDigits = base: i:
let
go = i:
if i < base
then [i]
else
let
r = i - ((i / base) * base);
q = (i - r) / base;
in
[r] ++ go q;
in
assert (builtin.isInt base);
assert (builtin.isInt i);
assert (base >= 2);
assert (i >= 0);
foundation.reverseList (go i);
/**
Convert the given positive integer to a string of its hexadecimal
representation. For example:
toHexString 0 => "0"
toHexString 16 => "10"
toHexString 250 => "FA"
*/
toHexString = let
hexDigits = {
"10" = "A";
"11" = "B";
"12" = "C";
"13" = "D";
"14" = "E";
"15" = "F";
};
toHexDigit = d:
if d < 10
then toString d
else hexDigits.${toString d};
in i: lib.concatMapStrings toHexDigit (toBaseDigits 16 i);
}

View file

@ -8,6 +8,7 @@
# derivation like fetchurl is allowed to do so since its result is
# by definition pure.
"http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy"
"HTTP_PROXY" "HTTPS_PROXY" "FTP_PROXY" "ALL_PROXY" "NO_PROXY"
];
}

View file

@ -8,6 +8,7 @@
# [nixpkgs]$ lib/fileset/tests.sh
# or:
# [nixpkgs]$ nix-build lib/tests/release.nix
set -euo pipefail
shopt -s inherit_errexit dotglob

View file

@ -0,0 +1,22 @@
{ lib }:
rec {
/* imports a flake.nix without acknowledging its lock file, useful for
referencing subflakes from a parent flake. The second argument allows
specifying the inputs of this flake.
Example:
callLocklessFlake {
path = ./directoryContainingFlake;
inputs = { inherit nixpkgs; };
}
*/
callLocklessFlake = { path, inputs ? { } }:
let
self = { outPath = path; } //
((import (path + "/flake.nix")).outputs (inputs // { self = self; }));
in
self;
}

View file

@ -53,6 +53,53 @@ rec {
inherit type isGVariant;
intConstructors = [
{
name = "mkInt32";
type = type.int32;
min = -2147483648;
max = 2147483647;
}
{
name = "mkUint32";
type = type.uint32;
min = 0;
max = 4294967295;
}
{
name = "mkInt64";
type = type.int64;
# Nix does not support such large numbers.
min = null;
max = null;
}
{
name = "mkUint64";
type = type.uint64;
min = 0;
# Nix does not support such large numbers.
max = null;
}
{
name = "mkInt16";
type = type.int16;
min = -32768;
max = 32767;
}
{
name = "mkUint16";
type = type.uint16;
min = 0;
max = 65535;
}
{
name = "mkUchar";
type = type.uchar;
min = 0;
max = 255;
}
];
/* Returns the GVariant value that most closely matches the given Nix value.
If no GVariant value can be found unambiguously then error is thrown.
@ -70,8 +117,20 @@ rec {
mkArray v
else if isGVariant v then
v
else if builtins.isInt v then
let
validConstructors = builtins.filter ({ min, max, ... }: (min == null || min <= v) && (max == null || v <= max)) intConstructors;
in
throw ''
The GVariant type for number ${builtins.toString v} is unclear.
Please wrap the value with one of the following, depending on the value type in GSettings schema:
${lib.concatMapStringsSep "\n" ({ name, type, ...}: "- `lib.gvariant.${name}` for `${type}`") validConstructors}
''
else if builtins.isAttrs v then
throw "Cannot construct GVariant value from an attribute set. If you want to construct a dictionary, you will need to create an array containing items constructed with `lib.gvariant.mkDictionaryEntry`."
else
throw "The GVariant type of ${v} can't be inferred.";
throw "The GVariant type of ${builtins.typeOf v} can't be inferred.";
/* Returns the GVariant array from the given type of the elements and a Nix list.

View file

@ -397,8 +397,6 @@ rec {
if ! isString text then throw "literalExpression expects a string."
else { _type = "literalExpression"; inherit text; };
literalExample = lib.warn "lib.literalExample is deprecated, use lib.literalExpression instead, or use lib.literalMD for a non-Nix description." literalExpression;
/* Transition marker for documentation that's already migrated to markdown
syntax. Has been a no-op for some while and been removed from nixpkgs.
Kept here to alert downstream users who may not be aware of the migration's

View file

@ -81,6 +81,8 @@ let
&& final.parsed.kernel == platform.parsed.kernel;
isCompatible = _: throw "2022-05-23: isCompatible has been removed in favor of canExecute, refer to the 22.11 changelog for details";
# Derived meta-data
useLLVM = final.isFreeBSD;
libc =
/**/ if final.isDarwin then "libSystem"
else if final.isMinGW then "msvcrt"

View file

@ -13,7 +13,7 @@ let
"x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin"
# FreeBSD
"i686-freebsd13" "x86_64-freebsd13"
"i686-freebsd" "x86_64-freebsd"
# Genode
"aarch64-genode" "i686-genode" "x86_64-genode"

View file

@ -328,7 +328,7 @@ rec {
# BSDs
x86_64-freebsd = {
config = "x86_64-unknown-freebsd13";
config = "x86_64-unknown-freebsd";
useLLVM = true;
};

View file

@ -326,11 +326,7 @@ rec {
# the normalized name for macOS.
macos = { execFormat = macho; families = { inherit darwin; }; name = "darwin"; };
ios = { execFormat = macho; families = { inherit darwin; }; };
# A tricky thing about FreeBSD is that there is no stable ABI across
# versions. That means that putting in the version as part of the
# config string is paramount.
freebsd12 = { execFormat = elf; families = { inherit bsd; }; name = "freebsd"; version = 12; };
freebsd13 = { execFormat = elf; families = { inherit bsd; }; name = "freebsd"; version = 13; };
freebsd = { execFormat = elf; families = { inherit bsd; }; name = "freebsd"; };
linux = { execFormat = elf; families = { }; };
netbsd = { execFormat = elf; families = { inherit bsd; }; };
none = { execFormat = unknown; families = { }; };

View file

@ -0,0 +1,26 @@
# Supported systems according to RFC0046's definition.
#
# https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md
{ lib }:
rec {
# List of systems that are built by Hydra.
hydra = tier1 ++ tier2 ++ tier3 ++ [
"aarch64-darwin"
];
tier1 = [
"x86_64-linux"
];
tier2 = [
"aarch64-linux"
"x86_64-darwin"
];
tier3 = [
"armv6l-linux"
"armv7l-linux"
"i686-linux"
"mipsel-linux"
];
}

View file

@ -0,0 +1,8 @@
{
outputs = { self, subflake, callLocklessFlake }: rec {
x = (callLocklessFlake {
path = subflake;
inputs = {};
}).subflakeOutput;
};
}

View file

@ -0,0 +1,5 @@
{
outputs = { self }: {
subflakeOutput = 1;
};
}

View file

@ -432,7 +432,6 @@ runTests {
"${builtins.storeDir}/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11";
in {
storePath = isStorePath goodPath;
# storePathDerivation = isStorePath (import ../.. { system = "x86_64-linux"; }).hello;
storePathAppendix = isStorePath
"${goodPath}/bin/python";
nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath)));
@ -446,7 +445,6 @@ runTests {
};
expected = {
storePath = true;
# storePathDerivation = true;
storePathAppendix = false;
nonAbsolute = false;
asPath = true;
@ -506,11 +504,6 @@ runTests {
expected = true;
};
# testHasInfixDerivation = {
# expr = hasInfix "hello" (import ../.. { system = "x86_64-linux"; }).hello;
# expected = true;
# };
testHasInfixPath = {
expr = hasInfix "tests" ./.;
expected = true;

Some files were not shown because too many files have changed in this diff Show more