Switch to extended Nixpkg's lib

This change makes use of the `extend` function inside `lib` to inject
a new `hm` field containing the Home Manager library functions. This
simplifies use of the Home Manager library in the modules and reduces
the risk of accidental infinite recursion.

PR #994
This commit is contained in:
Robert Helgesson 2020-01-16 23:41:14 +01:00
parent c8323a0bf1
commit 6e4b9af080
No known key found for this signature in database
GPG key ID: 36BDAA14C2797E89
19 changed files with 136 additions and 75 deletions

View file

@ -1,18 +1,20 @@
{ pkgs }: {
# Note, this should be "the standard library" + HM extensions.
lib
, pkgs
}:
let let
lib = pkgs.lib;
nmdSrc = pkgs.fetchFromGitLab { nmdSrc = pkgs.fetchFromGitLab {
name = "nmd"; name = "nmd";
owner = "rycee"; owner = "rycee";
repo = "nmd"; repo = "nmd";
rev = "9751ca5ef6eb2ef27470010208d4c0a20e89443d"; rev = "b437898c2b137c39d9c5f9a1cf62ec630f14d9fc";
sha256 = "0rbx10n8kk0bvp1nl5c8q79lz1w0p1b8103asbvwps3gmqd070hi"; sha256 = "18j1nh53cfpjpdiwn99x9kqpvr0s7hwngyc0a93xf4sg88ww93lq";
}; };
nmd = import nmdSrc { inherit pkgs; }; nmd = import nmdSrc { inherit lib pkgs; };
# Make sure the used package is scrubbed to avoid actually # Make sure the used package is scrubbed to avoid actually
# instantiating derivations. # instantiating derivations.
@ -29,7 +31,10 @@ let
hmModulesDocs = nmd.buildModulesDocs { hmModulesDocs = nmd.buildModulesDocs {
modules = modules =
import ../modules/modules.nix { inherit lib pkgs; } import ../modules/modules.nix {
inherit lib pkgs;
check = false;
}
++ [ scrubbedPkgsModule ]; ++ [ scrubbedPkgsModule ];
moduleRootPaths = [ ./.. ]; moduleRootPaths = [ ./.. ];
mkModuleUrl = path: mkModuleUrl = path:

View file

@ -36,6 +36,39 @@ home.file = {
Support for the list form will be removed in Home Manager version Support for the list form will be removed in Home Manager version
20.09. 20.09.
* The `lib` function attribute given to modules is now enriched with
an attribute `hm` containing extra library functions specific for Home
Manager. More specifically, `lib.hm` is now the same as `config.lib`
and should be the preferred choice since it is more robust.
+
Therefore, if your configuration makes use of, for example,
`config.lib.dag` to create activation script blocks, it is recommended
to change to `lib.hm.dag`.
+
Note, in the unlikely case that you are
+
** using Home Manager's NixOS or nix-darwin module,
** have made your own Home Manager module containing an top-level
option named `config` or `options`, and
** assign to this option in your system configuration inside a plain
attribute set, i.e., without a function argument,
+
then you must update your configuration to perform the option
assignment inside a `config` attribute. For example, instead of
+
[source,nix]
----
home-manager.users.jane = { config = "foo"; };
----
+
use
+
[source,nix]
----
home-manager.users.jane = { config.config = "foo"; };
----
[[sec-release-20.03-state-version-changes]] [[sec-release-20.03-state-version-changes]]
=== State Version Changes === State Version Changes

View file

@ -19,10 +19,16 @@ let
in in
fold f res res.config.warnings; fold f res res.config.warnings;
rawModule = lib.evalModules { extendedLib = import ./lib/stdlib-extended.nix pkgs.lib;
modules =
[ configuration ] hmModules =
++ (import ./modules.nix { inherit check lib pkgs; }); import ./modules.nix {
inherit check pkgs;
lib = extendedLib;
};
rawModule = extendedLib.evalModules {
modules = [ configuration ] ++ hmModules;
specialArgs = { specialArgs = {
modulesPath = builtins.toString ./.; modulesPath = builtins.toString ./.;
}; };

View file

@ -6,8 +6,6 @@ let
cfg = config.home.file; cfg = config.home.file;
dag = config.lib.dag;
homeDirectory = config.home.homeDirectory; homeDirectory = config.home.homeDirectory;
fileType = (import lib/file-type.nix { fileType = (import lib/file-type.nix {
@ -43,7 +41,7 @@ in
config = { config = {
# This verifies that the links we are about to create will not # This verifies that the links we are about to create will not
# overwrite an existing file. # overwrite an existing file.
home.activation.checkLinkTargets = dag.entryBefore ["writeBoundary"] ( home.activation.checkLinkTargets = hm.dag.entryBefore ["writeBoundary"] (
let let
check = pkgs.writeText "check" '' check = pkgs.writeText "check" ''
. ${./lib-bash/color-echo.sh} . ${./lib-bash/color-echo.sh}
@ -113,7 +111,7 @@ in
# and a failure during the intermediate state FA ∩ FB will not # and a failure during the intermediate state FA ∩ FB will not
# result in lost links because this set of links are in both the # result in lost links because this set of links are in both the
# source and target generation. # source and target generation.
home.activation.linkGeneration = dag.entryAfter ["writeBoundary"] ( home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] (
let let
link = pkgs.writeText "link" '' link = pkgs.writeText "link" ''
newGenFiles="$1" newGenFiles="$1"
@ -210,7 +208,7 @@ in
'' ''
); );
home.activation.checkFilesChanged = dag.entryBefore ["linkGeneration"] ( home.activation.checkFilesChanged = hm.dag.entryBefore ["linkGeneration"] (
'' ''
declare -A changedFiles declare -A changedFiles
'' + concatMapStrings (v: '' '' + concatMapStrings (v: ''
@ -220,7 +218,7 @@ in
'') (filter (v: v.onChange != "") (attrValues cfg)) '') (filter (v: v.onChange != "") (attrValues cfg))
); );
home.activation.onFilesChange = dag.entryAfter ["linkGeneration"] ( home.activation.onFilesChange = hm.dag.entryAfter ["linkGeneration"] (
concatMapStrings (v: '' concatMapStrings (v: ''
if [[ ${"$\{changedFiles"}["${v.target}"]} -eq 1 ]]; then if [[ ${"$\{changedFiles"}["${v.target}"]} -eq 1 ]]; then
${v.onChange} ${v.onChange}

View file

@ -6,9 +6,6 @@ let
cfg = config.home; cfg = config.home;
dag = config.lib.dag;
dagOf = (import ./lib/types.nix { inherit dag lib; }).dagOf;
languageSubModule = types.submodule { languageSubModule = types.submodule {
options = { options = {
base = mkOption { base = mkOption {
@ -235,11 +232,11 @@ in
}; };
home.activation = mkOption { home.activation = mkOption {
type = dagOf types.str; type = hm.types.dagOf types.str;
default = {}; default = {};
example = literalExample '' example = literalExample ''
{ {
myActivationAction = config.lib.dag.entryAfter ["writeBoundary"] ''' myActivationAction = lib.hm.dag.entryAfter ["writeBoundary"] '''
$DRY_RUN_CMD ln -s $VERBOSE_ARG \ $DRY_RUN_CMD ln -s $VERBOSE_ARG \
''${builtins.toPath ./link-me-directly} $HOME ''${builtins.toPath ./link-me-directly} $HOME
'''; ''';
@ -362,7 +359,7 @@ in
# A dummy entry acting as a boundary between the activation # A dummy entry acting as a boundary between the activation
# script's "check" and the "write" phases. # script's "check" and the "write" phases.
home.activation.writeBoundary = dag.entryAnywhere ""; home.activation.writeBoundary = hm.dag.entryAnywhere "";
# Install packages to the user environment. # Install packages to the user environment.
# #
@ -379,7 +376,7 @@ in
# In case the user has moved from a user-install of Home Manager # In case the user has moved from a user-install of Home Manager
# to a submodule managed one we attempt to uninstall the # to a submodule managed one we attempt to uninstall the
# `home-manager-path` package if it is installed. # `home-manager-path` package if it is installed.
home.activation.installPackages = dag.entryAfter ["writeBoundary"] ( home.activation.installPackages = hm.dag.entryAfter ["writeBoundary"] (
if config.submoduleSupport.externalPackageInstall if config.submoduleSupport.externalPackageInstall
then then
'' ''
@ -399,7 +396,7 @@ in
noteEcho Activating ${res.name} noteEcho Activating ${res.name}
${res.data} ${res.data}
''; '';
sortedCommands = dag.topoSort cfg.activation; sortedCommands = hm.dag.topoSort cfg.activation;
activationCmds = activationCmds =
if sortedCommands ? result then if sortedCommands ? result then
concatStringsSep "\n" (map mkCmd sortedCommands.result) concatStringsSep "\n" (map mkCmd sortedCommands.result)

View file

@ -1,6 +1,6 @@
{ lib }: { lib }:
{ rec {
dag = dag =
let let
d = import ./dag.nix { inherit lib; }; d = import ./dag.nix { inherit lib; };
@ -17,6 +17,7 @@
}; };
strings = import ./strings.nix { inherit lib; }; strings = import ./strings.nix { inherit lib; };
types = import ./types.nix { inherit dag lib; };
shell = import ./shell.nix { inherit lib; }; shell = import ./shell.nix { inherit lib; };
zsh = import ./zsh.nix { inherit lib; }; zsh = import ./zsh.nix { inherit lib; };

View file

@ -2,12 +2,6 @@
with lib; with lib;
let
stringsExtra = import ./strings.nix { inherit lib; };
in
{ {
# Constructs a type suitable for a `home.file` like option. The # Constructs a type suitable for a `home.file` like option. The
# target path may be either absolute or relative, in which case it # target path may be either absolute or relative, in which case it
@ -93,7 +87,7 @@ in
source = mkIf (config.text != null) ( source = mkIf (config.text != null) (
mkDefault (pkgs.writeTextFile { mkDefault (pkgs.writeTextFile {
inherit (config) executable text; inherit (config) executable text;
name = stringsExtra.storeFileName name; name = hm.strings.storeFileName name;
}) })
); );
}; };

View file

@ -0,0 +1,11 @@
# Just a convenience function that returns the given Nixpkgs standard
# library extended with the HM library.
nixpkgsLib:
let
mkHmLib = import ./.;
in
nixpkgsLib.extend (self: super: {
hm = mkHmLib { lib = super; };
})

View file

@ -4,7 +4,6 @@ with lib;
let let
hmLib = import ./default.nix { inherit lib; };
typesDag = import ./types-dag.nix { inherit dag lib; }; typesDag = import ./types-dag.nix { inherit dag lib; };
in in

View file

@ -6,7 +6,7 @@ let
cfg = config.manual; cfg = config.manual;
docs = import ../doc { inherit pkgs; }; docs = import ../doc { inherit lib pkgs; };
in in

View file

@ -5,7 +5,6 @@ with lib;
let let
cfg = config.dconf; cfg = config.dconf;
dag = config.lib.dag;
toDconfIni = generators.toINI { mkKeyValue = mkIniKeyValue; }; toDconfIni = generators.toINI { mkKeyValue = mkIniKeyValue; };
@ -65,7 +64,7 @@ in
}; };
config = mkIf (cfg.enable && cfg.settings != {}) { config = mkIf (cfg.enable && cfg.settings != {}) {
home.activation.dconfSettings = dag.entryAfter ["installPackages"] ( home.activation.dconfSettings = hm.dag.entryAfter ["installPackages"] (
let let
iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni cfg.settings); iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni cfg.settings);
in in

View file

@ -5,7 +5,6 @@ with lib;
let let
cfg = config.qt; cfg = config.qt;
dag = config.lib.dag;
in in
@ -69,7 +68,7 @@ in
# Enable GTK+ style for Qt4 in either case. # Enable GTK+ style for Qt4 in either case.
# It doesnt support the platform theme packages. # It doesnt support the platform theme packages.
home.activation.useGtkThemeInQt4 = dag.entryAfter ["writeBoundary"] '' home.activation.useGtkThemeInQt4 = hm.dag.entryAfter ["writeBoundary"] ''
$DRY_RUN_CMD ${pkgs.crudini}/bin/crudini $VERBOSE_ARG \ $DRY_RUN_CMD ${pkgs.crudini}/bin/crudini $VERBOSE_ARG \
--set "${config.xdg.configHome}/Trolltech.conf" Qt style GTK+ --set "${config.xdg.configHome}/Trolltech.conf" Qt style GTK+
''; '';

View file

@ -1,4 +1,6 @@
{ pkgs { pkgs
# Note, this should be "the standard library" + HM extensions.
, lib , lib
# Whether to enable module type checking. # Whether to enable module type checking.
@ -167,7 +169,7 @@ let
config._module.args.baseModules = modules; config._module.args.baseModules = modules;
config._module.args.pkgs = lib.mkDefault pkgs; config._module.args.pkgs = lib.mkDefault pkgs;
config._module.check = check; config._module.check = check;
config.lib = import ./lib { inherit lib; }; config.lib = lib.hm;
config.nixpkgs.system = mkDefault pkgs.system; config.nixpkgs.system = mkDefault pkgs.system;
}; };

View file

@ -26,8 +26,6 @@ let
cfg = config.programs.info; cfg = config.programs.info;
dag = config.lib.dag;
# Indexes info files found in this location # Indexes info files found in this location
homeInfoPath = "${config.home.profileDirectory}/share/info"; homeInfoPath = "${config.home.profileDirectory}/share/info";
@ -57,7 +55,7 @@ in
home.sessionVariables.INFOPATH = home.sessionVariables.INFOPATH =
"${cfg.homeInfoDirLocation}\${INFOPATH:+:}\${INFOPATH}"; "${cfg.homeInfoDirLocation}\${INFOPATH:+:}\${INFOPATH}";
home.activation.createHomeInfoDir = dag.entryAfter ["installPackages"] '' home.activation.createHomeInfoDir = hm.dag.entryAfter ["installPackages"] ''
oPATH=$PATH oPATH=$PATH
export PATH="${lib.makeBinPath [ pkgs.gzip ]}''${PATH:+:}$PATH" export PATH="${lib.makeBinPath [ pkgs.gzip ]}''${PATH:+:}$PATH"
$DRY_RUN_CMD mkdir -p "${cfg.homeInfoDirLocation}" $DRY_RUN_CMD mkdir -p "${cfg.homeInfoDirLocation}"

View file

@ -4,8 +4,6 @@ with lib;
let let
dag = config.lib.dag;
cfg = config.programs.mbsync; cfg = config.programs.mbsync;
# Accounts for which mbsync is enabled. # Accounts for which mbsync is enabled.
@ -180,7 +178,7 @@ in
home.activation = mkIf (mbsyncAccounts != []) { home.activation = mkIf (mbsyncAccounts != []) {
createMaildir = createMaildir =
dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] '' hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
$DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${ $DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${
concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts
} }

View file

@ -6,8 +6,6 @@ let
cfg = config.systemd.user; cfg = config.systemd.user;
dag = config.lib.dag;
enabled = cfg.services != {} enabled = cfg.services != {}
|| cfg.sockets != {} || cfg.sockets != {}
|| cfg.targets != {} || cfg.targets != {}
@ -230,7 +228,7 @@ in
# running this from the NixOS module then XDG_RUNTIME_DIR is not # running this from the NixOS module then XDG_RUNTIME_DIR is not
# set and systemd commands will fail. We'll therefore have to # set and systemd commands will fail. We'll therefore have to
# set it ourselves in that case. # set it ourselves in that case.
home.activation.reloadSystemD = dag.entryAfter ["linkGeneration"] ( home.activation.reloadSystemD = hm.dag.entryAfter ["linkGeneration"] (
let let
autoReloadCmd = '' autoReloadCmd = ''
${pkgs.ruby}/bin/ruby ${./systemd-activate.rb} \ ${pkgs.ruby}/bin/ruby ${./systemd-activate.rb} \

View file

@ -6,17 +6,27 @@ let
cfg = config.home-manager; cfg = config.home-manager;
hmModule = types.submodule ({name, ...}: { extendedLib = import ../modules/lib/stdlib-extended.nix pkgs.lib;
imports = import ../modules/modules.nix { inherit lib pkgs; };
config = { hmModule = types.submoduleWith {
submoduleSupport.enable = true; specialArgs = { lib = extendedLib; };
submoduleSupport.externalPackageInstall = cfg.useUserPackages; modules = [(
{name, ...}: {
imports = import ../modules/modules.nix {
inherit pkgs;
lib = extendedLib;
};
home.username = config.users.users.${name}.name; config = {
home.homeDirectory = config.users.users.${name}.home; submoduleSupport.enable = true;
}; submoduleSupport.externalPackageInstall = cfg.useUserPackages;
});
home.username = config.users.users.${name}.name;
home.homeDirectory = config.users.users.${name}.home;
};
}
)];
};
in in

View file

@ -6,22 +6,32 @@ let
cfg = config.home-manager; cfg = config.home-manager;
hmModule = types.submodule ({name, ...}: { extendedLib = import ../modules/lib/stdlib-extended.nix pkgs.lib;
imports = import ../modules/modules.nix { inherit lib pkgs; };
config = { hmModule = types.submoduleWith {
submoduleSupport.enable = true; specialArgs = { lib = extendedLib; };
submoduleSupport.externalPackageInstall = cfg.useUserPackages; modules = [(
{name, ...}: {
imports = import ../modules/modules.nix {
inherit pkgs;
lib = extendedLib;
};
# The per-user directory inside /etc/profiles is not known by config = {
# fontconfig by default. submoduleSupport.enable = true;
fonts.fontconfig.enable = submoduleSupport.externalPackageInstall = cfg.useUserPackages;
cfg.useUserPackages && config.fonts.fontconfig.enable;
home.username = config.users.users.${name}.name; # The per-user directory inside /etc/profiles is not known by
home.homeDirectory = config.users.users.${name}.home; # fontconfig by default.
}; fonts.fontconfig.enable =
}); cfg.useUserPackages && config.fonts.fontconfig.enable;
home.username = config.users.users.${name}.name;
home.homeDirectory = config.users.users.${name}.home;
};
}
)];
};
serviceEnvironment = serviceEnvironment =
optionalAttrs (cfg.backupFileExtension != null) { optionalAttrs (cfg.backupFileExtension != null) {

View file

@ -2,18 +2,21 @@
let let
lib = import ../modules/lib/stdlib-extended.nix pkgs.lib;
nmt = pkgs.fetchFromGitLab { nmt = pkgs.fetchFromGitLab {
owner = "rycee"; owner = "rycee";
repo = "nmt"; repo = "nmt";
rev = "89fb12a2aaa8ec671e22a033162c7738be714305"; rev = "6f866d1acb89fa15cd3b62baa052deae1f685c0c";
sha256 = "07yc1jkgw8vhskzk937k9hfba401q8rn4sgj9baw3fkjl9zrbcyf"; sha256 = "1qr1shhapjn4nnd4k6hml69ri8vgz4l8lakjll5hc516shs9a9nn";
}; };
modules = import ../modules/modules.nix { inherit lib pkgs; check = false; };
in in
import nmt { import nmt {
inherit pkgs; inherit lib pkgs modules;
modules = import ../modules/modules.nix { inherit pkgs; lib = pkgs.lib; };
testedAttrPath = [ "home" "activationPackage" ]; testedAttrPath = [ "home" "activationPackage" ];
tests = { tests = {
browserpass = ./modules/programs/browserpass.nix; browserpass = ./modules/programs/browserpass.nix;