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]
This commit is contained in:
		
							parent
							
								
									ebd4be7b97
								
							
						
					
					
						commit
						bf2e529228
					
				| @ -1,38 +1,57 @@ | |||||||
| #!/bin/bash -e | #!/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() { | usage() { | ||||||
|   cat <<'HERE' |   cat <<HERE | ||||||
| hledger-install.sh [-f|--force] [-q|--quiet] [-h|--help] | hledger-install.sh [-f|--force] [-v|--verbose] [-s|--status] [--version] [-h|--help] | ||||||
| 
 | 
 | ||||||
| Install hledger as reliably and quickly as possible, | Install the current release of hledger and related tools, as reliably and  | ||||||
| on any POSIX system, such as GNU/Linux, OSX, or FreeBSD. | quickly as possible, on any POSIX system, using cabal or stack. | ||||||
| Also installs haskell stack if needed (or with --force, always). | With --status, just lists the currently installed hledger tools. | ||||||
| With --quiet, try to show less output. |  | ||||||
| Usage: | Usage: | ||||||
| 
 | 
 | ||||||
|  curl -sSLO http://hledger.org/hledger-install.sh |  curl -sSLO http://hledger.org/hledger-install.sh | ||||||
|  less hledger-install.sh     # review for security issues |  less hledger-install.sh       # security review | ||||||
|  bash [-x] hledger-install.sh  # to see commands being run, add -x  |  bash [-x] hledger-install.sh  # to see commands being run, add -x  | ||||||
| 
 | 
 | ||||||
| or, if you prefer convenience to security: | or if you prefer convenience to security: | ||||||
| 
 | 
 | ||||||
|  curl -sSL http://hledger.org/hledger-install.sh | bash |  curl -sSL http://hledger.org/hledger-install.sh | bash | ||||||
| 
 | 
 | ||||||
| or | or: | ||||||
| 
 | 
 | ||||||
|  wget -qO- http://hledger.org/hledger-install.sh | bash |  wget -qO- http://hledger.org/hledger-install.sh | bash | ||||||
| 
 | 
 | ||||||
| This is based heavily on the 2017/07/17 version of  | Version $VERSION, installs hledger $HLEDGER_VERSION | ||||||
| https://github.com/commercialhaskell/stack/blob/master/etc/scripts/get-stack.sh  |  | ||||||
| which is copyright (c) 2015-2017, Stack contributors. |  | ||||||
| HERE | HERE | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| HLEDGERVER=1.3 | VERSION=20170720 | ||||||
| RESOLVER=lts-8 | RESOLVER="--resolver lts-8" | ||||||
| HELP="" | HLEDGER_VERSION=1.3 | ||||||
| 
 | HLEDGER_DIFF_VERSION=0.2.0.9 | ||||||
|  | HLEDGER_IADD_VERSION=1.2.2 | ||||||
|  | HLEDGER_INTEREST_VERSION=1.5.1 | ||||||
|  | HLEDGER_IRR_VERSION=0.1.1.11 | ||||||
|  | HLEDGER_MAIN_TOOLS="\ | ||||||
|  | hledger \ | ||||||
|  | hledger-ui \ | ||||||
|  | hledger-web \ | ||||||
|  | hledger-api \ | ||||||
|  | " | ||||||
|  | HLEDGER_OTHER_TOOLS="\ | ||||||
|  | hledger-diff \ | ||||||
|  | hledger-iadd \ | ||||||
|  | hledger-interest \ | ||||||
|  | hledger-irr \ | ||||||
|  | " | ||||||
| 
 | 
 | ||||||
|  | # start of (most of) get-stack.sh, https://github.com/commercialhaskell/stack/blob/master/etc/scripts/get-stack.sh | ||||||
|  | # modified at CHANGED markers | ||||||
| 
 | 
 | ||||||
