From 9343b660c914a95d4a90f6bd40cda7c87b401445 Mon Sep 17 00:00:00 2001 From: Daniel Thwaites Date: Tue, 18 Feb 2025 12:34:14 +0000 Subject: [PATCH] stylix: fix palette generator caching (#867) Ensure the palette generator is properly cached by fixing the bug introduced in commit efb734ff436d ("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> --- stylix/palette.json.mustache | 6 +-- stylix/palette.nix | 86 +++++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 38 deletions(-) diff --git a/stylix/palette.json.mustache b/stylix/palette.json.mustache index e8dde342..5e9f25e6 100644 --- a/stylix/palette.json.mustache +++ b/stylix/palette.json.mustache @@ -15,7 +15,7 @@ "base0D": "{{{base0D}}}", "base0E": "{{{base0E}}}", "base0F": "{{{base0F}}}", - "scheme": "Stylix", - "author": "Stylix", - "slug": "stylix" + "author": "{{author}}", + "scheme": "{{scheme}}", + "slug": "{{slug}}" } diff --git a/stylix/palette.nix b/stylix/palette.nix index 86518b78..b540eb0a 100644 --- a/stylix/palette.nix +++ b/stylix/palette.nix @@ -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";