Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 87 additions & 18 deletions modules/top-level/nixpkgs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -55,31 +55,100 @@ in
> Use this option with care.
'';
};

overlays = lib.mkOption {
type =
let
overlayType = lib.mkOptionType {
name = "nixpkgs-overlay";
description = "nixpkgs overlay";
check = lib.isFunction;
merge = lib.mergeOneOption;
};
in
lib.types.listOf overlayType;
default = [ ];
# First example from https://nixos.org/manual/nixpkgs/unstable/#what-if-your-favourite-vim-plugin-isnt-already-packaged
# Second example from https://github.com/nix-community/nixvim/pull/2430#discussion_r1805700738
# Third example from https://github.com/atimofeev/nixos-config/blob/0b1c1c47c4359d6a2aa9a5eeecb32fa89ad08c88/overlays/neovim-unwrapped.nix
example = lib.literalExpression ''
[

# Add a vim plugin that isn't packaged in nixpkgs
(final: prev: {
easygrep = final.vimUtils.buildVimPlugin {
name = "vim-easygrep";
src = final.fetchFromGitHub {
owner = "dkprice";
repo = "vim-easygrep";
rev = "d0c36a77cc63c22648e792796b1815b44164653a";
hash = "sha256-bL33/S+caNmEYGcMLNCanFZyEYUOUmSsedCVBn4tV3g=";
};
};
})

# Override neovim-unwrapped with one from a flake input
# Using `stdenv.hostPlatform` to access `system`
(final: prev: {
neovim-unwrapped =
inputs.neovim-nightly-overlay.packages.''${final.stdenv.hostPlatform.system}.default;
})

# Override neovim-unwrapped to tweak its desktop entry
(final: prev: {
neovim-unwrapped = prev.neovim-unwrapped.overrideAttrs (old: {
postInstall = old.postInstall or "" + '''
substituteInPlace $out/share/applications/nvim.desktop \
--replace "TryExec=nvim" "" \
--replace "Terminal=true" "Terminal=false" \
--replace "Exec=nvim %F" "Exec=kitty -e nvim %F"
''';
});
})

]
'';
description = ''
List of overlays to apply to Nixpkgs.
This option allows modifying the Nixpkgs package set accessed through the `pkgs` module argument.

For details, see the [Overlays chapter in the Nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#chap-overlays).

<!-- TODO: Remove -->
Overlays specified using the {option}`nixpkgs.overlays` option will be
applied after the overlays that were already included in `nixpkgs.pkgs`.

<!--
TODO:
If the {option}`nixpkgs.pkgs` option is set, overlays specified using `nixpkgs.overlays`
will be applied after the overlays that were already included in `nixpkgs.pkgs`.
-->
'';
};
};

config = {
# For now we only set this when `nixpkgs.pkgs` is defined
# TODO: construct a default pkgs instance from pkgsPath and cfg options
# https://github.com/nix-community/nixvim/issues/1784
_module.args = lib.optionalAttrs opt.pkgs.isDefined {
config =
let
# TODO: construct a default pkgs instance from pkgsPath and cfg options
# https://github.com/nix-community/nixvim/issues/1784

finalPkgs =
if opt.pkgs.isDefined then
cfg.pkgs.appendOverlays cfg.overlays
else
# TODO: Remove once pkgs can be constructed internally
throw ''
nixvim: `nixpkgs.pkgs` is not defined. In the future, this option will be optional.
Currently a pkgs instance must be evaluated externally and assigned to `nixpkgs.pkgs` option.
'';
in
{
# We explicitly set the default override priority, so that we do not need
# to evaluate finalPkgs in case an override is placed on `_module.args.pkgs`.
# After all, to determine a definition priority, we need to evaluate `._type`,
# which is somewhat costly for Nixpkgs. With an explicit priority, we only
# evaluate the wrapper to find out that the priority is lower, and then we
# don't need to evaluate `finalPkgs`.
pkgs = lib.mkOverride lib.modules.defaultOverridePriority cfg.pkgs.__splicedPackages;
_module.args.pkgs = lib.mkOverride lib.modules.defaultOverridePriority finalPkgs.__splicedPackages;
};

assertions = [
{
# TODO: Remove or rephrase once pkgs can be constructed internally
assertion = config._module.args ? pkgs;
message = ''
`nixpkgs.pkgs` is not defined. In the future, this option will be optional.
Currently a pkgs instance must be evaluated externally and assigned to `nixpkgs.pkgs` option.
'';
}
];
};
}
7 changes: 7 additions & 0 deletions tests/main.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
linkFarm,
pkgs,
pkgsUnfree,
self,
system,
}:
let
fetchTests = callTest ./fetch-tests.nix { };
Expand All @@ -20,6 +22,11 @@ let
module = {
_file = file;
imports = [ module ];
_module.args = {
# Give tests access to the flake
inherit self system;
inherit (self) inputs;
};
};
pkgs = pkgsUnfree;
};
Expand Down
74 changes: 74 additions & 0 deletions tests/test-sources/modules/nixpkgs.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
# TODO: expect not setting `nixpkgs.pkgs` to throw

overlays =
{ pkgs, ... }:
{
test.runNvim = false;

nixpkgs.overlays = [
(final: prev: {
foobar = "foobar";
})
];

assertions = [
{
assertion = pkgs.foobar or null == "foobar";
message = ''
Expected `pkgs.foobar` to be "foobar"
'';
}
];
};

# Test that overlays from both `nixpkgs.pkgs` _and_ `nixpkgs.overlays` are applied
stacked_overlays =
{
inputs,
system,
pkgs,
...
}:
{
test.runNvim = false;

nixpkgs.pkgs = import inputs.nixpkgs {
inherit system;
overlays = [
(final: prev: {
foobar = "foobar";
conflict = "a";
})
];
};

nixpkgs.overlays = [
(final: prev: {
hello = "world";
conflict = "b";
})
];

assertions = [
{
assertion = pkgs.foobar or null == "foobar";
message = ''
Expected `pkgs.foobar` to be "foobar"
'';
}
{
assertion = pkgs.hello or null == "world";
message = ''
Expected `pkgs.hello` to be "world"
'';
}
{
assertion = pkgs.conflict or null == "b";
message = ''
Expected `pkgs.conflict` to be "b"
'';
}
];
};
}