diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..8b442ce
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,30 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - 'v*'
+
+jobs:
+ release:
+ name: "Create Release"
+ runs-on: ubuntu-latest
+ steps:
+ - name: Is pre-release?
+ id: is_pre_release
+ run: |
+ version="${GITHUB_REF#refs/tags/}"
+ if [[ "${version}" =~ -.*$ ]]; then
+ echo ::set-output name=IS_PRERELEASE::true
+ else
+ echo ::set-output name=IS_PRERELEASE::false
+ fi
+ - name: Release
+ uses: docker://antonyurchenko/git-release:v3
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ DRAFT_RELEASE: "false"
+ PRE_RELEASE: ${{ steps.is_pre_release.outputs.IS_PRERELEASE }}
+ CHANGELOG_FILE: "CHANGELOG.md"
+ ALLOW_EMPTY_CHANGELOG: "false"
+ ALLOW_TAG_PREFIX: "true"
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..5ee35a6
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,102 @@
+name: Tests
+
+on:
+ push:
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+
+jobs:
+ tests:
+ name: "Scenarios"
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os:
+ - 'ubuntu-latest'
+ - 'macos-latest'
+ steps:
+ - uses: actions/checkout@v3
+
+ # NB: We have a Docker setup for testing -- why do all this?
+ # Because we want to confirm it runs on macOS, and
+ # there are no Docker images based on frickin' macOS.
+
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 2.7
+
+ - name: Install Test Dependencies
+ working-directory: test
+ run: |
+ gem install bundler
+ bundle install
+
+ - name: Install SDKMAN!
+ run: |
+ curl -s "https://get.sdkman.io" | bash
+ source "$HOME/.sdkman/bin/sdkman-init.sh"
+ sdk version
+
+ - name: Install fish
+ uses: fish-actions/install-fish@v1.1.0
+
+ - name: Install sdkman-for-fish
+ shell: fish "{0}"
+ run: |
+ fish --version
+ curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source \
+ && fisher install jorgebucaran/fisher
+ fisher install .
+
+ - name: Confirm install
+ shell: fish "{0}"
+ run: |
+ cat /etc/os-release || sw_vers || true
+ fish --version
+ fisher --version
+ sdk version
+
+ - name: Run Tests
+ working-directory: test
+ run: |
+ cucumber --publish-quiet --tags "not @pending"
+
+ confirm-installation:
+ name: "Check fisher install"
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os:
+ - 'ubuntu-22.04'
+ - 'macos-latest'
+ steps:
+ - name: Install fish
+ uses: fish-actions/install-fish@v1.1.0
+
+ - name: Install SDKMAN!
+ run: |
+ curl -s "https://get.sdkman.io" | bash
+
+ - name: Install fisher
+ shell: fish "{0}"
+ run: |
+ fish --version
+ curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source \
+ && fisher install jorgebucaran/fisher
+ fisher --version
+
+ - name: Install sdkman-for-fish
+ shell: fish "{0}"
+ run: |
+ fisher install reitzig/sdkman-for-fish@${{ github.sha }}
+
+ - name: Confirm install
+ shell: fish "{0}"
+ run: |
+ cat /etc/os-release || sw_vers || true
+ fish --version
+ fisher ls
+ sdk version
diff --git a/.idea/runConfigurations/Test.xml b/.idea/runConfigurations/Test.xml
index 700aee0..d9dacd3 100644
--- a/.idea/runConfigurations/Test.xml
+++ b/.idea/runConfigurations/Test.xml
@@ -3,12 +3,9 @@
-
-
-
+
-
-
+
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index d17c78f..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-matrix:
- include:
- - dist: bionic
- env: FISH=2
- addons:
- apt:
- sources:
- - sourceline: "ppa:fish-shell/release-2"
- packages:
- - fish
- - dist: bionic
- env: FISH=3
- addons:
- apt:
- sources:
- - sourceline: "ppa:fish-shell/release-3"
- packages:
- - fish
- - os: osx
- env: FISH=3
- addons:
- homebrew:
- packages:
- - fish # --> latest, i.e. >=3.1.2
- update: true # TODO: build should be green without, but isn't
-
-before_install:
- - curl -s "https://get.sdkman.io" | bash
- - bundle install --gemfile=test/Gemfile --no-cache
- - |-
- uname -a;
- fish --version;
- { source ~/.bash_profile || source ~/.bashrc; } && sdk version;
- ruby --version;
- echo "cucumber $(cucumber --version)";
-
-install:
- - |-
- mkdir -p "${HOME}"/.config/fish/{completions,conf.d,functions}
- cp completions/* "${HOME}"/.config/fish/completions/
- cp conf.d/* "${HOME}"/.config/fish/conf.d/
- cp functions/* "${HOME}"/.config/fish/functions/
-
-script:
- - (cd test && cucumber)
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..2949750
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,62 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and
+this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [2.0.0] - upcoming
+
+### Breaking
+
+- Drop (explicit) support for Fish 2
+
+### Features
+
+- Support custom SDKMAN! install path (issue #34)
+- Compatibility with SDKMAN! 5.18.2
+ - Completions for `env`, `home`, `flush` (issue #35)
+ - Correct behaviour of `env clear`.
+ - Honor `sdkman_auto_env=true` (issue #38)
+ - `broadcast` removed
+- Compatibility with fisher 4 (PR #37, #39)
+
+## [1.4.0] - 2019-11-06
+
+### Features
+
+- Compatibility with macOS (issue #29)
+
+## [1.3.0] - 2019-11-05
+
+### Features
+
+- Install SDKMAN! if missing (issue #26)
+
+## [1.2.0] - 2019-07-31
+
+### Features
+
+- Compatibility with fish 3 (issue #27)
+
+## [1.1.2] - 2019-01-06
+
+### Fixes
+
+- Re-initialize if user has changed (issue #25)
+
+## [1.1.1] - 2018-11-09
+
+### Fixes
+
+- Set `_HOME` environment variables (issue #24)
+
+## [1.1.0] - 2018-10-08
+
+### Features
+
+- Compatibility with fisher 3 (PR #22)
+
+## [1.0.0] - 2018-07-21
+
+Initial release.
diff --git a/LICENSE b/LICENSE
index 0b10c1a..fa759ed 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2018 Raphael Reitzig
+Copyright (c) 2018-2022 Raphael Reitzig
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 31a9c13..ea06203 100644
--- a/README.md
+++ b/README.md
@@ -9,30 +9,40 @@
Makes command `sdk` from [SDKMAN!] usable from [fish], including auto-completion.
Also adds binaries from installed SDKs to the PATH.
-Version 1.4.0 tested with
+Version 2.0.0 has been tested with
- - fish 2.7.1 and 3.1.2, and
- - SDKMAN! 5.8.2, on
- - Ubuntu 18.04 LTS and macOS 10.13
+ - fish 3.6.1, and
+ - SDKMAN! 5.18.2, on
+ - Ubuntu 22.04 LTS and macOS 12.6
## Install
With [fisher] (install separately):
```
-fisher install reitzig/sdkman-for-fish@v1.4.0
+fisher install reitzig/sdkman-for-fish@v2.0.0
```
_Note:_
- - Only compatible with fisher v3 upwards; v2 is no longer supported.
+ - Only compatible with fisher v4 upwards; v3 is no longer supported.
- You have to install [SDKMAN!] separately.
+ - If you have installed SDKMAN! at a custom location, you need to add
+ ```fish
+ set -g __sdkman_custom_dir /your/path/to/sdkman
+ ```
+ to a fish config file
+ [run _before_](https://fishshell.com/docs/current/language.html#configuration-files)
+ `.config/fish/conf.d/sdk.fish`;
+ for example, you can use `.config/fish/conf.d/config_sdk.fish`.
+
## Usage
It's all in the background; you should be able to run `sdk` and binaries installed
with `sdk` as you would expect.
+
## Contribute
When you make changes,
@@ -65,6 +75,7 @@ done
wait
```
+
## Acknowledgements
* Completion originally by [Ted Wise](https://github.com/ctwise); see his
@@ -81,5 +92,3 @@ wait
[SDKMAN!]: https://github.com/sdkman/sdkman-cli
[fish]: https://fishshell.com/
[fisher]: https://github.com/jorgebucaran/fisher
-[travis-link]: https://travis-ci.org/reitzig/sdkman-for-fish
-[travis-badge]: https://travis-ci.org/reitzig/sdkman-for-fish.svg?branch=master
diff --git a/completions/sdk.fish b/completions/sdk.fish
index 054c203..b92a0be 100644
--- a/completions/sdk.fish
+++ b/completions/sdk.fish
@@ -1,11 +1,11 @@
# Defines autocompletion for SDKMAN!
-# Copyright (c) 2018 Raphael Reitzig
+# Copyright (c) 2018-2022 Raphael Reitzig
# MIT License (MIT)
# https://github.com/reitzig/sdkman-for-fish
# Guard: SDKMAN! needs to be installed
-if not test -f "$HOME/.sdkman/bin/sdkman-init.sh"
+if not test -f "$SDKMAN_DIR/bin/sdkman-init.sh"
exit 0
end
@@ -165,16 +165,9 @@ complete -c sdk -f -n '__fish_sdkman_no_command' \
complete -c sdk -f -n '__fish_sdkman_command_has_enough_parameters 0 v version'
# block
-# broadcast
-complete -c sdk -f -n '__fish_sdkman_no_command' \
- -a 'b broadcast' \
- -d 'Display broadcast message'
-complete -c sdk -f -n '__fish_sdkman_command_has_enough_parameters 0 b broadcast'
- # block
-
# help
complete -c sdk -f -n '__fish_sdkman_no_command' \
- -a 'h help' \
+ -a 'help' \
-d 'Display help message'
complete -c sdk -f -n '__fish_sdkman_command_has_enough_parameters 0 h help'
# block
@@ -212,15 +205,39 @@ complete -c sdk -f -n '__fish_sdkman_command_has_enough_parameters 0 update'
# flush
complete -c sdk -f -n '__fish_sdkman_no_command' \
-a 'flush' \
- -d 'Clear out caches'
-complete -c sdk -f -n '__fish_sdkman_using_command flush' \
- -a 'broadcast' \
- -d 'Re-download news'
-complete -c sdk -f -n '__fish_sdkman_using_command flush' \
- -a 'archives' \
- -d 'Remove downloads'
+ -d 'Clear out archives and temporary storage folders'
complete -c sdk -f -n '__fish_sdkman_using_command flush' \
-a 'temp' \
- -d 'Clear installation prep folder'
+ -d 'Clear out staging work folder'
+complete -c sdk -f -n '__fish_sdkman_using_command flush' \
+ -a 'version' \
+ -d 'Flush version file'
complete -c sdk -f -n '__fish_sdkman_command_has_enough_parameters 1 flush'
# block
+
+# env
+complete -c sdk -f -n '__fish_sdkman_no_command' \
+ -a 'e env' \
+ -d 'Load environment from .sdkmanrc file'
+complete -c sdk -f -n '__fish_sdkman_using_command e env' \
+ -a 'init' \
+ -d 'Initialize .sdkmanrc file'
+complete -c sdk -f -n '__fish_sdkman_using_command e env' \
+ -a 'install' \
+ -d 'Install all candidate versions listed in .sdkmanrc'
+complete -c sdk -f -n '__fish_sdkman_using_command e env' \
+ -a 'clear' \
+ -d 'Unload currently loaded environment'
+complete -c sdk -f -n '__fish_sdkman_command_has_enough_parameters 1 e env'
+ # block
+
+# home
+complete -c sdk -f -n '__fish_sdkman_no_command' \
+ -a 'h home' \
+ -d 'Show installation folder of given candidate'
+complete -c sdk -f -n '__fish_sdkman_using_command h home' \
+ -a "(__fish_sdkman_candidates_with_versions)"
+complete -c sdk -f -n '__fish_sdkman_specifying_candidate h home' \
+ -a "(__fish_sdkman_installed_versions)"
+complete -c sdk -f -n '__fish_sdkman_command_has_enough_parameters 2 h home'
+ # block
diff --git a/conf.d/sdk.fish b/conf.d/sdk.fish
index 507b212..aa133f4 100644
--- a/conf.d/sdk.fish
+++ b/conf.d/sdk.fish
@@ -3,12 +3,23 @@
# Makes command and binaries from SDKMAN! available in fish.
# Delegates to bash for the `sdk` command.
-# Copyright (c) 2018 Raphael Reitzig
+# Copyright (c) 2018-2022 Raphael Reitzig
# MIT License (MIT)
# https://github.com/reitzig/sdkman-for-fish
-set __fish_sdkman_init "$HOME/.sdkman/bin/sdkman-init.sh"
-set __fish_sdkman_noexport_init "$HOME/.config/fisher/github.com/reitzig/sdkman-for-fish/sdkman-noexport-init.sh"
+# Account for custom install locations
+if set -q __sdkman_custom_dir
+ set -gx SDKMAN_DIR "$__sdkman_custom_dir"
+else
+ # This is the default location:
+ set -gx SDKMAN_DIR "$HOME/.sdkman"
+end
+
+set __fish_sdkman_init "$SDKMAN_DIR/bin/sdkman-init.sh"
+
+# Copied from https://github.com/jorgebucaran/fisher/blob/main/functions/fisher.fish to be consistent:
+set --query fisher_path || set --local fisher_path $__fish_config_dir
+set __fish_sdkman_noexport_init "$fisher_path/functions/__sdkman-noexport-init.sh"
# Guard: SDKMAN! needs to be installed
if not test -f "$__fish_sdkman_init"
@@ -42,7 +53,8 @@ function __fish_sdkman_run_in_bash
echo -e \"\$?\" > $pipe;
env | grep -e '^SDKMAN_\|^PATH' >> $pipe;
env | grep -i -E \"^(`echo \${SDKMAN_CANDIDATES_CSV} | sed 's/,/|/g'`)_HOME\" >> $pipe;
- echo \"SDKMAN_OFFLINE_MODE=\${SDKMAN_OFFLINE_MODE}\" >> $pipe" # it's not an environment variable!
+ echo \"SDKMAN_OFFLINE_MODE=\${SDKMAN_OFFLINE_MODE}\" >> $pipe;
+ echo \"SDKMAN_ENV=\${SDKMAN_ENV}\" >> $pipe" # it's not an environment variable!
set bashDump (cat $pipe; rm $pipe)
set sdkStatus $bashDump[1]
@@ -65,7 +77,7 @@ function __fish_sdkman_run_in_bash
if test -n value
set -gx $var $value
- # Note: This makes SDKMAN_OFFLINE_MODE an environment variable.
+ # Note: This makes SDKMAN_{OFFLINE_MODE,ENV} environment variables.
# That gives it the behaviour we _want_!
end
end
@@ -77,8 +89,16 @@ end
# If this is a subshell of a(n initialized) fish owned by the same user,
# no initialization necessary.
# Otherwise:
-if not set -q SDKMAN_DIR; or test (ls -ld "$SDKMAN_DIR" | awk '{print $3}') != (whoami)
- set -e SDKMAN_DIR
+if not set -q SDKMAN_CANDIDATES_DIR; or test (ls -ld "$SDKMAN_CANDIDATES_DIR" | awk '{print $3}') != (whoami)
__fish_sdkman_run_in_bash "source $__fish_sdkman_init"
end
+# Set up auto_env
+if grep -q "^sdkman_auto_env=true" "$SDKMAN_DIR/etc/config"
+ function __fish_sdkman_autoenv --on-variable PWD
+ # Run the (modified) init script, which performs the checks and calls for us!
+ __fish_sdkman_run_in_bash "source \"$__fish_sdkman_noexport_init\""
+
+ set -x SDKMAN_OLD_PWD "$PWD" # needed by the Bash implementation
+ end
+end
diff --git a/test/Dockerfile b/test/Dockerfile
index 4044d2b..9638acd 100644
--- a/test/Dockerfile
+++ b/test/Dockerfile
@@ -1,13 +1,19 @@
-FROM ruby:2.5.8-slim-buster
+FROM ubuntu
# Install dependencies
RUN apt-get update \
&& apt-get -y install \
- fish \
+ build-essential \
curl \
+ fish \
+ nano \
+ ruby \
+ ruby-dev \
+ tree \
unzip \
zip \
- && apt-get clean
+ && apt-get clean \
+ && gem install bundler
WORKDIR app
COPY test/Gemfile ./
@@ -22,11 +28,13 @@ USER test
RUN curl -s "https://get.sdkman.io" | bash
# To speed up tests, uncomment this shared setup:
-#SHELL ["/bin/bash", "-c"]
-#RUN source "$TEST_HOME/.sdkman/bin/sdkman-init.sh" \
-# && sdk install ant 1.9.9 \
-# && sdk install ant 1.10.1 \
-# && sdk install crash
+SHELL ["/bin/bash", "-c"]
+RUN source "$TEST_HOME/.sdkman/bin/sdkman-init.sh" \
+ && sdk install ant 1.9.7 \
+ && sdk install ant 1.9.9 \
+ && sdk install ant 1.10.1 \
+ && sdk install kscript 1.5.0 \
+ && sdk install kscript 1.6.0
# "Install" sdkman-for-fish
RUN mkdir -p $TEST_HOME/.config/fish/
@@ -38,4 +46,4 @@ RUN ls -R $TEST_HOME/.config/fish/
# Run tests
COPY test ./
ENTRYPOINT ["cucumber"]
-CMD []
+CMD ["--publish-quiet", "--tags", "not @pending"]
diff --git a/test/Gemfile b/test/Gemfile
index 70d69fe..802cef6 100644
--- a/test/Gemfile
+++ b/test/Gemfile
@@ -1,6 +1,6 @@
source "https://rubygems.org"
group :test do
- gem 'cucumber', '~> 3.1.0'
- gem 'rspec', '~> 3.7.0'
+ gem 'cucumber', '~> 5'
+ gem 'rspec', '~> 3'
end
diff --git a/test/features/autoenv.feature b/test/features/autoenv.feature
new file mode 100644
index 0000000..f13209d
--- /dev/null
+++ b/test/features/autoenv.feature
@@ -0,0 +1,84 @@
+Feature: Support autoenv setting
+ When the user sets `sdkman_auto_env=true`, we should always `use` the
+ candidates specified in `./.sdkmanrc`, if any.
+
+ Background:
+ Given SDKMAN! candidate list is up to date
+ And candidate ant is installed at version 1.9.7
+ And candidate ant is installed at version 1.9.9
+ And candidate ant is installed at version 1.10.1
+ And candidate kscript is installed at version 1.5.0
+ And candidate kscript is installed at version 1.6.0
+
+ Scenario: No action if autoenv turned off
+ Given SDKMAN! config sets sdkman_auto_env to false
+ And file /tmp/autoenv-test/.sdkmanrc exists with content
+ """
+ ant=1.9.9
+ """
+ When we run fish script
+ """
+ echo (basename (realpath $ANT_HOME)) > /tmp/autoenv-test.log
+ cd /tmp/autoenv-test
+ echo (basename (realpath $ANT_HOME)) >> /tmp/autoenv-test.log
+ cd ..
+ echo (basename (realpath $ANT_HOME)) >> /tmp/autoenv-test.log
+ """
+ Then file /tmp/autoenv-test.log contains
+ """
+ 1.10.1
+ 1.10.1
+ 1.10.1
+ """
+
+ Scenario: .sdkmanrc loaded if autoenv turned on
+ Given SDKMAN! config sets sdkman_auto_env to true
+ And file /tmp/autoenv-test/.sdkmanrc exists with content
+ """
+ ant=1.9.9
+ """
+ When we run fish script
+ """
+ echo (basename (realpath $ANT_HOME)) > /tmp/autoenv-test.log
+ cd /tmp/autoenv-test
+ echo (basename (realpath $ANT_HOME)) >> /tmp/autoenv-test.log
+ cd ..
+ echo (basename (realpath $ANT_HOME)) >> /tmp/autoenv-test.log
+ """
+ Then file /tmp/autoenv-test.log contains
+ """
+ 1.10.1
+ 1.9.9
+ 1.10.1
+ """
+
+ # TODO: But that PR had been merged back when -- re-investigate
+ @pending # This one doesn't work due to a bug in sdkman. Track: https://github.com/sdkman/sdkman-cli/pull/878
+ Scenario: Switching between directories with .sdkmanrc
+ Given SDKMAN! config sets sdkman_auto_env to true
+ And file /tmp/autoenv-test-1/.sdkmanrc exists with content
+ """
+ ant=1.9.9
+ kscript=1.5.0
+ """
+ And file /tmp/autoenv-test-2/.sdkmanrc exists with content
+ """
+ ant=1.9.7
+ """
+ When we run fish script
+ """
+ echo (basename (realpath $ANT_HOME)),(basename (realpath $KSCRIPT_HOME)) > /tmp/autoenv-test.log
+ cd /tmp/autoenv-test-1
+ echo (basename (realpath $ANT_HOME)),(basename (realpath $KSCRIPT_HOME)) >> /tmp/autoenv-test.log
+ cd ../autoenv-test-2
+ echo (basename (realpath $ANT_HOME)),(basename (realpath $KSCRIPT_HOME)) >> /tmp/autoenv-test.log
+ cd ..
+ echo (basename (realpath $ANT_HOME)),(basename (realpath $KSCRIPT_HOME)) >> /tmp/autoenv-test.log
+ """
+ Then file /tmp/autoenv-test.log contains
+ """
+ 1.10.1,1.6.0
+ 1.9.9,1.5.0
+ 1.9.7,1.6.0
+ 1.10.1,1.6.0
+ """
diff --git a/test/features/completions.feature b/test/features/completions.feature
index d2a2710..6565e10 100644
--- a/test/features/completions.feature
+++ b/test/features/completions.feature
@@ -5,11 +5,11 @@ Feature: Shell Completion
Given SDKMAN! candidate list is up to date
And candidate ant is installed at version 1.9.9
And candidate ant is installed at version 1.10.1
- And candidate crash is installed
+ And candidate kscript is installed
Scenario: Command list correct
When the user enters " " into the prompt
- Then completion should propose "b, broadcast, c, current, d, default, flush, h, help, i, install, list, ls, offline, rm, selfupdate, u, ug, uninstall, update, upgrade, use, v, version"
+ Then completion should propose "c, current, d, default, flush, h, help, i, install, list, ls, offline, rm, selfupdate, u, ug, uninstall, update, upgrade, use, v, version"
Scenario Outline: Commands complete
When the user enters "" into the prompt
@@ -17,11 +17,13 @@ Feature: Shell Completion
But completion should not propose
Examples:
| cmd | completions | exclusions |
- | b | b, broadcast | /^[^b]+$/ |
| c | c, current | /^[^c]+$/ |
| d | d, default | /^[^d]+$/ |
+ | e | e, env | /^[^e]+$/ |
| f | flush | /^[^f]+$/ |
- | h | h, help | /^[^h]+$/ |
+ | h | h, help, home | /^[^h]+$/ |
+ | he | help | |
+ | ho | home | |
| i | i, install | /^[^i]+$/ |
| in | install | |
| l | list, ls | /^[^l]+$/ |
@@ -36,7 +38,7 @@ Feature: Shell Completion
# Currently uncovered (except by fuzzy matches);
# include negatives to prevent accidents:
| a | | /^a/ |
- | e | | /^e/ |
+ | b | | /^b/ |
| g | | /^g/ |
| j | | /^j/ |
| k | | /^k/ |
@@ -72,19 +74,19 @@ Feature: Shell Completion
Then completion should propose ""
But completion should not propose
Examples:
- | cmd | completions | exclusions |
- | | ant, crash | gradle |
- | a | ant | gradle |
- | j | | /.*/ |
- | 1. | | /.*/ |
- | an | ant | gradle, crash | # some installed
- | gr | | /.*/ | # none installed
- | xyz | | /.*/ | # no such candidate
- | 'an ' | | /.*/ | # no such candidate installed
- | 'ant 1' | 1.10.1, 1.9.9 | /^\w+$/ |
- | 'ant 1.10.' | 1.10.1 | 1.9.9 |
- | 'ant 2' | | /.*/ |
- | 'ant 1.10.1 ' | | /.*/ | # only one version at a time
+ | cmd | completions | exclusions |
+ | | ant, kscript | gradle |
+ | a | ant | gradle |
+ | j | | /.*/ |
+ | 1. | | /.*/ |
+ | an | ant | gradle, kscript | # some installed
+ | gr | | /.*/ | # none installed
+ | xyz | | /.*/ | # no such candidate
+ | 'an ' | | /.*/ | # no such candidate installed
+ | 'ant 1' | 1.10.1, 1.9.9 | /^\w+$/ |
+ | 'ant 1.10.' | 1.10.1 | 1.9.9 |
+ | 'ant 2' | | /.*/ |
+ | 'ant 1.10.1 ' | | /.*/ | # only one version at a time
Scenario Outline: Completion for 'list'
When the user enters "list " into the prompt
@@ -92,7 +94,7 @@ Feature: Shell Completion
But completion should not propose
Examples:
| cmd | completions | exclusions |
- | an | ant | crash |
+ | an | ant | kscript |
| xyz | | /.*/ |
| 1. | | /.*/ |
| 'ant ' | | /.*/ |
@@ -102,26 +104,55 @@ Feature: Shell Completion
Then completion should propose ""
But completion should not propose
Examples:
- | cmd | completions | exclusions |
- | | ant, crash | gradle |
- | an | ant | crash, gradle |
- | j | | /.*/ |
- | 1. | | /.*/ |
- | 'ant ' | 1.10.1, 1.9.9 | /^\w+$/ |
- | 'ant 1.10.1 ' | | /.*/ |
+ | cmd | completions | exclusions |
+ | | ant, kscript | gradle |
+ | an | ant | kscript, gradle |
+ | j | | /.*/ |
+ | 1. | | /.*/ |
+ | 'ant ' | 1.10.1, 1.9.9 | /^\w+$/ |
+ | 'ant 1.10.1 ' | | /.*/ |
Scenario Outline: Completion for 'default'
When the user enters "default " into the prompt
Then completion should propose ""
But completion should not propose
Examples:
- | cmd | completions | exclusions |
- | | ant, crash | gradle |
- | an | ant | crash, gradle |
- | j | | /.*/ |
- | 1. | | /.*/ |
- | 'ant ' | 1.10.1, 1.9.9 | /^\w+$/ |
- | 'ant 1.10.1 ' | | /.*/ |
+ | cmd | completions | exclusions |
+ | | ant, kscript | gradle |
+ | an | ant | kscript, gradle |
+ | j | | /.*/ |
+ | 1. | | /.*/ |
+ | 'ant ' | 1.10.1, 1.9.9 | /^\w+$/ |
+ | 'ant 1.10.1 ' | | /.*/ |
+
+ Scenario Outline: Completion for 'home'
+ When the user enters "home " into the prompt
+ Then completion should propose ""
+ But completion should not propose
+ Examples:
+ | cmd | completions | exclusions |
+ | | ant, kscript | gradle |
+ | an | ant | kscript, gradle |
+ | j | | /.*/ |
+ | 1. | | /.*/ |
+ | 'ant ' | 1.10.1, 1.9.9 | /^\w+$/ |
+ | 'ant 1.10.1 ' | | /.*/ |
+
+ Scenario Outline: Completion for 'env'
+ When the user enters "env " into the prompt
+ Then completion should propose ""
+ But completion should not propose
+ Examples:
+ | cmd | completions | exclusions |
+ | | init, install, clear | /^(?!init\|install\|clear).*$/ |
+ | i | init, install | /^(?!init\|install).*$/ |
+ | ini | init | /^(?!init).*$/ |
+ | ins | install | /^(?!install).*$/ |
+ | c | clear | /^(?!clear).*$/ |
+ | b | | /.*/ |
+ | 'init ' | | /.*/ |
+ | 'clear ' | | /.*/ |
+ | 'install ' | | /.*/ |
Scenario Outline: Completion for 'current'
When the user enters "current " into the prompt
@@ -140,12 +171,12 @@ Feature: Shell Completion
Then completion should propose ""
But completion should not propose
Examples:
- | cmd | completions | exclusions |
- | | ant, crash | gradle |
- | an | ant | crash, gradle |
- | j | | /.*/ |
- | 1. | | /.*/ |
- | 'ant ' | | /^\w+$/ |
+ | cmd | completions | exclusions |
+ | | ant, kscript | gradle |
+ | an | ant | kscript, gradle |
+ | j | | /.*/ |
+ | 1. | | /.*/ |
+ | 'ant ' | | /^\w+$/ |
Scenario Outline: Completion for 'offline'
When the user enters "offline " into the prompt
@@ -175,25 +206,21 @@ Feature: Shell Completion
Then completion should propose ""
But completion should not propose
Examples:
- | cmd | completions | exclusions |
- | | archives, broadcast, temp | /^(?!archives\|broadcast\|temp).*$/ |
- | b | broadcast | /^(?!broadcast).*$/ |
- | a | archives | /^(?!archives\|broadcast).*$/ |
- | t | temp | /^(?!temp\|broadcast).*$/ |
- | x | | /.*/ |
- | 'temp ' | | /.*/ |
-
+ | cmd | completions | exclusions |
+ | | temp, version | /^(?!temp\|version).*$/ |
+ | t | temp | /^(?!temp).*$/ |
+ | v | version | /^(?!version).*$/ |
+ | x | | /.*/ |
+ | 'tmp ' | | /.*/ |
Scenario Outline: Completion for commands without parameters
When the user enters "" into the prompt
Then completion should not propose /.*/
Examples:
- | cmd |
- | 'version ' |
- | 'version a' |
- | 'broadcast ' |
- | 'broadcast a' |
- | 'help ' |
- | 'help a' |
- | 'update ' |
- | 'update a' |
+ | cmd |
+ | 'version ' |
+ | 'version a' |
+ | 'help ' |
+ | 'help a' |
+ | 'update ' |
+ | 'update a' |
diff --git a/test/features/corner_cases.feature b/test/features/corner_cases.feature
index a2c211f..a41338c 100644
--- a/test/features/corner_cases.feature
+++ b/test/features/corner_cases.feature
@@ -6,13 +6,27 @@ Feature: Corner Cases
Then environment variable SDKMAN_DIR has the original value
Scenario: sdk initialized for another user in this shell
+ # Use any directory outside of the user's home directory
Given environment variable SDKMAN_DIR is set to "/"
When a new Fish shell is launched
Then environment variable SDKMAN_DIR has the original value
- # TODO: add test that fails if `test` in conf.d/sdk.fish:80 errors (cf issue #28 et al.)
+ Scenario: Custom installation path
+ Given SDKMAN! is installed at /tmp/sdkman
+ And fish config file config_sdk.fish exists with content
+ """
+ set -g __sdkman_custom_dir /tmp/sdkman
+ """
+ When we run "sdk version" in Fish
+ Then the exit code is 0
+ And the output contains "SDKMAN!"
+ And environment variable SDKMAN_DIR has value "/tmp/sdkman"
+ And environment variable ANT_HOME has value "/tmp/sdkman/candidates/ant/current"
+ @pending # cf. issue #10
Scenario: PATH should contain only valid paths
- Given candidate crash is installed
- When candidate crash is uninstalled
- Then environment variable PATH cannot contain "sdkman/candidates/crash/"
+ Given candidate kscript is installed
+ When candidate kscript is uninstalled
+ Then environment variable PATH cannot contain "sdkman/candidates/kscript/"
+
+ # TODO: add test that fails if `test` in conf.d/sdk.fish:80 errors (cf issue #28 et al.)
diff --git a/test/features/step_definitions/corner_cases.rb b/test/features/step_definitions/corner_cases.rb
index 198cae4..2ae4120 100644
--- a/test/features/step_definitions/corner_cases.rb
+++ b/test/features/step_definitions/corner_cases.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'fileutils'
+
Given('environment variable {env_name} is not set') do |name|
@name = name
@expect_intermediate_value = false
@@ -22,6 +24,26 @@ Given('environment variable {env_name} is set to {string}') do |name, new_value|
BASH
end
+$install_default = "#{ENV['HOME']}/.sdkman"
+$install_custom = nil
+$install_backup = "#{$install_default}_bak"
+Given(/^SDKMAN! is installed at (.*)$/) do |path|
+ $install_custom = path
+ FileUtils.cp_r($install_default, $install_custom)
+ log "Backing up #{$install_default} at #{$install_backup}"
+ FileUtils.mv($install_default, $install_backup)
+end
+
+def _restore_install # called in After hook
+ unless $install_custom.nil?
+ log "Removing #{$install_custom}"
+ FileUtils.rm_rf($install_custom)
+ $install_custom = nil
+ log "Restoring #{$install_default} from #{$install_backup}"
+ FileUtils.mv($install_backup, $install_default)
+ end
+end
+
When('a new Fish shell is launched') do
@command += <<~BASH
fish -lc "env | grep -E \\"^#{@name}=\\"" \\
diff --git a/test/features/step_definitions/general.rb b/test/features/step_definitions/general.rb
new file mode 100644
index 0000000..ca994db
--- /dev/null
+++ b/test/features/step_definitions/general.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'fileutils'
+require 'tempfile'
+
+module GeneralHelper
+end
+World GeneralHelper
+
+When('we run fish script') do |script_content|
+ script_file = Tempfile.new('fish_script')
+ File.write(script_file, script_content)
+
+ out, status = Open3.capture2e("fish #{script_file.path}")
+ unless status.success?
+ warn(out)
+ raise "Fish command failed: #{out}"
+ end
+
+ @output_fish_script = out.strip
+end
+
+Then(/^the output is$/) do |text|
+ expect(@output_fish_script).to eq(text.strip)
+end
+
+When('we run {string} in Fish') do |command|
+ @response = run_fish_command(command)
+end
+
+Then('the exit code is {int}') do |code|
+ expect(@response[:status]).to eq(code)
+end
+
+Then(/^environment variable ([A-Z_]+) has value "([^"]+)"$/) do |key, value|
+ expect(@response[:env][key]).to eq(value)
+end
+
+And('the output contains {string}') do |content|
+ output = @response[:stdout]
+ .select { |line| !line.blank? }
+ .map { |line| line.strip }
+ expect(output).to include(content)
+end
+
+Then(/^file ([a-zA-Z0-9\-_.\/]+) contains$/) do |file,content|
+ expect(File.readlines(file).join("").strip).to eq(content.strip)
+end
diff --git a/test/features/step_definitions/setup.rb b/test/features/step_definitions/setup.rb
index 69fdd04..a295e3b 100644
--- a/test/features/step_definitions/setup.rb
+++ b/test/features/step_definitions/setup.rb
@@ -1,3 +1,6 @@
+require 'fileutils'
+require 'tempfile'
+
$index_updated = false # TODO: Hack since Cucumber doesn't have Feature-level hooks
Given(/^SDKMAN! candidate list is up to date$/) do
unless $index_updated
@@ -32,21 +35,88 @@ def _uninstall_candidate_version(candidate_dir)
end
When(/^candidate (\w+) is uninstalled$/) do |candidate|
- puts `ls ~/.sdkman/candidates/#{candidate}`
+ log `ls ~/.sdkman/candidates/#{candidate}`
Dir["#{ENV['HOME']}/.sdkman/candidates/#{candidate}/*"].each do |candidate_dir|
_uninstall_candidate_version(candidate_dir)
end
- puts `ls ~/.sdkman/candidates/#{candidate}`
+ log `ls ~/.sdkman/candidates/#{candidate}`
end
-# Uninstall all SDKMAN! candidates
-# TODO: Run after every scenario, this makes tests very slow.
-# Currently, Cucumber doesn't have Feature-level hooks, so we have to work around:
-# --> install only if not already installed;
-# if the test needs a candidate to _not_ be there, make it explicit.
-# --> clean up after _all_ features at least
-at_exit do
- Dir["#{ENV['HOME']}/.sdkman/candidates/*/*"].each do |candidate_dir|
- _uninstall_candidate_version(candidate_dir)
+Given(/^file ([a-zA-Z0-9\-_.\/]+) exists with content/) do |filename,content|
+ FileUtils.mkdir_p(File.dirname(filename))
+ File.write(filename, content)
+end
+
+$fish_config_files = []
+def _remove_fish_configs # called in After hook
+ $fish_config_files.each do |f|
+ log "Removing #{f}"
+ FileUtils.rm_f(f)
+ end
+ $fish_config_files = []
+end
+
+And(/^fish config file ([a-zA-Z0-9\-_.\/]+) exists with content$/) do |filename,content|
+ file = "#{ENV['HOME']}/.config/fish/conf.d/#{filename}"
+ FileUtils.mkdir_p(File.dirname(file))
+ File.write(file, content)
+ $fish_config_files << file
+end
+
+$config_file = "#{ENV['HOME']}/.sdkman/etc/config"
+$backup_config_file = nil
+def _restore_config # called in After hook
+ unless $backup_config_file.nil?
+ log "Restoring #{$config_file} from #{$backup_config_file.path}"
+ FileUtils.mv($backup_config_file, $config_file)
+ $backup_config_file = nil
end
end
+
+Given(/^SDKMAN! config sets ([a-z_]+) to (.*)$/) do |key,value|
+ if $backup_config_file.nil?
+ $backup_config_file = Tempfile.new('sdkman_config_backup_')
+ log "Backing up #{$config_file} at #{$backup_config_file.path}"
+ FileUtils.cp($config_file, $backup_config_file)
+ end
+
+ config = File.readlines($config_file).map { |line| line.split("=").map { |v| v.strip } }.to_h
+ config[key] = value
+ new_config_string = config.map { |k,v| "#{k}=#{v}" }.join("\n")
+
+ File.write($config_file, new_config_string)
+end
+
+# TODO: create shared helper for both config files
+#
+$fish_config = "#{ENV['HOME']}/.config/fish/config.fish"
+$backup_fish_config = nil
+def _restore_fish_config # called in After hook
+ unless $backup_fish_config.nil?
+ if $backup_fish_config == :none
+ log "Deleting #{$fish_config}"
+ FileUtils.rm($fish_config)
+ else
+ log "Restoring #{$fish_config} from #{$backup_fish_config.path}"
+ FileUtils.mv($backup_fish_config, $fish_config)
+ end
+ $backup_fish_config = nil
+ end
+end
+
+And(/^fish config contains `([^`]+)`$/) do |line|
+ if $backup_fish_config.nil?
+ if File.exist?($fish_config)
+ $backup_fish_config = Tempfile.new('fish_config_backup_')
+ log "Backing up #{$fish_config} at #{$backup_fish_config.path}"
+ FileUtils.cp($fish_config, $backup_fish_config)
+ else
+ $backup_fish_config = :none
+ end
+ end
+
+ config = File.exist?($fish_config) ? File.readlines($fish_config) : ''
+ config << "\n\n# Added by sdkman-for-fish test\n#{line}"
+
+ File.write($fish_config, config.join("\n"))
+end
diff --git a/test/features/support/helpers.rb b/test/features/support/helpers.rb
index 4ea155c..1b36c84 100644
--- a/test/features/support/helpers.rb
+++ b/test/features/support/helpers.rb
@@ -64,7 +64,7 @@ def run_fish_command(cmd)
end.to_h
out, status = Open3.capture2e(<<~FISH
- fish -c '#{cmd} > #{files[:stdout]} ^ #{files[:stderr]}; \
+ fish -c '#{cmd} > #{files[:stdout]} 2> #{files[:stderr]}; \
echo $status > #{files[:status]}; \
env > #{files[:env]}; \
'
diff --git a/test/features/support/hooks.rb b/test/features/support/hooks.rb
new file mode 100644
index 0000000..ea524cb
--- /dev/null
+++ b/test/features/support/hooks.rb
@@ -0,0 +1,21 @@
+require_relative '../step_definitions/setup'
+require_relative '../step_definitions/corner_cases.rb'
+
+After do |scenario|
+ _remove_fish_configs
+ _restore_fish_config
+ _restore_config
+ _restore_install
+end
+
+# Uninstall all SDKMAN! candidates
+# TODO: Run after every scenario, this makes tests very slow.
+# Currently, Cucumber doesn't have Feature-level hooks, so we have to work around:
+# --> install only if not already installed;
+# if the test needs a candidate to _not_ be there, make it explicit.
+# --> clean up after _all_ features at least
+at_exit do
+ Dir["#{ENV['HOME']}/.sdkman/candidates/*/*"].each do |candidate_dir|
+ _uninstall_candidate_version(candidate_dir)
+ end
+end
diff --git a/test/features/support/parameter_types.rb b/test/features/support/parameter_types.rb
index 492bdde..ba4d39d 100644
--- a/test/features/support/parameter_types.rb
+++ b/test/features/support/parameter_types.rb
@@ -6,6 +6,7 @@ ParameterType(
type: Array,
transformer: lambda do |*patterns|
patterns \
+ .select { |s| !s.nil? } # Huh? Well, if it helps...
.map(&:strip) \
.map do |s|
s = if %r{^/(.*)/$} =~ s
diff --git a/test/features/wrapper.feature b/test/features/wrapper.feature
index 529c61f..f6942f5 100644
--- a/test/features/wrapper.feature
+++ b/test/features/wrapper.feature
@@ -4,12 +4,16 @@ Feature: Wrapping of Bash
the effect sdk has on the Bash environment carries
over the current Fish session.
- We verifiy equality of (standard) output, exit code, and environment variables.
+ We verify equality of (standard) output, exit code, and environment variables.
Background:
Given SDKMAN! candidate list is up to date
And candidate ant is installed at version 1.9.9
And candidate ant is installed at version 1.10.1
+ And file /tmp/env-test/.sdkmanrc exists with content
+ """
+ ant=1.9.9
+ """
Scenario Outline:
When we run "" in Bash and Fish
@@ -27,4 +31,7 @@ Feature: Wrapping of Bash
| sdk update |
| sdk use ant 1.9.9 |
| sdk offline enable > /dev/null; sdk install ant foo |
- | sdk use ant 1.9.9 > /dev/null; sdk broadcast |
+ | sdk use ant 1.9.9 > /dev/null; sdk version |
+ | sdk home ant 1.9.9 |
+ | cd /tmp/env-test; sdk env |
+ | cd /tmp/env-test; sdk env; sdk env clear |