mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-16 23:03:40 +01:00
b3f4040512
This change does two things: * "NixOSizes" environment variables generation. This allows some more error-checking and opens possibilities for a modular environment configuration. From now on the most of environment variables are generated directly by the nix code. Generating sh code that generates environment variables is left in a few places where nontrivial access to a local environment state is needed. * By doing the first change this patch untangles bash from the environment configuration and makes it trivial to add a support for other non bash-compatible shells. Now to the sad part. This change is quite large (and I'm not sure it's possible to split it) and yet is not quite complete, it needs some changes to nixpkgs to be perfect. See !!! comments in modules/config/shells-environment.nix. Main principle behind this change is "change environment generation and nothing else". In particular, shell configuration principles stay exactly the same as before.
202 lines
5.9 KiB
Nix
202 lines
5.9 KiB
Nix
# This module defines a global environment configuration and
|
|
# a common configuration for all shells.
|
|
|
|
{ config, pkgs, ... }:
|
|
|
|
with pkgs.lib;
|
|
|
|
let
|
|
|
|
cfg = config.environment;
|
|
|
|
environOpts = { name, config, ... }: {
|
|
|
|
options = {
|
|
|
|
value = mkOption {
|
|
example = "/foo/bin";
|
|
description =
|
|
''
|
|
Variable value.
|
|
Exactly one of this or <option>list</option> must be set.
|
|
'';
|
|
type = types.uniq types.string;
|
|
};
|
|
|
|
list = mkOption {
|
|
default = null;
|
|
example = [ "/foo/bin" "/bar/bin" ];
|
|
description =
|
|
''
|
|
Variable value.
|
|
Exactly one of this or <option>value</option> must be set.
|
|
'';
|
|
type = types.nullOr (types.listOf types.string);
|
|
};
|
|
|
|
};
|
|
|
|
config = {
|
|
value = mkIf (config.list != null)
|
|
(concatStringsSep ":" config.list);
|
|
};
|
|
|
|
};
|
|
|
|
in
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
environment.variables = mkOption {
|
|
default = {};
|
|
description = ''
|
|
A set of environment variables used in the global environment.
|
|
'';
|
|
type = types.attrsOf types.optionSet;
|
|
options = [ environOpts ];
|
|
};
|
|
|
|
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 = with pkgs.lib.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
|
|
'';
|
|
|
|
environment.etc."environment".text =
|
|
''
|
|
${concatStringsSep "\n" (
|
|
(mapAttrsToList (n: v: ''export ${n}="${concatStringsSep ":" v}"'')
|
|
# This line is a kind of a hack because of !!! note above
|
|
(fold (mergeAttrsWithFunc concat) {} ([ (mapAttrs (n: v: [ v.value ]) 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
|
|
'';
|
|
|
|
};
|
|
|
|
}
|