-
Notifications
You must be signed in to change notification settings - Fork 1
Fix dune path in nested shells #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
gridbugs
merged 1 commit into
ocaml-dune:main
from
gridbugs:fix-dune-path-in-nested-shells
Aug 18, 2025
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,105 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # Equivalent to `which dune`, but `which` might not be installed. Bash's `type` | ||
| # supports -P which acts like `which` but is guaranteed to be installed, but | ||
| # older versions of bash might not support -P so we'll err on the side of | ||
| # caution and implement it here in the interest of portability. | ||
| __dune_which() { | ||
| echo "$PATH" | \ | ||
| tr ':' '\n' |\ | ||
| while read -r entry; do | ||
| if test -x "$entry/dune"; then | ||
| echo "$entry/dune" | ||
| return 0 | ||
| fi | ||
| done | ||
| return 1 | ||
| } | ||
|
|
||
| export __DUNE_SETUP_STATE="${__DUNE_SETUP_STATE:-incomplete}" | ||
|
|
||
| __dune_env() { | ||
| if [ "$#" != "1" ]; then | ||
| echo "__dune_env expected 1 argument, got $#" | ||
| return | ||
| fi | ||
| local ROOT="$1" | ||
|
|
||
| # Add dune to PATH unless it's already present. | ||
| # Affix colons on either side of $PATH to simplify matching (based on | ||
| # rustup's env script). | ||
| case :"$PATH": in | ||
| *:"$ROOT/bin":*) | ||
| # Do nothing since the bin directory is already in PATH. | ||
| case "$__DUNE_SETUP_STATE" in | ||
| incomplete) | ||
| # This is the first time __dune_env has been called, so attempt to set up | ||
| # the environment for dune and record in the global variable | ||
| # __DUNE_SETUP_STATE whether or not it succeeded. | ||
|
|
||
| # Add dune to PATH unless it's already present. | ||
| # Affix colons on either side of $PATH to simplify matching (based on | ||
| # rustup's env script). | ||
| case :"$PATH": in | ||
| *:"$ROOT/bin":*) | ||
| # Do nothing since the bin directory is already in PATH. | ||
| ;; | ||
| *) | ||
| export PATH="$ROOT/bin:$PATH" | ||
| ;; | ||
| esac | ||
|
|
||
| if [ "$(__dune_which)" = "$ROOT/bin/dune" ]; then | ||
| export __DUNE_SETUP_STATE=success | ||
|
|
||
| # Only load completions if the shell is interactive. | ||
| if [ -t 0 ]; then | ||
| # Load bash completions for dune. | ||
| # Suppress warning from shellcheck as it can't see the completion script. | ||
| # shellcheck disable=SC1091 | ||
| . "$ROOT"/share/bash-completion/completions/dune | ||
| fi | ||
| else | ||
| # Despite modifying the environment, running `dune` would resolve to | ||
| # the wrong dune instance. This can happen if the bin directory | ||
| # containing our dune was already present in PATH behind the bin | ||
| # directory of the default opam switch. | ||
| # TODO Possibly print a warning/hint in this case to help users fix | ||
| # their environment. | ||
| export __DUNE_SETUP_STATE=failure | ||
| fi | ||
| ;; | ||
| success) | ||
| # This is at least the second time this function was called in the | ||
| # current environment (possibly by the user sourcing their shell config | ||
| # or nesting shell sessions), and the previous time it was called it | ||
| # successfully modified the environment to give precedence to our dune | ||
| # executable. check that our dune still has precedence, and attempt to | ||
| # undo any opam-specific path shenanigans that have taken place since the | ||
| # last time this function was called. | ||
| if [ "$(__dune_which)" != "$ROOT/bin/dune" ]; then | ||
| case :"$PATH": in | ||
| *:"$ROOT/bin":*) | ||
| # Remove all opam bin directories from the PATH variable | ||
| # between the start of the PATH variable and the first | ||
| # occurrence of the dune binary distro's bin directory. | ||
| PATH_MAYBE_FIXED=$(echo "$PATH" | \ | ||
| tr ':' '\n' |\ | ||
| sed "1,\#^$ROOT/bin\$# { \#^$HOME/.opam#d; }" |\ | ||
| paste -sd ':' -) | ||
| # Only commit the change if it actually fixed the problem. | ||
| if [ "$(PATH=$PATH_MAYBE_FIXED __dune_which)" = "$ROOT/bin/dune" ]; then | ||
| export PATH="$PATH_MAYBE_FIXED" | ||
| else | ||
| # The attempt to fix the PATH variable failed, so give up. | ||
| export __DUNE_SETUP_STATE=failure | ||
| fi | ||
| ;; | ||
| *) | ||
| # The dune binary distro is no longer in the PATH variable at | ||
| # all, so give up. | ||
| export __DUNE_SETUP_STATE=failure | ||
| ;; | ||
| esac | ||
| fi | ||
| ;; | ||
| *) | ||
| # Prepending path in case a system-installed dune needs to be overridden | ||
| export PATH="$ROOT/bin:$PATH" | ||
| failure) | ||
| # A previous attempt at modifying the environment failed, so don't | ||
| # attempt further environment modifications here. | ||
| ;; | ||
| esac | ||
|
|
||
| # Only load completions if the shell is interactive. | ||
| if [ -t 0 ]; then | ||
| # Load bash completions for dune. | ||
| # Suppress warning from shellcheck as it can't see the completion script. | ||
| # shellcheck disable=SC1091 | ||
| . "$ROOT"/share/bash-completion/completions/dune | ||
| fi | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,63 @@ | ||
| #!/usr/bin/env fish | ||
|
|
||
| if ! set -q __DUNE_SETUP_STATE | ||
| set --export __DUNE_SETUP_STATE "incomplete" | ||
| end | ||
|
|
||
| function __dune_env | ||
| set dune_bin_path "$argv[1]/bin" | ||
| if ! contains "$dune_bin_path" $PATH; | ||
| fish_add_path --prepend --path "$dune_bin_path" | ||
| if [ "$(count $argv)" != "1" ] | ||
| echo "__dune_env expected 1 argument, got $(count $argv)" | ||
| end | ||
|
|
||
| set --local dune_root "$argv[1]" | ||
| set --local dune_bin "$dune_root/bin" | ||
|
|
||
| switch "$__DUNE_SETUP_STATE" | ||
| case incomplete | ||
| if ! contains "$dune_bin" $PATH; and [ -d "$dune_bin" ] | ||
| fish_add_path --prepend --path "$dune_bin" | ||
| end | ||
| if [ "$(type -P dune)" = "$dune_bin/dune" ] | ||
| set --export __DUNE_SETUP_STATE "success" | ||
| else | ||
| # Despite modifying the environment, running `dune` would resolve to | ||
| # the wrong dune instance. This can happen if the bin directory | ||
| # containing our dune was already present in PATH behind the bin | ||
| # directory of the default opam switch. | ||
| # TODO Possibly print a warning/hint in this case to help users fix | ||
| # their environment. | ||
| set --export __DUNE_SETUP_STATE "failure" | ||
| end | ||
| case success | ||
| # This is at least the second time this function was called in the | ||
| # current environment (possibly by the user sourcing their shell config | ||
| # or nesting shell sessions), and the previous time it was called it | ||
| # successfully modified the environment to give precedence to our dune | ||
| # executable. check that our dune still has precedence, and attempt to | ||
| # undo any opam-specific path shenanigans that have taken place since the | ||
| # last time this function was called. | ||
| if [ "$(type -P dune)" != "$dune_bin/dune" ] | ||
| if contains "$dune_bin" $PATH | ||
| # Remove all opam bin directories from the PATH variable | ||
| # between the start of the PATH variable and the first | ||
| # occurrence of the dune binary distro's bin directory. | ||
| set --local PATH_maybe_fixed $(printf "%s\n" $PATH | \ | ||
| sed "1,\#^$dune_bin\$# { \#^$HOME/.opam#d; }") | ||
| # Only commit the change if it actually fixed the problem. | ||
| if [ "$(PATH=$PATH_maybe_fixed type -P dune)" = "$dune_bin/dune" ] | ||
| set --export PATH $PATH_maybe_fixed | ||
| else | ||
| # The attempt to fix the PATH variable failed, so give up. | ||
| set --export __DUNE_SETUP_STATE "failure" | ||
| end | ||
| else | ||
| # The dune binary distro is no longer in the PATH variable at | ||
| # all, so give up. | ||
| set --export __DUNE_SETUP_STATE "failure" | ||
| end | ||
| end | ||
| case failure | ||
| # A previous attempt at modifying the environment failed, so don't | ||
| # attempt further environment modifications here. | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,94 @@ | ||
| #!/bin/sh | ||
|
|
||
| # Equivalent to `which dune`, but `which` might not be installed. | ||
| __dune_which() { | ||
| echo "$PATH" | \ | ||
| tr ':' '\n' |\ | ||
| while read -r entry; do | ||
| if test -x "$entry/dune"; then | ||
| echo "$entry/dune" | ||
| return 0 | ||
| fi | ||
| done | ||
| return 1 | ||
| } | ||
|
|
||
| export __DUNE_SETUP_STATE="${__DUNE_SETUP_STATE:-incomplete}" | ||
|
|
||
| __dune_env() { | ||
| if [ "$#" != "1" ]; then | ||
| echo "__dune_env expected 1 argument, got $#" | ||
| return | ||
| fi | ||
| __dune_root="$1" | ||
| __DUNE_ROOT="$1" | ||
|
|
||
| # Add dune to PATH unless it's already present. | ||
| # Affix colons on either side of $PATH to simplify matching (based on | ||
| # rustup's env script). | ||
| case :"$PATH": in | ||
| *:"$__dune_root/bin":*) | ||
| # Do nothing since the bin directory is already in PATH. | ||
| case "$__DUNE_SETUP_STATE" in | ||
| incomplete) | ||
| # This is the first time __dune_env has been called, so attempt to set up | ||
| # the environment for dune and record in the global variable | ||
| # __DUNE_SETUP_STATE whether or not it succeeded. | ||
|
|
||
| # Add dune to PATH unless it's already present. | ||
| # Affix colons on either side of $PATH to simplify matching (based on | ||
| # rustup's env script). | ||
| case :"$PATH": in | ||
| *:"$__DUNE_ROOT/bin":*) | ||
| # Do nothing since the bin directory is already in PATH. | ||
| ;; | ||
| *) | ||
| export PATH="$__DUNE_ROOT/bin:$PATH" | ||
| ;; | ||
| esac | ||
|
|
||
| if [ "$(__dune_which)" = "$__DUNE_ROOT/bin/dune" ]; then | ||
| export __DUNE_SETUP_STATE=success | ||
| else | ||
| # Despite modifying the environment, running `dune` would resolve to | ||
| # the wrong dune instance. This can happen if the bin directory | ||
| # containing our dune was already present in PATH behind the bin | ||
| # directory of the default opam switch. | ||
| # TODO Possibly print a warning/hint in this case to help users fix | ||
| # their environment. | ||
| export __DUNE_SETUP_STATE=failure | ||
| fi | ||
| ;; | ||
| success) | ||
| # This is at least the second time this function was called in the | ||
| # current environment (possibly by the user sourcing their shell config | ||
| # or nesting shell sessions), and the previous time it was called it | ||
| # successfully modified the environment to give precedence to our dune | ||
| # executable. check that our dune still has precedence, and attempt to | ||
| # undo any opam-specific path shenanigans that have taken place since the | ||
| # last time this function was called. | ||
| if [ "$(__dune_which)" != "$__DUNE_ROOT/bin/dune" ]; then | ||
| case :"$PATH": in | ||
| *:"$__DUNE_ROOT/bin":*) | ||
| # Remove all opam bin directories from the PATH variable | ||
| # between the start of the PATH variable and the first | ||
| # occurrence of the dune binary distro's bin directory. | ||
| PATH_MAYBE_FIXED=$(echo "$PATH" | \ | ||
| tr ':' '\n' |\ | ||
| sed "1,\#^$__DUNE_ROOT/bin\$# { \#^$HOME/.opam#d; }" |\ | ||
| paste -sd ':' -) | ||
| # Only commit the change if it actually fixed the problem. | ||
| if [ "$(PATH=$PATH_MAYBE_FIXED __dune_which)" = "$__DUNE_ROOT/bin/dune" ]; then | ||
| export PATH="$PATH_MAYBE_FIXED" | ||
| else | ||
| # The attempt to fix the PATH variable failed, so give up. | ||
| export __DUNE_SETUP_STATE=failure | ||
| fi | ||
| ;; | ||
| *) | ||
| # The dune binary distro is no longer in the PATH variable at | ||
| # all, so give up. | ||
| export __DUNE_SETUP_STATE=failure | ||
| ;; | ||
| esac | ||
| fi | ||
| ;; | ||
| *) | ||
| # Prepending path in case a system-installed dune needs to be overridden | ||
| export PATH="$__dune_root/bin:$PATH" | ||
| failure) | ||
| # A previous attempt at modifying the environment failed, so don't | ||
| # attempt further environment modifications here. | ||
| ;; | ||
| esac | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is
__DUNE_SETUP_STATEnot being exported here because it's already insuccessstate, and we want to continue it being in the same state?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep exactly