Compare commits
38 commits
main
...
contributo
Author | SHA1 | Date | |
---|---|---|---|
dd6d59a04d | |||
cac07bdeee | |||
3b9a7b9277 | |||
5fc6685efe | |||
7916f50847 | |||
63c79d1b48 | |||
590b181303 | |||
a38922846e | |||
6ce2f22854 | |||
0911efe6d2 | |||
06688e3ab8 | |||
01b6beb111 | |||
427ad23000 | |||
2ca5e185ce | |||
e0f04630de | |||
9e3062a5d8 | |||
df3269bfeb | |||
1462db9587 | |||
2613fed53e | |||
415acdce94 | |||
a4c9fde3e9 | |||
9cb4ed1ffc | |||
11c40a8dcf | |||
97466d7f6d | |||
ab9110a43b | |||
68d28c7f95 | |||
f144947b81 | |||
e987e7b28b | |||
7dc5f8db8e | |||
8f0b52892c | |||
735f118b90 | |||
adff8800eb | |||
ff9633d02b | |||
acb415f94f | |||
040494bb21 | |||
3864986c18 | |||
91911cb438 | |||
4e14b7b16c |
28
default.nix
28
default.nix
|
@ -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
|
|
45
flake.nix
45
flake.nix
|
@ -1,46 +1,5 @@
|
||||||
{
|
{
|
||||||
outputs = { self, ... }:
|
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}; };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
171
lib/default.nix
171
lib/default.nix
|
@ -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
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
}
|
|
1312
lib/licenses.nix
1312
lib/licenses.nix
File diff suppressed because it is too large
Load diff
|
@ -1,2 +0,0 @@
|
||||||
# Expose the minimum required version for evaluating Nixpkgs
|
|
||||||
"2.3"
|
|
|
@ -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 = {};
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
List of Aux maintainers.
|
|
||||||
```nix
|
|
||||||
handle = {
|
|
||||||
# Required
|
|
||||||
name = "Your name";
|
|
||||||
forgejo = "forgejoUsername";
|
|
||||||
forgejoId = your-forgejo-id;
|
|
||||||
|
|
||||||
# Optional, but at least one of email or matrix must be given
|
|
||||||
email = "address@example.org";
|
|
||||||
matrix = "@user:example.org";
|
|
||||||
|
|
||||||
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,
|
|
||||||
- `forgejo` is your forgejo handle (as it appears in the URL of your profile page, `https://git.auxolotl.org/<userhandle>`),
|
|
||||||
- `forgejoId` is your forgejo user ID, which can be found at `https://git.auxolotl.org/api/v1/users/<username>`,
|
|
||||||
- `keys` is a list of your PGP/GPG key fingerprints.
|
|
||||||
|
|
||||||
`handle == forgejo` is strongly preferred whenever `forgejo` is an acceptable attribute name and is short and convenient.
|
|
||||||
|
|
||||||
If `forgejo` begins with a numeral, `handle` should be prefixed with an underscore.
|
|
||||||
```nix
|
|
||||||
_1example = {
|
|
||||||
forgejo = "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, please ensure that you have added yourself in alphabetical order of your handle.
|
|
||||||
*/
|
|
||||||
{ }
|
|
|
@ -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
459
nodes/1_lib/default.nix
Normal 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
19
nodes/1_lib/scripts/test
Executable 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.
|
||||||
|
|
||||||
|
[36;1mnull[0m'
|
||||||
|
|
||||||
|
if [ "$(echo "$result")" = "$expected" ]
|
||||||
|
then
|
||||||
|
echo test passed
|
||||||
|
else
|
||||||
|
echo "test failed"
|
||||||
|
echo "$result"
|
||||||
|
fi
|
|
@ -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`.
|
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:
|
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)
|
- [`tests`](tests): Tests, see [Running tests](#running-tests)
|
||||||
- [`release.nix`](tests/release.nix): A derivation aggregating all tests
|
- [`release.nix`](tests/release.nix): A derivation aggregating all tests
|
||||||
- [`misc.nix`](tests/misc.nix): Evaluation unit tests for most sub-libraries
|
- [`misc.nix`](tests/misc.nix): Evaluation unit tests for most sub-libraries
|
|
@ -2025,16 +2025,4 @@ rec {
|
||||||
intersection;
|
intersection;
|
||||||
in
|
in
|
||||||
(x // y) // mask;
|
(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;
|
|
||||||
}
|
}
|
1
nodes/1_lib/source/default.nix
Normal file
1
nodes/1_lib/source/default.nix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import ../. # just to help tests pass, evetually remove this file
|
374
nodes/1_lib/source/deprecated/misc.nix
Normal file
374
nodes/1_lib/source/deprecated/misc.nix
Normal 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
|
||||||
|
;
|
||||||
|
}
|
591
nodes/1_lib/source/detangled/1_foundation.nix
Normal file
591
nodes/1_lib/source/detangled/1_foundation.nix
Normal 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 "[1;31mwarning: ${msg}[0m" (builtins.abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
|
||||||
|
else msg: builtins.trace "[1;31mwarning: ${msg}[0m";
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 don’t 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, it’s 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;
|
||||||
|
}
|
19
nodes/1_lib/source/detangled/2_static.nix
Normal file
19
nodes/1_lib/source/detangled/2_static.nix
Normal 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 = "";
|
||||||
|
# };
|
||||||
|
# }
|
321
nodes/1_lib/source/detangled/3_fixed-points.nix
Normal file
321
nodes/1_lib/source/detangled/3_fixed-points.nix
Normal 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;
|
||||||
|
}
|
593
nodes/1_lib/source/detangled/WIP_trivial.nix
Normal file
593
nodes/1_lib/source/detangled/WIP_trivial.nix
Normal 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);
|
||||||
|
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
# derivation like fetchurl is allowed to do so since its result is
|
# derivation like fetchurl is allowed to do so since its result is
|
||||||
# by definition pure.
|
# by definition pure.
|
||||||
"http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy"
|
"http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy"
|
||||||
|
"HTTP_PROXY" "HTTPS_PROXY" "FTP_PROXY" "ALL_PROXY" "NO_PROXY"
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
# [nixpkgs]$ lib/fileset/tests.sh
|
# [nixpkgs]$ lib/fileset/tests.sh
|
||||||
# or:
|
# or:
|
||||||
# [nixpkgs]$ nix-build lib/tests/release.nix
|
# [nixpkgs]$ nix-build lib/tests/release.nix
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
shopt -s inherit_errexit dotglob
|
shopt -s inherit_errexit dotglob
|
||||||
|
|
22
nodes/1_lib/source/flakes.nix
Normal file
22
nodes/1_lib/source/flakes.nix
Normal 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;
|
||||||
|
|
||||||
|
}
|
|
@ -53,6 +53,53 @@ rec {
|
||||||
|
|
||||||
inherit type isGVariant;
|
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.
|
/* Returns the GVariant value that most closely matches the given Nix value.
|
||||||
If no GVariant value can be found unambiguously then error is thrown.
|
If no GVariant value can be found unambiguously then error is thrown.
|
||||||
|
|
||||||
|
@ -70,8 +117,20 @@ rec {
|
||||||
mkArray v
|
mkArray v
|
||||||
else if isGVariant v then
|
else if isGVariant v then
|
||||||
v
|
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
|
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.
|
/* Returns the GVariant array from the given type of the elements and a Nix list.
|
||||||
|
|
|
@ -397,8 +397,6 @@ rec {
|
||||||
if ! isString text then throw "literalExpression expects a string."
|
if ! isString text then throw "literalExpression expects a string."
|
||||||
else { _type = "literalExpression"; inherit text; };
|
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
|
/* Transition marker for documentation that's already migrated to markdown
|
||||||
syntax. Has been a no-op for some while and been removed from nixpkgs.
|
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
|
Kept here to alert downstream users who may not be aware of the migration's
|
|
@ -81,6 +81,8 @@ let
|
||||||
&& final.parsed.kernel == platform.parsed.kernel;
|
&& 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";
|
isCompatible = _: throw "2022-05-23: isCompatible has been removed in favor of canExecute, refer to the 22.11 changelog for details";
|
||||||
# Derived meta-data
|
# Derived meta-data
|
||||||
|
useLLVM = final.isFreeBSD;
|
||||||
|
|
||||||
libc =
|
libc =
|
||||||
/**/ if final.isDarwin then "libSystem"
|
/**/ if final.isDarwin then "libSystem"
|
||||||
else if final.isMinGW then "msvcrt"
|
else if final.isMinGW then "msvcrt"
|
|
@ -13,7 +13,7 @@ let
|
||||||
"x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin"
|
"x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin"
|
||||||
|
|
||||||
# FreeBSD
|
# FreeBSD
|
||||||
"i686-freebsd13" "x86_64-freebsd13"
|
"i686-freebsd" "x86_64-freebsd"
|
||||||
|
|
||||||
# Genode
|
# Genode
|
||||||
"aarch64-genode" "i686-genode" "x86_64-genode"
|
"aarch64-genode" "i686-genode" "x86_64-genode"
|
|
@ -328,7 +328,7 @@ rec {
|
||||||
# BSDs
|
# BSDs
|
||||||
|
|
||||||
x86_64-freebsd = {
|
x86_64-freebsd = {
|
||||||
config = "x86_64-unknown-freebsd13";
|
config = "x86_64-unknown-freebsd";
|
||||||
useLLVM = true;
|
useLLVM = true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -326,11 +326,7 @@ rec {
|
||||||
# the normalized name for macOS.
|
# the normalized name for macOS.
|
||||||
macos = { execFormat = macho; families = { inherit darwin; }; name = "darwin"; };
|
macos = { execFormat = macho; families = { inherit darwin; }; name = "darwin"; };
|
||||||
ios = { execFormat = macho; families = { inherit darwin; }; };
|
ios = { execFormat = macho; families = { inherit darwin; }; };
|
||||||
# A tricky thing about FreeBSD is that there is no stable ABI across
|
freebsd = { execFormat = elf; families = { inherit bsd; }; name = "freebsd"; };
|
||||||
# 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; };
|
|
||||||
linux = { execFormat = elf; families = { }; };
|
linux = { execFormat = elf; families = { }; };
|
||||||
netbsd = { execFormat = elf; families = { inherit bsd; }; };
|
netbsd = { execFormat = elf; families = { inherit bsd; }; };
|
||||||
none = { execFormat = unknown; families = { }; };
|
none = { execFormat = unknown; families = { }; };
|
26
nodes/1_lib/source/systems/supported.nix
Normal file
26
nodes/1_lib/source/systems/supported.nix
Normal 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"
|
||||||
|
];
|
||||||
|
}
|
8
nodes/1_lib/source/tests/flakes/subflakeTest/flake.nix
Normal file
8
nodes/1_lib/source/tests/flakes/subflakeTest/flake.nix
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
outputs = { self, subflake, callLocklessFlake }: rec {
|
||||||
|
x = (callLocklessFlake {
|
||||||
|
path = subflake;
|
||||||
|
inputs = {};
|
||||||
|
}).subflakeOutput;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
outputs = { self }: {
|
||||||
|
subflakeOutput = 1;
|
||||||
|
};
|
||||||
|
}
|
|
@ -432,7 +432,6 @@ runTests {
|
||||||
"${builtins.storeDir}/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11";
|
"${builtins.storeDir}/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11";
|
||||||
in {
|
in {
|
||||||
storePath = isStorePath goodPath;
|
storePath = isStorePath goodPath;
|
||||||
# storePathDerivation = isStorePath (import ../.. { system = "x86_64-linux"; }).hello;
|
|
||||||
storePathAppendix = isStorePath
|
storePathAppendix = isStorePath
|
||||||
"${goodPath}/bin/python";
|
"${goodPath}/bin/python";
|
||||||
nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath)));
|
nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath)));
|
||||||
|
@ -446,7 +445,6 @@ runTests {
|
||||||
};
|
};
|
||||||
expected = {
|
expected = {
|
||||||
storePath = true;
|
storePath = true;
|
||||||
# storePathDerivation = true;
|
|
||||||
storePathAppendix = false;
|
storePathAppendix = false;
|
||||||
nonAbsolute = false;
|
nonAbsolute = false;
|
||||||
asPath = true;
|
asPath = true;
|
||||||
|
@ -506,11 +504,6 @@ runTests {
|
||||||
expected = true;
|
expected = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
# testHasInfixDerivation = {
|
|
||||||
# expr = hasInfix "hello" (import ../.. { system = "x86_64-linux"; }).hello;
|
|
||||||
# expected = true;
|
|
||||||
# };
|
|
||||||
|
|
||||||
testHasInfixPath = {
|
testHasInfixPath = {
|
||||||
expr = hasInfix "tests" ./.;
|
expr = hasInfix "tests" ./.;
|
||||||
expected = true;
|
expected = true;
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue