#!/bin/bash # # Copyright 2012 Marco Vermeulen # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # # function definitions # function __gvmtool_help { echo "" echo "Usage: gvm [version]" echo "" echo " command : install, uninstall, list, use, current, version, default, selfupdate, broadcast or help" echo " candidate : groovy, grails, griffon, gradle, vert.x" echo " version : optional, defaults to latest stable if not provided" echo "" echo "eg: gvm install groovy" } function __gvmtool_check_candidate_present { if [ -z "$1" ]; then echo -e "\nNo candidate provided." __gvmtool_help return 1 fi } function __gvmtool_check_version_present { if [ -z "$1" ]; then echo -e "\nNo candidate version provided." __gvmtool_help return 1 fi } function __gvmtool_determine_version { if [[ "${GVM_OFFLINE}" == "true" && -n "$1" && -d "${GVM_DIR}/${CANDIDATE}/$1" ]]; then VERSION="$1" elif [[ "${GVM_OFFLINE}" == "true" && -z "$1" && -L "${GVM_DIR}/${CANDIDATE}/current" ]]; then VERSION=$(readlink "${GVM_DIR}/${CANDIDATE}/current" | sed -e "s!${GVM_DIR}/${CANDIDATE}/!!g") elif [[ "${GVM_OFFLINE}" == "true" && -n "$1" ]]; then echo "Stop! ${CANDIDATE} ${1} is not available in aeroplane mode." return 1 elif [[ "${GVM_OFFLINE}" == "true" && -z "$1" ]]; then echo "${OFFLINE_MESSAGE}" return 1 elif [[ "${GVM_OFFLINE}" == "false" && -z "$1" ]]; then VERSION=$(curl -s "${GVM_SERVICE}/candidates/${CANDIDATE}/default") else VERSION_VALID=$(curl -s "${GVM_SERVICE}/candidates/${CANDIDATE}/$1") if [[ ${VERSION_VALID} == 'valid' ]]; then VERSION="$1" else echo "" echo "Stop! $1 is not a valid ${CANDIDATE} version." return 1 fi fi } function __gvmtool_build_version_csv { CANDIDATE="$1" CSV="" for version in $(ls -1 "${GVM_DIR}/${CANDIDATE}"); do if [ ${version} != 'current' ]; then CSV="${version},${CSV}" fi done CSV=${CSV%?} } function __gvmtool_determine_current_version { unset CURRENT CANDIDATE="$1" if [[ -n ${isolated_mode} && ${isolated_mode} == 1 ]]; then CURRENT=$(echo $PATH | sed -E "s|.gvm/${CANDIDATE}/([^/]+)/bin|!!\1!!|1" | sed -E "s|^.*!!(.+)!!.*$|\1|g") if [[ "${CURRENT}" == "current" ]]; then unset CURRENT fi fi if [[ -z ${CURRENT} ]]; then CURRENT=$(readlink "${GVM_DIR}/${CANDIDATE}/current" | sed -e "s!${GVM_DIR}/${CANDIDATE}/!!g") fi } function __gvmtool_download { CANDIDATE="$1" VERSION="$2" mkdir -p "${GVM_DIR}/archives" if [ ! -f "${GVM_DIR}/archives/${CANDIDATE}-${VERSION}.zip" ]; then echo "" echo "Downloading: ${CANDIDATE} ${VERSION}" echo "" DOWNLOAD_URL="${GVM_SERVICE}/download/${CANDIDATE}/${VERSION}?platform=${GVM_PLATFORM}" ZIP_ARCHIVE="${GVM_DIR}/archives/${CANDIDATE}-${VERSION}.zip" curl -L "${DOWNLOAD_URL}" > "${ZIP_ARCHIVE}" __gvmtool_validate_zip "${ZIP_ARCHIVE}" || return 1 else echo "" echo "Found a previously downloaded ${CANDIDATE} ${VERSION} archive. Not downloading it again..." __gvmtool_validate_zip "${GVM_DIR}/archives/${CANDIDATE}-${VERSION}.zip" || return 1 fi echo "" } function __gvmtool_validate_zip { ZIP_ARCHIVE="$1" ZIP_OK=$(unzip -t "${ZIP_ARCHIVE}" | grep 'No errors detected in compressed data') if [ -z "${ZIP_OK}" ]; then rm "${ZIP_ARCHIVE}" echo "" echo "Stop! The archive was corrupt and has been removed! Please try installing again." return 1 fi } function __gvmtool_default_environment_variables { if [ ! "${GVM_SERVICE}" ]; then GVM_SERVICE="http://localhost:8080" fi if [ ! "${GVM_DIR}" ]; then GVM_DIR="$HOME/.gvm" fi } function __gvmtool_check_upgrade_available { UPGRADE_AVAILABLE="" UPGRADE_NOTICE=$(echo "${BROADCAST_LIVE}" | grep 'Your version of GVM is out of date!') if [[ -n "${UPGRADE_NOTICE}" && ( "${COMMAND}" != 'selfupdate' ) ]]; then UPGRADE_AVAILABLE="true" fi } function __gvmtool_display_broadcast { COMMAND="$1" BROADCAST_FILE="${GVM_DIR}/var/broadcast" if [ -f "${BROADCAST_FILE}" ]; then BROADCAST_HIST=$(cat "${BROADCAST_FILE}") fi if [[ "${BROADCAST_LIVE}" != "${BROADCAST_HIST}" && "${COMMAND}" != 'broadcast' ]]; then mkdir -p "${GVM_DIR}/var" echo "${BROADCAST_LIVE}" > "${BROADCAST_FILE}" echo "${BROADCAST_LIVE}" fi } function __gvmtool_link_candidate_version { CANDIDATE="$1" VERSION="$2" # Change the 'current' symlink for the candidate, hence affecting all shells. if [ -L "${GVM_DIR}/${CANDIDATE}/current" ]; then unlink "${GVM_DIR}/${CANDIDATE}/current" fi ln -s "${GVM_DIR}/${CANDIDATE}/${VERSION}" "${GVM_DIR}/${CANDIDATE}/current" } function __gvmtool_install_candidate_version { CANDIDATE="$1" VERSION="$2" __gvmtool_download "${CANDIDATE}" "${VERSION}" || return 1 echo "Installing: ${CANDIDATE} ${VERSION}" mkdir -p "${GVM_DIR}/${CANDIDATE}" unzip -oq "${GVM_DIR}/archives/${CANDIDATE}-${VERSION}.zip" -d "/tmp/" mv "/tmp/${CANDIDATE}-${VERSION}" "${GVM_DIR}/${CANDIDATE}/${VERSION}" echo "Done installing!" echo "" } function __gvmtool_offline_list { echo "============================================================" echo "Aeroplane Mode: only showing installed ${CANDIDATE} versions" echo "------------------------------------------------------------" echo " " gvm_versions=($(echo ${CSV//,/ })) for (( i=0 ; i <= ${#gvm_versions} ; i++ )); do if [[ -n "${gvm_versions[$i]}" ]]; then if [[ "${gvm_versions[$i]}" == "${CURRENT}" ]]; then echo -e " > ${gvm_versions[$i]}" else echo -e " * ${gvm_versions[$i]}" fi fi done if [[ -z "${gvm_versions[@]}" ]]; then echo " None installed!" fi echo "------------------------------------------------------------" echo "* - installed " echo "> - currently in use " echo "------------------------------------------------------------" unset CSV gvm_versions } # # Command functions # function __gvmtool_install { CANDIDATE="$1" __gvmtool_check_candidate_present "${CANDIDATE}" || return 1 __gvmtool_determine_version "$2" || return 1 if [ -d "${GVM_DIR}/${CANDIDATE}/${VERSION}" ]; then echo "" echo "Stop! ${CANDIDATE} ${VERSION} is already installed." return 1 fi __gvmtool_install_candidate_version "${CANDIDATE}" "${VERSION}" || return 1 echo -n "Do you want to use ${CANDIDATE} ${VERSION} now? (Y/n): " read USE if [[ -z "${USE}" || "${USE}" == "y" || "${USE}" == "Y" ]]; then __gvmtool_link_candidate_version "${CANDIDATE}" "${VERSION}" echo "" echo Using "${CANDIDATE}" version "${VERSION}" fi } function __gvmtool_use { CANDIDATE="$1" __gvmtool_check_candidate_present "${CANDIDATE}" || return 1 __gvmtool_determine_version "$2" || return 1 if [[ "${GVM_OFFLINE}" == "false" && ! -d "${GVM_DIR}/${CANDIDATE}/${VERSION}" ]]; then echo "" echo "Stop! ${CANDIDATE} ${VERSION} is not installed." echo -n "Do you want to install it now? (Y/n): " read INSTALL if [[ -z "${INSTALL}" || "${INSTALL}" == "y" || "${INSTALL}" == "Y" ]]; then __gvmtool_install_candidate_version "${CANDIDATE}" "${VERSION}" else return 1 fi fi if [[ -n ${isolated_mode} && ${isolated_mode} == 1 ]]; then # Just update the *_HOME and PATH for this shell. case "${CANDIDATE}" in vert.x ) export VERTX_HOME="${GVM_DIR}/vert.x/${VERSION}" ;; * ) UPPER_CANDIDATE=`echo "${CANDIDATE}" | tr '[:lower:]' '[:upper:]'` export "${UPPER_CANDIDATE}_HOME"="${GVM_DIR}/${CANDIDATE}/${VERSION}" ;; esac # Replace the current path for the candidate with the selected version. export PATH=`echo $PATH | sed -E "s!${GVM_DIR}/${CANDIDATE}/([0-9][^/]+|current)!${GVM_DIR}/${CANDIDATE}/${VERSION}!g"` else __gvmtool_link_candidate_version "${CANDIDATE}" "${VERSION}" fi echo "" echo Using "${CANDIDATE}" version "${VERSION} in this shell." } function __gvmtool_default { CANDIDATE="$1" __gvmtool_check_candidate_present "${CANDIDATE}" || return 1 __gvmtool_determine_version "$2" || return 1 if [ ! -d "${GVM_DIR}/${CANDIDATE}/${VERSION}" ]; then echo "" echo "Stop! ${CANDIDATE} ${VERSION} is not installed." return 1 fi __gvmtool_link_candidate_version "${CANDIDATE}" "${VERSION}" echo "" echo "Default ${CANDIDATE} version set to ${VERSION}" } function __gvmtool_current { if [ -n "$1" ]; then CANDIDATE="$1" __gvmtool_determine_current_version "${CANDIDATE}" if [ -n "${CURRENT}" ]; then echo "Using ${CANDIDATE} version ${CURRENT}" else echo "Not using any version of ${CANDIDATE}" fi elif [[ -z "$1" && "${GVM_OFFLINE}" == "true" ]]; then echo "${OFFLINE_MESSAGE}" else # The candidates are assigned to an array for zsh compliance, a list of words is not iterable # Arrays are the only way, but unfortunately zsh arrays are not backward compatible with bash # In bash arrays are zero index based, in zsh they are 1 based(!) CANDIDATES=($(curl -s "${GVM_SERVICE}/candidates" | tr -d ",")) INSTALLED_COUNT=0 # The starts at 0 for bash, ends at the candidates array size for zsh for (( i=0; i <= ${#CANDIDATES}; i++ )); do # Eliminate empty entries due to incompatibility if [[ -n ${CANDIDATES[$i]} ]]; then __gvmtool_determine_current_version "${CANDIDATES[$i]}" if [ -n "${CURRENT}" ]; then if [ ${INSTALLED_COUNT} -eq 0 ]; then echo 'Using:' fi echo "${CANDIDATES[$i]}: ${CURRENT}" (( INSTALLED_COUNT += 1 )) fi fi done if [ ${INSTALLED_COUNT} -eq 0 ]; then echo 'No candidates are in use' fi fi } function __gvmtool_list { CANDIDATE="$1" __gvmtool_check_candidate_present "${CANDIDATE}" || return 1 __gvmtool_build_version_csv "${CANDIDATE}" __gvmtool_determine_current_version "${CANDIDATE}" FRAGMENT=$(curl -s "${GVM_SERVICE}/candidates/${CANDIDATE}/list?platform=${GVM_PLATFORM}¤t=${CURRENT}&installed=${CSV}") if [[ "${GVM_OFFLINE}" == "true" ]]; then __gvmtool_offline_list else echo "${FRAGMENT}" fi } function __gvmtool_uninstall { CANDIDATE="$1" VERSION="$2" __gvmtool_check_candidate_present "${CANDIDATE}" || return 1 __gvmtool_check_version_present "${VERSION}" || return 1 CURRENT=$(readlink "${GVM_DIR}/${CANDIDATE}/current" | sed -e "s_${GVM_DIR}/${CANDIDATE}/__g") if [[ -h "${GVM_DIR}/${CANDIDATE}/current" && ( "${VERSION}" == "${CURRENT}" ) ]]; then echo "" echo "Unselecting ${CANDIDATE} ${VERSION}..." unlink "${GVM_DIR}/${CANDIDATE}/current" fi echo "" if [ -d "${GVM_DIR}/${CANDIDATE}/${VERSION}" ]; then echo "Uninstalling ${CANDIDATE} ${VERSION}..." rm -rf "${GVM_DIR}/${CANDIDATE}/${VERSION}" else echo "${CANDIDATE} ${VERSION} is not installed." fi } function __gvmtool_version { echo "Groovy enVironment Manager ${GVM_VERSION}" } function __gvmtool_broadcast { if [ "${BROADCAST_HIST}" ]; then echo "${BROADCAST_HIST}" else echo "${BROADCAST_LIVE}" fi } function __gvmtool_selfupdate { if [[ "${GVM_OFFLINE}" == "true" ]]; then echo "${OFFLINE_MESSAGE}" else curl -s "${GVM_SERVICE}/selfupdate" | bash fi } # INSERT NEW COMMANDS BEFORE HERE # Main command function gvm { # # Various sanity checks and default settings # __gvmtool_default_environment_variables mkdir -p "${GVM_DIR}" BROADCAST_LIVE=$(curl -s "${GVM_SERVICE}/broadcast/${GVM_VERSION}") if [[ -z "${BROADCAST_LIVE}" ]]; then GVM_OFFLINE="true" BROADCAST_LIVE="${OFFLINE_BROADCAST}" else GVM_OFFLINE="false" fi __gvmtool_check_upgrade_available if [[ -n "${UPGRADE_AVAILABLE}" && ( "$1" != "broadcast" ) ]]; then echo "${BROADCAST_LIVE}" echo "" else __gvmtool_display_broadcast "$1" fi # Load the gvm config if it exists. if [ -f "${GVM_DIR}/etc/config" ]; then source "${GVM_DIR}/etc/config" fi # Check whether the command exists as an internal function... # # NOTE Internal commands use underscores rather than hyphens, # hence the name conversion as the first step here. CONVERTED_CMD_NAME=`echo "$1" | tr '-' '_'` CMD_FOUND="" if [[ -f "${GVM_DIR}/bin/gvm" ]]; then CMD_FOUND=$(grep __gvmtool_"${CONVERTED_CMD_NAME}" "${GVM_DIR}/bin/gvm") fi # ...no command provided if [[ -z "$1" ]]; then __gvmtool_help return 1 fi # ...or as a script on the path. SCRIPT_PATH="${GVM_DIR}/ext/gvm-$1.sh" if [[ -z "${CMD_FOUND}" && ! -f "${SCRIPT_PATH}" ]]; then echo -e "\nInvalid command: $1" __gvmtool_help return 1 fi # Check whether the candidate exists CANDIDATE_VALID=$(curl -s "${GVM_SERVICE}/candidates/$2") if [[ "${CANDIDATE_VALID}" == 'invalid' ]]; then echo -e "\nStop! $2 is not a valid candidate." return 1 fi # Execute the requested command if [ -n "${CMD_FOUND}" ]; then # It's available as a shell function __gvmtool_"${CONVERTED_CMD_NAME}" "$2" "$3" else # It's a shell script in the extensions directory ${SCRIPT_PATH} "$1" "$2" "$3" fi }