stylix: fix palette generator caching (#867)

Ensure the palette generator is properly cached by fixing the bug
introduced in commit efb734ff43 ("Prevent scheme generation from
running when result is not used (#56)"), where the added indirection
prevents the output of the palette generator becoming part of the final
system.

Using highestPrio as a condition should prevent the palette generator
being forced to run when the output is not used, which is the issue that
the indirection was meant to solve.

Link: https://github.com/danth/stylix/pull/867

Reviewed-by: NAHO <90870942+trueNAHO@users.noreply.github.com>
This commit is contained in:
Daniel Thwaites 2025-02-18 12:34:14 +00:00 committed by GitHub
parent d171b19c1c
commit 9343b660c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 54 additions and 38 deletions

View file

@ -15,7 +15,7 @@
"base0D": "{{{base0D}}}",
"base0E": "{{{base0E}}}",
"base0F": "{{{base0F}}}",
"scheme": "Stylix",
"author": "Stylix",
"slug": "stylix"
"author": "{{author}}",
"scheme": "{{scheme}}",
"slug": "{{slug}}"
}

View file

@ -3,30 +3,13 @@
pkgs,
lib,
config,
options,
...
}:
let
cfg = config.stylix;
paletteJSON =
let
generatedJSON = pkgs.runCommand "palette.json" { } ''
${palette-generator}/bin/palette-generator \
"${cfg.polarity}" \
${lib.escapeShellArg "${cfg.image}"} \
"$out"
'';
palette = lib.importJSON generatedJSON;
scheme = base16.mkSchemeAttrs palette;
json = scheme {
template = ./palette.json.mustache;
extension = ".json";
};
in
json;
generatedScheme = lib.importJSON paletteJSON;
in
{
options.stylix = {
@ -87,19 +70,32 @@ in
generated = {
json = lib.mkOption {
type = lib.types.path;
description = "The result of palette-generator.";
type = lib.types.package;
description = "The output file produced by the palette generator.";
readOnly = true;
internal = true;
default = paletteJSON;
# This *must* be the derivation running the palette generator,
# and not anything indirect such as filling a template, otherwise
# the output of the palette generator will not be protected from
# garbage collection.
default = pkgs.runCommand "palette.json" { } ''
${palette-generator}/bin/palette-generator \
"${cfg.polarity}" \
${lib.escapeShellArg "${cfg.image}"} \
"$out"
'';
};
palette = lib.mkOption {
type = lib.types.attrs;
description = "The imported json";
description = "The palette generated by the palette generator.";
readOnly = true;
internal = true;
default = generatedScheme;
default = (lib.importJSON cfg.generated.json) // {
author = "Stylix";
scheme = "Stylix";
slug = "stylix";
};
};
fileTree = lib.mkOption {
@ -123,7 +119,7 @@ in
lines
attrs
];
default = generatedScheme;
default = cfg.generated.palette;
defaultText = lib.literalMD ''
The colors used in the theming.
@ -149,21 +145,41 @@ in
# This attrset can be used like a function too, see
# https://github.com/SenchoPens/base16.nix/blob/b390e87cd404e65ab4d786666351f1292e89162a/README.md#theme-step-22
lib.stylix.colors = (base16.mkSchemeAttrs cfg.base16Scheme).override cfg.override;
lib.stylix.scheme = base16.mkSchemeAttrs cfg.base16Scheme;
stylix.generated.fileTree = {
# Making palette.json part of the system closure will protect it from
# garbage collection, so future configurations can be evaluated without
# having to generate the palette again. The generator is not kept, only
# the palette which came from it, so this uses very little disk space.
# The extra indirection should prevent the palette generator from running
# when the theme is manually specified. generated.json is necessary in
# the presence of overrides.
"stylix/generated.json".source = config.lib.stylix.scheme {
template = ./palette.json.mustache;
extension = ".json";
# The raw output of the palette generator.
"stylix/generated.json" = {
# We import the generated palette during evaluation but don't make it
# a dependency, which means the garbage collector is free to delete it
# immediately. Future evaluations may need to download, compile, and
# run the palette generator from scratch to recreate the same palette.
#
# To improve performance, we can make the generated file part of the
# system, which protects it from garbage collection and so increases
# the potential for reuse between evaluations.
#
# The palette generator executable is not affected, and can still be
# cleaned up as usual, so the overhead on system size is less than a
# kilobyte.
source = cfg.generated.json;
# Only do this when `base16Scheme` is still the option default, which
# is when the generated palette is used. Depending on the file in other
# cases would force the palette generator to run when we never read the
# output.
#
# Controlling this by comparing against the default value with == would
# also force the palette generator to run, as we would have to evaluate
# the default value to check for equality. To work around this, we
# check only the priority of the resolved value. The priority of option
# defaults is 1500 [1], and any value less than this means the user has
# changed the option.
#
# [1]: https://github.com/NixOS/nixpkgs/blob/5f30488d37f91fd41f0d40437621a8563a70b285/lib/modules.nix#L1063
enable = options.stylix.base16Scheme.highestPrio >= 1500;
};
# The current palette, with overrides applied.
"stylix/palette.json".source = config.lib.stylix.colors {
template = ./palette.json.mustache;
extension = ".json";