29027fd1e1
Using pkgs.lib on the spine of module evaluation is problematic because the pkgs argument depends on the result of module evaluation. To prevent an infinite recursion, pkgs and some of the modules are evaluated twice, which is inefficient. Using ‘with lib’ prevents this problem.
184 lines
6 KiB
Nix
184 lines
6 KiB
Nix
# This module defines a global environment configuration and
|
|
# a common configuration for all shells.
|
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
cfg = config.environment;
|
|
|
|
in
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
environment.variables = mkOption {
|
|
default = {};
|
|
description = ''
|
|
A set of environment variables used in the global environment.
|
|
The value of each variable can be either a string or a list of
|
|
strings. The latter is concatenated, interspersed with colon
|
|
characters.
|
|
'';
|
|
type = types.attrsOf (mkOptionType {
|
|
name = "a string or a list of strings";
|
|
merge = loc: defs:
|
|
let
|
|
defs' = filterOverrides defs;
|
|
res = (head defs').value;
|
|
in
|
|
if isList res then concatLists (getValues defs')
|
|
else if lessThan 1 (length defs') then
|
|
throw "The option `${showOption loc}' is defined multiple times, in ${showFiles (getFiles defs)}."
|
|
else if !isString res then
|
|
throw "The option `${showOption loc}' does not have a string value, in ${showFiles (getFiles defs)}."
|
|
else res;
|
|
});
|
|
apply = mapAttrs (n: v: if isList v then concatStringsSep ":" v else v);
|
|
};
|
|
|
|
environment.profiles = mkOption {
|
|
default = [];
|
|
description = ''
|
|
A list of profiles used to setup the global environment.
|
|
'';
|
|
type = types.listOf types.string;
|
|
};
|
|
|
|
environment.profileVariables = mkOption {
|
|
default = (p: {});
|
|
description = ''
|
|
A function which given a profile path should give back
|
|
a set of environment variables for that profile.
|
|
'';
|
|
# !!! this should be of the following type:
|
|
#type = types.functionTo (types.attrsOf (types.optionSet envVar));
|
|
# and envVar should be changed to something more like environOpts.
|
|
# Having unique `value' _or_ multiple `list' is much more useful
|
|
# than just sticking everything together with ':' unconditionally.
|
|
# Anyway, to have this type mentioned above
|
|
# types.optionSet needs to be transformed into a type constructor
|
|
# (it has a !!! mark on that in nixpkgs)
|
|
# for now we hack all this to be
|
|
type = types.functionTo (types.attrsOf (types.listOf types.string));
|
|
};
|
|
|
|
# !!! isn't there a better way?
|
|
environment.extraInit = mkOption {
|
|
default = "";
|
|
description = ''
|
|
Shell script code called during global environment initialisation
|
|
after all variables and profileVariables have been set.
|
|
This code is asumed to be shell-independent, which means you should
|
|
stick to pure sh without sh word split.
|
|
'';
|
|
type = types.lines;
|
|
};
|
|
|
|
environment.shellInit = mkOption {
|
|
default = "";
|
|
description = ''
|
|
Shell script code called during shell initialisation.
|
|
This code is asumed to be shell-independent, which means you should
|
|
stick to pure sh without sh word split.
|
|
'';
|
|
type = types.lines;
|
|
};
|
|
|
|
environment.loginShellInit = mkOption {
|
|
default = "";
|
|
description = ''
|
|
Shell script code called during login shell initialisation.
|
|
This code is asumed to be shell-independent, which means you should
|
|
stick to pure sh without sh word split.
|
|
'';
|
|
type = types.lines;
|
|
};
|
|
|
|
environment.interactiveShellInit = mkOption {
|
|
default = "";
|
|
description = ''
|
|
Shell script code called during interactive shell initialisation.
|
|
This code is asumed to be shell-independent, which means you should
|
|
stick to pure sh without sh word split.
|
|
'';
|
|
type = types.lines;
|
|
};
|
|
|
|
environment.shellAliases = mkOption {
|
|
default = {};
|
|
example = { ll = "ls -l"; };
|
|
description = ''
|
|
An attribute set that maps aliases (the top level attribute names in
|
|
this option) to command strings or directly to build outputs. The
|
|
aliases are added to all users' shells.
|
|
'';
|
|
type = types.attrs; # types.attrsOf types.stringOrPath;
|
|
};
|
|
|
|
environment.binsh = mkOption {
|
|
default = "${config.system.build.binsh}/bin/sh";
|
|
example = "\${pkgs.dash}/bin/dash";
|
|
type = types.path;
|
|
description = ''
|
|
The shell executable that is linked system-wide to
|
|
<literal>/bin/sh</literal>. Please note that NixOS assumes all
|
|
over the place that shell to be Bash, so override the default
|
|
setting only if you know exactly what you're doing.
|
|
'';
|
|
};
|
|
|
|
environment.shells = mkOption {
|
|
default = [];
|
|
example = [ "/run/current-system/sw/bin/zsh" ];
|
|
description = ''
|
|
A list of permissible login shells for user accounts.
|
|
No need to mention <literal>/bin/sh</literal>
|
|
here, it is placed into this list implicitly.
|
|
'';
|
|
type = types.listOf types.path;
|
|
};
|
|
|
|
};
|
|
|
|
config = {
|
|
|
|
system.build.binsh = pkgs.bashInteractive;
|
|
|
|
environment.etc."shells".text =
|
|
''
|
|
${concatStringsSep "\n" cfg.shells}
|
|
/bin/sh
|
|
'';
|
|
|
|
system.build.setEnvironment = pkgs.writeText "set-environment"
|
|
''
|
|
${concatStringsSep "\n" (
|
|
(mapAttrsToList (n: v: ''export ${n}="${concatStringsSep ":" v}"'')
|
|
# This line is a kind of a hack because of !!! note above
|
|
(zipAttrsWith (const concatLists) ([ (mapAttrs (n: v: [ v ]) cfg.variables) ] ++ map cfg.profileVariables cfg.profiles))))}
|
|
|
|
${cfg.extraInit}
|
|
|
|
# The setuid wrappers override other bin directories.
|
|
export PATH="${config.security.wrapperDir}:$PATH"
|
|
|
|
# ~/bin if it exists overrides other bin directories.
|
|
export PATH="$HOME/bin:$PATH"
|
|
'';
|
|
|
|
system.activationScripts.binsh = stringAfter [ "stdio" ]
|
|
''
|
|
# Create the required /bin/sh symlink; otherwise lots of things
|
|
# (notably the system() function) won't work.
|
|
mkdir -m 0755 -p /bin
|
|
ln -sfn "${cfg.binsh}" /bin/.sh.tmp
|
|
mv /bin/.sh.tmp /bin/sh # atomically replace /bin/sh
|
|
'';
|
|
|
|
};
|
|
|
|
}
|