Skip to content

Commit 63eb48f

Browse files
authored
fix(gemset): add cwd to Gemset and set RBENV_DIR env var (#173)
## Description This change adds a working dir field to the Gemset struct and passes this directory as the `RBENV_DIR` environment variable when executing gem commands. This ensures that `rbenv` uses the project's directory when resolving Ruby versions. ## Details The Ruby extension uses `zed::Command` to invoke commands for managing its gems: updating, installing, and uninstalling. It seems that `zed::Command` does not set the working directory (`cwd`), which causes the invoked commands to run against the root directory. Below is the log of running `rbenv` with debug mode enabled via the `RBENV_DEBUG` environment variable: ``` + '[' gem = ruby ']' + export RBENV_ROOT=/Users/rbenv/.rbenv + RBENV_ROOT=/Users/rbenv/.rbenv + exec /opt/homebrew/bin/rbenv exec gem install --norc --no-user-install --no-format-executable --no-document solargraph +(/opt/homebrew/bin/rbenv:23): '[' -z /Users/rbenv/.rbenv ']' +(/opt/homebrew/bin/rbenv:26): RBENV_ROOT=/Users/rbenv/.rbenv +(/opt/homebrew/bin/rbenv:28): export RBENV_ROOT +(/opt/homebrew/bin/rbenv:30): '[' -z '' ']' +(/opt/homebrew/bin/rbenv:31): RBENV_DIR=/ +(/opt/homebrew/bin/rbenv:38): export RBENV_DIR +(/opt/homebrew/bin/rbenv:40): '[' -n '' ']' +(/opt/homebrew/bin/rbenv:40): export RBENV_ORIG_PATH=/opt/homebrew/opt/rustup/bin:/Users/rbenv/.rbenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin +(/opt/homebrew/bin/rbenv:40): RBENV_ORIG_PATH=/opt/homebrew/opt/rustup/bin:/Users/rbenv/.rbenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin +(/opt/homebrew/bin/rbenv:64): shopt -s nullglob +(/opt/homebrew/bin/rbenv:67): rbenv_bin=/opt/homebrew/bin/rbenv ++(/opt/homebrew/bin/rbenv:68): canonicalize /opt/homebrew/bin/rbenv ++(/opt/homebrew/bin/rbenv:43): canonicalize(): local readlink resolved_path +++(/opt/homebrew/bin/rbenv:44): canonicalize(): type -P greadlink ++(/opt/homebrew/bin/rbenv:44): canonicalize(): readlink= +++(/opt/homebrew/bin/rbenv:44): canonicalize(): type -P readlink ++(/opt/homebrew/bin/rbenv:44): canonicalize(): readlink=/usr/bin/readlink +++(/opt/homebrew/bin/rbenv:46): canonicalize(): /usr/bin/readlink -f /opt/homebrew/bin/rbenv ++(/opt/homebrew/bin/rbenv:46): canonicalize(): resolved_path=/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv ++(/opt/homebrew/bin/rbenv:47): canonicalize(): printf '%s\n' /opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv ++(/opt/homebrew/bin/rbenv:48): canonicalize(): return 0 +(/opt/homebrew/bin/rbenv:68): libexec_dir=/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv +(/opt/homebrew/bin/rbenv:69): libexec_dir=/opt/homebrew/Cellar/rbenv/1.3.2/libexec +(/opt/homebrew/bin/rbenv:78): export PATH=/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/Users/rbenv/.rbenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin +(/opt/homebrew/bin/rbenv:78): PATH=/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/Users/rbenv/.rbenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin +(/opt/homebrew/bin/rbenv:80): RBENV_HOOK_PATH=:/Users/rbenv/.rbenv/rbenv.d +(/opt/homebrew/bin/rbenv:81): '[' '!' /opt/homebrew/Cellar/rbenv/1.3.2/rbenv.d -ef /Users/rbenv/.rbenv/rbenv.d ']' +(/opt/homebrew/bin/rbenv:83): RBENV_HOOK_PATH=:/Users/rbenv/.rbenv/rbenv.d:/opt/homebrew/Cellar/rbenv/1.3.2/rbenv.d +(/opt/homebrew/bin/rbenv:85): RBENV_HOOK_PATH=:/Users/rbenv/.rbenv/rbenv.d:/opt/homebrew/Cellar/rbenv/1.3.2/rbenv.d:/usr/etc/rbenv.d:/opt/homebrew/etc/rbenv.d:/etc/rbenv.d:/usr/lib/rbenv/hooks +(/opt/homebrew/bin/rbenv:89): RBENV_HOOK_PATH=/Users/rbenv/.rbenv/rbenv.d:/opt/homebrew/Cellar/rbenv/1.3.2/rbenv.d:/usr/etc/rbenv.d:/opt/homebrew/etc/rbenv.d:/etc/rbenv.d:/usr/lib/rbenv/hooks +(/opt/homebrew/bin/rbenv:90): export RBENV_HOOK_PATH +(/opt/homebrew/bin/rbenv:92): shopt -u nullglob +(/opt/homebrew/bin/rbenv:95): command=exec +(/opt/homebrew/bin/rbenv:96): case "$command" in ++(/opt/homebrew/bin/rbenv:109): type -P rbenv-exec +(/opt/homebrew/bin/rbenv:109): command_path=/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec +(/opt/homebrew/bin/rbenv:110): '[' -z /opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec ']' +(/opt/homebrew/bin/rbenv:118): shift 1 +(/opt/homebrew/bin/rbenv:119): '[' gem = --help ']' +(/opt/homebrew/bin/rbenv:126): exec /opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec gem install --norc --no-user-install --no-format-executable --no-document solargraph +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:20): '[' gem = --complete ']' ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:24): rbenv-version-name +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:6): '[' -z '' ']' ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:7): rbenv-version-file +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:13): target_dir= +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:28): '[' -n '' ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:31): find_local_version_file / +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:16): find_local_version_file(): local root=/ +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:17): find_local_version_file(): [[ / =~ ^//[^/]*$ ]] +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:18): find_local_version_file(): '[' -s //.ruby-version ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:22): find_local_version_file(): '[' -n / ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:23): find_local_version_file(): root= +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:17): find_local_version_file(): [[ '' =~ ^//[^/]*$ ]] +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:18): find_local_version_file(): '[' -s /.ruby-version ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:22): find_local_version_file(): '[' -n '' ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:22): find_local_version_file(): break +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:25): find_local_version_file(): return 1 +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:32): '[' / '!=' / ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file:33): echo /Users/rbenv/.rbenv/version +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:7): RBENV_VERSION_FILE=/Users/rbenv/.rbenv/version ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:8): rbenv-version-file-read /Users/rbenv/.rbenv/version +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file-read:6): VERSION_FILE=/Users/rbenv/.rbenv/version +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file-read:8): '[' -s /Users/rbenv/.rbenv/version ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-file-read:21): exit 1 ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:8): true +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:8): RBENV_VERSION= +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:11): IFS=' ' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:11): read -d '' -r -a scripts ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:11): rbenv-hooks version-name +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:9): '[' version-name = --complete ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:18): RBENV_COMMAND=version-name +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:19): '[' -z version-name ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:24): IFS=: +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:24): read -r -a hook_paths +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:26): shopt -s nullglob +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:32): shopt -u nullglob +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:11): true +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:17): '[' -z '' ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:18): echo system +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-version-name:19): exit +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:24): RBENV_VERSION=system +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:25): RBENV_COMMAND=gem +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:27): '[' -z gem ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:32): export RBENV_VERSION ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:33): rbenv-which gem +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:14): '[' gem = --complete ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:30): RBENV_COMMAND=gem +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:32): '[' -z gem ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:37): RBENV_VERSION=system +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:39): '[' system = system ']' ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:40): remove_from_path /Users/rbenv/.rbenv/shims ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:19): remove_from_path(): local path_to_remove=/Users/rbenv/.rbenv/shims ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:20): remove_from_path(): local path_before ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:21): remove_from_path(): local result=:/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/Users/rbenv/.rbenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin: ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:22): remove_from_path(): '[' '' '!=' :/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/Users/rbenv/.rbenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin: ']' ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:23): remove_from_path(): path_before=:/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/Users/rbenv/.rbenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin: ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:24): remove_from_path(): result=:/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin: ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:22): remove_from_path(): '[' :/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/Users/rbenv/.rbenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin: '!=' :/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin: ']' ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:23): remove_from_path(): path_before=:/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin: ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:24): remove_from_path(): result=:/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin: ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:22): remove_from_path(): '[' :/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin: '!=' :/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin: ']' ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:26): remove_from_path(): result=:/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:27): remove_from_path(): echo /opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:40): PATH=/opt/homebrew/Cellar/rbenv/1.3.2/libexec:/opt/homebrew/opt/rustup/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:40): command -v gem +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:40): RBENV_COMMAND_PATH=/usr/bin/gem +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:46): [[ ! -x /usr/bin/gem ]] +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:50): IFS=' ' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:50): read -d '' -r -a scripts ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:50): rbenv-hooks which +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:9): '[' which = --complete ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:18): RBENV_COMMAND=which +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:19): '[' -z which ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:24): IFS=: +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:24): read -r -a hook_paths +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:26): shopt -s nullglob +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:32): shopt -u nullglob +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:50): true +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:56): '[' -x /usr/bin/gem ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-which:57): echo /usr/bin/gem +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:33): RBENV_COMMAND_PATH=/usr/bin/gem +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:34): RBENV_BIN_PATH=/usr/bin +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:36): IFS=' ' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:36): read -d '' -r -a scripts ++(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:36): rbenv-hooks exec +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:9): '[' exec = --complete ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:18): RBENV_COMMAND=exec +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:19): '[' -z exec ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:24): IFS=: +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:24): read -r -a hook_paths +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:26): shopt -s nullglob +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:28): for script in '"$path/$RBENV_COMMAND"/*.bash' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:29): echo /opt/homebrew/Cellar/rbenv/1.3.2/rbenv.d/exec/gem-rehash.bash +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:27): for path in '"${hook_paths[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-hooks:32): shopt -u nullglob +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:36): true +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:37): for script in '"${scripts[@]}"' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:39): source /opt/homebrew/Cellar/rbenv/1.3.2/rbenv.d/exec/gem-rehash.bash ++(/opt/homebrew/Cellar/rbenv/1.3.2/rbenv.d/exec/gem-rehash.bash:1): export RUBYLIB=/opt/homebrew/Cellar/rbenv/1.3.2/rbenv.d/exec/gem-rehash: ++(/opt/homebrew/Cellar/rbenv/1.3.2/rbenv.d/exec/gem-rehash.bash:1): RUBYLIB=/opt/homebrew/Cellar/rbenv/1.3.2/rbenv.d/exec/gem-rehash: +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:42): shift 1 +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:43): '[' system '!=' system ']' +(/opt/homebrew/Cellar/rbenv/1.3.2/libexec/rbenv-exec:46): exec -a gem /usr/bin/gem install --norc --no-user-install --no-format-executable --no-document solargraph ``` In the beginning, there is this line `+(/opt/homebrew/bin/rbenv:31): RBENV_DIR=/` which indicates that the working directory is not set to the worktree and `rbenv` uses the root directory. The possible solutions are: - Set the system Ruby via `rbenv` - Set `RBENV_DIR` in the Ruby extension before invoking any `gem` command. It's a hack, but it works. - Check the `zed::Command` implementation to to see if the working directory can be changed to the worktree root. Closes #158 Closes #152
1 parent 8a61094 commit 63eb48f

File tree

3 files changed

+132
-31
lines changed

3 files changed

+132
-31
lines changed

src/gemset.rs

Lines changed: 122 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@ use std::path::PathBuf;
44

55
/// A simple wrapper around the `gem` command.
66
pub struct Gemset {
7-
pub gem_home: PathBuf,
7+
gem_home: PathBuf,
8+
working_dir: PathBuf,
89
command_executor: Box<dyn CommandExecutor>,
910
}
1011

1112
impl Gemset {
12-
pub fn new(gem_home: PathBuf, command_executor: Box<dyn CommandExecutor>) -> Self {
13+
pub fn new(
14+
gem_home: PathBuf,
15+
working_dir: PathBuf,
16+
command_executor: Box<dyn CommandExecutor>,
17+
) -> Self {
1318
Self {
1419
gem_home,
20+
working_dir,
1521
command_executor,
1622
}
1723
}
@@ -26,18 +32,33 @@ impl Gemset {
2632
}
2733

2834
pub fn env(&self, envs: Option<&[(&str, &str)]>) -> Vec<(String, String)> {
29-
let mut env_map: std::collections::HashMap<String, String> = envs
30-
.unwrap_or(&[])
31-
.iter()
32-
.map(|(k, v)| (k.to_string(), v.to_string()))
33-
.collect();
34-
35-
env_map.insert(
35+
let gem_bin_path = self.gem_home.join("bin");
36+
let gem_bin_str = gem_bin_path.display().to_string();
37+
let gem_path = (
3638
"GEM_PATH".to_string(),
3739
format!("{}:$GEM_PATH", self.gem_home.display()),
3840
);
3941

40-
env_map.into_iter().collect()
42+
let path_override = {
43+
let existing_path = envs
44+
.unwrap_or(&[])
45+
.iter()
46+
.find(|(k, _)| *k == "PATH")
47+
.map(|(_, v)| v)
48+
.map_or("$PATH", |v| v);
49+
50+
(
51+
"PATH".to_string(),
52+
format!("{}:{}", gem_bin_str, existing_path),
53+
)
54+
};
55+
56+
envs.unwrap_or(&[])
57+
.iter()
58+
.filter(|(k, _)| *k != "GEM_PATH" || *k != "PATH")
59+
.map(|(k, v)| (k.to_string(), v.to_string()))
60+
.chain([gem_path, path_override])
61+
.collect()
4162
}
4263

4364
pub fn install_gem(&self, name: &str) -> Result<(), String> {
@@ -108,7 +129,16 @@ impl Gemset {
108129
.gem_home
109130
.to_str()
110131
.ok_or("Failed to convert gem_home path to string")?;
111-
let command_envs = &[("GEM_HOME", gem_home_str), ("GEM_PATH", gem_home_str)];
132+
let working_dir_str = self
133+
.working_dir
134+
.to_str()
135+
.ok_or("Failed to convert working_dir path to string")?;
136+
137+
let command_envs = &[
138+
("GEM_HOME", gem_home_str),
139+
("GEM_PATH", gem_home_str),
140+
("RBENV_DIR", working_dir_str),
141+
];
112142

113143
self.command_executor
114144
.execute("gem", &full_args, command_envs)
@@ -209,15 +239,21 @@ mod tests {
209239
}
210240

211241
const TEST_GEM_HOME: &str = "/test/gem_home";
242+
const TEST_WORKING_DIR: &str = "/test/my_project";
212243

213244
fn create_gemset(mock_executor: MockGemCommandExecutor) -> Gemset {
214-
Gemset::new(TEST_GEM_HOME.into(), Box::new(mock_executor))
245+
Gemset::new(
246+
TEST_GEM_HOME.into(),
247+
TEST_WORKING_DIR.into(),
248+
Box::new(mock_executor),
249+
)
215250
}
216251

217252
#[test]
218253
fn test_gem_bin_path() {
219254
let gemset = Gemset::new(
220255
TEST_GEM_HOME.into(),
256+
TEST_WORKING_DIR.into(),
221257
Box::new(MockGemCommandExecutor::new()),
222258
);
223259
let path = gemset.gem_bin_path("ruby-lsp").unwrap();
@@ -228,10 +264,11 @@ mod tests {
228264
fn test_gem_env() {
229265
let gemset = Gemset::new(
230266
TEST_GEM_HOME.into(),
267+
TEST_WORKING_DIR.into(),
231268
Box::new(MockGemCommandExecutor::new()),
232269
);
233270
let env = gemset.env(None);
234-
assert_eq!(env.len(), 1);
271+
assert_eq!(env.len(), 2);
235272
assert_eq!(env[0].0, "GEM_PATH");
236273
assert_eq!(env[0].1, "/test/gem_home:$GEM_PATH");
237274
}
@@ -240,28 +277,32 @@ mod tests {
240277
fn test_gem_env_with_env_vars() {
241278
let gemset = Gemset::new(
242279
TEST_GEM_HOME.into(),
280+
TEST_WORKING_DIR.into(),
243281
Box::new(MockGemCommandExecutor::new()),
244282
);
245283
let env = gemset.env(Some(&[("GEM_HOME", "/home/user/.gem")]));
246-
assert_eq!(env.len(), 2);
284+
assert_eq!(env.len(), 3);
247285

248286
let env_map: std::collections::HashMap<String, String> = env.into_iter().collect();
249287
assert_eq!(env_map.get("GEM_HOME").unwrap(), "/home/user/.gem");
250288
assert_eq!(env_map.get("GEM_PATH").unwrap(), "/test/gem_home:$GEM_PATH");
289+
assert_eq!(env_map.get("PATH").unwrap(), "/test/gem_home/bin:$PATH");
251290
}
252291

253292
#[test]
254293
fn test_gem_env_with_env_vars_overwrite() {
255294
let gemset = Gemset::new(
256295
TEST_GEM_HOME.into(),
296+
TEST_WORKING_DIR.into(),
257297
Box::new(MockGemCommandExecutor::new()),
258298
);
259299
let env = gemset.env(Some(&[("GEM_PATH", "/home/user/.gem")]));
260-
assert_eq!(env.len(), 1);
300+
assert_eq!(env.len(), 3);
261301

262302
// GEM_PATH should be overwritten with our value
263303
let env_map: std::collections::HashMap<String, String> = env.into_iter().collect();
264304
assert_eq!(env_map.get("GEM_PATH").unwrap(), "/test/gem_home:$GEM_PATH");
305+
assert_eq!(env_map.get("PATH").unwrap(), "/test/gem_home/bin:$PATH");
265306
}
266307

267308
#[test]
@@ -278,7 +319,11 @@ mod tests {
278319
"--no-document",
279320
gem_name,
280321
],
281-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
322+
&[
323+
("GEM_HOME", TEST_GEM_HOME),
324+
("GEM_PATH", TEST_GEM_HOME),
325+
("RBENV_DIR", TEST_WORKING_DIR),
326+
],
282327
Ok(Output {
283328
status: Some(0),
284329
stdout: "Successfully installed ruby-lsp-1.0.0".as_bytes().to_vec(),
@@ -303,7 +348,11 @@ mod tests {
303348
"--no-document",
304349
gem_name,
305350
],
306-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
351+
&[
352+
("GEM_HOME", TEST_GEM_HOME),
353+
("GEM_PATH", TEST_GEM_HOME),
354+
("RBENV_DIR", TEST_WORKING_DIR),
355+
],
307356
Ok(Output {
308357
status: Some(1),
309358
stdout: Vec::new(),
@@ -325,7 +374,11 @@ mod tests {
325374
mock_executor.expect(
326375
"gem",
327376
&["update", "--norc", gem_name],
328-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
377+
&[
378+
("GEM_HOME", TEST_GEM_HOME),
379+
("GEM_PATH", TEST_GEM_HOME),
380+
("RBENV_DIR", TEST_WORKING_DIR),
381+
],
329382
Ok(Output {
330383
status: Some(0),
331384
stdout: "Gems updated: ruby-lsp".as_bytes().to_vec(),
@@ -343,7 +396,11 @@ mod tests {
343396
mock_executor.expect(
344397
"gem",
345398
&["update", "--norc", gem_name],
346-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
399+
&[
400+
("GEM_HOME", TEST_GEM_HOME),
401+
("GEM_PATH", TEST_GEM_HOME),
402+
("RBENV_DIR", TEST_WORKING_DIR),
403+
],
347404
Ok(Output {
348405
status: Some(1),
349406
stdout: Vec::new(),
@@ -371,7 +428,11 @@ mod tests {
371428
mock_executor.expect(
372429
"gem",
373430
&["list", "--norc", "--exact", gem_name],
374-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
431+
&[
432+
("GEM_HOME", TEST_GEM_HOME),
433+
("GEM_PATH", TEST_GEM_HOME),
434+
("RBENV_DIR", TEST_WORKING_DIR),
435+
],
375436
Ok(Output {
376437
status: Some(0),
377438
stdout: gem_list_output.as_bytes().to_vec(),
@@ -396,7 +457,11 @@ mod tests {
396457
mock_executor.expect(
397458
"gem",
398459
&["list", "--norc", "--exact", gem_name],
399-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
460+
&[
461+
("GEM_HOME", TEST_GEM_HOME),
462+
("GEM_PATH", TEST_GEM_HOME),
463+
("RBENV_DIR", TEST_WORKING_DIR),
464+
],
400465
Ok(Output {
401466
status: Some(0),
402467
stdout: gem_list_output.as_bytes().to_vec(),
@@ -417,7 +482,11 @@ mod tests {
417482
mock_executor.expect(
418483
"gem",
419484
&["list", "--norc", "--exact", gem_name],
420-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
485+
&[
486+
("GEM_HOME", TEST_GEM_HOME),
487+
("GEM_PATH", TEST_GEM_HOME),
488+
("RBENV_DIR", TEST_WORKING_DIR),
489+
],
421490
Ok(Output {
422491
status: Some(0),
423492
stdout: gem_list_output.as_bytes().to_vec(),
@@ -436,7 +505,11 @@ mod tests {
436505
mock_executor.expect(
437506
"gem",
438507
&["list", "--norc", "--exact", gem_name],
439-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
508+
&[
509+
("GEM_HOME", TEST_GEM_HOME),
510+
("GEM_PATH", TEST_GEM_HOME),
511+
("RBENV_DIR", TEST_WORKING_DIR),
512+
],
440513
Ok(Output {
441514
status: Some(127),
442515
stdout: Vec::new(),
@@ -463,7 +536,11 @@ mod tests {
463536
mock_executor.expect(
464537
"gem",
465538
&["outdated", "--norc"],
466-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
539+
&[
540+
("GEM_HOME", TEST_GEM_HOME),
541+
("GEM_PATH", TEST_GEM_HOME),
542+
("RBENV_DIR", TEST_WORKING_DIR),
543+
],
467544
Ok(Output {
468545
status: Some(0),
469546
stdout: outdated_output.as_bytes().to_vec(),
@@ -484,7 +561,11 @@ mod tests {
484561
mock_executor.expect(
485562
"gem",
486563
&["outdated", "--norc"],
487-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
564+
&[
565+
("GEM_HOME", TEST_GEM_HOME),
566+
("GEM_PATH", TEST_GEM_HOME),
567+
("RBENV_DIR", TEST_WORKING_DIR),
568+
],
488569
Ok(Output {
489570
status: Some(0),
490571
stdout: outdated_output.as_bytes().to_vec(),
@@ -503,7 +584,11 @@ mod tests {
503584
mock_executor.expect(
504585
"gem",
505586
&["outdated", "--norc"],
506-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
587+
&[
588+
("GEM_HOME", TEST_GEM_HOME),
589+
("GEM_PATH", TEST_GEM_HOME),
590+
("RBENV_DIR", TEST_WORKING_DIR),
591+
],
507592
Ok(Output {
508593
status: Some(1),
509594
stdout: Vec::new(),
@@ -527,7 +612,11 @@ mod tests {
527612
mock_executor.expect(
528613
"gem",
529614
&["uninstall", "--norc", gem_name, "--version", gem_version],
530-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
615+
&[
616+
("GEM_HOME", TEST_GEM_HOME),
617+
("GEM_PATH", TEST_GEM_HOME),
618+
("RBENV_DIR", TEST_WORKING_DIR),
619+
],
531620
Ok(Output {
532621
status: Some(0),
533622
stdout: format!("Successfully uninstalled {gem_name}-{gem_version}")
@@ -549,7 +638,7 @@ mod tests {
549638
mock_executor.expect(
550639
"gem",
551640
&["uninstall", "--norc", gem_name, "--version", gem_version],
552-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
641+
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME), ("RBENV_DIR", TEST_WORKING_DIR)],
553642
Ok(Output {
554643
status: Some(1),
555644
stdout: Vec::new(),
@@ -575,7 +664,11 @@ mod tests {
575664
mock_executor.expect(
576665
"gem",
577666
&["uninstall", "--norc", gem_name, "--version", gem_version],
578-
&[("GEM_HOME", TEST_GEM_HOME), ("GEM_PATH", TEST_GEM_HOME)],
667+
&[
668+
("GEM_HOME", TEST_GEM_HOME),
669+
("GEM_PATH", TEST_GEM_HOME),
670+
("RBENV_DIR", TEST_WORKING_DIR),
671+
],
579672
Err("Command not found: gem".to_string()),
580673
);
581674
let gemset = create_gemset(mock_executor);

src/language_servers/language_server.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,11 @@ pub trait LanguageServer {
222222
.to_string_lossy()
223223
.to_string();
224224

225-
let gemset = Gemset::new(PathBuf::from(&gem_home), Box::new(RealCommandExecutor));
225+
let gemset = Gemset::new(
226+
PathBuf::from(&gem_home),
227+
PathBuf::from(worktree.root_path()),
228+
Box::new(RealCommandExecutor),
229+
);
226230
let worktree_shell_env = worktree.shell_env();
227231
let worktree_shell_env_vars: Vec<(&str, &str)> = worktree_shell_env
228232
.iter()

src/ruby.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,11 @@ impl zed::Extension for RubyExtension {
154154
Err(_e) => {
155155
let gem_home = std::env::current_dir()
156156
.map_err(|e| format!("Failed to get extension directory: {e}"))?;
157-
let gemset = Gemset::new(gem_home, Box::new(RealCommandExecutor));
157+
let gemset = Gemset::new(
158+
gem_home,
159+
PathBuf::from(worktree.root_path()),
160+
Box::new(RealCommandExecutor),
161+
);
158162

159163
match gemset.install_gem("debug") {
160164
Ok(_) => rdbg_path = gemset.gem_bin_path("rdbg")?,

0 commit comments

Comments
 (0)