Remove a few format exceptions

This commit is contained in:
Robert Helgesson 2021-07-18 23:34:50 +02:00
parent 82b06103ae
commit 41903a14b0
No known key found for this signature in database
GPG Key ID: 36BDAA14C2797E89
11 changed files with 283 additions and 374 deletions

10
format
View File

@ -26,25 +26,15 @@ find . -name '*.nix' \
! -path ./modules/lib/file-type.nix \ ! -path ./modules/lib/file-type.nix \
! -path ./modules/manual.nix \ ! -path ./modules/manual.nix \
! -path ./modules/misc/news.nix \ ! -path ./modules/misc/news.nix \
! -path ./modules/misc/nixpkgs.nix \
! -path ./modules/misc/xdg.nix \
! -path ./modules/modules.nix \
! -path ./modules/programs/bash.nix \ ! -path ./modules/programs/bash.nix \
! -path ./modules/programs/firefox.nix \
! -path ./modules/programs/gpg.nix \ ! -path ./modules/programs/gpg.nix \
! -path ./modules/programs/ssh.nix \ ! -path ./modules/programs/ssh.nix \
! -path ./modules/programs/tmux.nix \ ! -path ./modules/programs/tmux.nix \
! -path ./modules/programs/zsh.nix \ ! -path ./modules/programs/zsh.nix \
! -path ./modules/services/gpg-agent.nix \ ! -path ./modules/services/gpg-agent.nix \
! -path ./modules/services/mpd.nix \ ! -path ./modules/services/mpd.nix \
! -path ./modules/services/sxhkd.nix \
! -path ./modules/systemd.nix \
! -path ./nix-darwin/default.nix \ ! -path ./nix-darwin/default.nix \
! -path ./tests/default.nix \ ! -path ./tests/default.nix \
! -path ./tests/modules/home-environment/session-variables.nix \ ! -path ./tests/modules/home-environment/session-variables.nix \
! -path ./tests/modules/programs/gpg/override-defaults.nix \ ! -path ./tests/modules/programs/gpg/override-defaults.nix \
! -path ./tests/modules/programs/zsh/session-variables.nix \
! -path ./tests/modules/services/sxhkd/service.nix \
! -path ./tests/modules/systemd/services.nix \
! -path ./tests/modules/systemd/session-variables.nix \
-exec nixfmt $CHECK_ARG {} + -exec nixfmt $CHECK_ARG {} +

View File

