github.com/benchkram/bob@v0.0.0-20240314204020-b7a57f2f9be9/install.sh (about)

     1  #!/bin/sh
     2  
     3  # Explanation https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425
     4  
     5  set -e
     6  
     7  owner="benchkram"
     8  name="bob"
     9  base="https://github.com/${owner}"
    10  
    11  cat /dev/null <<EOF
    12  ------------------------------------------------------------------------
    13  https://github.com/client9/shlib - portable posix shell functions
    14  Public domain - http://unlicense.org
    15  https://github.com/client9/shlib/blob/master/LICENSE.md
    16  but credit (and pull requests) appreciated.
    17  ------------------------------------------------------------------------
    18  EOF
    19  is_command() {
    20    command -v "$1" >/dev/null
    21  }
    22  echoerr() {
    23    echo "$@" 1>&2
    24  }
    25  log_prefix() {
    26    echo "$0"
    27  }
    28  _logp=7
    29  log_set_priority() {
    30    _logp="$1"
    31  }
    32  log_priority() {
    33    if test -z "$1"; then
    34      echo "$_logp"
    35      return
    36    fi
    37    [ "$1" -le "$_logp" ]
    38  }
    39  log_tag() {
    40    case $1 in
    41    0) echo "emerg" ;;
    42    1) echo "alert" ;;
    43    2) echo "crit" ;;
    44    3) echo "err" ;;
    45    4) echo "warning" ;;
    46    5) echo "notice" ;;
    47    6) echo "info" ;;
    48    7) echo "debug" ;;
    49    *) echo "$1" ;;
    50    esac
    51  }
    52  log_debug() {
    53    log_priority 7 || return 0
    54    echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
    55  }
    56  log_info() {
    57    log_priority 6 || return 0
    58    echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
    59  }
    60  log_err() {
    61    log_priority 3 || return 0
    62    echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
    63  }
    64  log_crit() {
    65    log_priority 2 || return 0
    66    echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
    67  }
    68  uname_os() {
    69    os=$(uname -s | tr '[:upper:]' '[:lower:]')
    70    case "$os" in
    71    cygwin_nt*) os="windows" ;;
    72    mingw*) os="windows" ;;
    73    msys_nt*) os="windows" ;;
    74    esac
    75    echo "$os"
    76  }
    77  uname_arch() {
    78    arch=$(uname -m)
    79    case $arch in
    80    x86_64) arch="amd64" ;;
    81    x86) arch="386" ;;
    82    i686) arch="386" ;;
    83    i386) arch="386" ;;
    84    aarch64) arch="arm64" ;;
    85    armv5*) arch="armv5" ;;
    86    armv6*) arch="armv6" ;;
    87    armv7*) arch="armv7" ;;
    88    esac
    89    echo ${arch}
    90  }
    91  uname_os_check() {
    92    os=$(uname_os)
    93    case "$os" in
    94    darwin) return 0 ;;
    95    dragonfly) return 0 ;;
    96    freebsd) return 0 ;;
    97    linux) return 0 ;;
    98    android) return 0 ;;
    99    nacl) return 0 ;;
   100    netbsd) return 0 ;;
   101    openbsd) return 0 ;;
   102    plan9) return 0 ;;
   103    solaris) return 0 ;;
   104    windows) return 0 ;;
   105    esac
   106    log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
   107    return 1
   108  }
   109  uname_arch_check() {
   110    arch=$(uname_arch)
   111    case "$arch" in
   112    386) return 0 ;;
   113    amd64) return 0 ;;
   114    arm64) return 0 ;;
   115    armv5) return 0 ;;
   116    armv6) return 0 ;;
   117    armv7) return 0 ;;
   118    ppc64) return 0 ;;
   119    ppc64le) return 0 ;;
   120    mips) return 0 ;;
   121    mipsle) return 0 ;;
   122    mips64) return 0 ;;
   123    mips64le) return 0 ;;
   124    s390x) return 0 ;;
   125    amd64p32) return 0 ;;
   126    esac
   127    log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value.  Please file bug report at https://github.com/client9/shlib"
   128    return 1
   129  }
   130  untar() {
   131    tarball=$1
   132    case "${tarball}" in
   133    *.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;;
   134    *.tar) tar --no-same-owner -xf "${tarball}" ;;
   135    *.zip) unzip "${tarball}" ;;
   136    *)
   137      log_err "untar unknown archive format for ${tarball}"
   138      return 1
   139      ;;
   140    esac
   141  }
   142  http_download_curl() {
   143    local_file=$1
   144    source_url=$2
   145    header=$3
   146    if [ -z "$header" ]; then
   147      code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url")
   148    else
   149      code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url")
   150    fi
   151    if [ "$code" != "200" ]; then
   152      log_debug "http_download_curl received HTTP status $code"
   153      return 1
   154    fi
   155    return 0
   156  }
   157  http_download_wget() {
   158    local_file=$1
   159    source_url=$2
   160    header=$3
   161    if [ -z "$header" ]; then
   162      wget -q -O "$local_file" "$source_url"
   163    else
   164      wget -q --header "$header" -O "$local_file" "$source_url"
   165    fi
   166  }
   167  http_download() {
   168    log_debug "http_download $2"
   169    if is_command curl; then
   170      http_download_curl "$@"
   171      return
   172    elif is_command wget; then
   173      http_download_wget "$@"
   174      return
   175    fi
   176    log_crit "http_download unable to find wget or curl"
   177    return 1
   178  }
   179  http_copy() {
   180    tmp=$(mktemp)
   181    http_download "${tmp}" "$1" "$2" || return 1
   182    body=$(cat "$tmp")
   183    rm -f "${tmp}"
   184    echo "$body"
   185  }
   186  github_release() {
   187    owner_repo=$1
   188    version=$2
   189    test -z "$version" && version="latest"
   190    giturl="https://github.com/${owner_repo}/releases/${version}"
   191    json=$(http_copy "$giturl" "Accept:application/json")
   192    test -z "$json" && return 1
   193    version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
   194    test -z "$version" && return 1
   195    echo "$version"
   196  }
   197  hash_sha256() {
   198    TARGET=${1:-/dev/stdin}
   199    if is_command gsha256sum; then
   200      hash=$(gsha256sum "$TARGET") || return 1
   201      echo "$hash" | cut -d ' ' -f 1
   202    elif is_command sha256sum; then
   203      hash=$(sha256sum "$TARGET") || return 1
   204      echo "$hash" | cut -d ' ' -f 1
   205    elif is_command shasum; then
   206      hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
   207      echo "$hash" | cut -d ' ' -f 1
   208    elif is_command openssl; then
   209      hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1
   210      echo "$hash" | cut -d ' ' -f a
   211    else
   212      log_crit "hash_sha256 unable to find command to compute sha-256 hash"
   213      return 1
   214    fi
   215  }
   216  hash_sha256_verify() {
   217    TARGET=$1
   218    checksums=$2
   219    if [ -z "$checksums" ]; then
   220      log_err "hash_sha256_verify checksum file not specified in arg2"
   221      return 1
   222    fi
   223    BASENAME=${TARGET##*/}
   224    want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
   225    if [ -z "$want" ]; then
   226      log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'"
   227      return 1
   228    fi
   229    got=$(hash_sha256 "$TARGET")
   230    if [ "$want" != "$got" ]; then
   231      log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got"
   232      return 1
   233    fi
   234  }
   235  cat /dev/null <<EOF
   236  ------------------------------------------------------------------------
   237  End of functions from https://github.com/client9/shlib
   238  ------------------------------------------------------------------------
   239  EOF
   240  
   241  # Get OS
   242  uname_os() {
   243    os=$(uname -s | tr '[:upper:]' '[:lower:]')
   244    case "$os" in
   245    cygwin_nt*) os="windows" ;;
   246    mingw*) os="windows" ;;
   247    msys_nt*) os="windows" ;;
   248    esac
   249    echo "$os"
   250  }
   251  
   252  # Get architecture info
   253  uname_arch() {
   254    arch=$(uname -m)
   255    case $arch in
   256    x86_64) arch="amd64" ;;
   257    x86) arch="386" ;;
   258    i686) arch="386" ;;
   259    i386) arch="386" ;;
   260    aarch64) arch="arm64" ;;
   261    armv5*) arch="armv5" ;;
   262    armv6*) arch="armv6" ;;
   263    armv7*) arch="armv7" ;;
   264    esac
   265    echo "$arch"
   266  }
   267  
   268  # Gets binary download URL from Github
   269  # ex. https://github.com/benchkram/bob/releases/download/0.5.3/bob_0.5.3_linux_amd64
   270  download_url() {
   271    version=$1
   272    os="$(uname_os)"
   273    arch="$(uname_arch)"
   274    url="${base}/${name}/releases/download/${version}/${name}_${version}_${os}_${arch}"
   275    echo "$url"
   276  }
   277  
   278  binary_name() {
   279    version=$1
   280    os="$(uname_os)"
   281    arch="$(uname_arch)"
   282    echo "${name}_${version}_${os}_${arch}"
   283  }
   284  
   285  # Get binaries checksums URL
   286  # ex. https://github.com/benchkram/bob/releases/download/0.5.3/checksums.txt
   287  checksums_url() {
   288    version=$1
   289    os="$(uname_os)"
   290    arch="$(uname_arch)"
   291    url="${base}/${name}/releases/download/${version}/checksums.txt"
   292    echo "$url"
   293  }
   294  
   295  # Validate supported OS
   296  validate_os() {
   297    os="$(uname_os)"
   298    if [ "$os" != "linux" ] && [ "$os" != "darwin" ]; then
   299      log_debug "your system is not supported"
   300      return 1
   301    fi
   302  }
   303  
   304  guidelines_autocompletion() {
   305    echo "
   306  To add auto-completion:
   307  
   308    BASH:
   309      * Add source <(bob completion) to your .bashrc
   310  
   311    ZSH:
   312      * Add source <(bob completion -z) to your .zshrc
   313  "
   314  }
   315  
   316  absolute_path() {
   317    cd "$(dirname "$1")"
   318    case $(basename $1) in
   319    ..) echo "$(dirname $(pwd))" ;;
   320    .) echo "$(pwd)" ;;
   321    *) echo "$(pwd)/$(basename $1)" ;;
   322    esac
   323  }
   324  
   325  validate_os
   326  
   327  tmpdir=$(mktemp -d)
   328  log_debug "downloading files into ${tmpdir}"
   329  
   330  bin_dir="${BIN_DIR:-$(pwd)}"
   331  
   332  # Create the bin dir if it doesn't exists
   333  if [ ! -d "${bin_dir}" ]; then
   334    echo "Create non-existing directory ${bin_dir}"
   335    if ! mkdir "${bin_dir}"; then
   336      echo "Kindly asking for your password in order to install ${name} to ${install_path}"
   337      sudo mkdir "${bin_dir}"
   338    fi
   339  fi
   340  
   341  install_path=$(absolute_path "$bin_dir"/${name})
   342  
   343  # If bob already exists in bin dir, remove it
   344  if [ -f "${install_path}" ]; then
   345    if ! rm "${install_path}"; then
   346      echo "Kindly asking for your password in order to remove ${install_path}"
   347      sudo rm "${install_path}"
   348    fi
   349  fi
   350  
   351  version="$(github_release "${owner}/${name}" "${BOB_VERSION}")"
   352  bin_name="$(binary_name "$version")"
   353  
   354  download_url="$(download_url "${version}")"
   355  http_download "${tmpdir}/$bin_name" "${download_url}"
   356  
   357  checksum_download_url="$(checksums_url "${version}")"
   358  http_download "${tmpdir}/checksums.txt" "${checksum_download_url}"
   359  hash_sha256_verify "${tmpdir}/$bin_name" "${tmpdir}/checksums.txt"
   360  
   361  mv "${tmpdir}/$bin_name" "${tmpdir}/${name}"
   362  
   363  if [ -w "${bin_dir}" ]; then
   364    test ! -d "${bin_dir}" && install -d "${bin_dir}"
   365    install "${tmpdir}/${name}" "${bin_dir}"
   366  else
   367    if ! install "${tmpdir}/${name}" "${bin_dir}"; then
   368      echo "Kindly asking for your password in order to install ${name} to ${install_path}"
   369      sudo install "${tmpdir}/${name}" "${bin_dir}"
   370    fi
   371  fi
   372  
   373  rm -rf "${tmpdir}"
   374  
   375  echo ""
   376  echo ""
   377  
   378  echo "Successfully installed ${name} in ${install_path}"
   379  
   380  guidelines_autocompletion