jdx / mise

dev tools, env vars, task runner
https://mise.jdx.dev
MIT License
8.03k stars 210 forks source link

Environment scripts are sourced in the context of the current working directory #2335

Open kj opened 6 days ago

kj commented 6 days ago

Describe the bug When I use _.source = to export environment variables, the script seems o be evaluated in the context of the current working directory rather than relative to the config file which sourced the script. This makes it very awkward to refer to paths relative to the script/config, as you can't use ${dirname "$0"} in a sourced script. You can work around it with ${BASH_SOURCE[0]} but that isn't portable.

I often want to refer to paths in context of each Mise config, so currently I'm using this, although it's not ideal:

# .mise/config.toml

[env]
_.source = 'env.sh'
# .mise/env.sh
if [ -n "$BASH_SOURCE" ]; then
  root="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")"
  # ...
fi

It seems like the sourced script gets evaluated whenever you enter a directory managed by Mise, or evaluated again if you enter a further nested directory with its own Mise config (which is where you're most likely to run into it). If you just enter the project directory, it will be evaluated at the project root, but if you skip that and enter the directory tree at some nested directory first, then the script will be evaluated from there.

To Reproduce

cd /tmp
mkdir -p env-test/foo/bar
cd env-test
cat >mise.toml <<EOF
[env]
_.source = 'env.sh'
EOF
cat >env.sh <<EOF
export FOO=\$(pwd)
EOF
echo $FOO
# => /tmp/env-test
cd foo/bar
echo $FOO
# => /tmp/env-test
cd /tmp
cd env-test/foo/bar
echo $FOO
# => /tmp/env-test/foo/bar

And if you have a nested Mise config, it will also be evaluated when you enter that context:

cd /tmp/env-test
mkdir baz
touch baz/mise.toml
echo $FOO
# => /tmp/env-test
cd baz
echo $FOO
# => /tmp/env-test/baz

Expected behavior The script should be sourced relative to the config file (perhaps this means temporarily changing the working directory while the script is sourced, then back). This allows scripts to reliably refer to paths relative to the Mise configuration context that they're defined in.

mise doctor output

version: 2024.6.6 linux-x64 (2024-06-21)
activated: yes
shims_on_path: no

build_info:
  Target: x86_64-unknown-linux-gnu
  Features: DEFAULT, NATIVE_TLS
  Built: Fri, 21 Jun 2024 12:25:15 +0000
  Rust Version: rustc 1.79.0 (129f3b996 2024-06-10)
  Profile: release

shell:
  /bin/bash
  GNU bash, version 5.2.26(1)-release (x86_64-pc-linux-gnu)
...