From 2fd7ee21d11bf7b06aff674663fe618e41eff5e2 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 22 Jan 2024 11:17:08 -0500 Subject: [PATCH] feat: adds --relative flag for relative path resolution in shebangs --- doc/manual/src/command-ref/nix-shell.md | 5 +++++ src/nix-build/nix-build.cc | 8 ++++++-- tests/functional/nix-shell.sh | 16 ++++++++++++---- tests/functional/shell.shebang.expr | 4 ++++ 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100755 tests/functional/shell.shebang.expr diff --git a/doc/manual/src/command-ref/nix-shell.md b/doc/manual/src/command-ref/nix-shell.md index 1eaf3c36aa7..470a6a43bd1 100644 --- a/doc/manual/src/command-ref/nix-shell.md +++ b/doc/manual/src/command-ref/nix-shell.md @@ -13,6 +13,7 @@ [`--exclude` *regexp*] [`--pure`] [`--keep` *name*] + [`--relative`] {{`--packages` | `-p`} {*packages* | *expressions*} … | [*path*]} # Disambiguation @@ -101,6 +102,10 @@ All options not listed here are passed to `nix-store When a `--pure` shell is started, keep the listed environment variables. + - `--relative`\ + If this flag is specified when using the shebang feature, relative paths + will be resolved relative to the script's location. + {{#include ./opt-common.md}} # Environment variables diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 4120ca3cf82..3cfc8b9c2c9 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -107,6 +107,7 @@ static void main_nix_build(int argc, char * * argv) auto myName = runEnv ? "nix-shell" : "nix-build"; auto inShebang = false; + auto inShebangRelative = false; std::string script; std::vector savedArgs; @@ -206,6 +207,9 @@ static void main_nix_build(int argc, char * * argv) else if (runEnv && (*arg == "--packages" || *arg == "-p")) packages = true; + else if (inShebang && (*arg == "--relative")) { + inShebangRelative = true; + } else if (inShebang && *arg == "-i") { auto interpreter = getArg(*arg, arg, end); interactive = false; @@ -300,7 +304,7 @@ static void main_nix_build(int argc, char * * argv) if (fromArgs) exprs.push_back(state->parseExprFromString( std::move(i), - state->rootPath(CanonPath::fromCwd(inShebang ? dirOf(script) : ".")))); + state->rootPath(CanonPath::fromCwd((inShebang && inShebangRelative) ? dirOf(script) : ".")))); else { auto absolute = i; try { @@ -313,7 +317,7 @@ static void main_nix_build(int argc, char * * argv) /* If we're in a #! script, interpret filenames relative to the script. */ exprs.push_back(state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state, - inShebang ? absPath(i, absPath(dirOf(script))) : i))))); + (inShebang && inShebangRelative) ? absPath(i, absPath(dirOf(script))) : i))))); } } diff --git a/tests/functional/nix-shell.sh b/tests/functional/nix-shell.sh index 702d3a6b566..ea77df08f6f 100644 --- a/tests/functional/nix-shell.sh +++ b/tests/functional/nix-shell.sh @@ -61,13 +61,21 @@ output=$($TEST_ROOT/shell.shebang.sh abc def) # Test nix-shell shebang mode with an alternate working directory sed -e "s|@ENV_PROG@|$(type -P env)|" shell.shebang.expr > $TEST_ROOT/shell.shebang.expr -chmod a+rx $TEST_ROOT/shell.shebang.expr +sed -e "s|nix-shell -E|nix-shell --relative -E|" \ + -e "s|@ENV_PROG@|$(type -P env)|" \ + shell.shebang.expr > $TEST_ROOT/shell.shebang.expr.relative +chmod a+rx $TEST_ROOT/shell.shebang.expr{,.relative} # Should fail due to expressions using relative path +pushd .. ! $TEST_ROOT/shell.shebang.expr bar +popd cp shell.nix config.nix $TEST_ROOT -# Should succeed -output=$($TEST_ROOT/shell.shebang.expr bar) -[ "$output" = '-e load(ARGV.shift) -- '"$TEST_ROOT"'/shell.shebang.expr bar' ] +# Should fail +pushd .. +! $TEST_ROOT/shell.shebang.expr bar +output=$($TEST_ROOT/shell.shebang.expr.relative bar) +popd +[ "$output" = '-e load(ARGV.shift) -- '"$TEST_ROOT"'/shell.shebang.expr.relative bar' ] # Test nix-shell shebang mode again with metacharacters in the filename. # First word of filename is chosen to not match any file in the test root. diff --git a/tests/functional/shell.shebang.expr b/tests/functional/shell.shebang.expr new file mode 100755 index 00000000000..51aef083951 --- /dev/null +++ b/tests/functional/shell.shebang.expr @@ -0,0 +1,4 @@ +#! @ENV_PROG@ nix-shell +#! nix-shell -E "with (import ./shell.nix {}); runCommand \"hi\" {buildInputs = [ruby];} \"\"" +#! nix-shell --pure -i ruby +puts ARGV[1]