Extend mkStateVersionOptionDefault so merged attrset callers can defer
warning emission to config.warnings while still exposing the effective
state-version default and option priority metadata.
Add dedicated lib tests for deferred warning behavior on both legacy and
current state versions.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
Add a helper for options whose defaults change across home.stateVersion boundaries. This centralizes the warning text and documentation shape so modules do not need to hand-roll the same migration pattern at each call site.
The helper takes legacy and current branches with a runtime value plus optional static documentation text. That keeps the actual default version-gated while avoiding option docs that depend on evaluated config. Add a focused test covering the legacy warning path, the new-value path, and an explicit legacy pin that should not warn.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
Removes the `uniq` constraint on `after` and `before` so that we can
merge multiple definitions for the same DAG entry:
{
dag = mkMerge [
{
foo = lib.hm.dag.entryBefore [ "bar" ] {
# definition 1
};
}
{
foo = lib.hm.dag.entryBefore [ "qux" ] {
# definition 2
};
}
{
foo = {
# definition 3
};
}
];
}
In this example `foo` will come before `bar` and `qux`.
This makes definitions like
home.activation.foo = mkIf false "bar"
work, where previously they would complain about
`home.activation.foobar.data` being used but not defined.
The crucial part is that we don't call `convertAllToDags` in
`dagOf.merge`, because we need to process `mkIf`/`mkMerge` properties
first. So we let `attrEquivalent.merge` do its job normally, but give
it a type `dagEntryOf` that does the conversion.
Ideally this shouldn't require so much boilerplate; I'd like to
implement something like
types.changeInto dagContentType elemType dagEntryAnywhere
in Nixpkgs.
Given an inner type, the former function generates a type that expect
DAG option values. The latter function is only present to temporarily
allow the `programs.ssh.matchBlocks` to keep accepting list values.