11f2b61261
This PR adds a `--format=bash` option to `spack commands` to auto-generate the Bash programmable tab completion script. It can be extended to work for other shells. Progress: - [x] Fix bug in superclass initialization in `ArgparseWriter` - [x] Refactor `ArgparseWriter` (see below) - [x] Ensure that output of old `--format` options remains the same - [x] Add `ArgparseCompletionWriter` and `BashCompletionWriter` - [x] Add `--aliases` option to add command aliases - [x] Standardize positional argument names - [x] Tests for `spack commands --format=bash` coverage - [x] Tests to make sure `spack-completion.bash` stays up-to-date - [x] Tests for `spack-completion.bash` coverage - [x] Speed up `spack-completion.bash` by caching subroutine calls This PR also necessitates a significant refactoring of `ArgparseWriter`. Previously, `ArgparseWriter` was mostly a single `_write` method which handled everything from extracting the information we care about from the parser to formatting the output. Now, `_write` only handles recursion, while the information extraction is split into a separate `parse` method, and the formatting is handled by `format`. This allows subclasses to completely redefine how the format will appear without overriding all of `_write`. Co-Authored-by: Todd Gamblin <tgamblin@llnl.gov>
195 lines
3.8 KiB
Bash
Executable file
195 lines
3.8 KiB
Bash
Executable file
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
|
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
|
#
|
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
|
|
#
|
|
# A testing framework for any POSIX-compatible shell.
|
|
#
|
|
|
|
# ------------------------------------------------------------------------
|
|
# Functions for color output.
|
|
# ------------------------------------------------------------------------
|
|
|
|
# Colors for output
|
|
red='\033[1;31m'
|
|
cyan='\033[1;36m'
|
|
green='\033[1;32m'
|
|
reset='\033[0m'
|
|
|
|
echo_red() {
|
|
printf "${red}$*${reset}\n"
|
|
}
|
|
|
|
echo_green() {
|
|
printf "${green}$*${reset}\n"
|
|
}
|
|
|
|
echo_msg() {
|
|
printf "${cyan}$*${reset}\n"
|
|
}
|
|
|
|
# ------------------------------------------------------------------------
|
|
# Generic functions for testing shell code.
|
|
# ------------------------------------------------------------------------
|
|
|
|
# counts of test successes and failures.
|
|
success=0
|
|
errors=0
|
|
|
|
# Print out a header for a group of tests.
|
|
title() {
|
|
echo
|
|
echo_msg "$@"
|
|
echo_msg "---------------------------------"
|
|
}
|
|
|
|
# echo FAIL in red text; increment failures
|
|
fail() {
|
|
echo_red FAIL
|
|
errors=$((errors+1))
|
|
}
|
|
|
|
#
|
|
# Echo SUCCESS in green; increment successes
|
|
#
|
|
pass() {
|
|
echo_green SUCCESS
|
|
success=$((success+1))
|
|
}
|
|
|
|
#
|
|
# Run a command and suppress output unless it fails.
|
|
# On failure, echo the exit code and output.
|
|
#
|
|
succeeds() {
|
|
printf "'%s' succeeds ... " "$*"
|
|
output=$("$@" 2>&1)
|
|
err="$?"
|
|
|
|
if [ "$err" != 0 ]; then
|
|
fail
|
|
echo_red "Command failed with error $err."
|
|
if [ -n "$output" ]; then
|
|
echo_msg "Output:"
|
|
echo "$output"
|
|
else
|
|
echo_msg "No output."
|
|
fi
|
|
else
|
|
pass
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Run a command and suppress output unless it succeeds.
|
|
# If the command succeeds, echo the output.
|
|
#
|
|
fails() {
|
|
printf "'%s' fails ... " "$*"
|
|
output=$("$@" 2>&1)
|
|
err="$?"
|
|
|
|
if [ "$err" = 0 ]; then
|
|
fail
|
|
echo_red "Command failed with error $err."
|
|
if [ -n "$output" ]; then
|
|
echo_msg "Output:"
|
|
echo "$output"
|
|
else
|
|
echo_msg "No output."
|
|
fi
|
|
else
|
|
pass
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Ensure that a string is in the output of a command.
|
|
# Suppresses output on success.
|
|
# On failure, echo the exit code and output.
|
|
#
|
|
contains() {
|
|
string="$1"
|
|
shift
|
|
|
|
printf "'%s' output contains '$string' ... " "$*"
|
|
output=$("$@" 2>&1)
|
|
err="$?"
|
|
|
|
if [ "${output#*$string}" = "${output}" ]; then
|
|
fail
|
|
echo_red "Command exited with error $err."
|
|
echo_red "'$string' was not in output."
|
|
if [ -n "$output" ]; then
|
|
echo_msg "Output:"
|
|
echo "$output"
|
|
else
|
|
echo_msg "No output."
|
|
fi
|
|
else
|
|
pass
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Ensure that a variable is set.
|
|
#
|
|
is_set() {
|
|
printf "'%s' is set ... " "$1"
|
|
if eval "[ -z \${${1:-}+x} ]"; then
|
|
fail
|
|
echo_msg "$1 was not set!"
|
|
else
|
|
pass
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Ensure that a variable is not set.
|
|
# Fails and prints the value of the variable if it is set.
|
|
#
|
|
is_not_set() {
|
|
printf "'%s' is not set ... " "$1"
|
|
if eval "[ ! -z \${${1:-}+x} ]"; then
|
|
fail
|
|
echo_msg "$1 was set:"
|
|
echo " $1"
|
|
else
|
|
pass
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Report the number of tests that succeeded and failed on exit.
|
|
#
|
|
teardown() {
|
|
if [ "$?" != 0 ]; then
|
|
trapped_error=true
|
|
else
|
|
trapped_error=false
|
|
fi
|
|
|
|
if type cleanup &> /dev/null
|
|
then
|
|
cleanup
|
|
fi
|
|
|
|
echo
|
|
echo "$success tests succeeded."
|
|
echo "$errors tests failed."
|
|
|
|
if [ "$trapped_error" = true ]; then
|
|
echo "Exited due to an error."
|
|
fi
|
|
|
|
if [ "$errors" = 0 ] && [ "$trapped_error" = false ]; then
|
|
pass
|
|
exit 0
|
|
else
|
|
fail
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
trap teardown EXIT
|