From bf2e529228be50ffde24c23fc23fc7ceb27b89db Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Thu, 20 Jul 2017 07:53:43 +0100 Subject: [PATCH] install: many improvements - install stack to $HOME/.local/bin for easier upgrade and passwordlessness - install missing and out-of-date official and third party hledger tools - try installing each tool individually - try cabal install if cabal is installed and stack isn't - always specify the resolver for stack install - be fairly quiet by default, replace --quiet with --verbose - --status shows installation status without doing anything - --version shows installer version - cleanup [ci skip] --- hledger-install/hledger-install.sh | 336 +++++++++++++++++++---------- 1 file changed, 226 insertions(+), 110 deletions(-) diff --git a/hledger-install/hledger-install.sh b/hledger-install/hledger-install.sh index 4d328bf57..edf58cadd 100755 --- a/hledger-install/hledger-install.sh +++ b/hledger-install/hledger-install.sh @@ -1,38 +1,57 @@ #!/bin/bash -e +# Easy hledger installation script for POSIX systems. +# Uses cabal if installed and stack is not, +# or stack, which it will install if needed (or if --force is used). +# Requires bash and some other POSIX tools. +# This is based on get-stack.sh which is copyright (c) 2015-2017, Stack contributors. usage() { - cat <<'HERE' -hledger-install.sh [-f|--force] [-q|--quiet] [-h|--help] + cat </dev/null 2>&1 ; then + SED="sed -r" +else + SED="sed -E" +fi + +# Get the given command's location, or empty string if it's not in $PATH. +cmd_location() { + command -v "$1" +} + +# Get the given command's version, or empty string if there's a problem. +cmd_version() { + (command "$1" --version 2>/dev/null | grep -E '[0-9]' | $SED -e 's/[^0-9]*([0-9][0-9.]*).*/\1/') || "" +} + +# Check whether the given command exists with given version +has_cmd_version() { + [[ $(cmd_version "$1") == "$2" ]] +} + +# Show a command's presence in $PATH, and its version if present. +print_cmd_version() { + if [[ $(cmd_location "$1") ]]; then + echo "$1" $(cmd_version "$1") is installed at $(cmd_location "$1") + else + echo "$1 not found" + fi +} + +# Show the installation status of the $HLEDGER_MAIN_TOOLS and $HLEDGER_OTHER_TOOLS. +print_hledger_versions() { + for cmd in $HLEDGER_MAIN_TOOLS $HLEDGER_OTHER_TOOLS; do print_cmd_version $cmd; done +} + +# Run a command, but first log it with "Trying" prepended. +try_info() { + echo Trying "$@" + $@ +} + +# start + +# process command-line flags + +HELPFLAG="" +STATUSFLAG="" +VERBOSEFLAG="" +VERSIONFLAG="" + while [ $# -gt 0 ]; do case "$1" in - -q|--quiet) - # This tries its best to reduce output by suppressing the script's own - # messages and passing "quiet" arguments to tools that support them. - QUIET="true" - shift - ;; -f|--force) FORCE="true" shift ;; + -v|--verbose) + VERBOSEFLAG="true" + shift + ;; + -s|--status) + STATUSFLAG="true" + shift + ;; + --version) + VERSIONFLAG="true" + shift + ;; -h|--help) - HELP="true" + HELPFLAG="true" shift ;; *) @@ -763,35 +789,125 @@ while [ $# -gt 0 ]; do esac done -if [[ $HELP ]] ; then +if [[ $HELPFLAG ]] ; then usage exit 0 fi -if ! has_stack ; then - echo "installing stack" - do_os +if [[ $VERSIONFLAG ]] ; then + echo $(basename $0) $VERSION + exit 0 fi -echo "stack $(stack_version) is installed at $(stack_location)" -if [[ -n "$QUIET" ]] ; then - STACKVERB=error #silent, error, warn, info, debug +if [[ $VERBOSEFLAG ]]; then + CABAL_VERBOSITY=1 # 0-3 + STACK_VERBOSITY=info # silent, error, warn, info, debug else - STACKVERB=info + CABAL_VERBOSITY=0 + STACK_VERBOSITY=error + QUIET="true" fi -PACKAGESCLI="hledger-lib-$HLEDGERVER hledger-$HLEDGERVER" -PACKAGESUI="$PACKAGESCLI hledger-ui-$HLEDGERVER" -PACKAGES="$PACKAGESUI hledger-web-$HLEDGERVER hledger-api-$HLEDGERVER" +# show current installed hledger packages +print_hledger_versions -if ! has_hledger ; then - install_hledger +if [[ $STATUSFLAG ]] ; then + exit 0 fi -echo "hledger $(hledger_version) is installed at $(hledger_location)" -echo "hledger-ui $(hledger_ui_version) is installed at $(hledger_ui_location)" -echo "hledger-web $(hledger_web_version) is installed at $(hledger_web_location)" -echo "hledger-api $(hledger_api_version) is installed at $(hledger_api_location)" +# select main hledger packages to install +#TOOLS_TO_INSTALL="" +## packages of main tools which are missing or older than latest version +#for t in $HLEDGER_MAIN_TOOLS; do +# if [[ $(cmd_version $t) < $HLEDGER_VERSION ]]; then +# TOOLS_TO_INSTALL="$TOOLS_TO_INSTALL $t-$HLEDGER_VERSION" +# fi +#done +## any depended-on hledger packages so that stack can pull those too from hackage when needed +#PACKAGES_TO_INSTALL=$TOOLS_TO_INSTALL +#if [[ $PACKAGES_TO_INSTALL ]]; then +# # most packages depend on hledger, add it if not already added +# if [[ ! $PACKAGES_TO_INSTALL =~ hledger-$HLEDGER_VERSION ]]; then +# PACKAGES_TO_INSTALL="hledger-$HLEDGER_VERSION $PACKAGES_TO_INSTALL" +# fi +# # and most depend on hledger-lib +# PACKAGES_TO_INSTALL="hledger-lib-$HLEDGER_VERSION $PACKAGES_TO_INSTALL" +#fi +# try installing each package that needs installing, in turn +# Try to install the executables of the given package(s) to $HOME/.local/bin, +# trying several methods, generally from quickest to most reliable, continuing on failure. +# Current the installation methods are: +# - if stack is not installed and cabal is, try cabal install +# - otherwise install stack if needed and try stack install with specific resolver and ghc +# For the stack method, it's necessary to provide not only the package(s) you want to +# install but also all dependencies which are not in the specified stackage $RESOLVER. +try_install() { + (cd # avoid any project-specific stack/cabal config, install at user level + (! has_cmd stack && has_cmd cabal && try_info cabal install "$@" --verbose=$CABAL_VERBOSITY ) || + (ensure_stack && ( + #(try_info stack install --install-ghc "$@" --verbosity=$STACK_VERBOSITY ) || # existing resolver + (try_info stack install --install-ghc $RESOLVER "$@" --verbosity=$STACK_VERBOSITY ) # specific resolver + ) + ) || + echo Failed to install "$@" + ) +} + +echo ---------- +if [[ $(cmd_version hledger) < $HLEDGER_VERSION ]]; then + echo Installing hledger + try_install hledger-$HLEDGER_VERSION hledger-lib-$HLEDGER_VERSION + echo +fi +if [[ $(cmd_version hledger-ui) < $HLEDGER_VERSION ]]; then + echo Installing hledger-ui + try_install hledger-ui-$HLEDGER_VERSION hledger-$HLEDGER_VERSION hledger-lib-$HLEDGER_VERSION brick-0.19 data-clist-0.1.2.0 + echo +fi +if [[ $(cmd_version hledger-web) < $HLEDGER_VERSION ]]; then + echo Installing hledger-web + try_install hledger-web-$HLEDGER_VERSION hledger-$HLEDGER_VERSION hledger-lib-$HLEDGER_VERSION + echo +fi +if [[ $(cmd_version hledger-api) < $HLEDGER_VERSION ]]; then + echo Installing hledger-api + try_install hledger-api-$HLEDGER_VERSION hledger-$HLEDGER_VERSION hledger-lib-$HLEDGER_VERSION + echo +fi +if [[ $(cmd_version hledger-diff) < $HLEDGER_DIFF_VERSION ]]; then + echo Installing hledger-diff + try_install hledger-diff-$HLEDGER_DIFF_VERSION hledger-lib-$HLEDGER_VERSION + echo +fi +if [[ $(cmd_version hledger-iadd) < $HLEDGER_IADD_VERSION ]]; then + echo Installing hledger-iadd + try_install hledger-iadd-$HLEDGER_IADD_VERSION hledger-lib-$HLEDGER_VERSION brick-0.19 data-clist-0.1.2.0 + echo +fi +if [[ $(cmd_version hledger-interest) < $HLEDGER_INTEREST_VERSION ]]; then + echo Installing hledger-interest + try_install hledger-interest-$HLEDGER_INTEREST_VERSION hledger-lib-$HLEDGER_VERSION + echo +fi +if [[ $(cmd_version hledger-irr) < $HLEDGER_IRR_VERSION ]]; then + echo Installing hledger-irr + try_install hledger-irr-$HLEDGER_IRR_VERSION hledger-lib-$HLEDGER_VERSION + echo +fi +echo ---------- + +# show new installation status +print_hledger_versions + +# warn if $HOME/.local/bin isn't in $PATH check_home_local_bin_on_path + +# TODO +# make sure all required deps are being mentioned in stack command lines +# should force ghc-8.0.2+/lts-8+ on osx sierra+ +# automate testing +# install hledger experimental tools +# detect latest hledger version & resolver ? +# detect latest installer version, self upgrade ?