From 40e4c9325e021fb3fed07ab73d69046facf7c0dc Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sun, 2 May 2021 16:58:41 +0000 Subject: [PATCH] welcome earlier, fix lint warnings and real errors --- _webi/bootstrap.sh | 228 +++++++++++++++++++++++++-------------------- _webi/releases.js | 27 ++++-- _webi/template.sh | 92 +++++++++++------- webi/install.sh | 14 ++- 4 files changed, 216 insertions(+), 145 deletions(-) diff --git a/_webi/bootstrap.sh b/_webi/bootstrap.sh index dfbf9de..33227c8 100644 --- a/_webi/bootstrap.sh +++ b/_webi/bootstrap.sh @@ -1,14 +1,24 @@ #!/bin/bash -{ +#set -x - set -e - set -u +function __install_webi() { #WEBI_PKG= #WEBI_HOST=https://webinstall.dev export WEBI_HOST + echo "" + echo "Thanks for using webi to install '${PKG_NAME:-}' on '$(uname -s)/$(uname -m)'." + echo "Have a problem? Experience a bug? Please let us know:" + echo " https://github.com/webinstall/packages/issues" + echo "" + WEBI_WELCOME=true + export WEBI_WELCOME + + set -e + set -u + mkdir -p "$HOME/.local/bin" cat << EOF > "$HOME/.local/bin/webi" @@ -16,133 +26,147 @@ set -e set -u +#set -x -{ - -export WEBI_TIMESTAMP=\$(date +%F_%H-%M-%S) -export _webi_tmp="\${_webi_tmp:-\$(mktemp -d -t webi-\$WEBI_TIMESTAMP.XXXXXXXX)}" - -if [ -n "\${_WEBI_PARENT:-}" ]; then - export _WEBI_CHILD=true -else - export _WEBI_CHILD= -fi -export _WEBI_PARENT=true - -## -## Detect acceptable package formats -## - -my_ext="" -set +e -# NOTE: the order here is least favorable to most favorable -if [ -n "\$(command -v pkgutil)" ]; then - my_ext="pkg,\$my_ext" -fi -# disable this check for the sake of building the macOS installer on Linux -#if [ -n "\$(command -v diskutil)" ]; then - # note: could also detect via hdiutil - my_ext="dmg,\$my_ext" -#fi -if [ -n "\$(command -v git)" ]; then - my_ext="git,\$my_ext" -fi -if [ -n "\$(command -v unxz)" ]; then - my_ext="xz,\$my_ext" -fi -if [ -n "\$(command -v unzip)" ]; then - my_ext="zip,\$my_ext" -fi -# for mac/linux 'exe' refers to the uncompressed binary without extension -my_ext="exe,\$my_ext" -if [ -n "\$(command -v tar)" ]; then - my_ext="tar,\$my_ext" -fi -my_ext="\$(echo "\$my_ext" | sed 's/,$//')" # nix trailing comma -set -e - +function __webi_main () { -## -## Detect http client -## + export WEBI_TIMESTAMP=\$(date +%F_%H-%M-%S) + export _webi_tmp="\${_webi_tmp:-\$(mktemp -d -t webi-\$WEBI_TIMESTAMP.XXXXXXXX)}" -set +e -export WEBI_CURL="\$(command -v curl)" -export WEBI_WGET="\$(command -v wget)" -set -e - -export WEBI_HOST="\${WEBI_HOST:-https://webinstall.dev}" -export WEBI_UA="\$(uname -a)" - - -webinstall() { - - my_package="\${1:-}" - if [ -z "\$my_package" ]; then - >&2 echo "Usage: webi @ ..." - >&2 echo "Example: webi node@lts rg" - exit 1 + if [ -n "\${_WEBI_PARENT:-}" ]; then + export _WEBI_CHILD=true + else + export _WEBI_CHILD= fi + export _WEBI_PARENT=true - export WEBI_BOOT="\$(mktemp -d -t "\$my_package-bootstrap.\$WEBI_TIMESTAMP.XXXXXXXX")" + ## + ## Detect acceptable package formats + ## - my_installer_url="\$WEBI_HOST/api/installers/\$my_package.sh?formats=\$my_ext" + my_ext="" set +e - if [ -n "\$WEBI_CURL" ]; then - curl -fsSL "\$my_installer_url" -H "User-Agent: curl \$WEBI_UA" \\ - -o "\$WEBI_BOOT/\$my_package-bootstrap.sh" - else - wget -q "\$my_installer_url" --user-agent="wget \$WEBI_UA" \\ - -O "\$WEBI_BOOT/\$my_package-bootstrap.sh" + # NOTE: the order here is least favorable to most favorable + if [ -n "\$(command -v pkgutil)" ]; then + my_ext="pkg,\$my_ext" + fi + # disable this check for the sake of building the macOS installer on Linux + #if [ -n "\$(command -v diskutil)" ]; then + # note: could also detect via hdiutil + my_ext="dmg,\$my_ext" + #fi + if [ -n "\$(command -v git)" ]; then + my_ext="git,\$my_ext" + fi + if [ -n "\$(command -v unxz)" ]; then + my_ext="xz,\$my_ext" fi - if ! [ \$? -eq 0 ]; then - >&2 echo "error fetching '\$my_installer_url'" - exit 1 + if [ -n "\$(command -v unzip)" ]; then + my_ext="zip,\$my_ext" fi + # for mac/linux 'exe' refers to the uncompressed binary without extension + my_ext="exe,\$my_ext" + if [ -n "\$(command -v tar)" ]; then + my_ext="tar,\$my_ext" + fi + my_ext="\$(echo "\$my_ext" | sed 's/,$//')" # nix trailing comma set -e - pushd "\$WEBI_BOOT" 2>&1 > /dev/null - bash "\$my_package-bootstrap.sh" - popd 2>&1 > /dev/null - rm -rf "\$WEBI_BOOT" + ## + ## Detect http client + ## -} + set +e + export WEBI_CURL="\$(command -v curl)" + export WEBI_WGET="\$(command -v wget)" + set -e + + export WEBI_HOST="\${WEBI_HOST:-https://webinstall.dev}" + export WEBI_UA="\$(uname -a)" + + + function webinstall() { + + my_package="\${1:-}" + if [ -z "\$my_package" ]; then + >&2 echo "Usage: webi @ ..." + >&2 echo "Example: webi node@lts rg" + exit 1 + fi -show_path_updates() { - - if ! [ -n "\${_WEBI_CHILD}" ]; then - if [ -f "\$_webi_tmp/.PATH.env" ]; then - my_paths=\$(cat "\$_webi_tmp/.PATH.env" | sort -u) - if [ -n "\$my_paths" ]; then - echo "IMPORTANT: You must update you PATH to use the installed program(s)" - echo "" - echo "You can CLOSE and REOPEN Terminal, or RUN these exports:" - echo "" - echo "\$my_paths" - echo "" + export WEBI_BOOT="\$(mktemp -d -t "\$my_package-bootstrap.\$WEBI_TIMESTAMP.XXXXXXXX")" + + my_installer_url="\$WEBI_HOST/api/installers/\$my_package.sh?formats=\$my_ext" + set +e + if [ -n "\$WEBI_CURL" ]; then + curl -fsSL "\$my_installer_url" -H "User-Agent: curl \$WEBI_UA" \\ + -o "\$WEBI_BOOT/\$my_package-bootstrap.sh" + else + wget -q "\$my_installer_url" --user-agent="wget \$WEBI_UA" \\ + -O "\$WEBI_BOOT/\$my_package-bootstrap.sh" + fi + if ! [ \$? -eq 0 ]; then + >&2 echo "error fetching '\$my_installer_url'" + exit 1 + fi + set -e + + pushd "\$WEBI_BOOT" 2>&1 > /dev/null + bash "\$my_package-bootstrap.sh" + popd 2>&1 > /dev/null + + rm -rf "\$WEBI_BOOT" + + } + + show_path_updates() { + + if ! [ -n "\${_WEBI_CHILD}" ]; then + if [ -f "\$_webi_tmp/.PATH.env" ]; then + my_paths=\$(cat "\$_webi_tmp/.PATH.env" | sort -u) + if [ -n "\$my_paths" ]; then + echo "IMPORTANT: You must update you PATH to use the installed program(s)" + echo "" + echo "You can either" + echo "A) can CLOSE and REOPEN Terminal or" + echo "B) RUN these exports:" + echo "" + echo "\$my_paths" + echo "" + fi + rm -f "\$_webi_tmp/.PATH.env" fi - rm -f "\$_webi_tmp/.PATH.env" fi - fi -} + } -for pkgname in "\$@" -do - webinstall "\$pkgname" -done + for pkgname in "\$@" + do + webinstall "\$pkgname" + done -show_path_updates + show_path_updates } +__webi_main "\$@" + EOF chmod a+x "$HOME/.local/bin/webi" if [ -n "${WEBI_PKG:-}" ]; then "$HOME/.local/bin/webi" "${WEBI_PKG}" + else + echo "" + echo "Hmm... no WEBI_PKG was specified. This is probably an error in the script." + echo "" + echo "Please open an issue with this information: Package '${PKG_NAME:-}' on '$(uname -s)/$(uname -m)'" + echo " https://github.com/webinstall/packages/issues" + echo "" fi } + +__install_webi diff --git a/_webi/releases.js b/_webi/releases.js index 31f3b59..6740faf 100644 --- a/_webi/releases.js +++ b/_webi/releases.js @@ -5,6 +5,8 @@ var path = require('path'); var request = require('@root/request'); var _normalize = require('../_webi/normalize.js'); +var reInstallTpl = /\s*#?\s*{{ installer }}/; + var Releases = module.exports; Releases.get = async function (pkgdir) { var get; @@ -18,6 +20,10 @@ Releases.get = async function (pkgdir) { }); }; +function padScript(txt) { + return txt.replace(/^/g, ' '); +} + Releases.renderBash = function ( pkgdir, rel, @@ -32,6 +38,7 @@ Releases.renderBash = function ( return fs.promises .readFile(path.join(pkgdir, 'install.sh'), 'utf8') .then(function (installTxt) { + installTxt = padScript(installTxt); var vers = rel.version.split('.'); var v = { major: vers.shift() || '', @@ -136,7 +143,7 @@ Releases.renderBash = function ( /^\s*#?PKG_FORMATS=.*/m, "PKG_FORMATS='" + ((rel && rel.formats) || []).join(',') + "'" ) - .replace(/{{ installer }}/, installTxt) + .replace(reInstallTpl, '\n' + installTxt) ); }); }); @@ -156,16 +163,19 @@ Releases.renderBatch = function ( return fs.promises .readFile(path.join(pkgdir, 'install.bat'), 'utf8') .then(function (installTxt) { + installTxt = padScript(installTxt); + /* var vers = rel.version.split('.'); var v = { major: vers.shift() || '', minor: vers.shift() || '', - patch: vers.join('.').replace(/[+\-].*/, ''), + patch: vers.join('.').replace(/[+\-].*$/, ''), build: vers .join('.') - .replace(/[^+\-]*/, '') + .replace(/[^+\-]*()/, '') .replace(/^-/, '') }; + */ return fs.promises .readFile(path.join(__dirname, 'template.bat'), 'utf8') .then(function (tplTxt) { @@ -174,7 +184,7 @@ Releases.renderBatch = function ( /^(REM )?WEBI_PKG=.*/im, "WEBI_PKG='" + pkg + '@' + ver + "'" ) - .replace(/{{ installer }}/, installTxt); + .replace(reInstallTpl, '\n' + installTxt); }); }); }; @@ -193,16 +203,19 @@ Releases.renderPowerShell = function ( return fs.promises .readFile(path.join(pkgdir, 'install.ps1'), 'utf8') .then(function (installTxt) { + installTxt = padScript(installTxt); + /* var vers = rel.version.split('.'); var v = { major: vers.shift() || '', minor: vers.shift() || '', - patch: vers.join('.').replace(/[+\-].*/, ''), + patch: vers.join('.').replace(/[+\-].*$/, ''), build: vers .join('.') - .replace(/[^+\-]*/, '') + .replace(/[^+\-]*()/, '') .replace(/^-/, '') }; + */ return fs.promises .readFile(path.join(__dirname, 'template.ps1'), 'utf8') .then(function (tplTxt) { @@ -232,7 +245,7 @@ Releases.renderPowerShell = function ( /^(#)?\$Env:WEBI_PKG_FILE\s*=.*/im, "$Env:WEBI_PKG_FILE = '" + rel.name + "'" ) - .replace(/{{ installer }}/, installTxt); + .replace(reInstallTpl, '\n' + installTxt); }); }); }; diff --git a/_webi/template.sh b/_webi/template.sh index 1823945..2fff936 100644 --- a/_webi/template.sh +++ b/_webi/template.sh @@ -1,5 +1,9 @@ #!/bin/bash +# shellcheck disable=2001 +# because I prefer to use sed rather than bash replace +# (there's too little space in my head to learn both syntaxes) + function __bootstrap_webi() { set -e @@ -37,7 +41,7 @@ function __bootstrap_webi() { ## Set up tmp, download, and install directories ## - WEBI_TMP=${WEBI_TMP:-"$(mktemp -d -t webinstall-${WEBI_PKG:-}.XXXXXXXX)"} + WEBI_TMP=${WEBI_TMP:-"$(mktemp -d -t webinstall-"${WEBI_PKG:-}".XXXXXXXX)"} export _webi_tmp="${_webi_tmp:-"$HOME/.local/opt/webi-tmp.d"}" mkdir -p "$HOME/Downloads" @@ -48,8 +52,10 @@ function __bootstrap_webi() { ## Detect http client ## set +e - export WEBI_CURL="$(command -v curl)" - export WEBI_WGET="$(command -v wget)" + WEBI_CURL="$(command -v curl)" + export WEBI_CURL + WEBI_WGET="$(command -v wget)" + export WEBI_WGET set -e # get the special formatted version (i.e. "go is go1.14" while node is "node v12.10.8") @@ -70,6 +76,8 @@ function __bootstrap_webi() { } # update symlinks according to $HOME/.local/opt and $HOME/.local/bin install paths. + # shellcheck disable=2120 + # webi_link may be used in the templated install script webi_link() { if [ -n "$(command -v pkg_link)" ]; then pkg_link @@ -92,14 +100,15 @@ function __bootstrap_webi() { # Test for existing version set +e my_path="$PATH" - export PATH="$(dirname "$pkg_dst_cmd"):$PATH" + PATH="$(dirname "$pkg_dst_cmd"):$PATH" + export PATH my_current_cmd="$(command -v "$pkg_cmd_name")" set -e if [ -n "$my_current_cmd" ]; then pkg_current_version="$(pkg_get_current_version 2> /dev/null | head -n 1)" # remove trailing '.0's for golang's sake - my_current_version="$(echo $pkg_current_version | sed 's:\.0::g')" - my_src_version="$(echo $WEBI_VERSION | sed 's:\.0::g')" + my_current_version="$(echo "$pkg_current_version" | sed 's:\.0::g')" + my_src_version="$(echo "$WEBI_VERSION" | sed 's:\.0::g')" my_canonical_name="$(_webi_canonical_name)" if [ "$my_src_version" == "$my_current_version" ]; then echo "$my_canonical_name already installed at $my_current_cmd" @@ -109,6 +118,8 @@ function __bootstrap_webi() { echo >&2 "WARN: possible conflict between $my_canonical_name and $pkg_current_version at $my_current_cmd" fi if [ -x "$pkg_src_cmd" ]; then + # shellcheck disable=2119 + # this function takes no args webi_link echo "switched to $my_canonical_name at $pkg_src" exit 0 @@ -125,7 +136,7 @@ function __bootstrap_webi() { else if [ "error" == "$WEBI_CHANNEL" ]; then # TODO pass back requested OS / Arch / Version - echo >&2 "Error: no '$PKG_NAME' release for '$WEBI_OS' on '$WEBI_ARCH' as one of '$WEBI_FORMATS' by the tag '$WEBI_TAG'" + echo >&2 "Error: no '$PKG_NAME' release for '${WEBI_OS:-}' on '$WEBI_ARCH' as one of '$WEBI_FORMATS' by the tag '${WEBI_TAG:-}'" echo >&2 " '$PKG_NAME' is available for '$PKG_OSES' on '$PKG_ARCHES' as one of '$PKG_FORMATS'" echo >&2 " (check that the package name and version are correct)" echo >&2 "" @@ -159,8 +170,7 @@ function __bootstrap_webi() { if [[ $- == *i* ]]; then my_show_progress="--show-progress" fi - wget -q $my_show_progress --user-agent="wget $WEBI_UA" -c "$my_url" -O "$my_dl.part" - if ! [ $? -eq 0 ]; then + if wget -q $my_show_progress --user-agent="wget $WEBI_UA" -c "$my_url" -O "$my_dl.part"; then echo >&2 "failed to download from $WEBI_PKG_URL" exit 1 fi @@ -172,6 +182,8 @@ function __bootstrap_webi() { if [[ $- == *i* ]]; then my_show_progress="" fi + # shellcheck disable=SC2086 + # we want the flags to be split curl -fSL $my_show_progress -H "User-Agent: curl $WEBI_UA" "$my_url" -o "$my_dl.part" fi mv "$my_dl.part" "$my_dl" @@ -182,7 +194,7 @@ function __bootstrap_webi() { # detect which archives can be used webi_extract() { - pushd "$WEBI_TMP" 2>&1 > /dev/null + pushd "$WEBI_TMP" > /dev/null 2>&1 if [ "tar" == "$WEBI_EXT" ]; then echo "Extracting $HOME/Downloads/$WEBI_PKG_FILE" tar xf "$HOME/Downloads/$WEBI_PKG_FILE" @@ -194,13 +206,13 @@ function __bootstrap_webi() { mv "$HOME/Downloads/$WEBI_PKG_FILE" . elif [ "xz" == "$WEBI_EXT" ]; then echo "Inflating $HOME/Downloads/$WEBI_PKG_FILE" - unxz -c "$HOME/Downloads/$WEBI_PKG_FILE" > $(basename "$WEBI_PKG_FILE") + unxz -c "$HOME/Downloads/$WEBI_PKG_FILE" > "$(basename "$WEBI_PKG_FILE")" else # do nothing echo "Failed to extract $HOME/Downloads/$WEBI_PKG_FILE" exit 1 fi - popd 2>&1 > /dev/null + popd > /dev/null 2>&1 } # use 'pathman' to update $HOME/.config/envman/PATH.env @@ -230,9 +242,11 @@ function __bootstrap_webi() { } # move commands from the extracted archive directory to $HOME/.local/opt or $HOME/.local/bin + # shellcheck disable=2120 + # webi_install may be sourced and used elsewhere webi_install() { if [ -n "$WEBI_SINGLE" ] || [ "single" == "${1:-}" ]; then - mkdir -p "$(dirname $pkg_src_cmd)" + mkdir -p "$(dirname "$pkg_src_cmd")" mv ./"$pkg_cmd_name"* "$pkg_src_cmd" else rm -rf "$pkg_src" @@ -285,15 +299,20 @@ function __bootstrap_webi() { WEBI_SINGLE= - echo "" - echo "Thanks for using webi to install '$PKG_NAME' on '$WEBI_OS/$WEBI_ARCH'." - echo "Have a problem? Experience a bug? Please let us know:" - echo " https://github.com/webinstall/packages/issues" - echo "" + if [[ -z ${WEBI_WELCOME:-} ]]; then + echo "" + echo "Thanks for using webi to install '$PKG_NAME' on '$WEBI_OS/$WEBI_ARCH'." + echo "Have a problem? Experience a bug? Please let us know:" + echo " https://github.com/webinstall/packages/issues" + echo "" + fi function __init_installer() { - {{ installer }} + # do nothing - to satisfy parser prior to templating + echo -n "" + + # {{ installer }} } @@ -323,38 +342,43 @@ function __bootstrap_webi() { pkg_src="${pkg_src:-$HOME/.local/opt/$pkg_cmd_name-v$WEBI_VERSION}" pkg_src_cmd="${pkg_src_cmd:-$pkg_src/bin/$pkg_cmd_name}" fi + # this script is templated and these are used elsewhere + # shellcheck disable=SC2034 pkg_src_bin="$(dirname "$pkg_src_cmd")" + # shellcheck disable=SC2034 pkg_dst_bin="$(dirname "$pkg_dst_cmd")" - [ -n "$(command -v pkg_pre_install)" ] && pkg_pre_install || webi_pre_install + if [[ -n "$(command -v pkg_pre_install)" ]]; then pkg_pre_install; else webi_pre_install; fi - pushd "$WEBI_TMP" 2>&1 > /dev/null + pushd "$WEBI_TMP" > /dev/null 2>&1 echo "Installing to $pkg_src_cmd" - [ -n "$(command -v pkg_install)" ] && pkg_install || webi_install + if [[ -n "$(command -v pkg_install)" ]]; then pkg_install; else webi_install; fi chmod a+x "$pkg_src" chmod a+x "$pkg_src_cmd" - popd 2>&1 > /dev/null + popd > /dev/null 2>&1 webi_link _webi_enable_exec - pushd "$WEBI_TMP" 2>&1 > /dev/null - [ -n "$(command -v pkg_post_install)" ] && pkg_post_install || webi_post_install - popd 2>&1 > /dev/null + pushd "$WEBI_TMP" > /dev/null 2>&1 + if [[ -n "$(command -v pkg_post_install)" ]]; then pkg_post_install; else webi_post_install; fi + popd > /dev/null 2>&1 - pushd "$WEBI_TMP" 2>&1 > /dev/null - [ -n "$(command -v pkg_done_message)" ] && pkg_done_message || _webi_done_message - popd 2>&1 > /dev/null + pushd "$WEBI_TMP" > /dev/null 2>&1 + if [[ -n "$(command -v pkg_done_message)" ]]; then pkg_done_message; else _webi_done_message; fi + popd > /dev/null 2>&1 echo "" fi webi_path_add "$HOME/.local/bin" - if [ -z "${_WEBI_CHILD:-}" ] && [ -f '$_webi_tmp/.PATH.env' ]; then - echo "You need to update your PATH to use $PKG_NAME:" - echo "" - cat "$_webi_tmp/.PATH.env" | sort -u - rm -f "$_webi_tmp/.PATH.env" + if [[ -z ${_WEBI_CHILD:-} ]] && [[ -f "$_webi_tmp/.PATH.env" ]]; then + if [[ -n $(cat "$_webi_tmp/.PATH.env") ]]; then + echo "You need to update your PATH to use $PKG_NAME:" + echo "" + sort -u "$_webi_tmp/.PATH.env" + rm -f "$_webi_tmp/.PATH.env" + fi fi # cleanup the temp directory diff --git a/webi/install.sh b/webi/install.sh index 0c26ab4..8df8d86 100644 --- a/webi/install.sh +++ b/webi/install.sh @@ -3,7 +3,7 @@ # Note: 'webi' is a special case. It's actually just a helper utility that comes with every installer. # See https://github.com/webinstall/packages/blob/master/_webi/bootstrap.sh for the source. -{ +function __faux_webi() { if [ -f "$HOME/.local/bin/webi" ]; then set +e @@ -12,10 +12,20 @@ if [ -z "$cur_webi" ]; then webi_path_add "$HOME/.local/bin" fi - echo "Installed 'webi'" else # for when this file is run on its own, not from webinstall.dev echo "Install any other package via https://webinstall.dev and webi will be installed as part of the bootstrap process" fi + echo "" + echo "'webi' installed to ~/.local/bin/webi" + echo "" + echo "Usage:" + echo " webi [@version] ..." + echo "" + echo "Example:" + echo " webi node@lts prettier vim-essentials" + echo "" } + +__faux_webi -- 2.25.1