| HOME_LOCAL_BIN="$HOME/.local/bin" | HOME_LOCAL_BIN="$HOME/.local/bin" | ||||||
| USR_LOCAL_BIN="/usr/local/bin" | USR_LOCAL_BIN="/usr/local/bin" | ||||||
| @ -477,12 +496,17 @@ install_from_bindist() { | |||||||
|     if ! tar xzf "$STACK_TEMP_DIR/$1.bindist" -C "$STACK_TEMP_DIR/$1"; then |     if ! tar xzf "$STACK_TEMP_DIR/$1.bindist" -C "$STACK_TEMP_DIR/$1"; then | ||||||
|       die "Extract bindist failed" |       die "Extract bindist failed" | ||||||
|     fi |     fi | ||||||
|     if ! sudocmd install -c -o 0 -g 0 -m 0755 "$STACK_TEMP_DIR/$1"/*/stack "$USR_LOCAL_BIN/stack"; then | #CHANGED | ||||||
|       die "Install to $USR_LOCAL_BIN/stack failed" | #    if ! sudocmd install -c -o 0 -g 0 -m 0755 "$STACK_TEMP_DIR/$1"/*/stack "$USR_LOCAL_BIN/stack"; then | ||||||
|  | #      die "Install to $USR_LOCAL_BIN/stack failed" | ||||||
|  |     if ! install -m 0755 "$STACK_TEMP_DIR/$1"/*/stack "$HOME_LOCAL_BIN/stack"; then | ||||||
|  |       die "Install to $HOME_LOCAL_BIN/stack failed" | ||||||
|     fi |     fi | ||||||
| 
 | 
 | ||||||
|     post_install_separator |     post_install_separator | ||||||
|     info "Stack has been installed to: $USR_LOCAL_BIN/stack" | #CHANGED | ||||||
|  | #    info "Stack has been installed to: $USR_LOCAL_BIN/stack" | ||||||
|  |     echo "Stack has been installed to: $HOME_LOCAL_BIN/stack" | ||||||
|     info "" |     info "" | ||||||
| 
 | 
 | ||||||
|     check_usr_local_bin_on_path |     check_usr_local_bin_on_path | ||||||
| @ -671,89 +695,91 @@ or pass --force to this script to install anyway." | |||||||
|   fi |   fi | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| has_hledger() { |  | ||||||
|   has_cmd hledger |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| hledger_location() { |  | ||||||
|   command -v hledger |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| hledger_version() { |  | ||||||
|   hledger --version | awk '{print $2}' |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| has_hledger_ui() { |  | ||||||
|   has_cmd hledger-ui |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| hledger_ui_location() { |  | ||||||
|   command -v hledger-ui |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| hledger_ui_version() { |  | ||||||
|   hledger-ui --version | awk '{print $2}' |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| has_hledger_web() { |  | ||||||
|   has_cmd hledger-web |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| hledger_web_location() { |  | ||||||
|   command -v hledger-web |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| hledger_web_version() { |  | ||||||
|   hledger-web --version | awk '{print $2}' |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| has_hledger_api() { |  | ||||||
|   has_cmd hledger-api |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| hledger_api_location() { |  | ||||||
|   command -v hledger-api |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| hledger_api_version() { |  | ||||||
|   hledger-api --version | awk '{print $2}' |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| # install latest hledger release with stack |  | ||||||
| install_hledger() { |  | ||||||
|   ( |  | ||||||
|   info "installing hledger $HLEDGERVER" |  | ||||||
|   # try to ensure we use the global stack project |  | ||||||
|   cd |  | ||||||
|   # try installing hledger in various ways, from quickest to most reliable |  | ||||||
|   # TODO should try only lts-8+ on osx sierra  # if [[ $(uname) == "Darwin" ]]; then |  | ||||||
|   stack install --verbosity $STACKVERB $PACKAGES || |  | ||||||
|   stack install --verbosity $STACKVERB $PACKAGES --install-ghc || |  | ||||||
|   stack install --verbosity $STACKVERB $PACKAGES --resolver $RESOLVER ||   |  | ||||||
|   stack install --verbosity $STACKVERB $PACKAGES --resolver $RESOLVER --install-ghc   |  | ||||||
|   ) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| trap cleanup_temp_dir EXIT | trap cleanup_temp_dir EXIT | ||||||
| 
 | 
 | ||||||
|  | # end of (most of) get-stack.sh | ||||||
|  | 
 | ||||||
|  | # hledger routines | ||||||
|  | 
 | ||||||
|  | # install stack if needed or always with --force, in $HOME/.local/bin | ||||||
|  | ensure_stack() { | ||||||
|  |   if ! $(has_stack) || [[ "$FORCE" == "true" ]] ; then | ||||||
|  |     echo "Installing stack" | ||||||
|  |     do_os | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # get a sed command that supports EREs | ||||||
|  | if sed -r </dev/null >/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 | while [ $# -gt 0 ]; do | ||||||
|   case "$1" in |   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) |     -f|--force) | ||||||
|       FORCE="true" |       FORCE="true" | ||||||
|       shift |       shift | ||||||
|       ;; |       ;; | ||||||
|  |     -v|--verbose) | ||||||
|  |       VERBOSEFLAG="true" | ||||||
|  |       shift | ||||||
|  |       ;; | ||||||
|  |     -s|--status) | ||||||
|  |       STATUSFLAG="true" | ||||||
|  |       shift | ||||||
|  |       ;; | ||||||
|  |     --version) | ||||||
|  |       VERSIONFLAG="true" | ||||||
|  |       shift | ||||||
|  |       ;; | ||||||
|     -h|--help) |     -h|--help) | ||||||
|       HELP="true" |       HELPFLAG="true" | ||||||
|       shift |       shift | ||||||
|       ;; |       ;; | ||||||
|     *) |     *) | ||||||
| @ -763,35 +789,125 @@ while [ $# -gt 0 ]; do | |||||||
|   esac |   esac | ||||||
| done | done | ||||||
| 
 | 
 | ||||||
| if [[ $HELP ]] ; then | if [[ $HELPFLAG ]] ; then | ||||||
|   usage |   usage | ||||||
|   exit 0 |   exit 0 | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| if ! has_stack ; then | if [[ $VERSIONFLAG ]] ; then | ||||||
|   echo "installing stack" |   echo $(basename $0) $VERSION | ||||||
|   do_os     |   exit 0 | ||||||
| fi | fi | ||||||
| echo "stack $(stack_version) is installed at $(stack_location)" |  | ||||||
| 
 | 
 | ||||||
| if [[ -n "$QUIET" ]] ; then | if [[ $VERBOSEFLAG ]]; then | ||||||
|   STACKVERB=error #silent, error, warn, info, debug |   CABAL_VERBOSITY=1       # 0-3 | ||||||
|  |   STACK_VERBOSITY=info    # silent, error, warn, info, debug | ||||||
| else | else | ||||||
|   STACKVERB=info |   CABAL_VERBOSITY=0 | ||||||
|  |   STACK_VERBOSITY=error | ||||||
|  |   QUIET="true" | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| PACKAGESCLI="hledger-lib-$HLEDGERVER hledger-$HLEDGERVER" | # show current installed hledger packages | ||||||
| PACKAGESUI="$PACKAGESCLI hledger-ui-$HLEDGERVER" | print_hledger_versions | ||||||
| PACKAGES="$PACKAGESUI hledger-web-$HLEDGERVER hledger-api-$HLEDGERVER" |  | ||||||
| 
 | 
 | ||||||
| if ! has_hledger ; then | if [[ $STATUSFLAG ]] ; then | ||||||
|   install_hledger |   exit 0 | ||||||
| fi | 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 | 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 ? | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user