diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..b8844f8
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,38 @@
+name: CI
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v1
+ with:
+ node-version: '12'
+ - name: Install bats
+ run: |
+ curl -L -# -o "v0.4.0.tar.gz" https://github.com/sstephenson/bats/archive/v0.4.0.tar.gz
+ tar -xzf v0.4.0.tar.gz
+ - name: Link dvm
+ run: |
+ npm link
+ - name: Check Error
+ run: |
+ ./bats-0.4.0/bin/bats ./test/error/install.bats
+ ./bats-0.4.0/bin/bats ./test/error/now-version.bats
+ ./bats-0.4.0/bin/bats ./test/error/command_not_found.bats
+ - name: dvm install 0.17.0
+ run: |
+ dvm install 0.17.0
+ - name: dvm checkout v0.17.0
+ run: |
+ dvm checkout v0.17.0
+ - name: Check Success
+ run: |
+ ./bats-0.4.0/bin/bats ./test/success/now-version.bats
+ ./bats-0.4.0/bin/bats ./test/success/help.bats
+ - name: Show dvm usage
+ run: dvm help
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b0d0f66
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+/node_modules
+
+# log
+*.log
+
+# cache
+.npm
+
+# env
+.env
+
+# swp,swo
+*.swp
+*.swo
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1820e64
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2020, Daiki Ogawa
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f5d246c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,43 @@
+[![CI Status](https://github.com/d-ogxwx/dvm/workflows/CI/badge.svg)](https://github.com/d-ogxwx/dvm/actions)
+
+# Dotty version manager
+
+Dotty version manager(dvm). Dotty is a next-generation compiler for Scala.
+
+
+
+## Configuration
+
+Add the following code to your shell configuration files such as `.bashrc` or `.bash_profile`.
+
+```bash
+$ export PATH=$PATH:$HOME/.dvm/now/dotty/bin
+```
+## Installation
+
+You have already installed npm, you can install via npm.
+
+```bash
+$ npm install -g @d-ogxwx/dvm
+```
+
+## Usage
+
+```bash
+Usage: dvm [options] [COMMAND]
+
+Commands:
+
+dvm install Install a specific dotty version.
+dvm install [-i|-interactive] Install a specific dotty version(interactive mode).
+dvm now-version Show an currently version on dvm.
+dvm now-version [-a|all] Show an currently version and all cached versions on dvm.
+dvm checkout Switch to a specific version cached on dvm.
+dvm checkout [-i|-interactive] Switch to a specific version cached on dvm(interactive mode).
+dvm rm Remove a specific dotty version.
+
+```
+
+
+
+
diff --git a/bin/dvm b/bin/dvm
new file mode 100755
index 0000000..25af793
--- /dev/null
+++ b/bin/dvm
@@ -0,0 +1,585 @@
+#!/usr/bin/env bash
+#
+# BSD 3-Clause License
+#
+# Copyright (c) 2020, Daiki Ogawa
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+DVM_DIR="$HOME/.dvm"
+DVM_VERSIONS_DIR="$DVM_DIR/versions"
+DVM_NOW_DIR="$DVM_DIR/now"
+
+function find_cached_versions() {
+ find "$DVM_VERSIONS_DIR" -type d -mindepth 2 | sed 's/\// /g' | awk '{print $(NF-1)}' | awk '!a[$0]++'
+}
+
+DVM_CACHED_VERSIONS=
+DVM_ARRAY_CACHED_VERSIONS=
+DVM_CACHED_VERSIONS_SIZE=
+
+DOTTY_VERSIONS=$(cat<<-EOF
+0.25.0-RC2
+0.25.0-RC1
+0.24.0
+0.24.0-RC1
+0.23.0-RC1
+0.22.0
+0.22.0-RC1
+0.21.0-RC1
+0.20.0
+0.20.0-RC1
+0.19.0
+0.19.0-RC1
+0.18.1
+0.18.1-RC1
+0.17.0
+0.17.0-RC1
+0.16.0
+0.16.0-RC3
+0.16.0-RC2
+0.16.0-RC1
+0.15.0
+0.15.0-RC1
+0.14.0
+0.14.0-RC1
+0.13.0
+0.13.0-RC1
+0.12.0
+0.12.0-RC1
+0.11.0
+0.11.0-RC1
+0.10.0
+0.10.0-RC1
+0.9.0
+0.9.0-RC1
+0.8.0
+0.8.0-RC1
+0.7.0
+0.7.0-RC1
+0.6.0
+0.6.0-RC1
+0.5.0-RC1
+0.4.0-RC1
+0.3.0-RC2
+0.3.0-RC1
+0.2.0-RC1
+0.1.2-RC1
+EOF
+)
+
+function usage () {
+ cat <<- EOF
+
+Usage: dvm [options] [COMMAND]
+
+Commands:
+
+dvm install Install a specific dotty version.
+dvm install [-i|-interactive] Install a specific dotty version(interactive mode).
+dvm now-version Show an currently version on dvm.
+dvm now-version [-a|all] Show an currently version and all cached versions on dvm.
+dvm checkout Switch to a specific version cached on dvm.
+dvm checkout [-i|-interactive] Switch to a specific version cached on dvm(interactive mode).
+dvm rm Remove a specific dotty version.
+
+
+EOF
+}
+
+function is_version () {
+ [[ "$1" =~ ^(0|1)\.([0-9]+)\.([0-9]+)(-RC1|-RC2|-RC3)?$ ]]
+}
+
+function is_v_prefix_version () {
+ [[ "$1" =~ ^[v](0|1)\.([0-9]+)\.([0-9]+)(-RC1|-RC2|-RC3)?$ ]]
+}
+
+function get_now_version() {
+ head -n 1 "$DVM_NOW_DIR/.version"
+}
+
+function get_cached_versions() {
+ find "$DVM_VERSIONS_DIR" -type d -mindepth 2 | sed 's/\// /g' | awk '{print $(NF-1)}' | awk '!a[$0]++'
+}
+
+function print_format1() {
+ printf " $1 \n"
+}
+
+function print_version_format () {
+ printf " $1 $2 \n"
+}
+
+function error() {
+ print_format1 "error: $1"
+ exit 1
+}
+
+function success() {
+ print_format1 "success: $1"
+}
+
+function print_selected_version () {
+ print_version_format ">" $1
+}
+
+function print_non_selected_version () {
+ print_version_format " " $1
+}
+
+function set_screen() {
+ tput smcup 2> /dev/null
+ tput civis 2> /dev/null
+ stty -echo
+}
+
+function reset_screen() {
+ tput cnorm 2> /dev/null
+ tput rmcup 2> /dev/null
+ stty echo
+}
+
+function dir_exists() {
+ [[ -d "$1" ]]
+}
+
+function file_exists() {
+ [[ -e "$1" ]]
+}
+
+function argument_exists () {
+ [[ -n "$1" ]]
+}
+
+function is_interactive_argument() {
+ [[ "-i" = "$1" ]] || [[ "-interactive" = "$1" ]]
+}
+
+function is_all_argument() {
+ [[ "$1" = "-a" ]] || [[ "$1" = "-all" ]]
+}
+
+function dvm_versions_dir_exists () {
+ ! find -d "$DVM_VERSIONS_DIR" &> /dev/null
+}
+
+function command_exists() {
+ command -v "$1" &> /dev/null
+}
+
+function print_selected_version_with_cached_versions () {
+ for version in ${DVM_CACHED_VERSIONS}; do
+ if [ "$version" = "$1" ]; then
+ print_selected_version "$version"
+ else
+ print_non_selected_version "$version"
+ fi
+ done
+}
+
+function print_dotty_versions () {
+ for version in ${DOTTY_VERSIONS}; do
+ echo "$version"
+ done
+}
+
+# -- print prev dotty version after matching a specific version
+function prev_dotty_version() {
+ print_dotty_versions | grep "$1" -B 1 | head -n 1
+}
+
+# -- print next dotty version after matching a specific version
+function next_dotty_version() {
+ print_dotty_versions | grep "$1" -A 1 | tail -n 1
+}
+
+function print_cached_versions () {
+ for version in $(find_cached_versions); do
+ echo "$version"
+ done
+}
+
+# -- print prev cached version after matching a specific version
+function prev_cached_version() {
+ print_cached_versions | grep "$1" -B 1 | head -n 1
+}
+
+# -- print next cached version after matching a specific version
+function next_cached_version() {
+ print_cached_versions | grep "$1" -A 1 | tail -n 1
+}
+
+#-- print menu
+function print_cached_versions_with_selected_version () {
+ for version in ${DVM_CACHED_VERSIONS}; do
+ if [[ "$version" = "$1" ]]; then
+ print_selected_version "$version"
+ else
+ print_non_selected_version "$version"
+ fi
+ done
+}
+
+#-- print menu
+function print_dotty_versions_with_selected_version () {
+ for version in ${DOTTY_VERSIONS}; do
+ if [[ "$version" = "$1" ]]; then
+ print_selected_version "$version"
+ else
+ print_non_selected_version "$version"
+ fi
+ done
+}
+
+function dvm_setup () {
+ mkdir -p "$DVM_VERSIONS_DIR"
+ mkdir -p "$DVM_NOW_DIR"
+ echo "" > "$DVM_NOW_DIR/.version"
+ success "set up .dvm\n"
+}
+
+function download_rollback() {
+ dotty_tar_path="$1"
+ printf "\nCanceled\n"
+ file_exists "$dotty_tar_path" && rm $dotty_tar_path
+ exit 1
+}
+
+function download() {
+
+ version="$1"
+
+ url="https://github.com/lampepfl/dotty/releases/download/$version/dotty-$version.tar.gz"
+
+ ! command_exists "curl" && error "curl command required. Please install curl command\n"
+
+ curl --output /dev/null --silent --head --fail $url
+ status=$?
+
+ [[ ! $status -eq 0 ]] && error "not found $url\n"
+
+ to="$DVM_VERSIONS_DIR/v$version"
+
+ print_format1 "From: $url"
+ print_format1 "To: $to\n"
+
+ dotty_tar_path="$DVM_VERSIONS_DIR/dotty-$version.tar.gz"
+
+ # -- trap
+ trap "download_rollback $dotty_tar_path" INT
+
+ curl -L -# -o "$dotty_tar_path" "$url"
+
+ tar -xzf "$dotty_tar_path" -C "$DVM_VERSIONS_DIR"
+
+ from=$(find "$DVM_VERSIONS_DIR" -type d -name "dotty-$version*")
+
+ #-- Rename
+ #-- example: dotty-0.0.1 -> v0.0.1
+ mv "$from" "$to"
+ rm "$dotty_tar_path"
+
+ success "download $version\n"
+}
+
+#-- print menu of using at interactive install
+function print_interactive_install_menu () {
+ printf "\n"
+ print_dotty_versions_with_selected_version "$1"
+ printf "\n"
+ print_format1 "k) Up, j) Down, Enter) Select, q) Quit"
+}
+
+function interactive_install () {
+
+ set_screen
+ clear
+
+ selected_version=
+
+ if file_exists "$DVM_NOW_DIR/.version"; then
+ selected_version="$(echo "$(get_now_version)" | sed 's/v//g')"
+ [[ -z "$selected_version" ]] && selected_version="$(print_dotty_versions | head -n 1)"
+ else
+ selected_version="$(print_dotty_versions | head -n 1)"
+ fi
+
+ print_interactive_install_menu "$selected_version"
+
+ while true; do
+ read -s -n 1 key
+ case "$key" in
+ "")
+ clear
+ #-- reset
+ reset_screen
+ install "$selected_version"
+ #-- example: Now version: 0.17.0
+ success "switch to the version $(get_now_version)"
+ echo
+ exit 0;;
+ k)
+ #-- Up
+ clear
+ selected_version=$(prev_dotty_version "$selected_version")
+ print_interactive_install_menu "$selected_version"
+ ;;
+ j)
+ #-- Down
+ clear
+ selected_version=$(next_dotty_version "$selected_version")
+ print_interactive_install_menu "$selected_version"
+ ;;
+ q)
+ #--Reset Screen
+ reset_screen
+ exit 1;
+ ;;
+ *)
+ ;;
+ esac
+ done
+}
+
+function install () {
+
+ version=
+
+ ! argument_exists "$1" && error "not found version argument.\n"
+
+ if is_interactive_argument "$1"; then
+ interactive_install
+ else
+ ! is_version "$1" && error "incorrect version argument. Example 0.17.0\n"
+
+ #-- $1 is not v prefix version.
+ version="$1"
+
+ #-- If .dvm directory does not exist, setup .dvm directory.
+ ! dir_exists "$DVM_VERSIONS_DIR" && dvm_setup
+
+ #-- Add v prefix
+ dir_exists "$DVM_VERSIONS_DIR/v$version" && error "this version has already cached on dvm\n"
+
+ download "$1"
+
+ print_format1 "Do you configure your dvm to use this version ($version): [y/n]\n"
+ read -s -n 1 input
+
+ if [ "$input" = "y" ]; then
+ # Must pass the added v prefix version.
+ checkout "v$version"
+ now_version=$(get_now_version)
+ success "switch to the version $now_version\n"
+ fi
+ exit 0;
+ fi
+}
+
+#-- print menu of using at interactive checkout
+function print_interactive_checkout_menu () {
+ printf "\n"
+ print_cached_versions_with_selected_version "$1"
+ printf "\n"
+ print_format1 "k) Up, j) Down, Enter) Select, q) Quit"
+}
+
+function interactive_checkout () {
+
+ dvm_versions_dir_exists && error "not found .dvm versions directory.\n"
+
+ # Init DVM_CACHED_VERSIONS
+ DVM_CACHED_VERSIONS=$(find_cached_versions)
+
+ selected_version=
+
+ if file_exists "$DVM_NOW_DIR/.version"; then
+ selected_version="$(get_now_version)"
+ [[ -z "$selected_version" ]] && selected_version="$(print_cached_versions | head -n 1)"
+ else
+ selected_version="$(print_cached_versions | head -n 1)"
+ fi
+
+ set_screen
+ clear
+
+ print_interactive_checkout_menu "$selected_version"
+
+ while true; do
+ read -s -n 1 key
+ case "$key" in
+ "")
+ clear
+ #--reset
+ reset_screen
+ checkout "$selected_version"
+ #-- example: Now version: 0.17.0
+ success "switch to the version $(get_now_version)"
+ echo
+ exit 0;;
+ k)
+ #-- Up
+ clear
+ selected_version=$(prev_cached_version "$selected_version")
+ print_interactive_checkout_menu "$selected_version"
+ ;;
+ j)
+ #-- Down
+ clear
+ selected_version=$(next_cached_version "$selected_version")
+ print_interactive_checkout_menu "$selected_version"
+ ;;
+ q)
+ #--Reset Screen
+ reset_screen
+ exit 1;
+ ;;
+ *)
+ ;;
+ esac
+ done
+}
+
+function checkout () {
+
+ ! argument_exists "$1" && error "not found argument.\n"
+
+ ! dir_exists "$DVM_DIR" && error "not found .dvm directory.\n"
+
+ ! dir_exists "$DVM_VERSIONS_DIR" && error "not found some cached versions.\n"
+
+ if is_interactive_argument "$1"; then
+ interactive_checkout
+ else
+ ! is_v_prefix_version "$1" && error "incorrect version argument.\n"
+ ! dir_exists "$DVM_VERSIONS_DIR/$1" && error "not match version which is cached on dvm.\n"
+ # -- checkout logic
+ version="$1"
+ dir_exists "$DVM_NOW_DIR/dotty" && rm -r "$DVM_NOW_DIR/dotty"
+ ln -fs "$DVM_VERSIONS_DIR/$version" "$DVM_NOW_DIR/dotty"
+ echo "$version" > "$DVM_NOW_DIR/.version"
+ success "switch to the version $(get_now_version)\n"
+ exit 0;
+ fi
+}
+
+function remove_cached_version() {
+
+ ! argument_exists "$1" && error "not exist version argument.\n"
+
+ ! is_v_prefix_version "$1" && error "incorrect version argument.\n"
+
+ ! dir_exists "$DVM_VERSIONS_DIR/$1" && error "this version is not cached on dvm.\n"
+
+ [[ "$(get_now_version)" = "$1" ]] && error "this version has set on dvm.\n"
+
+ while :
+ do
+ print_format1 "Delete this version ($1): [y/n]"
+ printf "\n"
+ read -s -n 1 input
+ case $input in
+ y)
+ rm -r "$DVM_VERSIONS_DIR/$version";
+ success "deleted dotty $version version.\n";
+ exit 0 ;;
+ n)
+ print_format1 "this operation is canceled.\n"
+ exit 0 ;;
+ *)
+ print_format1 "this operation is canceled.\n"
+ exit 0;;
+ esac
+ done
+}
+
+function print_now_version() {
+ success "now version $(get_now_version)\n";
+}
+
+function print_now_version_with_all_cached_versions() {
+ print_format1 "now version and some cached versions: "
+ now_version=$(get_now_version)
+ DVM_CACHED_VERSIONS=$(get_cached_versions)
+ printf "\n"
+ print_selected_version_with_cached_versions "$now_version"
+ printf "\n"
+ print_format1 "(>): this symbol represents a version which is set on dvm now.\n"
+}
+
+function now_version () {
+
+ ! dir_exists "$DVM_DIR" && error "not found .dvm directory.\n"
+
+ ! dir_exists "$DVM_VERSIONS_DIR" && error "not found some cached versions.\n"
+
+ ! file_exists "$DVM_NOW_DIR/.version" && error "not found now version.\n"
+
+ if argument_exists "$1" && is_all_argument "$1"; then
+ print_now_version_with_all_cached_versions
+ exit 0;
+ else
+ print_now_version
+ exit 0;
+ fi
+}
+
+#-- main
+if [ $# -eq 0 ]; then
+ usage
+ exit 1;
+else
+ echo
+ while [ $# -ne 0 ]; do
+ case "$1" in
+ help)
+ usage;
+ exit;;
+ i|install)
+ shift;
+ install "$1"
+ exit;;
+ rm)
+ shift;
+ remove_cached_version "$1";
+ ;;
+ checkout)
+ shift;
+ checkout "$1"
+ ;;
+ now-version)
+ shift;
+ now_version "$1"
+ ;;
+ *)
+ error "command not found.\n";
+ ;;
+ esac
+ done
+fi
+
diff --git a/demo.gif b/demo.gif
new file mode 100644
index 0000000..92177ac
Binary files /dev/null and b/demo.gif differ
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..b2d151a
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,5 @@
+{
+ "name": "@d-ogxwx/dvm",
+ "version": "1.0.0",
+ "lockfileVersion": 1
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..3c4c973
--- /dev/null
+++ b/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "@d-ogxwx/dvm",
+ "description": "dotty version manager",
+ "version": "1.0.0",
+ "author": {
+ "name": "Daiki Ogawa",
+ "url": "https://github.com/d-ogxwx"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/d-ogxwx/dvm"
+ },
+ "homepage": "https://github.com/d-ogxwx/dvm",
+ "bugs": "https://github.com/d-ogxwx/dvm/issues",
+ "contributors": [],
+ "keywords": [
+ "dvm",
+ "dotty",
+ "version",
+ "manager",
+ "dotty-version-manager"
+ ],
+ "files": [
+ "bin/dvm"
+ ],
+ "bin": {
+ "dvm": "./bin/dvm"
+ },
+ "os": [
+ "!win32"
+ ],
+ "engines": {
+ "node": "*",
+ "npm": "*"
+ },
+ "license": "LicenseRef-LICENSE"
+}
diff --git a/test/error/command_not_found.bats b/test/error/command_not_found.bats
new file mode 100644
index 0000000..a7a1eb2
--- /dev/null
+++ b/test/error/command_not_found.bats
@@ -0,0 +1,10 @@
+#!/usr/bin/env bats
+
+@test "dvm sample" {
+
+ expected=" error: command not found."
+
+ run dvm sample
+ [ "$status" -eq 1 ]
+ [ "${lines[0]}" = "$expected" ]
+}
diff --git a/test/error/install.bats b/test/error/install.bats
new file mode 100644
index 0000000..eb3e29c
--- /dev/null
+++ b/test/error/install.bats
@@ -0,0 +1,6 @@
+#!/usr/bin/evn bats
+
+@test "dvm install" {
+ run dvm install
+ [ "$status" -eq 1 ]
+}
diff --git a/test/error/now-version.bats b/test/error/now-version.bats
new file mode 100644
index 0000000..3224e4b
--- /dev/null
+++ b/test/error/now-version.bats
@@ -0,0 +1,6 @@
+#!/usr/bin/evn bats
+
+@test "dvm now-version" {
+ run dvm now-version
+ [ "$status" -eq 1 ]
+}
\ No newline at end of file
diff --git a/test/success/help.bats b/test/success/help.bats
new file mode 100644
index 0000000..f63e8d7
--- /dev/null
+++ b/test/success/help.bats
@@ -0,0 +1,8 @@
+#!/usr/bin/env bats
+
+@test "dvm help" {
+ expected="Usage: dvm [options] [COMMAND]"
+
+ run dvm help
+ [ "$status" -eq 0 ]
+}
diff --git a/test/success/now-version.bats b/test/success/now-version.bats
new file mode 100644
index 0000000..58c4c20
--- /dev/null
+++ b/test/success/now-version.bats
@@ -0,0 +1,6 @@
+#!/usr/bin/evn bats
+
+@test "dvm now-version" {
+ run dvm now-version
+ [ "$status" -eq 0 ]
+}