@ -6,40 +6,31 @@ with lib;
let let
isConfig = x: isConfig = x: builtins.isAttrs x || builtins.isFunction x;
builtins.isAttrs x || builtins.isFunction x;
optCall = f: x: optCall = f: x: if builtins.isFunction f then f x else f;
if builtins.isFunction f
then f x
else f;
mergeConfig = lhs_: rhs_: mergeConfig = lhs_: rhs_:
let let
lhs = optCall lhs_ { inherit pkgs; }; lhs = optCall lhs_ { inherit pkgs; };
rhs = optCall rhs_ { inherit pkgs; }; rhs = optCall rhs_ { inherit pkgs; };
in in lhs // rhs // optionalAttrs (lhs ? packageOverrides) {
lhs // rhs //
optionalAttrs (lhs ? packageOverrides) {
packageOverrides = pkgs: packageOverrides = pkgs:
optCall lhs.packageOverrides pkgs // optCall lhs.packageOverrides pkgs
optCall (attrByPath ["packageOverrides"] ({}) rhs) pkgs; // optCall (attrByPath [ "packageOverrides" ] ({ }) rhs) pkgs;
} // } // optionalAttrs (lhs ? perlPackageOverrides) {
optionalAttrs (lhs ? perlPackageOverrides) {
perlPackageOverrides = pkgs: perlPackageOverrides = pkgs:
optCall lhs.perlPackageOverrides pkgs // optCall lhs.perlPackageOverrides pkgs
optCall (attrByPath ["perlPackageOverrides"] ({}) rhs) pkgs; // optCall (attrByPath [ "perlPackageOverrides" ] ({ }) rhs) pkgs;
}; };
configType = mkOptionType { configType = mkOptionType {
name = "nixpkgs-config"; name = "nixpkgs-config";
description = "nixpkgs config"; description = "nixpkgs config";
check = x: check = x:
let traceXIfNot = c: let traceXIfNot = c: if c x then true else lib.traceSeqN 1 x false;
if c x then true
else lib.traceSeqN 1 x false;
in traceXIfNot isConfig; in traceXIfNot isConfig;
merge = args: fold (def: mergeConfig def.value) {}; merge = args: fold (def: mergeConfig def.value) { };
}; };
overlayType = mkOptionType { overlayType = mkOptionType {
@ -49,13 +40,9 @@ let
merge = lib.mergeOneOption; merge = lib.mergeOneOption;
}; };
_pkgs = import pkgsPath ( _pkgs = import pkgsPath (filterAttrs (n: v: v != null) config.nixpkgs);
filterAttrs (n: v: v != null) config.nixpkgs
);
in in {
{
options.nixpkgs = { options.nixpkgs = {
config = mkOption { config = mkOption {
default = null; default = null;
@ -91,17 +78,16 @@ in
overlays = mkOption { overlays = mkOption {
default = null; default = null;
example = literalExample example = literalExample ''
'' [ (self: super: {
[ (self: super: { openssh = super.openssh.override {
openssh = super.openssh.override { hpnSupport = true;
hpnSupport = true; withKerberos = true;
withKerberos = true; kerberos = self.libkrb5;
kerberos = self.libkrb5;
};
}; };
) ] };
''; ) ]
'';
type = types.nullOr (types.listOf overlayType); type = types.nullOr (types.listOf overlayType);
description = '' description = ''
List of overlays to use with the Nix Packages collection. (For List of overlays to use with the Nix Packages collection. (For
@ -144,9 +130,10 @@ in
_module.args = { _module.args = {
pkgs = mkOverride modules.defaultPriority _pkgs; pkgs = mkOverride modules.defaultPriority _pkgs;
pkgs_i686 = pkgs_i686 =
if _pkgs.stdenv.isLinux && _pkgs.stdenv.hostPlatform.isx86 if _pkgs.stdenv.isLinux && _pkgs.stdenv.hostPlatform.isx86 then
then _pkgs.pkgsi686Linux _pkgs.pkgsi686Linux
else { }; else
{ };
}; };
}; };
} }

View File

@ -16,14 +16,10 @@ let
defaultDataHome = "${config.home.homeDirectory}/.local/share"; defaultDataHome = "${config.home.homeDirectory}/.local/share";
getXdgDir = name: fallback: getXdgDir = name: fallback:
let let value = builtins.getEnv name;
value = builtins.getEnv name; in if value != "" then value else fallback;
in
if value != "" then value else fallback;
in in {
{
options.xdg = { options.xdg = {
enable = mkEnableOption "management of XDG base directories"; enable = mkEnableOption "management of XDG base directories";
@ -37,7 +33,7 @@ in
configFile = mkOption { configFile = mkOption {
type = fileType "<varname>xdg.configHome</varname>" cfg.configHome; type = fileType "<varname>xdg.configHome</varname>" cfg.configHome;
default = {}; default = { };
description = '' description = ''
Attribute set of files to link into the user's XDG Attribute set of files to link into the user's XDG
configuration home. configuration home.
@ -54,7 +50,7 @@ in
dataFile = mkOption { dataFile = mkOption {
type = fileType "<varname>xdg.dataHome</varname>" cfg.dataHome; type = fileType "<varname>xdg.dataHome</varname>" cfg.dataHome;
default = {}; default = { };
description = '' description = ''
Attribute set of files to link into the user's XDG Attribute set of files to link into the user's XDG
data home. data home.

View File

@ -1,14 +1,13 @@
{ pkgs { pkgs
# Note, this should be "the standard library" + HM extensions. # Note, this should be "the standard library" + HM extensions.
, lib , lib
# Whether to enable module type checking. # Whether to enable module type checking.
, check ? true , check ? true
# If disabled, the pkgs attribute passed to this function is used instead. # If disabled, the pkgs attribute passed to this function is used instead.
, useNixpkgsModule ? true , useNixpkgsModule ? true }:
}:
with lib; with lib;
@ -237,8 +236,8 @@ let
pkgsModule = { config, ... }: { pkgsModule = { config, ... }: {
config = { config = {
_module.args.baseModules = modules; _module.args.baseModules = modules;
_module.args.pkgsPath = lib.mkDefault ( _module.args.pkgsPath = lib.mkDefault
if versionAtLeast config.home.stateVersion "20.09" then (if versionAtLeast config.home.stateVersion "20.09" then
pkgs.path pkgs.path
else else
<nixpkgs>); <nixpkgs>);
@ -250,6 +249,4 @@ let
}; };
}; };
in in modules ++ [ pkgsModule ]
modules ++ [ pkgsModule ]

View File

@ -9,19 +9,15 @@ let
cfg = config.programs.firefox; cfg = config.programs.firefox;
mozillaConfigPath = mozillaConfigPath =
if isDarwin if isDarwin then "Library/Application Support/Mozilla" else ".mozilla";
then "Library/Application Support/Mozilla"
else ".mozilla";
firefoxConfigPath = firefoxConfigPath = if isDarwin then
if isDarwin "Library/Application Support/Firefox"
then "Library/Application Support/Firefox" else
else "${mozillaConfigPath}/firefox"; "${mozillaConfigPath}/firefox";
profilesPath = profilesPath =
if isDarwin if isDarwin then "${firefoxConfigPath}/Profiles" else firefoxConfigPath;
then "${firefoxConfigPath}/Profiles"
else firefoxConfigPath;
# The extensions path shared by all profiles; will not be supported # The extensions path shared by all profiles; will not be supported
# by future Firefox versions. # by future Firefox versions.
@ -32,24 +28,17 @@ let
paths = cfg.extensions; paths = cfg.extensions;
}; };
profiles = profiles = flip mapAttrs' cfg.profiles (_: profile:
flip mapAttrs' cfg.profiles (_: profile: nameValuePair "Profile${toString profile.id}" {
nameValuePair "Profile${toString profile.id}" { Name = profile.name;
Name = profile.name; Path = if isDarwin then "Profiles/${profile.path}" else profile.path;
Path = IsRelative = 1;
if isDarwin Default = if profile.isDefault then 1 else 0;
then "Profiles/${profile.path}" }) // {
else profile.path; General = { StartWithLastProfile = 1; };
IsRelative = 1;
Default = if profile.isDefault then 1 else 0;
}
) // {
General = {
StartWithLastProfile = 1;
};
}; };
profilesIni = generators.toINI {} profiles; profilesIni = generators.toINI { } profiles;
mkUserJs = prefs: extraPrefs: '' mkUserJs = prefs: extraPrefs: ''
// Generated by Home Manager. // Generated by Home Manager.
@ -61,17 +50,15 @@ let
${extraPrefs} ${extraPrefs}
''; '';
in in {
{
meta.maintainers = [ maintainers.rycee ]; meta.maintainers = [ maintainers.rycee ];
imports = [ imports = [
(mkRemovedOptionModule ["programs" "firefox" "enableAdobeFlash"] (mkRemovedOptionModule [ "programs" "firefox" "enableAdobeFlash" ]
"Support for this option has been removed.") "Support for this option has been removed.")
(mkRemovedOptionModule ["programs" "firefox" "enableGoogleTalk"] (mkRemovedOptionModule [ "programs" "firefox" "enableGoogleTalk" ]
"Support for this option has been removed.") "Support for this option has been removed.")
(mkRemovedOptionModule ["programs" "firefox" "enableIcedTea"] (mkRemovedOptionModule [ "programs" "firefox" "enableIcedTea" ]
"Support for this option has been removed.") "Support for this option has been removed.")
]; ];
@ -81,10 +68,10 @@ in
package = mkOption { package = mkOption {
type = types.package; type = types.package;
default = default = if versionAtLeast config.home.stateVersion "19.09" then
if versionAtLeast config.home.stateVersion "19.09" pkgs.firefox
then pkgs.firefox else
else pkgs.firefox-unwrapped; pkgs.firefox-unwrapped;
defaultText = literalExample "pkgs.firefox"; defaultText = literalExample "pkgs.firefox";
example = literalExample '' example = literalExample ''
pkgs.firefox.override { pkgs.firefox.override {
@ -106,7 +93,7 @@ in
extensions = mkOption { extensions = mkOption {
type = types.listOf types.package; type = types.listOf types.package;
default = []; default = [ ];
example = literalExample '' example = literalExample ''
with pkgs.nur.repos.rycee.firefox-addons; [ with pkgs.nur.repos.rycee.firefox-addons; [
https-everywhere https-everywhere
@ -141,7 +128,7 @@ in
}; };
profiles = mkOption { profiles = mkOption {
type = types.attrsOf (types.submodule ({config, name, ...}: { type = types.attrsOf (types.submodule ({ config, name, ... }: {
options = { options = {
name = mkOption { name = mkOption {
type = types.str; type = types.str;
@ -159,7 +146,7 @@ in
settings = mkOption { settings = mkOption {
type = with types; attrsOf (either bool (either int str)); type = with types; attrsOf (either bool (either int str));
default = {}; default = { };
example = literalExample '' example = literalExample ''
{ {
"browser.startup.homepage" = "https://nixos.org"; "browser.startup.homepage" = "https://nixos.org";
@ -224,7 +211,7 @@ in
}; };
}; };
})); }));
default = {}; default = { };
description = "Attribute set of Firefox profiles."; description = "Attribute set of Firefox profiles.";
}; };
@ -243,36 +230,27 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
assertions = [ assertions = [
( (let
let defaults =
defaults = catAttrs "name" (filter (a: a.isDefault) (attrValues cfg.profiles));
catAttrs "name" (filter (a: a.isDefault) (attrValues cfg.profiles)); in {
in { assertion = cfg.profiles == { } || length defaults == 1;
assertion = cfg.profiles == {} || length defaults == 1; message = "Must have exactly one default Firefox profile but found "
message = + toString (length defaults) + optionalString (length defaults > 1)
"Must have exactly one default Firefox profile but found " (", namely " + concatStringsSep ", " defaults);
+ toString (length defaults) })
+ optionalString (length defaults > 1)
(", namely " + concatStringsSep ", " defaults);
}
)
( (let
let duplicates = filterAttrs (_: v: length v != 1) (zipAttrs
duplicates = (mapAttrsToList (n: v: { "${toString v.id}" = n; }) (cfg.profiles)));
filterAttrs (_: v: length v != 1)
(zipAttrs
(mapAttrsToList (n: v: { "${toString v.id}" = n; })
(cfg.profiles)));
mkMsg = n: v: " - ID ${n} is used by ${concatStringsSep ", " v}"; mkMsg = n: v: " - ID ${n} is used by ${concatStringsSep ", " v}";
in { in {
assertion = duplicates == {}; assertion = duplicates == { };
message = message = ''
"Must not have Firefox profiles with duplicate IDs but\n" Must not have Firefox profiles with duplicate IDs but
+ concatStringsSep "\n" (mapAttrsToList mkMsg duplicates); '' + concatStringsSep "\n" (mapAttrsToList mkMsg duplicates);
} })
)
]; ];
warnings = optional (cfg.enableGnomeExtensions or false) '' warnings = optional (cfg.enableGnomeExtensions or false) ''
@ -282,65 +260,53 @@ in
its example for how to do this. its example for how to do this.
''; '';
home.packages = home.packages = let
let # The configuration expected by the Firefox wrapper.
# The configuration expected by the Firefox wrapper. fcfg = { enableGnomeExtensions = cfg.enableGnomeExtensions; };
fcfg = {
enableGnomeExtensions = cfg.enableGnomeExtensions; # A bit of hackery to force a config into the wrapper.
browserName = cfg.package.browserName or (builtins.parseDrvName
cfg.package.name).name;
# The configuration expected by the Firefox wrapper builder.
bcfg = setAttrByPath [ browserName ] fcfg;
package = if isDarwin then
cfg.package
else if versionAtLeast config.home.stateVersion "19.09" then
cfg.package.override (old: { cfg = old.cfg or { } // fcfg; })
else
(pkgs.wrapFirefox.override { config = bcfg; }) cfg.package { };
in [ package ];
home.file = mkMerge ([{
"${mozillaConfigPath}/${extensionPath}" = mkIf (cfg.extensions != [ ]) {
source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
recursive = true;
};
"${firefoxConfigPath}/profiles.ini" =
mkIf (cfg.profiles != { }) { text = profilesIni; };
}] ++ flip mapAttrsToList cfg.profiles (_: profile: {
"${profilesPath}/${profile.path}/.keep".text = "";
"${profilesPath}/${profile.path}/chrome/userChrome.css" =
mkIf (profile.userChrome != "") { text = profile.userChrome; };
"${profilesPath}/${profile.path}/chrome/userContent.css" =
mkIf (profile.userContent != "") { text = profile.userContent; };
"${profilesPath}/${profile.path}/user.js" =
mkIf (profile.settings != { } || profile.extraConfig != "") {
text = mkUserJs profile.settings profile.extraConfig;
}; };
# A bit of hackery to force a config into the wrapper. "${profilesPath}/${profile.path}/extensions" =
browserName = cfg.package.browserName mkIf (cfg.extensions != [ ]) {
or (builtins.parseDrvName cfg.package.name).name;
# The configuration expected by the Firefox wrapper builder.
bcfg = setAttrByPath [browserName] fcfg;
package =
if isDarwin then
cfg.package
else if versionAtLeast config.home.stateVersion "19.09" then
cfg.package.override (old: { cfg = old.cfg or {} // fcfg; })
else
(pkgs.wrapFirefox.override { config = bcfg; }) cfg.package { };
in
[ package ];
home.file = mkMerge (
[{
"${mozillaConfigPath}/${extensionPath}" = mkIf (cfg.extensions != []) {
source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
recursive = true;
};
"${firefoxConfigPath}/profiles.ini" = mkIf (cfg.profiles != {}) {
text = profilesIni;
};
}]
++ flip mapAttrsToList cfg.profiles (_: profile: {
"${profilesPath}/${profile.path}/.keep".text = "";
"${profilesPath}/${profile.path}/chrome/userChrome.css" =
mkIf (profile.userChrome != "") {
text = profile.userChrome;
};
"${profilesPath}/${profile.path}/chrome/userContent.css" =
mkIf (profile.userContent != "") {
text = profile.userContent;
};
"${profilesPath}/${profile.path}/user.js" =
mkIf (profile.settings != {} || profile.extraConfig != "") {
text = mkUserJs profile.settings profile.extraConfig;
};
"${profilesPath}/${profile.path}/extensions" = mkIf (cfg.extensions != []) {
source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}"; source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
recursive = true; recursive = true;
force = true; force = true;
}; };
}) }));
);
}; };
} }

View File

@ -1,4 +1,4 @@
{config, lib, pkgs, ...}: { config, lib, pkgs, ... }:
with lib; with lib;
@ -6,22 +6,16 @@ let
cfg = config.services.sxhkd; cfg = config.services.sxhkd;
keybindingsStr = concatStringsSep "\n" ( keybindingsStr = concatStringsSep "\n" (mapAttrsToList (hotkey: command:
mapAttrsToList (hotkey: command: optionalString (command != null) ''
optionalString (command != null) '' ${hotkey}
${hotkey} ${command}
${command} '') cfg.keybindings);
''
)
cfg.keybindings
);
in in {
{
imports = [ imports = [
(mkRemovedOptionModule ["services" "sxhkd" "extraPath"] (mkRemovedOptionModule [ "services" "sxhkd" "extraPath" ]
"This option is no longer needed and can be removed.") "This option is no longer needed and can be removed.")
]; ];
options.services.sxhkd = { options.services.sxhkd = {
@ -31,19 +25,21 @@ in
type = types.package; type = types.package;
default = pkgs.sxhkd; default = pkgs.sxhkd;
defaultText = "pkgs.sxhkd"; defaultText = "pkgs.sxhkd";
description = "Package containing the <command>sxhkd</command> executable."; description =
"Package containing the <command>sxhkd</command> executable.";
}; };
extraOptions = mkOption { extraOptions = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = [ ]; default = [ ];
description = "Command line arguments to invoke <command>sxhkd</command> with."; description =
"Command line arguments to invoke <command>sxhkd</command> with.";
example = literalExample ''[ "-m 1" ]''; example = literalExample ''[ "-m 1" ]'';
}; };
keybindings = mkOption { keybindings = mkOption {
type = types.attrsOf (types.nullOr types.str); type = types.attrsOf (types.nullOr types.str);
default = {}; default = { };
description = "An attribute set that assigns hotkeys to commands."; description = "An attribute set that assigns hotkeys to commands.";
example = literalExample '' example = literalExample ''
{ {
@ -72,17 +68,14 @@ in
home.packages = [ cfg.package ]; home.packages = [ cfg.package ];
xdg.configFile."sxhkd/sxhkdrc".text = concatStringsSep "\n" [ xdg.configFile."sxhkd/sxhkdrc".text =
keybindingsStr concatStringsSep "\n" [ keybindingsStr cfg.extraConfig ];
cfg.extraConfig
];
xsession.initExtra = xsession.initExtra = let
let sxhkdCommand = "${cfg.package}/bin/sxhkd ${toString cfg.extraOptions}";
sxhkdCommand = "${cfg.package}/bin/sxhkd ${toString cfg.extraOptions}"; in ''
in '' systemctl --user stop sxhkd.scope 2> /dev/null || true
systemctl --user stop sxhkd.scope 2> /dev/null || true systemd-cat -t sxhkd systemd-run --user --scope -u sxhkd ${sxhkdCommand} &
systemd-cat -t sxhkd systemd-run --user --scope -u sxhkd ${sxhkdCommand} & '';
'';
}; };
} }

View File

@ -7,27 +7,28 @@ let
inherit (lib) getAttr hm isBool literalExample mkIf mkMerge mkOption types; inherit (lib) getAttr hm isBool literalExample mkIf mkMerge mkOption types;
# From <nixpkgs/nixos/modules/system/boot/systemd-lib.nix> # From <nixpkgs/nixos/modules/system/boot/systemd-lib.nix>
mkPathSafeName = lib.replaceChars ["@" ":" "\\" "[" "]"] ["-" "-" "-" "" ""]; mkPathSafeName =
lib.replaceChars [ "@" ":" "\\" "[" "]" ] [ "-" "-" "-" "" "" ];
enabled = cfg.services != {} enabled = cfg.services != { } # \
|| cfg.slices != {} || cfg.slices != { } # \
|| cfg.sockets != {} || cfg.sockets != { } # \
|| cfg.targets != {} || cfg.targets != { } # \
|| cfg.timers != {} || cfg.timers != { } # \
|| cfg.paths != {} || cfg.paths != { } # \
|| cfg.mounts != {} || cfg.mounts != { } # \
|| cfg.automounts != {} || cfg.automounts != { } # \
|| cfg.sessionVariables != {}; || cfg.sessionVariables != { };
toSystemdIni = lib.generators.toINI { toSystemdIni = lib.generators.toINI {
listsAsDuplicateKeys = true; listsAsDuplicateKeys = true;
mkKeyValue = key: value: mkKeyValue = key: value:
let let
value' = value' = if isBool value then
if isBool value then (if value then "true" else "false") (if value then "true" else "false")
else toString value; else
in toString value;
"${key}=${value'}"; in "${key}=${value'}";
}; };
buildService = style: name: serviceCfg: buildService = style: name: serviceCfg:
@ -43,32 +44,26 @@ let
destination = lib.escapeShellArg "/${filename}"; destination = lib.escapeShellArg "/${filename}";
} + "/${filename}"; } + "/${filename}";
wantedBy = target: wantedBy = target: {
{ name = "systemd/user/${target}.wants/${filename}";
name = "systemd/user/${target}.wants/${filename}";
value = { inherit source; };
};
in
lib.singleton {
name = "systemd/user/${filename}";
value = { inherit source; }; value = { inherit source; };
} };
++ in lib.singleton {
map wantedBy (serviceCfg.Install.WantedBy or []); name = "systemd/user/${filename}";
value = { inherit source; };
} ++ map wantedBy (serviceCfg.Install.WantedBy or [ ]);
buildServices = style: serviceCfgs: buildServices = style: serviceCfgs:
lib.concatLists (lib.mapAttrsToList (buildService style) serviceCfgs); lib.concatLists (lib.mapAttrsToList (buildService style) serviceCfgs);
servicesStartTimeoutMs = builtins.toString cfg.servicesStartTimeoutMs; servicesStartTimeoutMs = builtins.toString cfg.servicesStartTimeoutMs;
unitType = unitKind: with types; unitType = unitKind:
let with types;
primitive = either bool (either int str); let primitive = either bool (either int str);
in in attrsOf (attrsOf (attrsOf (either primitive (listOf primitive)))) // {
attrsOf (attrsOf (attrsOf (either primitive (listOf primitive)))) description = "systemd ${unitKind} unit configuration";
// { };
description = "systemd ${unitKind} unit configuration";
};
unitDescription = type: '' unitDescription = type: ''
Definition of systemd per-user ${type} units. Attributes are Definition of systemd per-user ${type} units. Attributes are
@ -82,31 +77,29 @@ let
</citerefentry>. </citerefentry>.
''; '';
unitExample = type: literalExample '' unitExample = type:
{ literalExample ''
${lib.toLower type}-name = { {
Unit = { ${lib.toLower type}-name = {
Description = "Example description"; Unit = {
Documentation = [ "man:example(1)" "man:example(5)" ]; Description = "Example description";
}; Documentation = [ "man:example(1)" "man:example(5)" ];
};
${type} = { ${type} = {
};
}; };
}; };
}; '';
'';
sessionVariables = mkIf (cfg.sessionVariables != {}) { sessionVariables = mkIf (cfg.sessionVariables != { }) {
"environment.d/10-home-manager.conf".text = "environment.d/10-home-manager.conf".text = lib.concatStringsSep "\n"
lib.concatStringsSep "\n" ( (lib.mapAttrsToList (n: v: "${n}=${toString v}") cfg.sessionVariables)
lib.mapAttrsToList (n: v: "${n}=${toString v}") cfg.sessionVariables + "\n";
) + "\n"; };
};
in in {
{
meta.maintainers = [ lib.maintainers.rycee ]; meta.maintainers = [ lib.maintainers.rycee ];
options = { options = {
@ -123,56 +116,56 @@ in
}; };
services = mkOption { services = mkOption {
default = {}; default = { };
type = unitType "service"; type = unitType "service";
description = unitDescription "service"; description = unitDescription "service";
example = unitExample "Service"; example = unitExample "Service";
}; };
slices = mkOption { slices = mkOption {
default = {}; default = { };
type = unitType "slices"; type = unitType "slices";
description = unitDescription "slices"; description = unitDescription "slices";
example = unitExample "Slices"; example = unitExample "Slices";
}; };
sockets = mkOption { sockets = mkOption {
default = {}; default = { };
type = unitType "socket"; type = unitType "socket";
description = unitDescription "socket"; description = unitDescription "socket";
example = unitExample "Socket"; example = unitExample "Socket";
}; };
targets = mkOption { targets = mkOption {
default = {}; default = { };
type = unitType "target"; type = unitType "target";
description = unitDescription "target"; description = unitDescription "target";
example = unitExample "Target"; example = unitExample "Target";
}; };
timers = mkOption { timers = mkOption {
default = {}; default = { };
type = unitType "timer"; type = unitType "timer";
description = unitDescription "timer"; description = unitDescription "timer";
example = unitExample "Timer"; example = unitExample "Timer";
}; };
paths = mkOption { paths = mkOption {
default = {}; default = { };
type = unitType "path"; type = unitType "path";
description = unitDescription "path"; description = unitDescription "path";
example = unitExample "Path"; example = unitExample "Path";
}; };
mounts = mkOption { mounts = mkOption {
default = {}; default = { };
type = unitType "mount"; type = unitType "mount";
description = unitDescription "mount"; description = unitDescription "mount";
example = unitExample "Mount"; example = unitExample "Mount";
}; };
automounts = mkOption { automounts = mkOption {
default = {}; default = { };
type = unitType "automount"; type = unitType "automount";
description = unitDescription "automount"; description = unitDescription "automount";
example = unitExample "Automount"; example = unitExample "Automount";
@ -180,10 +173,9 @@ in
startServices = mkOption { startServices = mkOption {
default = "suggest"; default = "suggest";
type = with types; either bool (enum ["suggest" "legacy" "sd-switch"]); type = with types;
apply = p: either bool (enum [ "suggest" "legacy" "sd-switch" ]);
if isBool p then if p then "legacy" else "suggest" apply = p: if isBool p then if p then "legacy" else "suggest" else p;
else p;
description = '' description = ''
Whether new or changed services that are wanted by active targets Whether new or changed services that are wanted by active targets
should be started. Additionally, stop obsolete services from the should be started. Additionally, stop obsolete services from the
@ -231,7 +223,7 @@ in
}; };
sessionVariables = mkOption { sessionVariables = mkOption {
default = {}; default = { };
type = with types; attrsOf (either int str); type = with types; attrsOf (either int str);
example = { EDITOR = "vim"; }; example = { EDITOR = "vim"; };
description = '' description = ''
@ -248,54 +240,44 @@ in
config = mkMerge [ config = mkMerge [
{ {
assertions = [ assertions = [{
{ assertion = enabled -> pkgs.stdenv.isLinux;
assertion = enabled -> pkgs.stdenv.isLinux; message = let
message = names = lib.concatStringsSep ", " (lib.attrNames ( # \
let cfg.services # \
names = lib.concatStringsSep ", " ( // cfg.slices # \
lib.attrNames ( // cfg.sockets # \
cfg.services // cfg.slices // cfg.sockets // cfg.targets // cfg.targets # \
// cfg.timers // cfg.paths // cfg.mounts // cfg.sessionVariables // cfg.timers # \
) // cfg.paths # \
); // cfg.mounts # \
in // cfg.sessionVariables));
"Must use Linux for modules that require systemd: " + names; in "Must use Linux for modules that require systemd: " + names;
} }];
];
} }
# If we run under a Linux system we assume that systemd is # If we run under a Linux system we assume that systemd is
# available, in particular we assume that systemctl is in PATH. # available, in particular we assume that systemctl is in PATH.
(mkIf pkgs.stdenv.isLinux { (mkIf pkgs.stdenv.isLinux {
xdg.configFile = mkMerge [ xdg.configFile = mkMerge [
(lib.listToAttrs ( (lib.listToAttrs ((buildServices "service" cfg.services)
(buildServices "service" cfg.services) ++ (buildServices "slices" cfg.slices)
++ ++ (buildServices "socket" cfg.sockets)
(buildServices "slices" cfg.slices) ++ (buildServices "target" cfg.targets)
++ ++ (buildServices "timer" cfg.timers)
(buildServices "socket" cfg.sockets) ++ (buildServices "path" cfg.paths)
++ ++ (buildServices "mount" cfg.mounts)
(buildServices "target" cfg.targets) ++ (buildServices "automount" cfg.automounts)))
++
(buildServices "timer" cfg.timers)
++
(buildServices "path" cfg.paths)
++
(buildServices "mount" cfg.mounts)
++
(buildServices "automount" cfg.automounts)
))
sessionVariables sessionVariables
]; ];
# Run systemd service reload if user is logged in. If we're # Run systemd service reload if user is logged in. If we're
# 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 = hm.dag.entryAfter ["linkGeneration"] ( home.activation.reloadSystemd = hm.dag.entryAfter [ "linkGeneration" ]
let (let
cmd = { cmd = {
suggest = '' suggest = ''
PATH=${dirOf cfg.systemctlPath}:$PATH \ PATH=${dirOf cfg.systemctlPath}:$PATH \
@ -306,44 +288,41 @@ in
${pkgs.ruby}/bin/ruby ${./systemd-activate.rb} \ ${pkgs.ruby}/bin/ruby ${./systemd-activate.rb} \
"''${oldGenPath=}" "$newGenPath" "${servicesStartTimeoutMs}" "''${oldGenPath=}" "$newGenPath" "${servicesStartTimeoutMs}"
''; '';
sd-switch = sd-switch = let
let timeoutArg = if cfg.servicesStartTimeoutMs != 0 then
timeoutArg = "--timeout " + servicesStartTimeoutMs
if cfg.servicesStartTimeoutMs != 0 then else
"--timeout " + servicesStartTimeoutMs "";
else in ''
""; ${pkgs.sd-switch}/bin/sd-switch \
in '' ''${DRY_RUN:+--dry-run} $VERBOSE_ARG ${timeoutArg} \
${pkgs.sd-switch}/bin/sd-switch \ ''${oldGenPath:+--old-units $oldGenPath/home-files/.config/systemd/user} \
''${DRY_RUN:+--dry-run} $VERBOSE_ARG ${timeoutArg} \ --new-units $newGenPath/home-files/.config/systemd/user
''${oldGenPath:+--old-units $oldGenPath/home-files/.config/systemd/user} \ '';
--new-units $newGenPath/home-files/.config/systemd/user
'';
}; };
ensureRuntimeDir = "XDG_RUNTIME_DIR=\${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"; ensureRuntimeDir =
"XDG_RUNTIME_DIR=\${XDG_RUNTIME_DIR:-/run/user/$(id -u)}";
systemctl = "${ensureRuntimeDir} ${cfg.systemctlPath}"; systemctl = "${ensureRuntimeDir} ${cfg.systemctlPath}";
in in ''
'' systemdStatus=$(${systemctl} --user is-system-running 2>&1 || true)
systemdStatus=$(${systemctl} --user is-system-running 2>&1 || true)
if [[ $systemdStatus == 'running' || $systemdStatus == 'degraded' ]]; then if [[ $systemdStatus == 'running' || $systemdStatus == 'degraded' ]]; then
if [[ $systemdStatus == 'degraded' ]]; then if [[ $systemdStatus == 'degraded' ]]; then
warnEcho "The user systemd session is degraded:" warnEcho "The user systemd session is degraded:"
${systemctl} --user --no-pager --state=failed ${systemctl} --user --no-pager --state=failed
warnEcho "Attempting to reload services anyway..." warnEcho "Attempting to reload services anyway..."
fi
${ensureRuntimeDir} \
${getAttr cfg.startServices cmd}
else
echo "User systemd daemon not running. Skipping reload."
fi fi
unset systemdStatus ${ensureRuntimeDir} \
'' ${getAttr cfg.startServices cmd}
); else
echo "User systemd daemon not running. Skipping reload."
fi
unset systemdStatus
'');
}) })
]; ];
} }

View File

@ -13,11 +13,8 @@ with lib;
}; };
}; };
nixpkgs.overlays = [ nixpkgs.overlays =
(self: super: { [ (self: super: { zsh = pkgs.writeScriptBin "dummy-zsh" ""; }) ];
zsh = pkgs.writeScriptBin "dummy-zsh" "";
})
];
nmt.script = '' nmt.script = ''
assertFileExists home-files/.zshrc assertFileExists home-files/.zshrc

View File

@ -9,7 +9,9 @@
services.sxhkd = { services.sxhkd = {
enable = true; enable = true;
package = pkgs.runCommandLocal "dummy-package" { } "mkdir $out" // { outPath = "@sxhkd@"; }; package = pkgs.runCommandLocal "dummy-package" { } "mkdir $out" // {
outPath = "@sxhkd@";
};
extraOptions = [ "-m 1" ]; extraOptions = [ "-m 1" ];
}; };

View File

@ -5,9 +5,7 @@ with lib;
{ {
config = { config = {
systemd.user.services."test-service@" = { systemd.user.services."test-service@" = {
Unit = { Unit = { Description = "A basic test service"; };
Description = "A basic test service";
};
Service = { Service = {
Environment = [ "VAR1=1" "VAR2=2" ]; Environment = [ "VAR1=1" "VAR2=2" ];
@ -19,15 +17,17 @@ with lib;
serviceFile=home-files/.config/systemd/user/test-service@.service serviceFile=home-files/.config/systemd/user/test-service@.service
assertFileExists $serviceFile assertFileExists $serviceFile
assertFileContent $serviceFile \ assertFileContent $serviceFile \
${builtins.toFile "services-expected.conf" '' ${
[Service] builtins.toFile "services-expected.conf" ''
Environment=VAR1=1 [Service]
Environment=VAR2=2 Environment=VAR1=1
ExecStart=/some/exec/start/command --with-arguments "%i" Environment=VAR2=2
ExecStart=/some/exec/start/command --with-arguments "%i"
[Unit] [Unit]
Description=A basic test service Description=A basic test service
''} ''
}
''; '';
}; };
} }

View File

@ -10,11 +10,13 @@
nmt.script = '' nmt.script = ''
envFile=home-files/.config/environment.d/10-home-manager.conf envFile=home-files/.config/environment.d/10-home-manager.conf
assertFileExists $envFile assertFileExists $envFile
assertFileContent $envFile ${pkgs.writeText "expected" '' assertFileContent $envFile ${
LOCALE_ARCHIVE_2_27=${pkgs.glibcLocales}/lib/locale/locale-archive pkgs.writeText "expected" ''
V_int=1 LOCALE_ARCHIVE_2_27=${pkgs.glibcLocales}/lib/locale/locale-archive
V_str=2 V_int=1
''} V_str=2
''
}
''; '';
}; };
} }