#!/bin/sh # Code generated by binstaller. DO NOT EDIT. # set -e usage() { this=$1 cat </dev/null } echoerr() { echo "$@" 1>&2 } _logp=6 log_set_priority() { _logp="$1" } log_priority() { if test -z "$1"; then echo "$_logp" return fi [ "$1" -le "$_logp" ] } log_tag() { case $1 in 0) echo "emerg" ;; 1) echo "alert" ;; 2) echo "crit" ;; 3) echo "err" ;; 4) echo "warning" ;; 5) echo "notice" ;; 6) echo "info" ;; 7) echo "debug" ;; *) echo "$1" ;; esac } log_debug() { log_priority 7 || return 0 echoerr "$(log_prefix)" "$(log_tag 7)" "$@" } log_info() { log_priority 6 || return 0 echoerr "$(log_prefix)" "$(log_tag 6)" "$@" } log_err() { log_priority 3 || return 0 echoerr "$(log_prefix)" "$(log_tag 3)" "$@" } log_crit() { log_priority 2 || return 0 echoerr "$(log_prefix)" "$(log_tag 2)" "$@" } uname_os() { os=$(uname -s | tr '[:upper:]' '[:lower:]') case "$os" in msys*) os="windows" ;; mingw*) os="windows" ;; cygwin*) os="windows" ;; esac if [ "$os" = "sunos" ]; then if [ "$(uname -o)" = "illumos" ]; then os="illumos" else os="solaris" fi fi echo "$os" } uname_arch() { arch=$(uname -m) case $arch in x86_64) arch="amd64" ;; i86pc) arch="amd64" ;; x86) arch="386" ;; i686) arch="386" ;; i386) arch="386" ;; aarch64) arch="arm64" ;; armv5*) arch="armv5" ;; armv6*) arch="armv6" ;; armv7*) arch="armv7" ;; esac echo "${arch}" } uname_os_check() { os=$(uname_os) case "$os" in darwin) return 0 ;; dragonfly) return 0 ;; freebsd) return 0 ;; linux) return 0 ;; android) return 0 ;; midnightbsd) return 0 ;; nacl) return 0 ;; netbsd) return 0 ;; openbsd) return 0 ;; plan9) return 0 ;; solaris) return 0 ;; illumos) return 0 ;; windows) return 0 ;; esac 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" return 1 } uname_arch_check() { arch=$(uname_arch) case "$arch" in 386) return 0 ;; amd64) return 0 ;; arm64) return 0 ;; armv5) return 0 ;; armv6) return 0 ;; armv7) return 0 ;; ppc64) return 0 ;; ppc64le) return 0 ;; mips) return 0 ;; mipsle) return 0 ;; mips64) return 0 ;; mips64le) return 0 ;; s390x) return 0 ;; amd64p32) return 0 ;; esac 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" return 1 } cat /dev/null </dev/null) || return 1 echo "$hash" | cut -d ' ' -f 1 elif is_command openssl; then hash=$(openssl dgst -sha256 "$TARGET") || return 1 echo "$hash" | cut -d ' ' -f 2 else log_crit "hash_sha256 unable to find command to compute sha-256 hash" return 1 fi } hash_compute() { hash_sha256 "$1" } # shellcheck shell=sh # Terminal progress reporting functions progress_init() { # Only show progress on interactive terminals and when not disabled if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then return 0 fi # OSC 9;4 sequences are safely ignored by unsupporting terminals # Only need special handling for tmux passthrough if [ -n "$TMUX" ]; then # Tmux passthrough: DCS tmux; ST # ESC characters in the wrapped sequence must be doubled # Format: ESC P tmux; ESC ESC ] 9;4; ... ESC ESC \ ESC \ PROGRESS_START=$(printf '\033Ptmux;\033\033]9;4;') # shellcheck disable=SC1003 PROGRESS_END=$(printf '\033\033\\\033\\') else # Direct OSC 9;4 - terminals that don't support it will safely ignore PROGRESS_START=$(printf '\033]9;4;') PROGRESS_END=$(printf '\007') fi } # Start pulsing progress animation progress_pulse_start() { # Only show progress on interactive terminals and when not disabled if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then return 0 fi # Send OSC 9;4 with state 3 (indeterminate/pulsing) once # The terminal will handle the continuous animation printf "%s3%s" "$PROGRESS_START" "$PROGRESS_END" >&2 } # Clear progress indicator progress_clear() { # Only show progress on interactive terminals and when not disabled if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then return 0 fi printf "%s0;%s" "$PROGRESS_START" "$PROGRESS_END" >&2 } untar() { tarball=$1 strip_components=${2:-0} # default 0 case "${tarball}" in *.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" --strip-components "${strip_components}" ;; *.tar.xz) tar --no-same-owner -xJf "${tarball}" --strip-components "${strip_components}" ;; *.tar.bz2) tar --no-same-owner -xjf "${tarball}" --strip-components "${strip_components}" ;; *.tar) tar --no-same-owner -xf "${tarball}" --strip-components "${strip_components}" ;; *.gz) gunzip "${tarball}" ;; *.zip) # unzip doesn't have a standard --strip-components # Workaround: extract to a subdir and move contents up if stripping if [ "$strip_components" -gt 0 ]; then extract_dir=$(basename "${tarball%.zip}")_extracted unzip -q "${tarball}" -d "${extract_dir}" # Move contents of the *first* directory found inside extract_dir up # This assumes wrap_in_directory=true convention first_subdir=$(find "${extract_dir}" -mindepth 1 -maxdepth 1 -type d -print -quit) if [ -n "$first_subdir" ]; then # Move all contents (* includes hidden files) mv "${first_subdir}"/* . # Optionally remove the now-empty subdir and the extract_dir rmdir "${first_subdir}" rmdir "${extract_dir}" else log_warn "Could not find subdirectory in zip to strip components from ${extract_dir}" # Files are extracted in current dir anyway, proceed fi else unzip -q "${tarball}" fi ;; *) log_err "untar unknown archive format for ${tarball}" return 1 ;; esac } hash_verify() { TARGET_PATH=$1 SUMFILE=$2 if [ -z "${SUMFILE}" ]; then log_err "hash_verify checksum file not specified in arg2" return 1 fi got=$(hash_compute "$TARGET_PATH") if [ -z "${got}" ]; then log_err "failed to calculate hash: ${TARGET_PATH}" return 1 fi BASENAME=${TARGET_PATH##*/} # Check for line matches in checksum file # Format: " " or " *" # Filename may include path prefix (e.g., "deployment/m2/file.tar.gz") while IFS= read -r line || [ -n "$line" ]; do # Normalize tabs to spaces line=$(echo "$line" | tr '\t' ' ') # Remove trailing spaces for hash-only line check line_trimmed=$(echo "$line" | sed 's/[[:space:]]*$//') # Check for hash-only line (no filename) - early return if [ "$line_trimmed" = "$got" ]; then return 0 fi # Extract hash and filename parts # First field is the hash, rest is filename (which may contain spaces) line_hash=$(echo "$line" | cut -d' ' -f1) # Skip if hash doesn't match if [ "$line_hash" != "$got" ]; then continue fi # Hash matches, now check filename # Remove the hash part from the beginning of the line line_rest="${line#"$got"}" # Remove leading spaces while [ "${line_rest#[ ]}" != "$line_rest" ]; do line_rest="${line_rest#[ ]}" done # Remove leading asterisk if present (binary mode indicator) if [ "${line_rest#\*}" != "$line_rest" ]; then line_rest="${line_rest#\*}" fi # Extract just the filename without any path line_filename="${line_rest##*/}" # Check if the filename matches if [ "$line_filename" = "$BASENAME" ]; then return 0 fi done < "$SUMFILE" log_err "hash_verify checksum for '$TARGET_PATH' did not verify" log_err " Expected hash: ${got}" log_err " Checksum file content:" cat "$SUMFILE" >&2 return 1 } # GitHub HTTP download functions with GITHUB_TOKEN support github_http_download_curl() { local_file=$1 source_url=$2 header=$3 if [ -n "$GITHUB_TOKEN" ]; then log_debug "Using GITHUB_TOKEN for authentication" if [ -z "$header" ]; then curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -o "$local_file" "$source_url" else curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -H "$header" -o "$local_file" "$source_url" fi else if [ -z "$header" ]; then curl -fsSL -o "$local_file" "$source_url" else curl -fsSL -H "$header" -o "$local_file" "$source_url" fi fi } github_http_download_wget() { local_file=$1 source_url=$2 header=$3 if [ -n "$GITHUB_TOKEN" ]; then log_debug "Using GITHUB_TOKEN for authentication" if [ -z "$header" ]; then wget -q --header "Authorization: Bearer $GITHUB_TOKEN" -O "$local_file" "$source_url" else wget -q --header "Authorization: Bearer $GITHUB_TOKEN" --header "$header" -O "$local_file" "$source_url" fi else if [ -z "$header" ]; then wget -q -O "$local_file" "$source_url" else wget -q --header "$header" -O "$local_file" "$source_url" fi fi } github_http_download() { log_debug "github_http_download $2" if is_command curl; then github_http_download_curl "$@" return elif is_command wget; then github_http_download_wget "$@" return fi log_crit "github_http_download unable to find wget or curl" return 1 } github_http_copy() { tmp=$(mktemp) github_http_download "${tmp}" "$@" || return 1 body=$(cat "$tmp") rm -f "${tmp}" echo "$body" } github_release() { owner_repo=$1 version=$2 test -z "$version" && version="latest" giturl="https://github.com/${owner_repo}/releases/${version}" json=$(github_http_copy "$giturl" "Accept:application/json") test -z "$json" && return 1 version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//') test -z "$version" && return 1 echo "$version" } # --- Embedded Checksums (Format: VERSION:FILENAME:HASH) --- EMBEDDED_CHECKSUMS=" 4.9.0:tenv_v4.9.0_Darwin_arm64.tar.gz:9fe1bea568d89c877198caa3af8cdf78c44263aedd6117feb783be4f242bf09b 4.9.0:tenv_v4.9.0_Darwin_x86_64.tar.gz:d2b807d5885222745e64421911ffc35dcc15a3e9e77820fe73d0508a26cda726 4.9.0:tenv_v4.9.0_Linux_arm64.tar.gz:7b1e3e46e946f6ae60fb5b8a307b6481771708b6a571d0ca42e106bb490cb062 4.9.0:tenv_v4.9.0_Linux_armv6.tar.gz:86ca60fb1020d17d73217a0f94233a4931205e7225c11ebbfcbfb62f05d3ee85 4.9.0:tenv_v4.9.0_Linux_x86_64.tar.gz:3aa5bbd0147405518d29eca0468c7ea9a93326a5fbef758799caece8428442a6 4.9.0:tenv_v4.9.0_Windows_arm64.zip:360cba142fdd2a731ac895b87b32e62724e41bf5afc6aed0459bf1f9d4de6c63 4.9.0:tenv_v4.9.0_Windows_armv6.zip:1d751bc4e0abdfb30bffed4bd2c8615ab149632ce595af471e971204b769391c 4.9.0:tenv_v4.9.0_Windows_x86_64.zip:2b798e4155478425be2c07a8ec857dd31c66fe418f20f8fc9cac4b4a5cf91fe2" # Find embedded checksum for a given version and filename find_embedded_checksum() { version="$1" filename="$2" echo "$EMBEDDED_CHECKSUMS" | grep -E "^${version}:${filename}:" | cut -d':' -f3 } parse_args() { BINDIR="${BINSTALLER_BIN:-${HOME}/.local/bin}" DRY_RUN=0 while getopts "b:dqh?xn" arg; do case "$arg" in b) BINDIR="$OPTARG" ;; d) log_set_priority 10 ;; q) log_set_priority 3 ;; h | \?) usage "$0" ;; x) set -x ;; n) DRY_RUN=1 ;; esac done shift $((OPTIND - 1)) TAG="${1:-latest}" } tag_to_version() { if [ "$TAG" = "latest" ]; then log_info "checking GitHub for latest tag" REALTAG=$(github_release "${REPO}" "${TAG}") && true test -n "$REALTAG" || { log_crit "Could not determine latest tag for ${REPO}" exit 1 } else # Assume TAG is a valid tag/version string REALTAG="$TAG" fi if test -z "$REALTAG"; then log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${REPO}/releases for details" exit 1 fi VERSION=${REALTAG#v} # Strip leading 'v' TAG="$REALTAG" # Use the resolved tag log_info "Resolved version: ${VERSION} (tag: ${TAG})" } resolve_asset_filename() { # --- Apply Rules --- ASSET_FILENAME="" if [ "${UNAME_ARCH}" = 'amd64' ] && true then ARCH='x86_64' fi if [ "${UNAME_OS}" = 'darwin' ] && true then OS='Darwin' fi if [ "${UNAME_OS}" = 'linux' ] && true then OS='Linux' fi if [ "${UNAME_OS}" = 'windows' ] && true then OS='Windows' fi if [ "${UNAME_OS}" = 'windows' ] && true then EXT='.zip' fi if [ -z "${ASSET_FILENAME}" ]; then ASSET_FILENAME="tenv_${TAG}_${OS}_${ARCH}${EXT}" fi } # Cleanup function to remove temporary files and stop progress cleanup() { # Stop progress animation progress_clear if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then log_debug "Cleaning up temporary directory: $TMPDIR" rm -rf -- "$TMPDIR" fi } execute() { STRIP_COMPONENTS=0 CHECKSUM_FILENAME="tenv_${TAG}_checksums.txt" # --- Construct URLs --- GITHUB_DOWNLOAD="https://github.com/${REPO}/releases/download" ASSET_URL="${GITHUB_DOWNLOAD}/${TAG}/${ASSET_FILENAME}" CHECKSUM_URL="" if [ -n "$CHECKSUM_FILENAME" ]; then CHECKSUM_URL="${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM_FILENAME}" fi # --- Download and Verify --- TMPDIR=$(mktemp -d) # Set up cleanup trap that includes progress clearing trap cleanup EXIT HUP INT TERM log_debug "Downloading files into ${TMPDIR}" log_info "Downloading ${ASSET_URL}" github_http_download "${TMPDIR}/${ASSET_FILENAME}" "${ASSET_URL}" # Try to find embedded checksum first EMBEDDED_HASH=$(find_embedded_checksum "$VERSION" "$ASSET_FILENAME") if [ -n "$EMBEDDED_HASH" ]; then log_info "Using embedded checksum for verification" # Verify using embedded hash got=$(hash_compute "${TMPDIR}/${ASSET_FILENAME}") if [ "$got" != "$EMBEDDED_HASH" ]; then log_crit "Checksum verification failed for ${ASSET_FILENAME}" log_crit "Expected: ${EMBEDDED_HASH}" log_crit "Got: ${got}" return 1 fi log_info "Checksum verification successful" elif [ -n "$CHECKSUM_URL" ]; then # Fall back to downloading checksum file log_info "Downloading checksums from ${CHECKSUM_URL}" github_http_download "${TMPDIR}/${CHECKSUM_FILENAME}" "${CHECKSUM_URL}" log_info "Verifying checksum ..." hash_verify "${TMPDIR}/${ASSET_FILENAME}" "${TMPDIR}/${CHECKSUM_FILENAME}" else log_info "No checksum found, skipping verification." fi if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then log_debug "Target is raw binary" else log_info "Extracting ${ASSET_FILENAME}..." (cd "${TMPDIR}" && untar "${ASSET_FILENAME}" "${STRIP_COMPONENTS}") fi BINARY_NAME='atmos' if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}" else BINARY_PATH="${TMPDIR}/atmo" fi if [ "${UNAME_OS}" = "windows" ]; then case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac fi if [ ! -f "${BINARY_PATH}" ]; then log_crit "Binary not found: ${BINARY_PATH}" log_crit "Listing contents of ${TMPDIR} ..." if command -v find >/dev/null 2>&1; then cd "${TMPDIR}" && find . else cd "${TMPDIR}" && ls -R . fi return 1 fi progress_clear # Install the binary INSTALL_PATH="${BINDIR}/${BINARY_NAME}" if [ "$DRY_RUN" = "1" ]; then log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})" else log_info "Installing binary to ${INSTALL_PATH}" test ! -d "${BINDIR}" && install -d "${BINDIR}" install "${BINARY_PATH}" "${INSTALL_PATH}" log_info "${BINARY_NAME} installation complete!" fi BINARY_NAME='tenv' if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}" else BINARY_PATH="${TMPDIR}/tenv" fi if [ "${UNAME_OS}" = "windows" ]; then case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac fi if [ ! -f "${BINARY_PATH}" ]; then log_crit "Binary not found: ${BINARY_PATH}" log_crit "Listing contents of ${TMPDIR} ..." if command -v find >/dev/null 2>&1; then cd "${TMPDIR}" && find . else cd "${TMPDIR}" && ls -R . fi return 1 fi progress_clear # Install the binary INSTALL_PATH="${BINDIR}/${BINARY_NAME}" if [ "$DRY_RUN" = "1" ]; then log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})" else log_info "Installing binary to ${INSTALL_PATH}" test ! -d "${BINDIR}" && install -d "${BINDIR}" install "${BINARY_PATH}" "${INSTALL_PATH}" log_info "${BINARY_NAME} installation complete!" fi BINARY_NAME='terraform' if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}" else BINARY_PATH="${TMPDIR}/terraform" fi if [ "${UNAME_OS}" = "windows" ]; then case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac fi if [ ! -f "${BINARY_PATH}" ]; then log_crit "Binary not found: ${BINARY_PATH}" log_crit "Listing contents of ${TMPDIR} ..." if command -v find >/dev/null 2>&1; then cd "${TMPDIR}" && find . else cd "${TMPDIR}" && ls -R . fi return 1 fi progress_clear # Install the binary INSTALL_PATH="${BINDIR}/${BINARY_NAME}" if [ "$DRY_RUN" = "1" ]; then log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})" else log_info "Installing binary to ${INSTALL_PATH}" test ! -d "${BINDIR}" && install -d "${BINDIR}" install "${BINARY_PATH}" "${INSTALL_PATH}" log_info "${BINARY_NAME} installation complete!" fi BINARY_NAME='terragrunt' if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}" else BINARY_PATH="${TMPDIR}/terragrunt" fi if [ "${UNAME_OS}" = "windows" ]; then case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac fi if [ ! -f "${BINARY_PATH}" ]; then log_crit "Binary not found: ${BINARY_PATH}" log_crit "Listing contents of ${TMPDIR} ..." if command -v find >/dev/null 2>&1; then cd "${TMPDIR}" && find . else cd "${TMPDIR}" && ls -R . fi return 1 fi progress_clear # Install the binary INSTALL_PATH="${BINDIR}/${BINARY_NAME}" if [ "$DRY_RUN" = "1" ]; then log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})" else log_info "Installing binary to ${INSTALL_PATH}" test ! -d "${BINDIR}" && install -d "${BINDIR}" install "${BINARY_PATH}" "${INSTALL_PATH}" log_info "${BINARY_NAME} installation complete!" fi BINARY_NAME='terramate' if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}" else BINARY_PATH="${TMPDIR}/terramate" fi if [ "${UNAME_OS}" = "windows" ]; then case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac fi if [ ! -f "${BINARY_PATH}" ]; then log_crit "Binary not found: ${BINARY_PATH}" log_crit "Listing contents of ${TMPDIR} ..." if command -v find >/dev/null 2>&1; then cd "${TMPDIR}" && find . else cd "${TMPDIR}" && ls -R . fi return 1 fi progress_clear # Install the binary INSTALL_PATH="${BINDIR}/${BINARY_NAME}" if [ "$DRY_RUN" = "1" ]; then log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})" else log_info "Installing binary to ${INSTALL_PATH}" test ! -d "${BINDIR}" && install -d "${BINDIR}" install "${BINARY_PATH}" "${INSTALL_PATH}" log_info "${BINARY_NAME} installation complete!" fi BINARY_NAME='tf' if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}" else BINARY_PATH="${TMPDIR}/tf" fi if [ "${UNAME_OS}" = "windows" ]; then case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac fi if [ ! -f "${BINARY_PATH}" ]; then log_crit "Binary not found: ${BINARY_PATH}" log_crit "Listing contents of ${TMPDIR} ..." if command -v find >/dev/null 2>&1; then cd "${TMPDIR}" && find . else cd "${TMPDIR}" && ls -R . fi return 1 fi progress_clear # Install the binary INSTALL_PATH="${BINDIR}/${BINARY_NAME}" if [ "$DRY_RUN" = "1" ]; then log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})" else log_info "Installing binary to ${INSTALL_PATH}" test ! -d "${BINDIR}" && install -d "${BINDIR}" install "${BINARY_PATH}" "${INSTALL_PATH}" log_info "${BINARY_NAME} installation complete!" fi BINARY_NAME='tofu' if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}" else BINARY_PATH="${TMPDIR}/tofu" fi if [ "${UNAME_OS}" = "windows" ]; then case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac fi if [ ! -f "${BINARY_PATH}" ]; then log_crit "Binary not found: ${BINARY_PATH}" log_crit "Listing contents of ${TMPDIR} ..." if command -v find >/dev/null 2>&1; then cd "${TMPDIR}" && find . else cd "${TMPDIR}" && ls -R . fi return 1 fi progress_clear # Install the binary INSTALL_PATH="${BINDIR}/${BINARY_NAME}" if [ "$DRY_RUN" = "1" ]; then log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})" else log_info "Installing binary to ${INSTALL_PATH}" test ! -d "${BINDIR}" && install -d "${BINDIR}" install "${BINARY_PATH}" "${INSTALL_PATH}" log_info "${BINARY_NAME} installation complete!" fi } # --- Configuration --- NAME='tenv' REPO='tofuutils/tenv' EXT='.tar.gz' # use in logging routines log_prefix() { echo "${REPO}" } parse_args "$@" progress_init progress_pulse_start # --- Determine target platform --- OS="${BINSTALLER_OS:-$(uname_os)}" UNAME_OS="${OS}" ARCH="${BINSTALLER_ARCH:-$(uname_arch)}" UNAME_ARCH="${ARCH}" log_info "Detected Platform: ${OS}/${ARCH}" # --- Validate platform --- uname_os_check "$OS" uname_arch_check "$ARCH" tag_to_version resolve_asset_filename execute