diff options
-rw-r--r-- | src/libcmd/installables.cc | 18 | ||||
-rw-r--r-- | src/libcmd/installables.hh | 9 | ||||
-rw-r--r-- | src/nix/develop.cc | 4 | ||||
-rw-r--r-- | src/nix/run.cc | 9 | ||||
-rw-r--r-- | tests/functional/shell-hello.nix | 16 | ||||
-rw-r--r-- | tests/functional/shell.sh | 8 |
6 files changed, 56 insertions, 8 deletions
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index a9d25671c..f40136411 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -674,7 +674,7 @@ BuiltPaths Installable::toBuiltPaths( } } -StorePathSet Installable::toStorePaths( +StorePathSet Installable::toStorePathSet( ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, @@ -688,13 +688,27 @@ StorePathSet Installable::toStorePaths( return outPaths; } +StorePaths Installable::toStorePaths( + ref<Store> evalStore, + ref<Store> store, + Realise mode, OperateOn operateOn, + const Installables & installables) +{ + StorePaths outPaths; + for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) { + auto thisOutPaths = path.outPaths(); + outPaths.insert(outPaths.end(), thisOutPaths.begin(), thisOutPaths.end()); + } + return outPaths; +} + StorePath Installable::toStorePath( ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, ref<Installable> installable) { - auto paths = toStorePaths(evalStore, store, mode, operateOn, {installable}); + auto paths = toStorePathSet(evalStore, store, mode, operateOn, {installable}); if (paths.size() != 1) throw Error("argument '%s' should evaluate to one store path", installable->what()); diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index b0dc0dc02..ad5b4f759 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -166,7 +166,14 @@ struct Installable const Installables & installables, BuildMode bMode = bmNormal); - static std::set<StorePath> toStorePaths( + static std::set<StorePath> toStorePathSet( + ref<Store> evalStore, + ref<Store> store, + Realise mode, + OperateOn operateOn, + const Installables & installables); + + static std::vector<StorePath> toStorePaths( ref<Store> evalStore, ref<Store> store, Realise mode, diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 8b92d4ccc..e9326cae9 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -340,7 +340,7 @@ struct Common : InstallableCommand, MixProfile for (auto & [installable_, dir_] : redirects) { auto dir = absPath(dir_); auto installable = parseInstallable(store, installable_); - auto builtPaths = Installable::toStorePaths( + auto builtPaths = Installable::toStorePathSet( getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable}); for (auto & path: builtPaths) { auto from = store->printStorePath(path); @@ -554,7 +554,7 @@ struct CmdDevelop : Common, MixEnvironment bool found = false; - for (auto & path : Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, {bashInstallable})) { + for (auto & path : Installable::toStorePathSet(getEvalStore(), store, Realise::Outputs, OperateOn::Output, {bashInstallable})) { auto s = store->printStorePath(path) + "/bin/bash"; if (pathExists(s)) { shell = s; diff --git a/src/nix/run.cc b/src/nix/run.cc index 1c16ce2c9..94d492ca7 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -113,7 +113,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment setEnviron(); - auto unixPath = tokenizeString<Strings>(getEnv("PATH").value_or(""), ":"); + std::vector<std::string> pathAdditions; while (!todo.empty()) { auto path = todo.front(); @@ -121,7 +121,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment if (!done.insert(path).second) continue; if (true) - unixPath.push_front(store->printStorePath(path) + "/bin"); + pathAdditions.push_back(store->printStorePath(path) + "/bin"); auto propPath = store->printStorePath(path) + "/nix-support/propagated-user-env-packages"; if (accessor->stat(propPath).type == FSAccessor::tRegular) { @@ -130,7 +130,10 @@ struct CmdShell : InstallablesCommand, MixEnvironment } } - setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1); + auto unixPath = tokenizeString<Strings>(getEnv("PATH").value_or(""), ":"); + unixPath.insert(unixPath.begin(), pathAdditions.begin(), pathAdditions.end()); + auto unixPathString = concatStringsSep(":", unixPath); + setenv("PATH", unixPathString.c_str(), 1); Strings args; for (auto & arg : command) args.push_back(arg); diff --git a/tests/functional/shell-hello.nix b/tests/functional/shell-hello.nix index 3fdd3501d..dfe66ef93 100644 --- a/tests/functional/shell-hello.nix +++ b/tests/functional/shell-hello.nix @@ -23,4 +23,20 @@ with import ./config.nix; chmod +x $dev/bin/hello2 ''; }; + + salve-mundi = mkDerivation { + name = "salve-mundi"; + outputs = [ "out" ]; + meta.outputsToInstall = [ "out" ]; + buildCommand = + '' + mkdir -p $out/bin + + cat > $out/bin/hello <<EOF + #! ${shell} + echo "Salve Mundi from $out/bin/hello" + EOF + chmod +x $out/bin/hello + ''; + }; } diff --git a/tests/functional/shell.sh b/tests/functional/shell.sh index d2f7cf14e..8bbeabedf 100644 --- a/tests/functional/shell.sh +++ b/tests/functional/shell.sh @@ -10,6 +10,14 @@ nix shell -f shell-hello.nix hello -c hello NixOS | grep 'Hello NixOS' nix shell -f shell-hello.nix hello^dev -c hello2 | grep 'Hello2' nix shell -f shell-hello.nix 'hello^*' -c hello2 | grep 'Hello2' + +if isDaemonNewer "2.20.0pre20231220"; then + # Test that command line attribute ordering is reflected in the PATH + # https://github.com/NixOS/nix/issues/7905 + nix shell -f shell-hello.nix hello salve-mundi -c hello | grep 'Hello World' + nix shell -f shell-hello.nix salve-mundi hello -c hello | grep 'Salve Mundi' +fi + requireSandboxSupport chmod -R u+w $TEST_ROOT/store0 || true |