-
Notifications
You must be signed in to change notification settings - Fork 27
Description
TL;DR:
- When having conflicting configs in .apply chains, should the newest win or do we have to make priorities explicit using mkForce?
- Multiple occurences of the same flag (i.e. "--greeting") get concatenated. Is this intended?
- grepping the wrapper scripts seems not to be robust enough.
Some things I noted when studying the checks in apply.nix:
The semantics are not clear from reading the tests to .apply:
# Apply with initial settings
initialConfig = helloModule.apply {
inherit pkgs;
flags."--verbose" = { };
};
# Extend the configuration
extendedConfig = initialConfig.apply {
flags."--greeting" = "extended";
flags."--extra" = "flag";
};
# Test mkForce to override a value
forcedConfig = initialConfig.apply (
{ lib, ... }:
{
flags."--greeting" = lib.mkForce "forced"; # <-- here it is implied that we need to `mkForce` to avoid conflicts
flags."--forced-flag" = { };
}
);
# Test extending via wrapper.passthru.configuration.apply
passthruExtendedConfig = initialConfig.wrapper.passthru.configuration.apply {
flags."--passthru" = "test";
};
# Test chaining apply multiple levels deep
doubleApply = extendedConfig.apply {
flags."--greeting" = "double"; # <-- here we do not use mkForce
flags."--double" = "level2";
};
tripleApply = doubleApply.apply {
flags."--greeting" = "triple"; # <-- here we do not use mkForce as well
flags."--triple" = "level3";
};When trying to look at it myself I found the following:
Consider this demo-wrapper.nix
{
config,
lib,
wlib,
...
}:
{
options.foo = lib.mkOption {
type = lib.types.str;
default = "foo (default)";
};
options.bar = lib.mkOption {
type = lib.types.str;
default = "bar (default)";
};
config.package = config.pkgs.hello;
config.foo = lib.mkDefault "foo (initial)";
config.flags = {
"--greeting" = "hi (initial)";
};
}and then use it as follows (flake.nix):
{
description = "A very basic flake";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
wrappers.url = "github:lassulus/wrappers";
};
outputs = { self, nixpkgs, wrappers }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
lib = pkgs.lib;
demoWrapperModule = import ./demo-wrapper.nix;
fooEvaledWrappers = wrappers.lib.wrapModule demoWrapperModule;
fooApplied = fooEvaledWrappers.apply {
foo = "foo (applied)";
flags = { "--greeting" = "hi (apply)"; };
};
fooApplied2 = fooApplied.apply {
foo = lib.mkForce "foo (applied2)"; # <-- this will yield an error if I don't use mkForce
flags = { "--greeting" = "hi (apply2)"; }; # <-- this works without mkForce
};
in
{
fooWrappers = fooApplied2;
};
}Evaluating the flags yields:
/> ~/repos/nix-pg/ > nix eval .#fooWrappers.flags $(vi_mode_prompt_info)
{ "--greeting" = "hi (apply)hi (apply2)hi (initial)"; }
As you can see, the flags get concatenated. Is this intended?
Another thing I found is that grepping the wrapper scripts seems not to be robust enough:
For example, in this test:
tripleApply = doubleApply.apply {
flags."--greeting" = "triple";
flags."--triple" = "level3";
}; # Check triple apply - greeting should be "triple" (newest wins)
if ! grep -q "triple" "$tripleScript"; then
echo "FAIL: triple apply should have 'triple' greeting"
cat "$tripleScript"
exit 1
fi
grepping for 'triple' would succeed independent of whether the greeting flag is set to "triple" because the world "triple" also occurs in the flag "--triple".
Also the comment "newest wins" leads me to believe that the concatenation of flags is not intended. But it leaves the question to whether new values should win, or whether we need to control that via mkForce.