diff --git a/doc/default.nix b/doc/default.nix index acfa1f1e4..97c1914a5 100644 --- a/doc/default.nix +++ b/doc/default.nix @@ -1,18 +1,20 @@ -{ pkgs }: +{ + # Note, this should be "the standard library" + HM extensions. + lib +, pkgs +}: let - lib = pkgs.lib; - nmdSrc = pkgs.fetchFromGitLab { name = "nmd"; owner = "rycee"; repo = "nmd"; - rev = "9751ca5ef6eb2ef27470010208d4c0a20e89443d"; - sha256 = "0rbx10n8kk0bvp1nl5c8q79lz1w0p1b8103asbvwps3gmqd070hi"; + rev = "b437898c2b137c39d9c5f9a1cf62ec630f14d9fc"; + sha256 = "18j1nh53cfpjpdiwn99x9kqpvr0s7hwngyc0a93xf4sg88ww93lq"; }; - nmd = import nmdSrc { inherit pkgs; }; + nmd = import nmdSrc { inherit lib pkgs; }; # Make sure the used package is scrubbed to avoid actually # instantiating derivations. @@ -29,7 +31,10 @@ let hmModulesDocs = nmd.buildModulesDocs { modules = - import ../modules/modules.nix { inherit lib pkgs; } + import ../modules/modules.nix { + inherit lib pkgs; + check = false; + } ++ [ scrubbedPkgsModule ]; moduleRootPaths = [ ./.. ]; mkModuleUrl = path: diff --git a/doc/release-notes/rl-2003.adoc b/doc/release-notes/rl-2003.adoc index 290242056..fc1dcd7cf 100644 --- a/doc/release-notes/rl-2003.adoc +++ b/doc/release-notes/rl-2003.adoc @@ -36,6 +36,39 @@ home.file = { Support for the list form will be removed in Home Manager version 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]] === State Version Changes diff --git a/modules/default.nix b/modules/default.nix index 9f6404ff9..7f3494e4d 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -19,10 +19,16 @@ let in fold f res res.config.warnings; - rawModule = lib.evalModules { - modules = - [ configuration ] - ++ (import ./modules.nix { inherit check lib pkgs; }); + extendedLib = import ./lib/stdlib-extended.nix pkgs.lib; + + hmModules = + import ./modules.nix { + inherit check pkgs; + lib = extendedLib; + }; + + rawModule = extendedLib.evalModules { + modules = [ configuration ] ++ hmModules; specialArgs = { modulesPath = builtins.toString ./.; }; diff --git a/modules/files.nix b/modules/files.nix index 0fb5ec942..94b3aa565 100644 --- a/modules/files.nix +++ b/modules/files.nix @@ -6,8 +6,6 @@ let cfg = config.home.file; - dag = config.lib.dag; - homeDirectory = config.home.homeDirectory; fileType = (import lib/file-type.nix { @@ -43,7 +41,7 @@ in config = { # This verifies that the links we are about to create will not # overwrite an existing file. - home.activation.checkLinkTargets = dag.entryBefore ["writeBoundary"] ( + home.activation.checkLinkTargets = hm.dag.entryBefore ["writeBoundary"] ( let check = pkgs.writeText "check" '' . ${./lib-bash/color-echo.sh} @@ -113,7 +111,7 @@ in # and a failure during the intermediate state FA ∩ FB will not # result in lost links because this set of links are in both the # source and target generation. - home.activation.linkGeneration = dag.entryAfter ["writeBoundary"] ( + home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] ( let link = pkgs.writeText "link" '' newGenFiles="$1" @@ -210,7 +208,7 @@ in '' ); - home.activation.checkFilesChanged = dag.entryBefore ["linkGeneration"] ( + home.activation.checkFilesChanged = hm.dag.entryBefore ["linkGeneration"] ( '' declare -A changedFiles '' + concatMapStrings (v: '' @@ -220,7 +218,7 @@ in '') (filter (v: v.onChange != "") (attrValues cfg)) ); - home.activation.onFilesChange = dag.entryAfter ["linkGeneration"] ( + home.activation.onFilesChange = hm.dag.entryAfter ["linkGeneration"] ( concatMapStrings (v: '' if [[ ${"$\{changedFiles"}["${v.target}"]} -eq 1 ]]; then ${v.onChange} diff --git a/modules/home-environment.nix b/modules/home-environment.nix index c9515d4f3..0b2fb8f4e 100644 --- a/modules/home-environment.nix +++ b/modules/home-environment.nix @@ -6,9 +6,6 @@ let cfg = config.home; - dag = config.lib.dag; - dagOf = (import ./lib/types.nix { inherit dag lib; }).dagOf; - languageSubModule = types.submodule { options = { base = mkOption { @@ -235,11 +232,11 @@ in }; home.activation = mkOption { - type = dagOf types.str; + type = hm.types.dagOf types.str; default = {}; example = literalExample '' { - myActivationAction = config.lib.dag.entryAfter ["writeBoundary"] ''' + myActivationAction = lib.hm.dag.entryAfter ["writeBoundary"] ''' $DRY_RUN_CMD ln -s $VERBOSE_ARG \ ''${builtins.toPath ./link-me-directly} $HOME '''; @@ -362,7 +359,7 @@ in # A dummy entry acting as a boundary between the activation # script's "check" and the "write" phases. - home.activation.writeBoundary = dag.entryAnywhere ""; + home.activation.writeBoundary = hm.dag.entryAnywhere ""; # Install packages to the user environment. # @@ -379,7 +376,7 @@ in # In case the user has moved from a user-install of Home Manager # to a submodule managed one we attempt to uninstall the # `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 then '' @@ -399,7 +396,7 @@ in noteEcho Activating ${res.name} ${res.data} ''; - sortedCommands = dag.topoSort cfg.activation; + sortedCommands = hm.dag.topoSort cfg.activation; activationCmds = if sortedCommands ? result then concatStringsSep "\n" (map mkCmd sortedCommands.result) diff --git a/modules/lib/default.nix b/modules/lib/default.nix index 754713cab..6b2bbacc2 100644 --- a/modules/lib/default.nix +++ b/modules/lib/default.nix @@ -1,6 +1,6 @@ { lib }: -{ +rec { dag = let d = import ./dag.nix { inherit lib; }; @@ -17,6 +17,7 @@ }; strings = import ./strings.nix { inherit lib; }; + types = import ./types.nix { inherit dag lib; }; shell = import ./shell.nix { inherit lib; }; zsh = import ./zsh.nix { inherit lib; }; diff --git a/modules/lib/file-type.nix b/modules/lib/file-type.nix index efbb33b23..3096a6d37 100644 --- a/modules/lib/file-type.nix +++ b/modules/lib/file-type.nix @@ -2,12 +2,6 @@ with lib; -let - - stringsExtra = import ./strings.nix { inherit lib; }; - -in - { # Constructs a type suitable for a `home.file` like option. The # target path may be either absolute or relative, in which case it @@ -93,7 +87,7 @@ in source = mkIf (config.text != null) ( mkDefault (pkgs.writeTextFile { inherit (config) executable text; - name = stringsExtra.storeFileName name; + name = hm.strings.storeFileName name; }) ); }; diff --git a/modules/lib/stdlib-extended.nix b/modules/lib/stdlib-extended.nix new file mode 100644 index 000000000..307f7a07c --- /dev/null +++ b/modules/lib/stdlib-extended.nix @@ -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; }; + }) diff --git a/modules/lib/types.nix b/modules/lib/types.nix index da8b7d4f2..78a875f51 100644 --- a/modules/lib/types.nix +++ b/modules/lib/types.nix @@ -4,7 +4,6 @@ with lib; let - hmLib = import ./default.nix { inherit lib; }; typesDag = import ./types-dag.nix { inherit dag lib; }; in diff --git a/modules/manual.nix b/modules/manual.nix index e4c127c0d..ab01c4500 100644 --- a/modules/manual.nix +++ b/modules/manual.nix @@ -6,7 +6,7 @@ let cfg = config.manual; - docs = import ../doc { inherit pkgs; }; + docs = import ../doc { inherit lib pkgs; }; in diff --git a/modules/misc/dconf.nix b/modules/misc/dconf.nix index ef87f8972..f5c9bf714 100644 --- a/modules/misc/dconf.nix +++ b/modules/misc/dconf.nix @@ -5,7 +5,6 @@ with lib; let cfg = config.dconf; - dag = config.lib.dag; toDconfIni = generators.toINI { mkKeyValue = mkIniKeyValue; }; @@ -65,7 +64,7 @@ in }; config = mkIf (cfg.enable && cfg.settings != {}) { - home.activation.dconfSettings = dag.entryAfter ["installPackages"] ( + home.activation.dconfSettings = hm.dag.entryAfter ["installPackages"] ( let iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni cfg.settings); in diff --git a/modules/misc/qt.nix b/modules/misc/qt.nix index 60de87742..d0ba16d73 100644 --- a/modules/misc/qt.nix +++ b/modules/misc/qt.nix @@ -5,7 +5,6 @@ with lib; let cfg = config.qt; - dag = config.lib.dag; in @@ -69,7 +68,7 @@ in # Enable GTK+ style for Qt4 in either case. # It doesn’t 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 \ --set "${config.xdg.configHome}/Trolltech.conf" Qt style GTK+ ''; diff --git a/modules/modules.nix b/modules/modules.nix index 8087b8d3a..b38e7e794 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -1,4 +1,6 @@ { pkgs + + # Note, this should be "the standard library" + HM extensions. , lib # Whether to enable module type checking. @@ -167,7 +169,7 @@ let config._module.args.baseModules = modules; config._module.args.pkgs = lib.mkDefault pkgs; config._module.check = check; - config.lib = import ./lib { inherit lib; }; + config.lib = lib.hm; config.nixpkgs.system = mkDefault pkgs.system; }; diff --git a/modules/programs/info.nix b/modules/programs/info.nix index 93dcaf474..863bdcc19 100644 --- a/modules/programs/info.nix +++ b/modules/programs/info.nix @@ -26,8 +26,6 @@ let cfg = config.programs.info; - dag = config.lib.dag; - # Indexes info files found in this location homeInfoPath = "${config.home.profileDirectory}/share/info"; @@ -57,7 +55,7 @@ in home.sessionVariables.INFOPATH = "${cfg.homeInfoDirLocation}\${INFOPATH:+:}\${INFOPATH}"; - home.activation.createHomeInfoDir = dag.entryAfter ["installPackages"] '' + home.activation.createHomeInfoDir = hm.dag.entryAfter ["installPackages"] '' oPATH=$PATH export PATH="${lib.makeBinPath [ pkgs.gzip ]}''${PATH:+:}$PATH" $DRY_RUN_CMD mkdir -p "${cfg.homeInfoDirLocation}" diff --git a/modules/programs/mbsync.nix b/modules/programs/mbsync.nix index e50086bb2..7537f6d5c 100644 --- a/modules/programs/mbsync.nix +++ b/modules/programs/mbsync.nix @@ -4,8 +4,6 @@ with lib; let - dag = config.lib.dag; - cfg = config.programs.mbsync; # Accounts for which mbsync is enabled. @@ -180,7 +178,7 @@ in home.activation = mkIf (mbsyncAccounts != []) { createMaildir = - dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] '' + hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] '' $DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${ concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts } diff --git a/modules/systemd.nix b/modules/systemd.nix index 50bc0e346..561640205 100644 --- a/modules/systemd.nix +++ b/modules/systemd.nix @@ -6,8 +6,6 @@ let cfg = config.systemd.user; - dag = config.lib.dag; - enabled = cfg.services != {} || cfg.sockets != {} || cfg.targets != {} @@ -230,7 +228,7 @@ in # running this from the NixOS module then XDG_RUNTIME_DIR is not # set and systemd commands will fail. We'll therefore have to # set it ourselves in that case. - home.activation.reloadSystemD = dag.entryAfter ["linkGeneration"] ( + home.activation.reloadSystemD = hm.dag.entryAfter ["linkGeneration"] ( let autoReloadCmd = '' ${pkgs.ruby}/bin/ruby ${./systemd-activate.rb} \ diff --git a/nix-darwin/default.nix b/nix-darwin/default.nix index 1482c7bb2..24f042a7f 100644 --- a/nix-darwin/default.nix +++ b/nix-darwin/default.nix @@ -6,17 +6,27 @@ let cfg = config.home-manager; - hmModule = types.submodule ({name, ...}: { - imports = import ../modules/modules.nix { inherit lib pkgs; }; + extendedLib = import ../modules/lib/stdlib-extended.nix pkgs.lib; - config = { - submoduleSupport.enable = true; - submoduleSupport.externalPackageInstall = cfg.useUserPackages; + hmModule = types.submoduleWith { + specialArgs = { lib = extendedLib; }; + modules = [( + {name, ...}: { + imports = import ../modules/modules.nix { + inherit pkgs; + lib = extendedLib; + }; - home.username = config.users.users.${name}.name; - home.homeDirectory = config.users.users.${name}.home; - }; - }); + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; + + home.username = config.users.users.${name}.name; + home.homeDirectory = config.users.users.${name}.home; + }; + } + )]; + }; in diff --git a/nixos/default.nix b/nixos/default.nix index f53b4d4d6..6b7d559a6 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -6,22 +6,32 @@ let cfg = config.home-manager; - hmModule = types.submodule ({name, ...}: { - imports = import ../modules/modules.nix { inherit lib pkgs; }; + extendedLib = import ../modules/lib/stdlib-extended.nix pkgs.lib; - config = { - submoduleSupport.enable = true; - submoduleSupport.externalPackageInstall = cfg.useUserPackages; + hmModule = types.submoduleWith { + specialArgs = { lib = extendedLib; }; + modules = [( + {name, ...}: { + imports = import ../modules/modules.nix { + inherit pkgs; + lib = extendedLib; + }; - # The per-user directory inside /etc/profiles is not known by - # fontconfig by default. - fonts.fontconfig.enable = - cfg.useUserPackages && config.fonts.fontconfig.enable; + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; - home.username = config.users.users.${name}.name; - home.homeDirectory = config.users.users.${name}.home; - }; - }); + # The per-user directory inside /etc/profiles is not known by + # 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 = optionalAttrs (cfg.backupFileExtension != null) { diff --git a/tests/default.nix b/tests/default.nix index 6f2b5ec04..ab5e4a005 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -2,18 +2,21 @@ let + lib = import ../modules/lib/stdlib-extended.nix pkgs.lib; + nmt = pkgs.fetchFromGitLab { owner = "rycee"; repo = "nmt"; - rev = "89fb12a2aaa8ec671e22a033162c7738be714305"; - sha256 = "07yc1jkgw8vhskzk937k9hfba401q8rn4sgj9baw3fkjl9zrbcyf"; + rev = "6f866d1acb89fa15cd3b62baa052deae1f685c0c"; + sha256 = "1qr1shhapjn4nnd4k6hml69ri8vgz4l8lakjll5hc516shs9a9nn"; }; + modules = import ../modules/modules.nix { inherit lib pkgs; check = false; }; + in import nmt { - inherit pkgs; - modules = import ../modules/modules.nix { inherit pkgs; lib = pkgs.lib; }; + inherit lib pkgs modules; testedAttrPath = [ "home" "activationPackage" ]; tests = { browserpass = ./modules/programs/browserpass.nix;