Skip to content

Commit

Permalink
Merge remote-tracking branch 'other/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] committed Sep 15, 2024
2 parents 68584f8 + 6fa704d commit 9db4db0
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 49 deletions.
3 changes: 3 additions & 0 deletions lib/fetchers.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
# by definition pure.
"http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy"
"HTTP_PROXY" "HTTPS_PROXY" "FTP_PROXY" "ALL_PROXY" "NO_PROXY"

# https proxies typically need to inject custom root CAs too
"NIX_SSL_CERT_FILE"
];

}
138 changes: 91 additions & 47 deletions lib/fixed-points.nix
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ rec {
See [`extends`](#function-library-lib.fixedPoints.extends) for an example use case.
There `self` is also often called `final`.
# Inputs
`f`
Expand All @@ -90,7 +89,12 @@ rec {
:::
*/
fix = f: let x = f x; in x;
fix =
f:
let
x = f x;
in
x;

/**
A variant of `fix` that records the original recursive attribute set in the
Expand All @@ -99,14 +103,20 @@ rec {
This is useful in combination with the `extends` function to
implement deep overriding.
# Inputs
`f`
: 1\. Function argument
*/
fix' = f: let x = f x // { __unfix__ = f; }; in x;
fix' =
f:
let
x = f x // {
__unfix__ = f;
};
in
x;

/**
Return the fixpoint that `f` converges to when called iteratively, starting
Expand All @@ -117,7 +127,6 @@ rec {
0
```
# Inputs
`f`
Expand All @@ -134,13 +143,12 @@ rec {
(a -> a) -> a -> a
```
*/
converge = f: x:
converge =
f: x:
let
x' = f x;
in
if x' == x
then x
else converge f x';
if x' == x then x else converge f x';

/**
Extend a function using an overlay.
Expand All @@ -149,7 +157,6 @@ rec {
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
Expand Down Expand Up @@ -257,7 +264,6 @@ rec {
```
:::
# Inputs
`overlay`
Expand Down Expand Up @@ -299,8 +305,7 @@ rec {
:::
*/
extends =
overlay:
f:
overlay: f:
# The result should be thought of as a function, the argument of that function is not an argument to `extends` itself
(
final:
Expand All @@ -311,63 +316,98 @@ rec {
);

/**
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
Compose two overlay functions and return a single overlay function that combines them.
For more details see: [composeManyExtensions](#function-library-lib.fixedPoints.composeManyExtensions).
*/
composeExtensions =
f: g: final: prev:
let
fApplied = f final prev;
prev' = prev // fApplied;
in
fApplied // g final prev';

/**
Composes a list of [`overlays`](#chap-overlays) and returns a single overlay function that combines them.
:::{.note}
The result is produced by using the update operator `//`.
This means nested values of previous overlays are not merged recursively.
In other words, previously defined attributes are replaced, ignoring the previous value, unless referenced by the overlay; for example `final: prev: { foo = final.foo + 1; }`.
:::
# Inputs
`f`
`extensions`
: 1\. Function argument
: A list of overlay functions
:::{.note}
The order of the overlays in the list is important.
:::
`g`
: Each overlay function takes two arguments, by convention `final` and `prev`, and returns an attribute set.
- `final` is the result of the fixed-point function, with all overlays applied.
- `prev` is the result of the previous overlay function(s).
: 2\. Function argument
# Type
`final`
```
# Pseudo code
let
# final prev
# ↓ ↓
OverlayFn = { ... } -> { ... } -> { ... };
in
composeManyExtensions :: ListOf OverlayFn -> OverlayFn
```
: 3\. Function argument
# Examples
:::{.example}
## `lib.fixedPoints.composeManyExtensions` usage example
```nix
let
# The "original function" that is extended by the overlays.
# Note that it doesn't have prev: as argument since no overlay function precedes it.
original = final: { a = 1; };
`prev`
# Each overlay function has 'final' and 'prev' as arguments.
overlayA = final: prev: { b = final.c; c = 3; };
overlayB = final: prev: { c = 10; x = prev.c or 5; };
: 4\. Function argument
*/
composeExtensions =
f: g: final: prev:
let fApplied = f final prev;
prev' = prev // fApplied;
in fApplied // g final prev';
extensions = composeManyExtensions [ overlayA overlayB ];
/**
Compose several extending functions of the type expected by 'extends' into
one where changes made in preceding functions are made available to
subsequent ones.
# Caluculate the fixed point of all composed overlays.
fixedpoint = lib.fix (lib.extends extensions original );
in fixedpoint
=>
{
a = 1;
b = 10;
c = 10;
x = 3;
}
```
composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
^final ^prev ^overrides ^final ^prev ^overrides
```
:::
*/
composeManyExtensions =
lib.foldr (x: y: composeExtensions x y) (final: prev: {});
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 = makeExtensible (final: { })
nix-repl> obj
{ __unfix__ = «lambda»; extend = «lambda»; }
nix-repl> obj = obj.extend (self: super: { foo = "foo"; })
nix-repl> obj = obj.extend (final: prev: { 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 = obj.extend (final: prev: { foo = prev.foo + " + "; bar = "bar"; foobar = final.foo + final.bar; })
nix-repl> obj
{ __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
Expand All @@ -379,7 +419,6 @@ rec {
Same as `makeExtensible` but the name of the extending attribute is
customized.
# Inputs
`extenderName`
Expand All @@ -390,8 +429,13 @@ rec {
: 2\. Function argument
*/
makeExtensibleWithCustomName = extenderName: rattrs:
fix' (self: (rattrs self) // {
${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);
});
makeExtensibleWithCustomName =
extenderName: rattrs:
fix' (
self:
(rattrs self)
// {
${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);
}
);
}
7 changes: 7 additions & 0 deletions lib/licenses.nix
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,13 @@ lib.mapAttrs mkLicense ({
redistributable = true;
};

fsl11Asl20 = {
fullName = "Functional Source License, Version 1.1, Apache 2.0 Future License";
url = "https://fsl.software/FSL-1.1-Apache-2.0.template.md";
free = false;
redistributable = true;
};

ftl = {
spdxId = "FTL";
fullName = "Freetype Project License";
Expand Down
5 changes: 4 additions & 1 deletion lib/systems/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,11 @@ let
};
wine = (pkgs.winePackagesFor "wine${toString final.parsed.cpu.bits}").minimal;
in
# Note: we guarantee that the return value is either `null` or a path
# to an emulator program. That is, if an emulator requires additional
# arguments, a wrapper should be used.
if pkgs.stdenv.hostPlatform.canExecute final
then "${pkgs.runtimeShell} -c '\"$@\"' --"
then "${pkgs.execline}/bin/exec"
else if final.isWindows
then "${wine}/bin/wine${optionalString (final.parsed.cpu.bits == 64) "64"}"
else if final.isLinux && pkgs.stdenv.hostPlatform.isLinux && final.qemuArch != null
Expand Down
3 changes: 3 additions & 0 deletions lib/tests/modules.sh
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ checkConfigOutput '^"42"$' config.value ./declare-coerced-value.nix
checkConfigOutput '^"24"$' config.value ./declare-coerced-value.nix ./define-value-string.nix
checkConfigError 'A definition for option .* is not.*string or signed integer convertible to it.*. Definition values:\n\s*- In .*: \[ \]' config.value ./declare-coerced-value.nix ./define-value-list.nix

# Check coerced option merging.
checkConfigError 'The option .value. in .*/declare-coerced-value.nix. is already declared in .*/declare-coerced-value-no-default.nix.' config.value ./declare-coerced-value.nix ./declare-coerced-value-no-default.nix

# Check coerced value with unsound coercion
checkConfigOutput '^12$' config.value ./declare-coerced-value-unsound.nix
checkConfigError 'A definition for option .* is not of type .*. Definition values:\n\s*- In .*: "1000"' config.value ./declare-coerced-value-unsound.nix ./define-value-string-bigint.nix
Expand Down
9 changes: 9 additions & 0 deletions lib/tests/modules/declare-coerced-value-no-default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{ lib, ... }:

{
options = {
value = lib.mkOption {
type = lib.types.coercedTo lib.types.int builtins.toString lib.types.str;
};
};
}
2 changes: 1 addition & 1 deletion lib/types.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,7 @@ rec {
getSubOptions = finalType.getSubOptions;
getSubModules = finalType.getSubModules;
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
typeMerge = t1: t2: null;
typeMerge = t: null;
functor = (defaultFunctor name) // { wrapped = finalType; };
nestedTypes.coercedType = coercedType;
nestedTypes.finalType = finalType;
Expand Down

0 comments on commit 9db4db0

Please sign in to comment.