mirror of
https://github.com/hercules-ci/flake-parts.git
synced 2025-04-09 02:24:01 +00:00
Merge 1e37f1e031
into c9afaba3df
This commit is contained in:
commit
2ddff2953b
10 changed files with 364 additions and 121 deletions
|
@ -1,6 +1,10 @@
|
|||
|
||||
# Separate `dev` flake
|
||||
|
||||
Wouldn't recommend this pattern normally, but I'm trying to keep
|
||||
deps low for `flake-parts` until we have split dev inputs
|
||||
that don't carry over to dependent lock files.
|
||||
|
||||
```sh
|
||||
nix develop --impure -f './dev' 'mySystem.devShells.default'
|
||||
nix repl -f './dev'
|
||||
```
|
||||
|
|
|
@ -1,16 +1,36 @@
|
|||
let
|
||||
flake-parts = builtins.getFlake (toString ../.);
|
||||
lib = flake-parts.inputs.nixpkgs-lib.lib;
|
||||
sourceInfo = inputs.flake-parts.sourceInfo; # used by pre-commit module, etc
|
||||
flake = builtins.getFlake (toString ./.);
|
||||
fmc-lib = (builtins.getFlake (toString ../.)).lib;
|
||||
args = {
|
||||
inherit self;
|
||||
} // flake.inputs;
|
||||
self = {
|
||||
inherit (flake) inputs;
|
||||
outPath = ../.; # used by pre-commit module, etc
|
||||
outputs = self.config.flake;
|
||||
} //
|
||||
fmc-lib.mkFlake
|
||||
{ inputs = args; }
|
||||
./flake-module.nix;
|
||||
inputs = flake.inputs // { inherit flake-parts; };
|
||||
makeResult = specialArgs: flakeModule: result:
|
||||
let
|
||||
outputs = flake.outputs // flake-parts.lib.mkFlake
|
||||
{
|
||||
inputs = inputs // { self = result; };
|
||||
# debugging tool
|
||||
specialArgs = {
|
||||
replaceSpecialArgs = newSpecialArgs:
|
||||
let
|
||||
newSpecialArgs' =
|
||||
if lib.isFunction newSpecialArgs
|
||||
then newSpecialArgs specialArgs
|
||||
else newSpecialArgs;
|
||||
newResult = makeResult newSpecialArgs' flakeModule newResult;
|
||||
in
|
||||
newResult;
|
||||
} // specialArgs;
|
||||
}
|
||||
flakeModule;
|
||||
in
|
||||
outputs // sourceInfo // {
|
||||
inherit inputs outputs sourceInfo;
|
||||
_type = "flake";
|
||||
};
|
||||
in
|
||||
self.config.flake // { inherit (flake) inputs; }
|
||||
let
|
||||
# eagerly import to reproduce inline evaluation
|
||||
result = makeResult { } (import ./flake-module.nix) result;
|
||||
in
|
||||
result
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
{ config, lib, inputs, withSystem, ... }:
|
||||
|
||||
{
|
||||
{ config, inputs, lib, options, specialArgs, withSystem, ... } @ args:
|
||||
let
|
||||
rootArgs = args;
|
||||
rootConfig = config;
|
||||
rootOptions = options;
|
||||
rootSpecialArgs = specialArgs;
|
||||
in
|
||||
# debugging tool
|
||||
specialArgs.flakeModuleTransformer or (args: flakeModule: flakeModule) args {
|
||||
imports = [
|
||||
inputs.pre-commit-hooks-nix.flakeModule
|
||||
inputs.hercules-ci-effects.flakeModule # herculesCI attr
|
||||
];
|
||||
systems = [ "x86_64-linux" "aarch64-darwin" ];
|
||||
config.systems = [ "x86_64-linux" "aarch64-darwin" ];
|
||||
|
||||
hercules-ci.flake-update = {
|
||||
config.hercules-ci.flake-update = {
|
||||
enable = true;
|
||||
autoMergeMethod = "merge";
|
||||
when.dayOfMonth = 1;
|
||||
};
|
||||
|
||||
perSystem = { config, pkgs, ... }: {
|
||||
config.perSystem = { config, pkgs, ... }: {
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
nativeBuildInputs = [
|
||||
|
@ -38,11 +44,18 @@
|
|||
in tests.runTests pkgs.emptyFile // { internals = tests; };
|
||||
|
||||
};
|
||||
flake = {
|
||||
# for repl exploration / debug
|
||||
config.config = config;
|
||||
options.mySystem = lib.mkOption { default = config.allSystems.${builtins.currentSystem}; };
|
||||
config.effects = withSystem "x86_64-linux" ({ pkgs, hci-effects, ... }: {
|
||||
config.flake = { config, options, specialArgs, ... } @ args: {
|
||||
# for REPL exploration / debugging
|
||||
config.allFlakeModuleArgs = args // config._module.args // specialArgs;
|
||||
config.allRootModuleArgs = rootArgs // rootConfig._module.args // rootSpecialArgs;
|
||||
config.transformFlakeModule = flakeModuleTransformer:
|
||||
rootSpecialArgs.replaceSpecialArgs (prevSpecialArgs: prevSpecialArgs // {
|
||||
inherit flakeModuleTransformer;
|
||||
});
|
||||
options.mySystem = lib.mkOption {
|
||||
default = rootConfig.allSystems.${builtins.currentSystem};
|
||||
};
|
||||
config.effects = withSystem "x86_64-linux" ({ hci-effects, pkgs, ... }: {
|
||||
tests = {
|
||||
template = pkgs.callPackage ./tests/template.nix { inherit hci-effects; };
|
||||
};
|
||||
|
|
|
@ -2,17 +2,54 @@
|
|||
#
|
||||
# nix build -f dev checks.x86_64-linux.eval-tests
|
||||
|
||||
rec {
|
||||
f-p = builtins.getFlake (toString ../..);
|
||||
flake-parts = f-p;
|
||||
let
|
||||
flake-parts = builtins.getFlake (toString ../..);
|
||||
lib = flake-parts.inputs.nixpkgs-lib.lib;
|
||||
in
|
||||
(lib.makeExtensibleWithCustomName "extendEvalTests" (evalTests: {
|
||||
inherit evalTests;
|
||||
inherit flake-parts;
|
||||
flake-parts-lib = evalTests.flake-parts.lib;
|
||||
inherit lib;
|
||||
|
||||
devFlake = builtins.getFlake (toString ../.);
|
||||
nixpkgs = devFlake.inputs.nixpkgs;
|
||||
nixpkgs = evalTests.devFlake.inputs.nixpkgs;
|
||||
|
||||
f-p-lib = f-p.lib;
|
||||
inherit (evalTests.flake-parts-lib) mkFlake;
|
||||
weakEvalTests.callFlake = { ... } @ flake:
|
||||
let
|
||||
sourceInfo = flake.sourceInfo or { };
|
||||
inputs = flake.inputs or { };
|
||||
outputs = flake.outputs inputs;
|
||||
result = outputs;
|
||||
in
|
||||
result;
|
||||
strongEvalTests.callFlake = { ... } @ flake:
|
||||
let
|
||||
sourceInfo = { outPath = "/unknown_eval-tests_flake"; } //
|
||||
flake.sourceInfo or { };
|
||||
inputs = flake.inputs or { };
|
||||
outputs = flake.outputs (inputs // { self = result; });
|
||||
result = outputs // sourceInfo // {
|
||||
inherit inputs outputs sourceInfo;
|
||||
_type = "flake";
|
||||
};
|
||||
in
|
||||
assert builtins.isFunction flake.outputs;
|
||||
result;
|
||||
|
||||
inherit (f-p-lib) mkFlake;
|
||||
inherit (f-p.inputs.nixpkgs-lib) lib;
|
||||
withWeakEvalTests = evalTests.extendEvalTests (finalEvalTests: prevEvalTests:
|
||||
builtins.mapAttrs (name: value: finalEvalTests.weakEvalTests.${name})
|
||||
prevEvalTests.weakEvalTests
|
||||
);
|
||||
withStrongEvalTests = evalTests.extendEvalTests (finalEvalTests: prevEvalTests:
|
||||
builtins.mapAttrs (name: value: finalEvalTests.strongEvalTests.${name})
|
||||
prevEvalTests.strongEvalTests
|
||||
);
|
||||
|
||||
exhibitingInfiniteRecursion = false;
|
||||
exhibitInfiniteRecursion = evalTests.extendEvalTests
|
||||
(finalEvalTest: prevEvalTests: { exhibitingInfiniteRecursion = true; });
|
||||
|
||||
pkg = system: name: derivation {
|
||||
name = name;
|
||||
|
@ -20,41 +57,202 @@ rec {
|
|||
system = system;
|
||||
};
|
||||
|
||||
empty = mkFlake
|
||||
{ inputs.self = { }; }
|
||||
{
|
||||
empty = evalTests.callFlake {
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.self = { };
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
systems = [ ];
|
||||
};
|
||||
};
|
||||
weakEvalTests.emptyResult = {
|
||||
apps = { };
|
||||
checks = { };
|
||||
devShells = { };
|
||||
formatter = { };
|
||||
legacyPackages = { };
|
||||
nixosConfigurations = { };
|
||||
nixosModules = { };
|
||||
overlays = { };
|
||||
packages = { };
|
||||
};
|
||||
strongEvalTests.emptyResult = let
|
||||
_type = "flake";
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.self = { };
|
||||
outputs = evalTests.weakEvalTests.emptyResult;
|
||||
sourceInfo.outPath = "/unknown_eval-tests_flake";
|
||||
result = outputs // sourceInfo // { inherit _type inputs outputs sourceInfo; };
|
||||
in result;
|
||||
runEmptyTests = ok:
|
||||
assert evalTests.empty == evalTests.emptyResult;
|
||||
ok;
|
||||
emptyTestsResult = evalTests.runEmptyTests "ok";
|
||||
|
||||
example1 = mkFlake
|
||||
{ inputs.self = { }; }
|
||||
{
|
||||
tooEmpty = evalTests.callFlake {
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.self = { };
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
};
|
||||
};
|
||||
# Shallow evaluation is successful…
|
||||
weakEvalTests.tooEmptyResultTried0.success = true;
|
||||
weakEvalTests.tooEmptyResultTried0.value = { };
|
||||
weakEvalTests.tooEmptyResultTried0TestTried.success = true;
|
||||
weakEvalTests.tooEmptyResultTried0TestTried.value = false;
|
||||
# …including for flake outputs…
|
||||
strongEvalTests.tooEmptyResultTried0 = evalTests.weakEvalTests.tooEmptyResultTried0;
|
||||
strongEvalTests.tooEmptyResultTried0TestTried = evalTests.weakEvalTests.tooEmptyResultTried0TestTried;
|
||||
# …but any evaluations of attribute values (flake output values) are not.
|
||||
weakEvalTests.tooEmptyResultTried1.success = true;
|
||||
weakEvalTests.tooEmptyResultTried1.value = {
|
||||
apps = { };
|
||||
checks = { };
|
||||
devShells = { };
|
||||
formatter = { };
|
||||
legacyPackages = { };
|
||||
nixosConfigurations = { };
|
||||
nixosModules = { };
|
||||
overlays = { };
|
||||
packages = { };
|
||||
};
|
||||
weakEvalTests.tooEmptyResultTried1TestTried.success = false;
|
||||
weakEvalTests.tooEmptyResultTried1TestTried.value = false;
|
||||
strongEvalTests.tooEmptyResultTried1.success = true;
|
||||
strongEvalTests.tooEmptyResultTried1.value = let
|
||||
_type = "flake";
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.self = { };
|
||||
outputs = evalTests.weakEvalTests.tooEmptyResultTried1.value;
|
||||
sourceInfo.outPath = "/unknown_eval-tests_flake";
|
||||
result = outputs // sourceInfo // { inherit _type inputs outputs sourceInfo; };
|
||||
in result;
|
||||
strongEvalTests.tooEmptyResultTried1TestTried.success = false;
|
||||
strongEvalTests.tooEmptyResultTried1TestTried.value = false;
|
||||
runTooEmptyTests = ok:
|
||||
let
|
||||
tooEmptyResultTried = builtins.tryEval evalTests.tooEmpty;
|
||||
tooEmptyResultTried0TestTried = builtins.tryEval (tooEmptyResultTried == evalTests.tooEmptyResultTried0);
|
||||
tooEmptyResultTried1TestTried = builtins.tryEval (tooEmptyResultTried == evalTests.tooEmptyResultTried1);
|
||||
in
|
||||
assert tooEmptyResultTried0TestTried == evalTests.tooEmptyResultTried0TestTried;
|
||||
assert tooEmptyResultTried1TestTried == evalTests.tooEmptyResultTried1TestTried;
|
||||
ok;
|
||||
tooEmptyTestsResult = evalTests.runTooEmptyTests "ok";
|
||||
|
||||
example1 = evalTests.callFlake {
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.self = { };
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
systems = [ "a" "b" ];
|
||||
perSystem = { system, ... }: {
|
||||
packages.hello = pkg system "hello";
|
||||
packages.hello = evalTests.pkg system "hello";
|
||||
};
|
||||
};
|
||||
};
|
||||
weakEvalTests.example1Result = {
|
||||
apps = { a = { }; b = { }; };
|
||||
checks = { a = { }; b = { }; };
|
||||
devShells = { a = { }; b = { }; };
|
||||
formatter = { };
|
||||
legacyPackages = { a = { }; b = { }; };
|
||||
nixosConfigurations = { };
|
||||
nixosModules = { };
|
||||
overlays = { };
|
||||
packages = {
|
||||
a = { hello = evalTests.pkg "a" "hello"; };
|
||||
b = { hello = evalTests.pkg "b" "hello"; };
|
||||
};
|
||||
};
|
||||
strongEvalTests.example1Result = let
|
||||
_type = "flake";
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.self = { };
|
||||
outputs = evalTests.weakEvalTests.example1Result;
|
||||
sourceInfo.outPath = "/unknown_eval-tests_flake";
|
||||
result = outputs // sourceInfo // { inherit _type inputs outputs sourceInfo; };
|
||||
in result;
|
||||
runExample1Tests = ok:
|
||||
assert evalTests.example1 == evalTests.example1Result;
|
||||
ok;
|
||||
example1TestsResult = evalTests.runExample1Tests "ok";
|
||||
|
||||
packagesNonStrictInDevShells = mkFlake
|
||||
{ inputs.self = packagesNonStrictInDevShells; /* approximation */ }
|
||||
{
|
||||
# This test case is a fun one. In the REPL, try `exhibitInfiniteRecursion.*`.
|
||||
# In the case that `mkFlake` *isn't* called from a flake, `inputs.self` is
|
||||
# unlikely to refer to the result of the `mkFlake` evaluation. If
|
||||
# `inputs.self` isn't actually self-referential, evaluating attribute values
|
||||
# of `self` is not divergent. Evaluation of `self.outPath` is useful for
|
||||
# paths in documentation & error messages. However, if that evaluation occurs
|
||||
# in a `builtins.addErrorContext` message forced by an erroring `self`, both
|
||||
# `self` will never evaluate *and* `builtins.toString self.outPath` must
|
||||
# evaluate, causing Nix to instead throw an infinite recursion error. Even
|
||||
# just `inputs.self ? outPath` throws an infinite recursion error.
|
||||
# (`builtins.tryEval` can only catch errors created by `builtins.throw` or
|
||||
# `builtins.assert`, so evaluation is guarded with
|
||||
# `exhibitingInfiniteRecursion` here to keep `runTests` from diverging.)
|
||||
# In this particular case, `mkFlake` evaluates `self ? outPath` to know if the
|
||||
# default module location it provides should be generic or specific. As
|
||||
# explained, this evaluation is unsafe under an uncatchably divergent `self`.
|
||||
# Thus, `outPath` cannot be safely sourced from `self` at the top-level.
|
||||
#
|
||||
# When tests are exhibititing infinite recursion, the abnormally correct
|
||||
# `self` is provided.
|
||||
weakEvalTests.nonexistentOption = let result = evalTests.callFlake {
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.self = if !evalTests.exhibitingInfiniteRecursion then { } else result;
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
config.systems = [ ];
|
||||
config.nonexistentOption = null;
|
||||
};
|
||||
}; in result;
|
||||
# When using actual flakes, this test always diverges. Unless tests are
|
||||
# exhibiting infinite recursion, the flake is made equivalent to `empty`.
|
||||
strongEvalTests.nonexistentOption = evalTests.callFlake {
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.self = { };
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } ({
|
||||
config.systems = [ ];
|
||||
} // (if !evalTests.exhibitingInfiniteRecursion then { } else {
|
||||
config.nonexistentOption = null;
|
||||
}));
|
||||
};
|
||||
weakEvalTests.nonexistentOptionResultTried0.success = true;
|
||||
weakEvalTests.nonexistentOptionResultTried0.value = { };
|
||||
weakEvalTests.nonexistentOptionResultTried0TestTried.success = true;
|
||||
weakEvalTests.nonexistentOptionResultTried0TestTried.value = false;
|
||||
strongEvalTests.nonexistentOptionResultTried0 = evalTests.weakEvalTests.nonexistentOptionResultTried0;
|
||||
strongEvalTests.nonexistentOptionResultTried0TestTried = evalTests.weakEvalTests.nonexistentOptionResultTried0TestTried;
|
||||
runNonexistentOptionTests = ok:
|
||||
let
|
||||
nonexistentOptionResultTried = builtins.tryEval evalTests.nonexistentOption;
|
||||
nonexistentOptionResultTried0TestTried = builtins.tryEval (nonexistentOptionResultTried == evalTests.nonexistentOptionResultTried0);
|
||||
in
|
||||
assert nonexistentOptionResultTried0TestTried == evalTests.nonexistentOptionResultTried0TestTried;
|
||||
ok;
|
||||
nonexistentOptionTestsResult = evalTests.runNonexistentOptionTests "ok";
|
||||
|
||||
packagesNonStrictInDevShells = evalTests.callFlake {
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
# approximation
|
||||
inputs.self = evalTests.packagesNonStrictInDevShells;
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
systems = [ "a" "b" ];
|
||||
perSystem = { system, self', ... }: {
|
||||
packages.hello = pkg system "hello";
|
||||
perSystem = { self', system, ... }: {
|
||||
packages.hello = evalTests.pkg system "hello";
|
||||
packages.default = self'.packages.hello;
|
||||
devShells = throw "can't be strict in perSystem.devShells!";
|
||||
};
|
||||
flake.devShells = throw "can't be strict in devShells!";
|
||||
};
|
||||
|
||||
easyOverlay = mkFlake
|
||||
{ inputs.self = { }; }
|
||||
{
|
||||
imports = [ flake-parts.flakeModules.easyOverlay ];
|
||||
easyOverlay = evalTests.callFlake {
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.self = { };
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
imports = [ inputs.flake-parts.flakeModules.easyOverlay ];
|
||||
systems = [ "a" "aarch64-linux" ];
|
||||
perSystem = { system, config, final, pkgs, ... }: {
|
||||
packages.default = config.packages.hello;
|
||||
packages.hello = pkg system "hello";
|
||||
packages.hello = evalTests.pkg system "hello";
|
||||
packages.hello_new = final.hello;
|
||||
overlayAttrs = {
|
||||
hello = config.packages.hello;
|
||||
|
@ -63,11 +261,13 @@ rec {
|
|||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
flakeModulesDeclare = mkFlake
|
||||
{ inputs.self = { outPath = ./.; }; }
|
||||
({ config, ... }: {
|
||||
imports = [ flake-parts.flakeModules.flakeModules ];
|
||||
flakeModulesDeclare = evalTests.callFlake {
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.self = { outPath = ./.; };
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } ({ config, inputs, lib, ... }: {
|
||||
imports = [ inputs.flake-parts.flakeModules.flakeModules ];
|
||||
systems = [ ];
|
||||
flake.flakeModules.default = { lib, ... }: {
|
||||
options.flake.test123 = lib.mkOption { default = "option123"; };
|
||||
|
@ -77,92 +277,90 @@ rec {
|
|||
flake.test123 = "123test";
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
flakeModulesImport = mkFlake
|
||||
{ inputs.self = { }; }
|
||||
{
|
||||
imports = [ flakeModulesDeclare.flakeModules.default ];
|
||||
flakeModulesImport = evalTests.callFlake {
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.flakeModulesDeclare = evalTests.flakeModulesDeclare;
|
||||
inputs.self = { };
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
imports = [ inputs.flakeModulesDeclare.flakeModules.default ];
|
||||
};
|
||||
};
|
||||
runFlakeModulesImportTests = ok:
|
||||
assert evalTests.flakeModulesImport.test123 == "123test";
|
||||
ok;
|
||||
flakeModulesImportTestsResult = evalTests.runFlakeModulesImportTests "ok";
|
||||
|
||||
flakeModulesDisable = mkFlake
|
||||
{ inputs.self = { }; }
|
||||
{
|
||||
imports = [ flakeModulesDeclare.flakeModules.default ];
|
||||
disabledModules = [ flakeModulesDeclare.flakeModules.extra ];
|
||||
flakeModulesDisable = evalTests.callFlake {
|
||||
inputs.flake-parts = evalTests.flake-parts;
|
||||
inputs.flakeModulesDeclare = evalTests.flakeModulesDeclare;
|
||||
inputs.self = { };
|
||||
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
imports = [ inputs.flakeModulesDeclare.flakeModules.default ];
|
||||
disabledModules = [ inputs.flakeModulesDeclare.flakeModules.extra ];
|
||||
};
|
||||
};
|
||||
runFlakeModulesDisableTests = ok:
|
||||
assert evalTests.flakeModulesDisable.test123 == "option123";
|
||||
ok;
|
||||
flakeModulesDisableTestsResult = evalTests.runFlakeModulesDisableTests "ok";
|
||||
|
||||
nixpkgsWithoutEasyOverlay = import nixpkgs {
|
||||
nixpkgsWithoutEasyOverlay = import evalTests.nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = { };
|
||||
};
|
||||
|
||||
nixpkgsWithEasyOverlay = import nixpkgs {
|
||||
nixpkgsWithEasyOverlay = import evalTests.nixpkgs {
|
||||
# non-memoized
|
||||
system = "x86_64-linux";
|
||||
overlays = [ easyOverlay.overlays.default ];
|
||||
overlays = [ evalTests.easyOverlay.overlays.default ];
|
||||
config = { };
|
||||
};
|
||||
|
||||
nixpkgsWithEasyOverlayMemoized = import nixpkgs {
|
||||
nixpkgsWithEasyOverlayMemoized = import evalTests.nixpkgs {
|
||||
# memoized
|
||||
system = "aarch64-linux";
|
||||
overlays = [ easyOverlay.overlays.default ];
|
||||
overlays = [ evalTests.easyOverlay.overlays.default ];
|
||||
config = { };
|
||||
};
|
||||
|
||||
tryEvalOutputs = outputs: builtins.seq (builtins.attrNames outputs) outputs;
|
||||
|
||||
runTests = ok:
|
||||
|
||||
assert empty == {
|
||||
apps = { };
|
||||
checks = { };
|
||||
devShells = { };
|
||||
formatter = { };
|
||||
legacyPackages = { };
|
||||
nixosConfigurations = { };
|
||||
nixosModules = { };
|
||||
overlays = { };
|
||||
packages = { };
|
||||
};
|
||||
assert evalTests.runEmptyTests true;
|
||||
|
||||
assert example1 == {
|
||||
apps = { a = { }; b = { }; };
|
||||
checks = { a = { }; b = { }; };
|
||||
devShells = { a = { }; b = { }; };
|
||||
formatter = { };
|
||||
legacyPackages = { a = { }; b = { }; };
|
||||
nixosConfigurations = { };
|
||||
nixosModules = { };
|
||||
overlays = { };
|
||||
packages = {
|
||||
a = { hello = pkg "a" "hello"; };
|
||||
b = { hello = pkg "b" "hello"; };
|
||||
};
|
||||
};
|
||||
assert evalTests.runTooEmptyTests true;
|
||||
|
||||
assert evalTests.runExample1Tests true;
|
||||
|
||||
assert evalTests.runNonexistentOptionTests true;
|
||||
|
||||
# - exported package becomes part of overlay.
|
||||
# - perSystem is invoked for the right system, when system is non-memoized
|
||||
assert nixpkgsWithEasyOverlay.hello == pkg "x86_64-linux" "hello";
|
||||
assert evalTests.nixpkgsWithEasyOverlay.hello == evalTests.pkg "x86_64-linux" "hello";
|
||||
|
||||
# - perSystem is invoked for the right system, when system is memoized
|
||||
assert nixpkgsWithEasyOverlayMemoized.hello == pkg "aarch64-linux" "hello";
|
||||
assert evalTests.nixpkgsWithEasyOverlayMemoized.hello == evalTests.pkg "aarch64-linux" "hello";
|
||||
|
||||
# - Non-exported package does not become part of overlay.
|
||||
assert nixpkgsWithEasyOverlay.default or null != pkg "x86_64-linux" "hello";
|
||||
assert evalTests.nixpkgsWithEasyOverlay.default or null != evalTests.pkg "x86_64-linux" "hello";
|
||||
|
||||
# - hello_old comes from super
|
||||
assert nixpkgsWithEasyOverlay.hello_old == nixpkgsWithoutEasyOverlay.hello;
|
||||
assert evalTests.nixpkgsWithEasyOverlay.hello_old == evalTests.nixpkgsWithoutEasyOverlay.hello;
|
||||
|
||||
# - `hello_new` shows that the `final` wiring works
|
||||
assert nixpkgsWithEasyOverlay.hello_new == nixpkgsWithEasyOverlay.hello;
|
||||
assert evalTests.nixpkgsWithEasyOverlay.hello_new == evalTests.nixpkgsWithEasyOverlay.hello;
|
||||
|
||||
assert flakeModulesImport.test123 == "123test";
|
||||
assert evalTests.runFlakeModulesImportTests true;
|
||||
|
||||
assert flakeModulesDisable.test123 == "option123";
|
||||
assert evalTests.runFlakeModulesDisableTests true;
|
||||
|
||||
assert packagesNonStrictInDevShells.packages.a.default == pkg "a" "hello";
|
||||
assert evalTests.packagesNonStrictInDevShells.packages.a.default == evalTests.pkg "a" "hello";
|
||||
|
||||
ok;
|
||||
|
||||
result = runTests "ok";
|
||||
}
|
||||
result = evalTests.runTests "ok";
|
||||
})).withWeakEvalTests
|
||||
|
|
5
lib.nix
5
lib.nix
|
@ -37,8 +37,11 @@ let
|
|||
attrs@{ staticModules ? [ ] }: mkOptionType {
|
||||
name = "deferredModule";
|
||||
description = "module";
|
||||
descriptionClass = "noun";
|
||||
check = x: isAttrs x || isFunction x || path.check x;
|
||||
merge = loc: defs: staticModules ++ map (def: lib.setDefaultModuleLocation "${def.file}, via option ${showOption loc}" def.value) defs;
|
||||
merge = loc: defs: {
|
||||
imports = staticModules ++ map (def: lib.setDefaultModuleLocation "${def.file}, via option ${showOption loc}" def.value) defs;
|
||||
};
|
||||
inherit (submoduleWith { modules = staticModules; })
|
||||
getSubOptions
|
||||
getSubModules;
|
||||
|
|
|
@ -15,7 +15,9 @@ let
|
|||
};
|
||||
|
||||
getExe = x:
|
||||
"${lib.getBin x}/bin/${x.meta.mainProgram or (throw ''Package ${x.name or ""} does not have meta.mainProgram set, so I don't know how to find the main executable. You can set meta.mainProgram, or pass the full path to executable, e.g. program = "''${pkg}/bin/foo"'')}";
|
||||
"${lib.getBin x}/bin/${x.meta.mainProgram or (throw
|
||||
''Package ${x.name or ""} does not have meta.mainProgram set, so I don't know how to find the main executable. You can set `meta.mainProgram`, or pass the full path to executable, e.g. program = "''${pkg}/bin/foo"''
|
||||
)}";
|
||||
|
||||
appType = lib.types.submodule {
|
||||
options = {
|
||||
|
|
|
@ -9,22 +9,23 @@
|
|||
let
|
||||
system =
|
||||
config._module.args.system or
|
||||
config._module.args.pkgs.stdenv.hostPlatform.system or
|
||||
(throw "moduleWithSystem: Could not determine the configuration's system parameter for this module system application.");
|
||||
config._module.args.pkgs.stdenv.hostPlatform.system or (throw
|
||||
"moduleWithSystem: Could not determine the `system` parameter for this module set evaluation."
|
||||
);
|
||||
|
||||
allArgs = withSystem system (args: args);
|
||||
allPerSystemArgs = withSystem system (args: args);
|
||||
|
||||
lazyArgsPerParameter = f: builtins.mapAttrs
|
||||
(k: v: allArgs.${k} or (throw "moduleWithSystem: module argument `${k}` does not exist."))
|
||||
lazyPerSystemArgsPerParameter = f: builtins.mapAttrs
|
||||
(k: v: allPerSystemArgs.${k} or (throw "moduleWithSystem: per-system argument `${k}` does not exist."))
|
||||
(builtins.functionArgs f);
|
||||
|
||||
# Use reflection to make the call lazy in the argument.
|
||||
# Restricts args to the ones declared.
|
||||
callLazily = f: a: f (lazyArgsPerParameter f);
|
||||
callLazily = f: a: f (lazyPerSystemArgsPerParameter f);
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(callLazily module allArgs)
|
||||
(callLazily module allPerSystemArgs)
|
||||
];
|
||||
};
|
||||
};
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
#
|
||||
{
|
||||
config = {
|
||||
perSystem = { inputs', lib, ... }: {
|
||||
perSystem = { inputs', lib, options, ... }: {
|
||||
config = {
|
||||
_module.args.pkgs = lib.mkOptionDefault (
|
||||
builtins.seq
|
||||
(inputs'.nixpkgs or (throw "flake-parts: The flake does not have a `nixpkgs` input. Please add it, or set `perSystem._module.args.pkgs` yourself."))
|
||||
inputs'.nixpkgs or (throw
|
||||
"flake-parts: The flake does not have a `nixpkgs` input. Please add it, or set `${options._module.args}.pkgs` yourself."
|
||||
)
|
||||
inputs'.nixpkgs.legacyPackages
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, flake-parts-lib, self, ... }:
|
||||
{ config, lib, flake-parts-lib, inputs, self, ... }:
|
||||
let
|
||||
inherit (lib)
|
||||
genAttrs
|
||||
|
@ -92,7 +92,7 @@ in
|
|||
type = mkPerSystemType ({ config, system, ... }: {
|
||||
_file = ./perSystem.nix;
|
||||
config = {
|
||||
_module.args.inputs' = mapAttrs (k: rootConfig.perInput system) self.inputs;
|
||||
_module.args.inputs' = mapAttrs (k: rootConfig.perInput system) inputs;
|
||||
_module.args.self' = rootConfig.perInput system self;
|
||||
|
||||
# Custom error messages
|
||||
|
@ -103,9 +103,9 @@ in
|
|||
_module.args.moduleWithSystem = throwAliasError "moduleWithSystem";
|
||||
};
|
||||
});
|
||||
apply = modules: system:
|
||||
apply = module: system:
|
||||
(lib.evalModules {
|
||||
inherit modules;
|
||||
modules = [ module ];
|
||||
prefix = [ "perSystem" system ];
|
||||
specialArgs = {
|
||||
inherit system;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Definitions can be imported from a separate file like this one
|
||||
|
||||
{ self, lib, ... }: {
|
||||
perSystem = { config, self', inputs', pkgs, ... }: {
|
||||
{ config, lib, inputs, ... }: {
|
||||
perSystem = { config, inputs', pkgs, ... }: {
|
||||
# Definitions like this are entirely equivalent to the ones
|
||||
# you may have directly in flake.nix.
|
||||
packages.hello = pkgs.hello;
|
||||
|
@ -9,8 +9,8 @@
|
|||
flake = {
|
||||
nixosModules.hello = { pkgs, ... }: {
|
||||
environment.systemPackages = [
|
||||
# or self.inputs.nixpkgs.legacyPackages.${pkgs.stdenv.hostPlatform.system}.hello
|
||||
self.packages.${pkgs.stdenv.hostPlatform.system}.hello
|
||||
# or inputs.nixpkgs.legacyPackages.${pkgs.stdenv.hostPlatform.system}.hello
|
||||
config.flake.packages.${pkgs.stdenv.hostPlatform.system}.hello
|
||||
];
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue