From 7790746d38856872ecaa1b8e69f18044d9a16031 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Sun, 20 Oct 2024 00:11:36 +0100 Subject: [PATCH] modules/nixpkgs: add `useGlobalPackages` option --- modules/top-level/nixpkgs.nix | 5 ++- tests/nixpkgs-module.nix | 76 ++++++++++++++++++++++++++++++++ wrappers/_shared.nix | 35 ++++++++------- wrappers/modules/nixpkgs.nix | 83 +++++++++++++++++++++++++++++++++++ wrappers/modules/shared.nix | 4 ++ 5 files changed, 185 insertions(+), 18 deletions(-) create mode 100644 wrappers/modules/nixpkgs.nix diff --git a/modules/top-level/nixpkgs.nix b/modules/top-level/nixpkgs.nix index 5e4c7b04..5aec8816 100644 --- a/modules/top-level/nixpkgs.nix +++ b/modules/top-level/nixpkgs.nix @@ -41,8 +41,9 @@ in # } # ''; defaultText = lib.literalMD '' - The `pkgs` inherited from your host config (i.e. NixOS, home-manager, or nix-darwin), - or the `pkgs` supplied to `makeNixvimWithModule` when building a standalone nixvim. + If `useGlobalPackages` is true, `pkgs` is inherited from your host config + (i.e. NixOS, home-manager, or nix-darwin). + Or the `pkgs` supplied to `makeNixvimWithModule` when building a standalone nixvim. > [!CAUTION] > This default will be removed in a future version of nixvim diff --git a/tests/nixpkgs-module.nix b/tests/nixpkgs-module.nix index 67f79619..031ce209 100644 --- a/tests/nixpkgs-module.nix +++ b/tests/nixpkgs-module.nix @@ -33,6 +33,49 @@ let testModule = name: module: (evalModule name module).config.build.test; + # Unlike above, this imports the full nixvimConfiguration, + # allowing us to integration test the wrapper module + # + # This means `pkgs` probably gets used "for real", e.g. in the `files` module + testWrappers = + name: pkgs: module: + linkFarmFromDrvs name ( + lib.mapAttrsToList + ( + name': wrapper: + let + wrapperConfiguration = lib.evalModules { + modules = lib.toList module ++ [ + wrapper + { _module.check = false; } + { _module.args.pkgs = pkgs; } + { + # Stub `lib` option, required for bootstrapping wrapper module + options.lib = lib.mkOption { + type = with lib.types; attrsOf attrs; + default = { }; + }; + } + { + programs.nixvim.test = { + name = "${name}-${name'}"; + buildNixvim = false; + runNvim = false; + runCommand = runCommandLocal; + }; + } + ]; + }; + in + wrapperConfiguration.config.programs.nixvim.build.test + ) + { + nixos = self.nixosModules.default; + hm = self.homeManagerModules.default; + nix-darwin = self.nixDarwinModules.default; + } + ); + in linkFarmFromDrvs "nixpkgs-module-test" [ @@ -148,4 +191,37 @@ linkFarmFromDrvs "nixpkgs-module-test" [ } )) + (testWrappers "useGlobalPackages-empty" pkgs { }) + (testWrappers "useGlobalPackages-true" pkgs { + programs.nixvim.nixpkgs.useGlobalPackages = true; + }) + (testWrappers "useGlobalPackages-false" pkgs { + programs.nixvim.nixpkgs.useGlobalPackages = false; + }) + (testWrappers "useGlobalPackages-with-pkgs" pkgs { + _file = "test-file"; + programs.nixvim = { + nixpkgs.useGlobalPackages = true; + nixpkgs.pkgs = pkgs; + test.assertions = expect: [ + (expect "count" 1) + (expect "any" "`programs.nixvim.nixpkgs.useGlobalPackages' is enabled, but `programs.nixvim.nixpkgs.pkgs' is overridden.") + (expect "any" "- In `test-file'") + ]; + }; + }) + (testWrappers "useGlobalPackages-with-pkgs-arg" pkgs { + _file = "test-file"; + programs.nixvim = { + _module.args.pkgs = lib.mkForce pkgs; + nixpkgs.useGlobalPackages = true; + test.assertions = expect: [ + (expect "count" 1) + (expect "any" "`programs.nixvim.nixpkgs.useGlobalPackages' is enabled, but `programs.nixvim._module.args.pkgs' is overridden.") + # FIXME: can't showDefs for an attrOf an option + # (expect "any" "- In `test-file'") + ]; + }; + }) + ] diff --git a/wrappers/_shared.nix b/wrappers/_shared.nix index 424c4c82..85843418 100644 --- a/wrappers/_shared.nix +++ b/wrappers/_shared.nix @@ -23,30 +23,33 @@ let map mkIf mkMerge - mkOption optionalAttrs setAttrByPath ; cfg = config.programs.nixvim; + + # FIXME: buildPlatform can't use mkOptionDefault because it already defaults to hostPlatform + buildPlatformPrio = (lib.mkOptionDefault null).priority - 1; + + nixpkgsModule = + { config, ... }: + { + _file = ./_shared.nix; + nixpkgs = { + # Use global packages in nixvim's submodule + pkgs = lib.mkIf config.nixpkgs.useGlobalPackages (lib.mkDefault pkgs); + + # Inherit platform spec + hostPlatform = lib.mkOptionDefault pkgs.stdenv.hostPlatform; + buildPlatform = lib.mkOverride buildPlatformPrio pkgs.stdenv.buildPlatform; + }; + }; + nixvimConfiguration = config.lib.nixvim.modules.evalNixvim ( evalArgs // { modules = evalArgs.modules or [ ] ++ [ - { - _file = ./_shared.nix; - - nixpkgs = { - # Use global packages by default in nixvim's submodule - # TODO: `useGlobalPackages` option and/or deprecate using host packages? - pkgs = lib.mkDefault pkgs; - - # Inherit platform spec - # FIXME: buildPlatform can't use option-default because it already has a default - # (it defaults to hostPlatform)... - hostPlatform = lib.mkOptionDefault pkgs.stdenv.hostPlatform; - buildPlatform = lib.mkDefault pkgs.stdenv.buildPlatform; - }; - } + nixpkgsModule ]; } ); diff --git a/wrappers/modules/nixpkgs.nix b/wrappers/modules/nixpkgs.nix new file mode 100644 index 00000000..898713a3 --- /dev/null +++ b/wrappers/modules/nixpkgs.nix @@ -0,0 +1,83 @@ +{ + lib, + config, + options, + ... +}: +let + cfg = config.nixpkgs; + opts = options.nixpkgs; + argOpts = lib.modules.mergeAttrDefinitionsWithPrio options._module.args; + + normalPrio = lib.modules.defaultOverridePriority; + defaultPrio = (lib.mkDefault null).priority; + optionDefaultPrio = (lib.mkOptionDefault null).priority; + # FIXME: buildPlatform can't use mkOptionDefault because it already defaults to hostPlatform + buildPlatformPrio = optionDefaultPrio - 1; + + mkGlobalPackagesAssertion = + { + assertion, + option ? null, + loc ? option.loc, + issue ? "is overridden", + }: + { + assertion = cfg.useGlobalPackages -> assertion; + message = + "`${lib.showOption opts.useGlobalPackages.loc}' is enabled, " + + "but `${lib.showOption loc}' ${issue}. " + + lib.optionalString ( + option != null + ) "Definition values:${lib.options.showDefs option.definitionsWithLocations}"; + }; +in +{ + options = { + nixpkgs.useGlobalPackages = lib.mkOption { + type = lib.types.bool; + default = true; # TODO: Added 2025-01-15; switch to false one release after adding a deprecation warning + defaultText = lib.literalMD ''`true`, but will change to `false` in a future version.''; + description = '' + Whether Nixvim should use the ${config.meta.wrapper.name} configuration's `pkgs`, + instead of constructing its own instance. + ''; + }; + }; + + config = { + assertions = map mkGlobalPackagesAssertion [ + { + assertion = opts.pkgs.highestPrio == defaultPrio; + option = opts.pkgs; + issue = "is overridden"; + } + { + assertion = argOpts.pkgs.highestPrio == normalPrio; + # FIXME: can't showDefs for an attrOf an option + loc = options._module.args.loc ++ [ "pkgs" ]; + issue = "is overridden"; + } + { + assertion = opts.hostPlatform.highestPrio == optionDefaultPrio; + option = opts.hostPlatform; + issue = "is overridden"; + } + { + assertion = opts.buildPlatform.highestPrio == buildPlatformPrio; + option = opts.buildPlatform; + issue = "is overridden"; + } + { + assertion = cfg.config == { }; + option = opts.config; + issue = "is not empty"; + } + { + assertion = cfg.overlays == [ ]; + option = opts.overlays; + issue = "is not empty"; + } + ]; + }; +} diff --git a/wrappers/modules/shared.nix b/wrappers/modules/shared.nix index 3aa9f7c5..cd580ed5 100644 --- a/wrappers/modules/shared.nix +++ b/wrappers/modules/shared.nix @@ -11,4 +11,8 @@ }; }; }; + + imports = [ + ./nixpkgs.nix + ]; }