NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
11.68k stars 1.45k forks source link

nix-shell shebang does not interpret -E relative to script dir #4232

Closed lilyball closed 2 weeks ago

lilyball commented 3 years ago

Describe the bug

When using nix-shell in a shebang, it interprets filenames given to it relative to the script dir, but it interprets the -E flag relative to the cwd. This is rather problematic. I can't think of any reason to want the -E flag interpreted relative to the current dir and doing so means I'm forced to write a deps.nix file to disk next to my script if I need to import some other file at a known path.

More generally, I should be able to replace #!nix-shell deps.nix -i bash with #!nix-shell -E 'import ./deps.nix' -i bash.

Steps To Reproduce

Write a script that looks something like

#!/usr/bin/env nix-shell
#!nix-shell -i bash -E "with import ./deps.nix {}; mkShell { buildInputs = [bash]; }"
echo it works

Expected behavior

It shouldn't matter what my cwd is when I execute this, it should behave the same and import the deps.nix file that lives right next to the script.

Actual behavior

It tries to import ./deps.nix from whatever my cwd is.

nix-env --version output

nix-env (Nix) 2.3.7

lilyball commented 3 years ago

On a related note, relative paths given to -I are interpreted relative to cwd but should also be script-relative when used in a shebang.

expipiplus1 commented 3 years ago

I ran into this a couple of days ago too, here is my workaround, a Haskell/Bash polyglot

#! /usr/bin/env bash
{- 2>/dev/null
# vim: set ft=haskell
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
exec nix-shell \
  "$DIR/shell.nix" \
  --pure \
  --run "runghc $(printf "%q " "$0" "$@")"
-}
-- haskell code...
nixos-discourse commented 3 years ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/relative-paths-when-using-nix-shell-as-an-interpreter/1180/5

lilyball commented 3 years ago

@expipiplus1 Neat, but in my case I need to support bash, tcl, perl, python, and ruby scripts, and I need a solution that my non-Nix-savvy coworkers can copy&paste, so the polyglot route is kind of problematic.

stale[bot] commented 3 years ago

I marked this as stale due to inactivity. → More info

lilyball commented 3 years ago

Still a problem last I checked

matthewbauer commented 3 years ago

PR: https://github.com/NixOS/nix/pull/5088

stale[bot] commented 2 years ago

I marked this as stale due to inactivity. → More info

andersk commented 2 years ago

Still an issue in Nix 2.8.0.

DavidDTA commented 2 years ago

This is also an issue for positional arguments. The existing behavior directly contradicts the documentation here:

For example, the Python example could have been written as:

#! /usr/bin/env nix-shell
#! nix-shell deps.nix -i python

where the file deps.nix in the same directory as the #!-script contains:

lf- commented 1 year ago

I am currently looking at the source code. This is a plain old bug: it is intended to work properly and there is even a comment to that effect from like 2017. I'm going to see what I can do.