bash: Make interactive the default
The status quo of `bash` not being interactive is frustrating for many users,
because trying to use it interactively is just messed up, and
`bashInteractive` is not intuitive and barely discoverable.
This was brought to my (and many others) attention by @stahnma in his
[talk at CfgMgmtCamp 2025](https://cfp.cfgmgmtcamp.org/ghent2025/talk/YUVUTN/),
where he highlighted this as one of the frustrations he ran into when
learning Nix.
Why this is fine:
- No reason for not making interactive the default was given in the original commit (6c6ff6f36f), but probably it was due to the increase in closure size
- The closure size only increases by 6.9MiB (19.5%) today, with the
added dependency on the store paths for readline and ncurses, which
are needed on systems in almost all cases anyways
- If somebody really needs to get a more minimal system, they can use
the newly-introduced `bashNonInteractive` instead now
- Though to apply it consistently, they'll need to do that in an
overlay like
```
final: prev: {
bash = self.bashNonInteractive;
}
```
Or alternatively using the `system.replaceDependencies.replacements`
NixOS option approach.
While there's also other such `*Interactive` packages that could use the
same treatment, `bash` is a great start.
This was already attempted before in
https://github.com/NixOS/nixpkgs/pull/151227, but was not continued for
unknown reason.
To avoid stdenv becoming bigger, all uses of bash in the (working)
stdenv's are changed to the explicitly non-interactive version here.
This commit will however still cause a mass rebuild for all packages (and reverse deps)
making use of the default bash.
This commit is contained in:
@@ -22,7 +22,7 @@
|
|||||||
pkg-config,
|
pkg-config,
|
||||||
texinfo,
|
texinfo,
|
||||||
bison,
|
bison,
|
||||||
bash,
|
bashNonInteractive,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
@@ -79,7 +79,7 @@ stdenv.mkDerivation rec {
|
|||||||
buildInputs =
|
buildInputs =
|
||||||
[
|
[
|
||||||
perl
|
perl
|
||||||
bash
|
bashNonInteractive
|
||||||
]
|
]
|
||||||
++ lib.optionals enableGhostscript [
|
++ lib.optionals enableGhostscript [
|
||||||
ghostscript
|
ghostscript
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
lib,
|
lib,
|
||||||
autoreconfHook,
|
autoreconfHook,
|
||||||
bash,
|
bashNonInteractive,
|
||||||
libtool,
|
libtool,
|
||||||
fetchFromGitHub,
|
fetchFromGitHub,
|
||||||
nix-update-script,
|
nix-update-script,
|
||||||
@@ -48,7 +48,7 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
buildInputs = [
|
buildInputs = [
|
||||||
autoreconfHook
|
autoreconfHook
|
||||||
# For patchShebangs in postInstall
|
# For patchShebangs in postInstall
|
||||||
bash
|
bashNonInteractive
|
||||||
perl
|
perl
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
, zlib
|
, zlib
|
||||||
|
|
||||||
# platform-specific dependencies
|
# platform-specific dependencies
|
||||||
, bash
|
, bashNonInteractive
|
||||||
, darwin
|
, darwin
|
||||||
, windows
|
, windows
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ in with passthru; stdenv.mkDerivation (finalAttrs: {
|
|||||||
|
|
||||||
inherit nativeBuildInputs;
|
inherit nativeBuildInputs;
|
||||||
buildInputs = lib.optionals (!stdenv.hostPlatform.isWindows) [
|
buildInputs = lib.optionals (!stdenv.hostPlatform.isWindows) [
|
||||||
bash # only required for patchShebangs
|
bashNonInteractive # only required for patchShebangs
|
||||||
] ++ buildInputs;
|
] ++ buildInputs;
|
||||||
|
|
||||||
prePatch = optionalString stdenv.hostPlatform.isDarwin ''
|
prePatch = optionalString stdenv.hostPlatform.isDarwin ''
|
||||||
@@ -329,7 +329,7 @@ in with passthru; stdenv.mkDerivation (finalAttrs: {
|
|||||||
|
|
||||||
postPatch = optionalString (!stdenv.hostPlatform.isWindows) ''
|
postPatch = optionalString (!stdenv.hostPlatform.isWindows) ''
|
||||||
substituteInPlace Lib/subprocess.py \
|
substituteInPlace Lib/subprocess.py \
|
||||||
--replace-fail "'/bin/sh'" "'${bash}/bin/sh'"
|
--replace-fail "'/bin/sh'" "'${bashNonInteractive}/bin/sh'"
|
||||||
'' + optionalString mimetypesSupport ''
|
'' + optionalString mimetypesSupport ''
|
||||||
substituteInPlace Lib/mimetypes.py \
|
substituteInPlace Lib/mimetypes.py \
|
||||||
--replace-fail "@mime-types@" "${mailcap}"
|
--replace-fail "@mime-types@" "${mailcap}"
|
||||||
@@ -611,7 +611,7 @@ in with passthru; stdenv.mkDerivation (finalAttrs: {
|
|||||||
] ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
|
] ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
|
||||||
# Ensure we don't have references to build-time packages.
|
# Ensure we don't have references to build-time packages.
|
||||||
# These typically end up in shebangs.
|
# These typically end up in shebangs.
|
||||||
pythonOnBuildForHost buildPackages.bash
|
pythonOnBuildForHost buildPackages.bashNonInteractive
|
||||||
];
|
];
|
||||||
|
|
||||||
separateDebugInfo = true;
|
separateDebugInfo = true;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
lib,
|
lib,
|
||||||
fetchurl,
|
fetchurl,
|
||||||
libiconv,
|
libiconv,
|
||||||
bash,
|
bashNonInteractive,
|
||||||
updateAutotoolsGnuConfigScriptsHook,
|
updateAutotoolsGnuConfigScriptsHook,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ stdenv.mkDerivation rec {
|
|||||||
];
|
];
|
||||||
buildInputs =
|
buildInputs =
|
||||||
lib.optionals (!stdenv.hostPlatform.isMinGW) [
|
lib.optionals (!stdenv.hostPlatform.isMinGW) [
|
||||||
bash
|
bashNonInteractive
|
||||||
]
|
]
|
||||||
++ lib.optionals (!stdenv.hostPlatform.isLinux && !stdenv.hostPlatform.isCygwin) [
|
++ lib.optionals (!stdenv.hostPlatform.isLinux && !stdenv.hostPlatform.isCygwin) [
|
||||||
# HACK, see #10874 (and 14664)
|
# HACK, see #10874 (and 14664)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
fetchurl,
|
fetchurl,
|
||||||
perl,
|
perl,
|
||||||
libintl,
|
libintl,
|
||||||
bash,
|
bashNonInteractive,
|
||||||
updateAutotoolsGnuConfigScriptsHook,
|
updateAutotoolsGnuConfigScriptsHook,
|
||||||
gnulib,
|
gnulib,
|
||||||
gawk,
|
gawk,
|
||||||
@@ -83,7 +83,7 @@ stdenv.mkDerivation {
|
|||||||
nativeBuildInputs = [ updateAutotoolsGnuConfigScriptsHook ];
|
nativeBuildInputs = [ updateAutotoolsGnuConfigScriptsHook ];
|
||||||
buildInputs =
|
buildInputs =
|
||||||
[
|
[
|
||||||
bash
|
bashNonInteractive
|
||||||
libintl
|
libintl
|
||||||
]
|
]
|
||||||
++ optionals stdenv.hostPlatform.isSunOS [
|
++ optionals stdenv.hostPlatform.isSunOS [
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
fetchurl,
|
fetchurl,
|
||||||
perl,
|
perl,
|
||||||
libintl,
|
libintl,
|
||||||
bash,
|
bashNonInteractive,
|
||||||
updateAutotoolsGnuConfigScriptsHook,
|
updateAutotoolsGnuConfigScriptsHook,
|
||||||
gnulib,
|
gnulib,
|
||||||
gawk,
|
gawk,
|
||||||
@@ -57,7 +57,7 @@ let
|
|||||||
xz
|
xz
|
||||||
libintl
|
libintl
|
||||||
libiconv
|
libiconv
|
||||||
bash
|
bashNonInteractive
|
||||||
gnulib
|
gnulib
|
||||||
gawk
|
gawk
|
||||||
freebsd
|
freebsd
|
||||||
|
|||||||
@@ -6,8 +6,7 @@
|
|||||||
, bison
|
, bison
|
||||||
, util-linux
|
, util-linux
|
||||||
|
|
||||||
# patch for cygwin requires readline support
|
, interactive ? true
|
||||||
, interactive ? stdenv.hostPlatform.isCygwin
|
|
||||||
, readline
|
, readline
|
||||||
, withDocs ? null
|
, withDocs ? null
|
||||||
, forFHSEnv ? false
|
, forFHSEnv ? false
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ let
|
|||||||
runtimeShell = prevStage.ccWrapperStdenv.shell;
|
runtimeShell = prevStage.ccWrapperStdenv.shell;
|
||||||
};
|
};
|
||||||
|
|
||||||
bash = prevStage.bash or bootstrapTools;
|
bashNonInteractive = prevStage.bashNonInteractive or bootstrapTools;
|
||||||
|
|
||||||
thisStdenv = import ../generic {
|
thisStdenv = import ../generic {
|
||||||
name = "${name}-stdenv-darwin";
|
name = "${name}-stdenv-darwin";
|
||||||
@@ -168,7 +168,7 @@ let
|
|||||||
inherit extraNativeBuildInputs;
|
inherit extraNativeBuildInputs;
|
||||||
|
|
||||||
preHook =
|
preHook =
|
||||||
lib.optionalString (!isBuiltByNixpkgsCompiler bash) ''
|
lib.optionalString (!isBuiltByNixpkgsCompiler bashNonInteractive) ''
|
||||||
# Don't patch #!/interpreter because it leads to retained
|
# Don't patch #!/interpreter because it leads to retained
|
||||||
# dependencies on the bootstrapTools in the final stdenv.
|
# dependencies on the bootstrapTools in the final stdenv.
|
||||||
dontPatchShebangs=1
|
dontPatchShebangs=1
|
||||||
@@ -181,9 +181,9 @@ let
|
|||||||
export PATH_LOCALE=${prevStage.darwin.locale}/share/locale
|
export PATH_LOCALE=${prevStage.darwin.locale}/share/locale
|
||||||
'';
|
'';
|
||||||
|
|
||||||
shell = bash + "/bin/bash";
|
shell = bashNonInteractive + "/bin/bash";
|
||||||
initialPath = [
|
initialPath = [
|
||||||
bash
|
bashNonInteractive
|
||||||
prevStage.file
|
prevStage.file
|
||||||
bootstrapTools
|
bootstrapTools
|
||||||
];
|
];
|
||||||
@@ -328,7 +328,7 @@ let
|
|||||||
# SDK packages include propagated packages and source release packages built during the bootstrap.
|
# SDK packages include propagated packages and source release packages built during the bootstrap.
|
||||||
sdkPackages = prevStage: {
|
sdkPackages = prevStage: {
|
||||||
inherit (prevStage)
|
inherit (prevStage)
|
||||||
bash
|
bashNonInteractive
|
||||||
libpng
|
libpng
|
||||||
libxml2
|
libxml2
|
||||||
libxo
|
libxo
|
||||||
@@ -408,7 +408,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
|
|||||||
# stage should only access the stage that came before it.
|
# stage should only access the stage that came before it.
|
||||||
ccWrapperStdenv = self.stdenv;
|
ccWrapperStdenv = self.stdenv;
|
||||||
|
|
||||||
bash = bootstrapTools // {
|
bashNonInteractive = bootstrapTools // {
|
||||||
shellPath = "/bin/bash";
|
shellPath = "/bin/bash";
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -600,7 +600,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
|
|||||||
(llvmLibrariesPackages prevStage)
|
(llvmLibrariesPackages prevStage)
|
||||||
{
|
{
|
||||||
inherit (prevStage)
|
inherit (prevStage)
|
||||||
bash
|
bashNonInteractive
|
||||||
cctools
|
cctools
|
||||||
coreutils
|
coreutils
|
||||||
cpio
|
cpio
|
||||||
@@ -847,14 +847,14 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
|
|||||||
inherit (prevStage) ccWrapperStdenv;
|
inherit (prevStage) ccWrapperStdenv;
|
||||||
|
|
||||||
# Avoid an infinite recursion due to the SDK’s including ncurses, which depends on bash in its `dev` output.
|
# Avoid an infinite recursion due to the SDK’s including ncurses, which depends on bash in its `dev` output.
|
||||||
bash = super.bash.override { stdenv = self.darwin.bootstrapStdenv; };
|
bashNonInteractive = super.bashNonInteractive.override { stdenv = self.darwin.bootstrapStdenv; };
|
||||||
|
|
||||||
# Avoid pulling in a full python and its extra dependencies for the llvm/clang builds.
|
# Avoid pulling in a full python and its extra dependencies for the llvm/clang builds.
|
||||||
libxml2 = super.libxml2.override { pythonSupport = false; };
|
libxml2 = super.libxml2.override { pythonSupport = false; };
|
||||||
|
|
||||||
# Use Bash from this stage to avoid propagating Bash from a previous stage to the final stdenv.
|
# Use Bash from this stage to avoid propagating Bash from a previous stage to the final stdenv.
|
||||||
ncurses = super.ncurses.override {
|
ncurses = super.ncurses.override {
|
||||||
stdenv = self.darwin.bootstrapStdenv.override { shell = lib.getExe self.bash; };
|
stdenv = self.darwin.bootstrapStdenv.override { shell = lib.getExe self.bashNonInteractive; };
|
||||||
};
|
};
|
||||||
|
|
||||||
darwin = super.darwin.overrideScope (
|
darwin = super.darwin.overrideScope (
|
||||||
@@ -1162,7 +1162,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
|
|||||||
extraAttrs = {
|
extraAttrs = {
|
||||||
inherit bootstrapTools;
|
inherit bootstrapTools;
|
||||||
libc = prevStage.darwin.libSystem;
|
libc = prevStage.darwin.libSystem;
|
||||||
shellPackage = prevStage.bash;
|
shellPackage = prevStage.bashNonInteractive;
|
||||||
};
|
};
|
||||||
|
|
||||||
disallowedRequisites = [ bootstrapTools.out ];
|
disallowedRequisites = [ bootstrapTools.out ];
|
||||||
@@ -1172,7 +1172,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
|
|||||||
with prevStage;
|
with prevStage;
|
||||||
[
|
[
|
||||||
apple-sdk
|
apple-sdk
|
||||||
bash
|
bashNonInteractive
|
||||||
bzip2.bin
|
bzip2.bin
|
||||||
bzip2.out
|
bzip2.out
|
||||||
cc.expand-response-params
|
cc.expand-response-params
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ let
|
|||||||
expand-response-params = "";
|
expand-response-params = "";
|
||||||
bsdcp = linkBootstrap { paths = [ "bin/bsdcp" ]; };
|
bsdcp = linkBootstrap { paths = [ "bin/bsdcp" ]; };
|
||||||
patchelf = linkBootstrap { paths = [ "bin/patchelf" ]; };
|
patchelf = linkBootstrap { paths = [ "bin/patchelf" ]; };
|
||||||
bash = linkBootstrap {
|
bashNonInteractive = linkBootstrap {
|
||||||
paths = [
|
paths = [
|
||||||
"bin/bash"
|
"bin/bash"
|
||||||
"bin/sh"
|
"bin/sh"
|
||||||
@@ -376,13 +376,13 @@ let
|
|||||||
gawk
|
gawk
|
||||||
diffutils
|
diffutils
|
||||||
patch
|
patch
|
||||||
bash
|
bashNonInteractive
|
||||||
xz
|
xz
|
||||||
gzip
|
gzip
|
||||||
bzip2
|
bzip2
|
||||||
bsdcp
|
bsdcp
|
||||||
];
|
];
|
||||||
shell = "${prevStage.bash}/bin/bash";
|
shell = "${prevStage.bashNonInteractive}/bin/bash";
|
||||||
stdenvNoCC = import ../generic {
|
stdenvNoCC = import ../generic {
|
||||||
inherit
|
inherit
|
||||||
config
|
config
|
||||||
@@ -471,7 +471,7 @@ in
|
|||||||
# we CAN'T import LLVM because the compiler built here is used to build the final compiler and the final compiler must not be built by the bootstrap compiler
|
# we CAN'T import LLVM because the compiler built here is used to build the final compiler and the final compiler must not be built by the bootstrap compiler
|
||||||
inherit (bootstrapTools)
|
inherit (bootstrapTools)
|
||||||
patchelf
|
patchelf
|
||||||
bash
|
bashNonInteractive
|
||||||
curl
|
curl
|
||||||
coreutils
|
coreutils
|
||||||
diffutils
|
diffutils
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
pkgs.gzip
|
pkgs.gzip
|
||||||
pkgs.bzip2.bin
|
pkgs.bzip2.bin
|
||||||
pkgs.gnumake
|
pkgs.gnumake
|
||||||
pkgs.bash
|
pkgs.bashNonInteractive
|
||||||
pkgs.patch
|
pkgs.patch
|
||||||
pkgs.xz.bin
|
pkgs.xz.bin
|
||||||
|
|
||||||
|
|||||||
@@ -770,7 +770,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
|
|||||||
bzip2
|
bzip2
|
||||||
xz
|
xz
|
||||||
zlib
|
zlib
|
||||||
bash
|
bashNonInteractive
|
||||||
binutils
|
binutils
|
||||||
coreutils
|
coreutils
|
||||||
diffutils
|
diffutils
|
||||||
@@ -806,7 +806,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
|
|||||||
gzip
|
gzip
|
||||||
bzip2
|
bzip2
|
||||||
xz
|
xz
|
||||||
bash
|
bashNonInteractive
|
||||||
binutils.bintools
|
binutils.bintools
|
||||||
coreutils
|
coreutils
|
||||||
diffutils
|
diffutils
|
||||||
@@ -866,7 +866,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
|
|||||||
gzip
|
gzip
|
||||||
bzip2
|
bzip2
|
||||||
xz
|
xz
|
||||||
bash
|
bashNonInteractive
|
||||||
coreutils
|
coreutils
|
||||||
diffutils
|
diffutils
|
||||||
findutils
|
findutils
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
stdenv,
|
stdenv,
|
||||||
fetchFromGitHub,
|
fetchFromGitHub,
|
||||||
cmake,
|
cmake,
|
||||||
bash,
|
bashNonInteractive,
|
||||||
gnugrep,
|
gnugrep,
|
||||||
fixDarwinDylibNames,
|
fixDarwinDylibNames,
|
||||||
file,
|
file,
|
||||||
@@ -37,7 +37,7 @@ stdenv.mkDerivation rec {
|
|||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ cmake ] ++ lib.optional stdenv.hostPlatform.isDarwin fixDarwinDylibNames;
|
nativeBuildInputs = [ cmake ] ++ lib.optional stdenv.hostPlatform.isDarwin fixDarwinDylibNames;
|
||||||
buildInputs = lib.optional stdenv.hostPlatform.isUnix bash;
|
buildInputs = lib.optional stdenv.hostPlatform.isUnix bashNonInteractive;
|
||||||
|
|
||||||
patches = [
|
patches = [
|
||||||
# This patches makes sure we do not attempt to use the MD5 implementation
|
# This patches makes sure we do not attempt to use the MD5 implementation
|
||||||
|
|||||||
@@ -5586,17 +5586,18 @@ with pkgs;
|
|||||||
### SHELLS
|
### SHELLS
|
||||||
|
|
||||||
runtimeShell = "${runtimeShellPackage}${runtimeShellPackage.shellPath}";
|
runtimeShell = "${runtimeShellPackage}${runtimeShellPackage.shellPath}";
|
||||||
runtimeShellPackage = bash;
|
runtimeShellPackage = bashNonInteractive;
|
||||||
|
|
||||||
bash = lowPrio (callPackage ../shells/bash/5.nix { });
|
bash = callPackage ../shells/bash/5.nix { };
|
||||||
|
bashNonInteractive = lowPrio (callPackage ../shells/bash/5.nix {
|
||||||
|
interactive = false;
|
||||||
|
});
|
||||||
# WARNING: this attribute is used by nix-shell so it shouldn't be removed/renamed
|
# WARNING: this attribute is used by nix-shell so it shouldn't be removed/renamed
|
||||||
bashInteractive = callPackage ../shells/bash/5.nix {
|
bashInteractive = bash;
|
||||||
interactive = true;
|
bashFHS = callPackage ../shells/bash/5.nix {
|
||||||
};
|
|
||||||
bashInteractiveFHS = callPackage ../shells/bash/5.nix {
|
|
||||||
interactive = true;
|
|
||||||
forFHSEnv = true;
|
forFHSEnv = true;
|
||||||
};
|
};
|
||||||
|
bashInteractiveFHS = bashFHS;
|
||||||
|
|
||||||
carapace = callPackage ../shells/carapace {
|
carapace = callPackage ../shells/carapace {
|
||||||
buildGoModule = buildGo123Module;
|
buildGoModule = buildGo123Module;
|
||||||
|
|||||||
Reference in New Issue
Block a user