Skip to content

Commit

Permalink
Merge pull request NixOS#9648 from cole-h/nix-shell-ordering
Browse files Browse the repository at this point in the history
nix shell: reflect command line order in PATH order

(cherry picked from commit b91c935)
Change-Id: If16c120bb74857c2817366e74e5b0877eb997260
  • Loading branch information
eldritch horrors committed Mar 4, 2024
1 parent aaf1ed1 commit 1809841
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 8 deletions.
18 changes: 16 additions & 2 deletions src/libcmd/installables.cc
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ BuiltPaths Installable::toBuiltPaths(
}
}

StorePathSet Installable::toStorePaths(
StorePathSet Installable::toStorePathSet(
ref<Store> evalStore,
ref<Store> store,
Realise mode, OperateOn operateOn,
Expand All @@ -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());
Expand Down
9 changes: 8 additions & 1 deletion src/libcmd/installables.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/nix/develop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 6 additions & 3 deletions src/nix/run.cc
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,15 @@ 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();
todo.pop();
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) {
Expand All @@ -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);
Expand Down
16 changes: 16 additions & 0 deletions tests/functional/shell-hello.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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
'';
};
}
8 changes: 8 additions & 0 deletions tests/functional/shell.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 1809841

Please sign in to comment.