Skip to content

Commit

Permalink
wip (#37)
Browse files Browse the repository at this point in the history
* wip

- Recommend having a wrapper direnv function so that people dont have to write asdf exec direnv stuff

- Old shim is now part of asdf direnv extension command.

- You can have an .envrc with use asdf even if the directory has no .tool-versions file. All asdf current tools will be activated. In alphabetical order, since we only preserve PATH order when a .tool-versions file is present.

- Remove all variants of use asdf * have been removed.

  Doing use asdf will just ask asdf which versions are available in current directory.
  use asdf local/global were just internal apis and not intended for people to use.
  use asdf tool version was a bad choice since people should store versions on their .tool-versions file.

- Move commands to new asdf `lib/commands/*.bash` location
  See https://asdf-vm.com/#/plugins-create?id=extension-commands-for-asdf-cli

* use `asdf exec direnv` in .bashrc (#39)

asdf direnv triggers a dirname error

Co-authored-by: Michael Paul Killian <[email protected]>
  • Loading branch information
vic and michi-zuri authored Aug 22, 2020
1 parent 8fab1a9 commit 414e584
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 218 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ jobs:
if: matrix.os == 'macos-latest'
run: brew install coreutils

- name: Install bats
- name: Install bats-core on Unix systems
run: |
git clone https://github.com/bats-core/bats-core.git $HOME/bats-core
git clone --depth 1 --branch v1.1.0 https://github.com/bats-core/bats-core.git $HOME/bats-core
echo "::add-path::$HOME/bats-core/bin"
- name: Install asdf
run: |
Expand Down Expand Up @@ -96,8 +97,7 @@ jobs:

- name: Run ShellCheck
run: |
shellcheck bin/*
shellcheck shims/*
shellcheck bin/* lib/commands/*
format:
runs-on: macos-latest
Expand Down
116 changes: 60 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,23 +94,16 @@ Then edit your `.bashrc` or equivalent shell profile:
```bash
# File: ~/.bashrc

# If you have the following line enabled, comment or remove it.
## . $HOME/.asdf/asdf.sh

# In order to bypass asdf shims. We *only* add the `ASDF_DIR/bin`
# directory to PATH, since we still want to use `asdf` but not its shims.
export PATH="$HOME/.asdf/bin:$PATH"

# Hook direnv into your shell.
eval "$(asdf exec direnv hook bash)"

# A shortcut for asdf managed direnv.
direnv() { asdf exec direnv "$@"; }
```

If you are not using bash, adapt the previous snippet by following the
[instructions to hook direnv into various other SHELLS](https://github.com/direnv/direnv/blob/master/docs/hook.md)

Note that even when the `shims` directory is no longer in PATH, you are always
able to invoke any asdf managed command via `asdf exec`.

##### Global asdf-direnv integration.

The [`~/.config/direnv/direnvrc`](https://direnv.net/#faq) file is a good place
Expand All @@ -120,7 +113,7 @@ The following snippet makes the `use asdf` feature available:

```bash
# File: ~/.config/direnv/direnvrc
source $(asdf which direnv_use_asdf)
source "$(asdf direnv hook asdf)"

# Uncomment the following line to make direnv silent by default.
# export DIRENV_LOG_FORMAT=""
Expand All @@ -135,10 +128,10 @@ On your project directory, create an `.envrc` file like this:

```bash
# File: /your/project/.envrc
use asdf # activates plugins listed by `asdf current`
use asdf
```

Finally, run `asdf exec direnv allow .envrc` to trust your new file.
Finally, run `direnv allow` to trust your new file.

###### Cached environment

Expand All @@ -162,42 +155,6 @@ direnv: using asdf nodejs 12.6.0
direnv: export +MIX_ARCHIVES +MIX_HOME +NPM_CONFIG_PREFIX ~PATH
```

#### Other `use asdf` options.

`use asdf` with no argument is equivalent to `use asdf current`.

_Note_: Tool versions are resolved just like `asdf current tool-name`.

When a tool gets activated, this plugin will automatically watch the file
specifying its version (be it a tool-versions file or legacy version file) for
changes.

- `use asdf current` **(default)**

Just an alias for `use asdf global` followed by `use asdf local`. Activating
global plugins first makes sure your local tools are first on PATH.

- `use asdf TOOL_NAME [VERSION]`

Load the environment for a tool and version.

- `use asdf FILE_NAME`

Load the environment for tools listed on file.

- `use asdf local`

Only load the environment for tools present in upmost `.tool-versions` file.

- `use asdf global`

Only load the environment for tools not present in upmost `.tool-versions` file.

This works by listing all your installed plugins and filtering out those present
in the upmost `.tool-versions` file. Effectively activating any globally
selected plugin like those present on `~/.tool-versions` and also those local
tools that use legacy filenames.

## Benchmark

![benchmark](https://user-images.githubusercontent.com/38746192/67657932-8483fb80-f99b-11e9-96d8-3d46d419ea62.png)
Expand Down Expand Up @@ -240,10 +197,26 @@ without asdf-direnv:
hyperfine --cleanup 'npm uninstall -g yarn' 'npm install -g yarn'
```

### Tips for direnv beginners
### Pro-Tips

- Take a look at `direnv help true`.

- Getting `$ASDF_DIR/shims` out of the PATH.

Some users might want to bypass asdf shims altogether. To do so,
include only `$ASDF_DIR/bin` in your PATH but exclude the shims
directory.

All shims are still available via `asdf exec <shim>`

```bash
# ~/.bashrc or equivalent

# Dont source `~/.asdf/asdf.sh`
PATH="$PATH:~/.asdf/bin"
source "~/.asdf/lib/asdf.sh" # just load the asdf wrapper function
```

- If you want to silence the console output of direnv, you can do that by
setting an empty environment variable: `export DIRENV_LOG_FORMAT=""`.

Expand All @@ -255,13 +228,44 @@ hyperfine --cleanup 'npm uninstall -g yarn' 'npm install -g yarn'
direnv exec /some/project npm
```

- Remember that activation order is important. In the following example, toolB
will be present before toolA in PATH.
- Remember that activation order is important.

If a local `.tool-versions` file is present, the order of listed plugins will be
preserved, so that toolA will be present before toolB in PATH.

```bash
# .tool-versions
toolA 1.0
toolB 2.0
```

- You can `use asdf` even if current directory has no `.tool-versions` file.

In this case the the activated versions will be the same than those returned
by `asdf current` command.

- You can override any tool version via environment variables.

See the asdf documentation regarding versions from environment variables.

```bash
# .envrc
use asdf toolA 1.0
use asdf toolB 2.0
ASDF_PLUGIN_VERSION=1.0
use asdf
```

- You can omit direnv on your global `~/.tool-versions` file.

You just need to provide the version via an environment variable.

```bash
# File: ~/.bashrc

# Hook direnv into your shell.
eval "$(env ASDF_DIRENV_VERSION=2.20.0 asdf direnv hook bash)"

# A shortcut for asdf managed direnv.
direnv() { env ASDF_DIRENV_VERSION=2.20.0 asdf direnv "$@"; }
```

- Remember `direnv` can reload the environment whenever a file changes. By
Expand All @@ -275,8 +279,8 @@ But you can easily watch more files when needed.
watch_file "package.json"
```

- Using `asdf exec direnv status` can be helpful to inspect current state. Also,
you might want to take a look to `asdf exec direnv --help`.
- Using `direnv status` can be helpful to inspect current state. Also,
you might want to take a look to `direnv --help`.

## Useful links

Expand Down
9 changes: 9 additions & 0 deletions lib/commands/command-hook-asdf.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

use_asdf() {
source_env "$(asdf direnv _asdf_cached_envrc "$@")"
}

if [ "1" == "$DIRENV_IN_ENVRC" ] && [ "$0" == "${BASH_SOURCE[0]}" ]; then
echo "$0"
fi
67 changes: 25 additions & 42 deletions bin/direnv_use_asdf → lib/commands/command.bash
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,7 @@ _load_asdf_utils() {
fi
}

_die() {
log_error "$*"
exit 1
}

_asdf_env_file() {
_asdf_cached_envrc() {
local dump_dir tools_file tools_cksum env_file
dump_dir="$(asdf where direnv)/env"
tools_file="$(_local_versions_file)"
Expand All @@ -58,43 +53,22 @@ _asdf_env_file() {
rm "$dump_dir/$(echo "$tools_cksum" | cut -d- -f1-2)"-* 2>/dev/null || true
log_status "Creating env file $env_file"

_asdf_env "$@" | _no_dups >"$env_file"
_asdf_envrc "$tools_file" | _no_dups >"$env_file"
echo "$env_file"
}

_asdf_env() {
if [ -z "$*" ] || [ "current" == "$*" ]; then
_asdf_env global
_asdf_env local

elif [ "global" == "$*" ]; then
_load_global_plugins_env "$(_local_versions_file)"

elif [ "local" == "$*" ]; then
_load_local_plugins_env "$(_local_versions_file)"

elif [ -f "$1" ]; then # [tool-versions file]
_load_local_plugins_env "$1"

elif [ -n "$1" ] && [ -z "$2" ]; then # [name] only
check_if_plugin_exists "$1"
_load_plugin_version_and_file "$1"

elif [ -n "$1" ] && [ -n "$2" ]; then # [name] [version]
check_if_version_exists "$1" "$2"
_plugin_env_bash "$1" "$2"

else
_die "use asdf: Invalid args. See README.md for some examples."
fi
_asdf_envrc() {
local tools_file="$1"
_load_global_plugins_env "$tools_file"
_load_local_plugins_env "$tools_file"
}

# compute a checksump to see if we can use the cache or have to compute the environment again
_cksum() {
local file="$1"
# working directory, the arguments given to use_asdf, direnv status, and the tools-version modification times.
# shellcheck disable=SC2154 # var is referenced but not assigned.
cksum <(pwd) <(echo "$@") <("$direnv" status) <(ls -l "$file") | cut -d' ' -f 1 | tr $'\n' '-' | sed -e 's/-$//'
cksum <(pwd) <(echo "$@") <("$direnv" status) <(test -f "$file" && ls -l "$file") | cut -d' ' -f 1 | tr $'\n' '-' | sed -e 's/-$//'
}

_tgrep() {
Expand Down Expand Up @@ -122,8 +96,8 @@ _local_versions_file() {
tool_versions="$(find_up .tool-versions)"
if [ -f "$tool_versions" ]; then
echo "$tool_versions"
else
_die "could not find .tool-versions file"
elif [ -f "$HOME/.tool-versions" ]; then
echo "$HOME/.tool-versions"
fi
}

Expand All @@ -138,11 +112,11 @@ _all_plugins_list() {

_except_local_plugins_list() {
local tool_versions=$1
local tmp_local_plugin_names
tmp_local_plugin_names="$(mktemp)"
_plugins_in_file "$tool_versions" >"$tmp_local_plugin_names"
_all_plugins_list | _new_items "$tmp_local_plugin_names"
rm "$tmp_local_plugin_names"
if [ -f "$tool_versions" ]; then
_all_plugins_list | _new_items <(_plugins_in_file "$tool_versions")
else
_all_plugins_list
fi
}

_load_global_plugins_env() {
Expand All @@ -152,7 +126,9 @@ _load_global_plugins_env() {

_load_local_plugins_env() {
local tool_versions=$1
_plugins_in_file "$tool_versions" | _tail_r | _each_do _load_plugin_version_and_file
if [ -f "$tool_versions" ]; then
_plugins_in_file "$tool_versions" | _tail_r | _each_do _load_plugin_version_and_file
fi
}

# from asdf plugin_current_command
Expand Down Expand Up @@ -213,4 +189,11 @@ _plugin_env_bash() {
_path_changed_entries "$old_path" "$new_path" | _tail_r | _each_do echo PATH_add
}

"$@"
case "$1" in
"_"*)
"$@"
;;
*)
exec "$direnv" "$@"
;;
esac
31 changes: 0 additions & 31 deletions shims/direnv_use_asdf

This file was deleted.

14 changes: 7 additions & 7 deletions test/test_helpers.bash
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ die() {
exit 1
}

direnv() {
asdf direnv "$@"
}

setup_asdf_direnv() {
ASDF_CMD="$(command -v asdf)"
test -x "$ASDF_CMD" || die "Expected asdf command to be available."
Expand Down Expand Up @@ -46,17 +50,13 @@ clean_asdf_direnv() {
}

envrc_load() {
eval "$(asdf exec direnv export bash)"
}

allow_direnv() {
asdf exec direnv allow
eval "$(direnv export bash)"
}

envrc_use_asdf() {
echo 'source $(asdf which direnv_use_asdf)' >".envrc"
echo 'source $(asdf direnv hook asdf)' >".envrc"
echo "use asdf $*" >>".envrc"
allow_direnv
direnv allow
}

dummy_bin_path() {
Expand Down
Loading

0 comments on commit 414e584

Please sign in to comment.