Skip to content
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

wip #37

Merged
merged 2 commits into from
Aug 22, 2020
Merged

wip #37

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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