lib/deprecations: add state version default helper
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>
This commit is contained in:
parent
856b01ebd1
commit
95496df8c0
3 changed files with 152 additions and 0 deletions
|
|
@ -107,4 +107,54 @@
|
|||
value;
|
||||
in
|
||||
pathStr: attrs: migrate pathStr attrs;
|
||||
|
||||
/*
|
||||
Builds `default` and `defaultText` values for options whose defaults
|
||||
change based on `home.stateVersion`, while warning users on the legacy
|
||||
branch.
|
||||
|
||||
Example:
|
||||
let
|
||||
stateVersionDefault = lib.hm.deprecations.mkStateVersionOptionDefault {
|
||||
inherit (config.home) stateVersion;
|
||||
since = "26.05";
|
||||
optionPath = [ "programs" "example" "foo" ];
|
||||
legacy.value = "old";
|
||||
current.value = "new";
|
||||
};
|
||||
in
|
||||
lib.mkOption {
|
||||
inherit (stateVersionDefault) default defaultText;
|
||||
};
|
||||
*/
|
||||
mkStateVersionOptionDefault =
|
||||
{
|
||||
stateVersion,
|
||||
since,
|
||||
optionPath,
|
||||
legacy,
|
||||
current,
|
||||
extraWarning ? "",
|
||||
}:
|
||||
let
|
||||
option = lib.showOption optionPath;
|
||||
legacyText = legacy.text or (lib.generators.toPretty { } legacy.value);
|
||||
currentText = current.text or (lib.generators.toPretty { } current.value);
|
||||
warning = ''
|
||||
The default value of `${option}` has changed from `${legacyText}` to `${currentText}`.
|
||||
You are currently using the legacy default (`${legacyText}`) because `home.stateVersion` is less than "${since}".
|
||||
To silence this warning and keep legacy behavior, set:
|
||||
${option} = ${legacyText};
|
||||
To adopt the new default behavior, set:
|
||||
${option} = ${currentText};
|
||||
''
|
||||
+ lib.optionalString (extraWarning != "") ("\n" + extraWarning);
|
||||
in
|
||||
{
|
||||
default =
|
||||
if lib.versionAtLeast stateVersion since then current.value else lib.warn warning legacy.value;
|
||||
defaultText = lib.literalExpression ''
|
||||
if lib.versionAtLeast config.home.stateVersion "${since}" then ${currentText} else ${legacyText}
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@
|
|||
lib-types-either-suboptions-docs-lib = ./either-suboptions-docs-lib.nix;
|
||||
|
||||
lib-types-gvariant-merge = ./gvariant-merge.nix;
|
||||
lib-types-state-version-option-default = ./state-version-option-default.nix;
|
||||
}
|
||||
|
|
|
|||
101
tests/lib/types/state-version-option-default.nix
Normal file
101
tests/lib/types/state-version-option-default.nix
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
legacyDefault = lib.hm.deprecations.mkStateVersionOptionDefault {
|
||||
stateVersion = "25.11";
|
||||
since = "26.05";
|
||||
optionPath = [
|
||||
"test"
|
||||
"values"
|
||||
"legacy"
|
||||
];
|
||||
legacy.value = "legacy";
|
||||
current.value = "new";
|
||||
};
|
||||
|
||||
newDefault = lib.hm.deprecations.mkStateVersionOptionDefault {
|
||||
stateVersion = "26.05";
|
||||
since = "26.05";
|
||||
optionPath = [
|
||||
"test"
|
||||
"values"
|
||||
"new"
|
||||
];
|
||||
legacy.value = "legacy";
|
||||
current.value = "new";
|
||||
};
|
||||
in
|
||||
{
|
||||
options.test.values = {
|
||||
legacy = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
inherit (legacyDefault)
|
||||
default
|
||||
defaultText
|
||||
;
|
||||
};
|
||||
|
||||
new = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
inherit (newDefault)
|
||||
default
|
||||
defaultText
|
||||
;
|
||||
};
|
||||
|
||||
pinnedLegacy = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
inherit (legacyDefault)
|
||||
default
|
||||
defaultText
|
||||
;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
assertions = [
|
||||
{
|
||||
assertion = legacyDefault.defaultText._type == "literalExpression";
|
||||
message = "mkStateVersionOptionDefault should return a literalExpression defaultText.";
|
||||
}
|
||||
{
|
||||
assertion =
|
||||
lib.hasInfix ''config.home.stateVersion "26.05"'' legacyDefault.defaultText.text
|
||||
&& lib.hasInfix ''"new"'' legacyDefault.defaultText.text
|
||||
&& lib.hasInfix ''"legacy"'' legacyDefault.defaultText.text;
|
||||
message = "mkStateVersionOptionDefault should keep defaultText as static text instead of evaluating config.";
|
||||
}
|
||||
];
|
||||
|
||||
test.values.pinnedLegacy = "legacy";
|
||||
|
||||
home.file."result.txt".text = ''
|
||||
legacy=${config.test.values.legacy}
|
||||
new=${config.test.values.new}
|
||||
pinnedLegacy=${config.test.values.pinnedLegacy}
|
||||
'';
|
||||
|
||||
test.asserts.evalWarnings.expected = [
|
||||
''
|
||||
The default value of `test.values.legacy` has changed from `"legacy"` to `"new"`.
|
||||
You are currently using the legacy default (`"legacy"`) because `home.stateVersion` is less than "26.05".
|
||||
To silence this warning and keep legacy behavior, set:
|
||||
test.values.legacy = "legacy";
|
||||
To adopt the new default behavior, set:
|
||||
test.values.legacy = "new";
|
||||
''
|
||||
];
|
||||
|
||||
nmt.script = ''
|
||||
assertFileContent home-files/result.txt ${pkgs.writeText "state-version-option-default.txt" ''
|
||||
legacy=legacy
|
||||
new=new
|
||||
pinnedLegacy=legacy
|
||||
''}
|
||||
'';
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue