Compare commits
7 Commits
add-tf-too
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3f4f1bfeb | ||
|
|
9052e555b8 | ||
| ffd982948a | |||
| 106f00e062 | |||
| 0757be90a1 | |||
|
|
e913b5c8be | ||
| 3ea9c12edd |
203
README.md
203
README.md
@@ -1,96 +1,152 @@
|
||||
# binst
|
||||
|
||||
A collection of installation scripts for binary tools, generated using [binstaller](https://github.com/binary-install/binstaller). These scripts are portable POSIX shell scripts that work across Linux, macOS, and Windows (Git Bash/WSL) and are designed to be a simple, secure way to install self-contained binaries from GitHub releases.
|
||||
A curated collection of portable installation scripts for binary tools, powered by [binstaller](https://github.com/binary-install/binstaller).
|
||||
|
||||
* [Quick Start](#quick-start)
|
||||
* [Workflows](#workflows)
|
||||
* [Creating New Installation Scripts](#creating-new-installation-scripts)
|
||||
* [Notes](#notes)
|
||||
* [Binary Names](#binary-names)
|
||||
## Overview
|
||||
|
||||
This repository provides POSIX-compliant shell scripts that simplify the installation of popular binary tools from GitHub releases. Each script is:
|
||||
|
||||
- **Portable**: Works across Linux, macOS, and Windows (Git Bash/WSL)
|
||||
- **Secure**: Includes checksum verification for downloaded binaries
|
||||
- **Simple**: Single command installation with no dependencies
|
||||
- **Self-contained**: No package manager or runtime required
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Quick Start](#quick-start)
|
||||
- [Available Tools](#available-tools)
|
||||
- [Usage](#usage)
|
||||
- [Installing Binaries](#installing-binaries)
|
||||
- [Using Task Commands](#using-task-commands)
|
||||
- [Creating New Scripts](#creating-new-scripts)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Automatic Generation](#automatic-generation)
|
||||
- [Manual Configuration](#manual-configuration)
|
||||
- [Configuration](#configuration)
|
||||
- [Binary Names](#binary-names)
|
||||
- [Contributing](#contributing)
|
||||
- [License](#license)
|
||||
|
||||
## Quick Start
|
||||
|
||||
Install any binary using its generated script:
|
||||
Install any binary directly using its installation script:
|
||||
|
||||
```bash
|
||||
# install trufflehog
|
||||
$ scripts/trufflehog-install.sh
|
||||
# Install trufflehog
|
||||
./scripts/trufflehog-install.sh
|
||||
|
||||
# install task
|
||||
$ scripts/task-install.sh
|
||||
# Install task
|
||||
./scripts/task-install.sh
|
||||
|
||||
# Install checkov
|
||||
./scripts/checkov-install.sh
|
||||
```
|
||||
|
||||
## Workflows
|
||||
Binaries are installed to `~/.local/bin` by default (customizable via environment variables).
|
||||
|
||||
Common workflows for the creation, maintenance, usage of the installation scripts are encapsulated in [Task](https://taskfile.dev) tasks.
|
||||
## Available Tools
|
||||
|
||||
Installation scripts are located in the `scripts/` directory. Run `ls scripts/` to see all available tools, or browse the directory on GitHub.
|
||||
|
||||
## Usage
|
||||
|
||||
### Installing Binaries
|
||||
|
||||
Run any installation script directly:
|
||||
|
||||
```bash
|
||||
# list available tasks
|
||||
$ task --list
|
||||
|
||||
task: Available tasks for this project:
|
||||
* default: Create a new installation script for a binary
|
||||
* embed-checksums: Embed checksums into a binst configuration file.
|
||||
* gen: Generate installation script from binst configuration.
|
||||
* init: Initialize binst configuration for a GitHub project.
|
||||
* install-*: Install a binary using its installation script.
|
||||
* latest-release: Determine the latest release available for a given repo.
|
||||
|
||||
# install a binary
|
||||
$ task install-trufflehog
|
||||
./scripts/<tool-name>-install.sh
|
||||
```
|
||||
|
||||
### Creating New Installation Scripts
|
||||
The script will:
|
||||
1. Detect your OS and architecture
|
||||
2. Download the latest release from GitHub
|
||||
3. Verify checksums
|
||||
4. Install the binary to your PATH
|
||||
|
||||
The default task uses binstaller to creates a new installation script for a binary from
|
||||
its GitHub repository. This is often the only step needed to add a new installation
|
||||
script to the collection.
|
||||
### Using Task Commands
|
||||
|
||||
This repository includes [Taskfile](https://taskfile.dev) automation for common workflows:
|
||||
|
||||
To install binstaller, run:
|
||||
```bash
|
||||
$ scripts/binstaller-install.sh
|
||||
# List all available tasks
|
||||
task --list
|
||||
|
||||
# Install a specific binary via Task
|
||||
task install-trufflehog
|
||||
task install-aichat
|
||||
task install-checkov
|
||||
```
|
||||
|
||||
To create a new installation script:
|
||||
Available tasks:
|
||||
- `task` - Create a new installation script (requires `REPO` variable)
|
||||
- `task install-*` - Install a binary using its script
|
||||
- `task init` - Initialize binstaller configuration for a GitHub project
|
||||
- `task embed-checksums` - Embed checksums into a configuration file
|
||||
- `task gen` - Generate installation script from configuration
|
||||
- `task latest-release` - Check the latest release version
|
||||
|
||||
## Creating New Scripts
|
||||
|
||||
### Prerequisites
|
||||
|
||||
First, install binstaller:
|
||||
|
||||
```bash
|
||||
# create a new installation script by providing the GitHub repository as an argument:
|
||||
$ task REPO=owner/repo-name
|
||||
|
||||
# detailes summary
|
||||
$ task --summary
|
||||
task: default
|
||||
|
||||
Create a new installation script for a binary by initializing a binst config,
|
||||
embedding checksums, and generating the installation script. The latest release, as
|
||||
determined by the latest-release task, will be used unless a specific version is
|
||||
provided.
|
||||
|
||||
Invoke this task like:
|
||||
task default REPO=trufflesecurity/trufflehog
|
||||
|
||||
vars:
|
||||
CONFIG_DIR: "./config"
|
||||
SCRIPT_DIR: "./scripts"
|
||||
BINARY: "{{.REPO | base}}"
|
||||
VERSION: "latest"
|
||||
|
||||
requires:
|
||||
vars:
|
||||
- REPO
|
||||
|
||||
commands:
|
||||
- Task: init
|
||||
- Task: embed-checksums
|
||||
- Task: gen
|
||||
./scripts/binstaller-install.sh
|
||||
```
|
||||
|
||||
## Notes
|
||||
### Automatic Generation
|
||||
|
||||
The easiest way to add a new installation script is using the default Task workflow:
|
||||
|
||||
```bash
|
||||
# Create script for a GitHub repository
|
||||
task REPO=owner/repo-name
|
||||
|
||||
# Example: Add installation script for trufflehog
|
||||
task REPO=trufflesecurity/trufflehog
|
||||
```
|
||||
|
||||
This command will:
|
||||
1. Initialize a binstaller configuration file
|
||||
2. Fetch and embed checksums from the latest release
|
||||
3. Generate the installation script
|
||||
|
||||
For more details on the default task:
|
||||
|
||||
```bash
|
||||
task --summary
|
||||
```
|
||||
|
||||
### Manual Configuration
|
||||
|
||||
For advanced use cases, you can manually create or edit configuration files:
|
||||
|
||||
1. **Initialize configuration**:
|
||||
```bash
|
||||
task init REPO=owner/repo-name
|
||||
```
|
||||
|
||||
2. **Edit the configuration** in `config/repo-name.binstaller.yml` as needed
|
||||
|
||||
3. **Embed checksums**:
|
||||
```bash
|
||||
task embed-checksums BINARY=repo-name
|
||||
```
|
||||
|
||||
4. **Generate the script**:
|
||||
```bash
|
||||
task gen BINARY=repo-name
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Binary Names
|
||||
|
||||
Sometimes the binary executable name differs from the GitHub repository name. When this occurs, the `asset.binaries` section in the configuration file defines the actual binary name. If this is the case, the generated installation script will need to be manually edited.
|
||||
In some cases, the binary executable name differs from the GitHub repository name. When this occurs, specify the actual binary name in the `asset.binaries` section of the configuration file.
|
||||
|
||||
As an example, the released artifact for [stacklok/toolhive](https://github.com/stacklok/toolhive) is named `thv` rather than `toolhive`. The [configuration file](config/toolhive.binstaller.yml) specifies the correct name for the binary in the `asset.binaries` section.
|
||||
**Example**: The [stacklok/toolhive](https://github.com/stacklok/toolhive) repository releases a binary named `thv`. The [configuration file](config/toolhive.binstaller.yml) handles this:
|
||||
|
||||
```yaml
|
||||
repo: stacklok/toolhive
|
||||
@@ -100,5 +156,22 @@ binaries:
|
||||
path: thv
|
||||
```
|
||||
|
||||
After generation, you may wish to rename the installation script from `thv-install.sh` to `toolhive-install.sh` for consistency.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! To add a new binary installation script:
|
||||
|
||||
1. Fork this repository
|
||||
2. Create a new script using `task REPO=owner/repo-name`
|
||||
3. Test the installation script
|
||||
4. Submit a pull request
|
||||
|
||||
Please ensure:
|
||||
- The binary is a popular, well-maintained tool
|
||||
- The installation script works across all supported platforms
|
||||
- Checksums are embedded for security
|
||||
|
||||
## License
|
||||
|
||||
MIT. See [LICENSE](LICENSE) for details.
|
||||
|
||||
@@ -54,18 +54,6 @@ tasks:
|
||||
requires:
|
||||
vars: ["REPO"]
|
||||
|
||||
latest-release:
|
||||
desc: Determine the latest release available for a given repo.
|
||||
summary: |
|
||||
Determine the latest release available for a given GitHub repository.
|
||||
|
||||
Invoke this task like:
|
||||
task latest-release REPO=trufflesecurity/trufflehog
|
||||
cmd: |
|
||||
gh release view -R {{.REPO}} --json tagName --jq .tagName
|
||||
requires:
|
||||
vars: ["REPO"]
|
||||
|
||||
embed-checksums:
|
||||
desc: Embed checksums into a binst configuration file.
|
||||
summary: |
|
||||
@@ -81,7 +69,15 @@ tasks:
|
||||
set +o errexit
|
||||
binst embed-checksums --config {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml --version {{.VERSION}} --mode download
|
||||
if [ $? -ne 0 ]; then
|
||||
binst embed-checksums --config {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml --version {{.VERSION}} --mode calculate
|
||||
# this is tougher than it should be...
|
||||
# without this, checksums aren't written to the file at all
|
||||
printf 'checksums:\n' >> {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml
|
||||
binst embed-checksums \
|
||||
--config {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml \
|
||||
--version latest \
|
||||
--mode calculate
|
||||
# then the formatting is weird, so in-place edit using yq
|
||||
yq -i {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml
|
||||
fi
|
||||
|
||||
vars:
|
||||
@@ -103,6 +99,19 @@ tasks:
|
||||
requires:
|
||||
vars: ["BINARY"]
|
||||
|
||||
latest-release:
|
||||
desc: Determine the latest release available for a given repo.
|
||||
summary: |
|
||||
Determine the latest release available for a given GitHub repository.
|
||||
|
||||
Invoke this task like:
|
||||
task latest-release REPO=trufflesecurity/trufflehog
|
||||
cmd: |
|
||||
gh release view -R {{.REPO}} --json tagName --jq .tagName
|
||||
requires:
|
||||
vars: ["REPO"]
|
||||
|
||||
|
||||
install-*:
|
||||
desc: Install a binary using its installation script.
|
||||
summary: |
|
||||
|
||||
@@ -23,3 +23,19 @@ asset:
|
||||
- when:
|
||||
os: windows
|
||||
ext: .zip
|
||||
checksums:
|
||||
algorithm: sha256
|
||||
embedded_checksums:
|
||||
v0.30.0:
|
||||
- filename: aichat-v0.30.0-aarch64-apple-darwin.tar.gz
|
||||
hash: 680d36ed7f7ba8a2c2490a099df26c9da54495903c27956109a89c87eeb9edb3
|
||||
- filename: aichat-v0.30.0-aarch64-pc-windows-msvc.zip
|
||||
hash: 2f381e70ddaf0831df7e0181a1d25d700bb0d7e53287393a47fd435c253d6091
|
||||
- filename: aichat-v0.30.0-aarch64-unknown-linux-musl.tar.gz
|
||||
hash: eb1cd0948569404c5d9d01c10b32b902e11f8231073315456454dec246bdf26e
|
||||
- filename: aichat-v0.30.0-x86_64-apple-darwin.tar.gz
|
||||
hash: 94aa09315773929e027bcb399f78661c2ddffd887b65348bae446601989d9ddd
|
||||
- filename: aichat-v0.30.0-x86_64-pc-windows-msvc.zip
|
||||
hash: 89df8c4ccd6dad310ac713eb5d550494ae7fa14722cde346588fab38ff4afd8f
|
||||
- filename: aichat-v0.30.0-x86_64-unknown-linux-musl.tar.gz
|
||||
hash: 6b0cc08c5ceb551dc52bfac2221752f82215be5908c70605d655e9b91ab1557c
|
||||
|
||||
@@ -20,20 +20,3 @@ asset:
|
||||
- when:
|
||||
os: windows
|
||||
ext: .zip
|
||||
checksums:
|
||||
algorithm: sha256
|
||||
template: checksums.txt
|
||||
embedded_checksums:
|
||||
v0.12.0:
|
||||
- filename: binst_Darwin_arm64.tar.gz
|
||||
hash: 2c3a8cf9b8f95edb5d97b905ccb0204800b25f1a9bc2b4ad704596e756e41eb9
|
||||
- filename: binst_Darwin_x86_64.tar.gz
|
||||
hash: bd9eae149f5735671bf1f32204f5ba9f10de269a290755f21f93bf1bb5d09b03
|
||||
- filename: binst_Linux_arm64.tar.gz
|
||||
hash: 76bca4884ee3fa229d915473ddd53ab4d04c34c9e4b5a1eda36d9751763af916
|
||||
- filename: binst_Linux_x86_64.tar.gz
|
||||
hash: af36ebb92c01ad4b9867a79eb45d1a130efbce20930896ec7578b3746416ee41
|
||||
- filename: binst_Windows_arm64.zip
|
||||
hash: 133784089efd57f5a0164b84ac74c4924c299342c88eb40be65155193ca37761
|
||||
- filename: binst_Windows_x86_64.zip
|
||||
hash: afcc9eab78de6bfa1ce360aebbf1a48738c519cdbe6a9560e6979ec3a4fcb4ef
|
||||
|
||||
58
config/tenv.binstaller.yml
Normal file
58
config/tenv.binstaller.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/binary-install/binstaller/main/schema/InstallSpec.json
|
||||
schema: v1
|
||||
repo: tofuutils/tenv
|
||||
asset:
|
||||
template: tenv_${TAG}_${OS}_${ARCH}${EXT}
|
||||
default_extension: .tar.gz
|
||||
binaries:
|
||||
- name: atmos
|
||||
path: atmos
|
||||
- name: tenv
|
||||
path: tenv
|
||||
- name: terraform
|
||||
path: terraform
|
||||
- name: terragrunt
|
||||
path: terragrunt
|
||||
- name: terramate
|
||||
path: terramate
|
||||
- name: tf
|
||||
path: tf
|
||||
- name: tofu
|
||||
path: tofu
|
||||
rules:
|
||||
- when:
|
||||
arch: amd64
|
||||
arch: x86_64
|
||||
- when:
|
||||
os: darwin
|
||||
os: Darwin
|
||||
- when:
|
||||
os: linux
|
||||
os: Linux
|
||||
- when:
|
||||
os: windows
|
||||
os: Windows
|
||||
- when:
|
||||
os: windows
|
||||
ext: .zip
|
||||
checksums:
|
||||
algorithm: sha256
|
||||
template: tenv_${TAG}_checksums.txt
|
||||
embedded_checksums:
|
||||
v4.9.0:
|
||||
- filename: tenv_v4.9.0_Darwin_arm64.tar.gz
|
||||
hash: 9fe1bea568d89c877198caa3af8cdf78c44263aedd6117feb783be4f242bf09b
|
||||
- filename: tenv_v4.9.0_Darwin_x86_64.tar.gz
|
||||
hash: d2b807d5885222745e64421911ffc35dcc15a3e9e77820fe73d0508a26cda726
|
||||
- filename: tenv_v4.9.0_Linux_arm64.tar.gz
|
||||
hash: 7b1e3e46e946f6ae60fb5b8a307b6481771708b6a571d0ca42e106bb490cb062
|
||||
- filename: tenv_v4.9.0_Linux_armv6.tar.gz
|
||||
hash: 86ca60fb1020d17d73217a0f94233a4931205e7225c11ebbfcbfb62f05d3ee85
|
||||
- filename: tenv_v4.9.0_Linux_x86_64.tar.gz
|
||||
hash: 3aa5bbd0147405518d29eca0468c7ea9a93326a5fbef758799caece8428442a6
|
||||
- filename: tenv_v4.9.0_Windows_arm64.zip
|
||||
hash: 360cba142fdd2a731ac895b87b32e62724e41bf5afc6aed0459bf1f9d4de6c63
|
||||
- filename: tenv_v4.9.0_Windows_armv6.zip
|
||||
hash: 1d751bc4e0abdfb30bffed4bd2c8615ab149632ce595af471e971204b769391c
|
||||
- filename: tenv_v4.9.0_Windows_x86_64.zip
|
||||
hash: 2b798e4155478425be2c07a8ec857dd31c66fe418f20f8fc9cac4b4a5cf91fe2
|
||||
@@ -409,7 +409,13 @@ github_release() {
|
||||
}
|
||||
|
||||
# --- Embedded Checksums (Format: VERSION:FILENAME:HASH) ---
|
||||
EMBEDDED_CHECKSUMS=""
|
||||
EMBEDDED_CHECKSUMS="
|
||||
0.30.0:aichat-v0.30.0-aarch64-apple-darwin.tar.gz:680d36ed7f7ba8a2c2490a099df26c9da54495903c27956109a89c87eeb9edb3
|
||||
0.30.0:aichat-v0.30.0-aarch64-pc-windows-msvc.zip:2f381e70ddaf0831df7e0181a1d25d700bb0d7e53287393a47fd435c253d6091
|
||||
0.30.0:aichat-v0.30.0-aarch64-unknown-linux-musl.tar.gz:eb1cd0948569404c5d9d01c10b32b902e11f8231073315456454dec246bdf26e
|
||||
0.30.0:aichat-v0.30.0-x86_64-apple-darwin.tar.gz:94aa09315773929e027bcb399f78661c2ddffd887b65348bae446601989d9ddd
|
||||
0.30.0:aichat-v0.30.0-x86_64-pc-windows-msvc.zip:89df8c4ccd6dad310ac713eb5d550494ae7fa14722cde346588fab38ff4afd8f
|
||||
0.30.0:aichat-v0.30.0-x86_64-unknown-linux-musl.tar.gz:6b0cc08c5ceb551dc52bfac2221752f82215be5908c70605d655e9b91ab1557c"
|
||||
|
||||
# Find embedded checksum for a given version and filename
|
||||
find_embedded_checksum() {
|
||||
|
||||
615
scripts/checkov-install.sh
Executable file
615
scripts/checkov-install.sh
Executable file
@@ -0,0 +1,615 @@
|
||||
#!/bin/sh
|
||||
# Code generated by binstaller. DO NOT EDIT.
|
||||
#
|
||||
set -e
|
||||
usage() {
|
||||
this=$1
|
||||
cat <<EOF
|
||||
$this: download ${NAME} from ${REPO}
|
||||
|
||||
Usage: $this [-b bindir] [-d] [-q] [-n] [tag]
|
||||
-b sets bindir or installation directory, Defaults to ${BINSTALLER_BIN:-${HOME}/.local/bin}
|
||||
-d turns on debug logging
|
||||
-q turns on quiet mode (errors only)
|
||||
-n turns on dry run mode
|
||||
[tag] is a tag from
|
||||
https://github.com/bridgecrewio/checkov/releases
|
||||
If tag is missing, then latest will be used.
|
||||
|
||||
Environment variables:
|
||||
BINSTALLER_NO_PROGRESS=1 Disable progress indicators
|
||||
BINSTALLER_OS=... Override OS detection
|
||||
BINSTALLER_ARCH=... Override architecture detection
|
||||
|
||||
Generated by binstaller
|
||||
https://github.com/binary-install/binstaller
|
||||
EOF
|
||||
exit 2
|
||||
}
|
||||
|
||||
cat /dev/null <<EOF
|
||||
------------------------------------------------------------------------
|
||||
https://github.com/client9/shlib - portable posix shell functions
|
||||
Public domain - http://unlicense.org
|
||||
https://github.com/client9/shlib/blob/master/LICENSE.md
|
||||
but credit (and pull requests) appreciated.
|
||||
------------------------------------------------------------------------
|
||||
EOF
|
||||
is_command() {
|
||||
command -v "$1" >/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 <<EOF
|
||||
------------------------------------------------------------------------
|
||||
End of functions from https://github.com/client9/shlib
|
||||
------------------------------------------------------------------------
|
||||
EOF
|
||||
|
||||
|
||||
hash_sha256() {
|
||||
TARGET=${1:-/dev/stdin}
|
||||
if is_command gsha256sum; then
|
||||
hash=$(gsha256sum "$TARGET") || return 1
|
||||
echo "$hash" | cut -d ' ' -f 1
|
||||
elif is_command sha256sum; then
|
||||
hash=$(sha256sum "$TARGET") || return 1
|
||||
echo "$hash" | cut -d ' ' -f 1
|
||||
elif is_command shasum; then
|
||||
hash=$(shasum -a 256 "$TARGET" 2>/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; <doubled ESC sequence> 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: "<hash> <filename>" or "<hash> *<filename>"
|
||||
# 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="
|
||||
3.2.497:checkov_darwin_X86_64.zip:35129a227f25dc37c2347e8b7b6f61984243201807beeb27eb4f33fda0cbe32a
|
||||
3.2.497:checkov_linux_X86_64.zip:f713e29c9b0d477df4d2e4b57428dfe3b8333ce425093d626cc02d87e532e627
|
||||
3.2.497:checkov_linux_arm64.zip:05060050d59207e6c99fd1d4aae8b2711d0f192c33bbfca7a1de139468bdaeea
|
||||
3.2.497:checkov_windows_X86_64.zip:3b2e958c4b6d8a50c573e693ba3a3e6270145a26fad403635179b51e51152f1f"
|
||||
|
||||
# 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})"
|
||||
}
|
||||
|
||||
|
||||
|
||||
is_rosetta2_available() {
|
||||
[ "$(uname -s)" = Darwin ] || return 1
|
||||
[ "$(uname -m)" = arm64 ] || return 1
|
||||
arch -arch x86_64 true 2>/dev/null
|
||||
}
|
||||
resolve_asset_filename() {
|
||||
|
||||
# --- Apply Rules ---
|
||||
ASSET_FILENAME=""
|
||||
if [ "${UNAME_ARCH}" = 'amd64' ] && true
|
||||
then
|
||||
ARCH='X86_64'
|
||||
fi
|
||||
if [ -z "${ASSET_FILENAME}" ]; then
|
||||
ASSET_FILENAME="checkov_${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=""
|
||||
|
||||
# --- 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='checkov'
|
||||
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
|
||||
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
|
||||
else
|
||||
BINARY_PATH="${TMPDIR}/dist/checkov"
|
||||
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='checkov'
|
||||
REPO='bridgecrewio/checkov'
|
||||
EXT='.zip'
|
||||
|
||||
# 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}"
|
||||
|
||||
if is_rosetta2_available; then
|
||||
log_info 'Apple Silicon with Rosetta 2 found: using amd64 as ARCH'
|
||||
ARCH="${BINSTALLER_ARCH:-amd64}"
|
||||
else
|
||||
ARCH="${BINSTALLER_ARCH:-$(uname_arch)}"
|
||||
fi
|
||||
|
||||
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
|
||||
834
scripts/tenv-install.sh
Executable file
834
scripts/tenv-install.sh
Executable file
@@ -0,0 +1,834 @@
|
||||
#!/bin/sh
|
||||
# Code generated by binstaller. DO NOT EDIT.
|
||||
#
|
||||
set -e
|
||||
usage() {
|
||||
this=$1
|
||||
cat <<EOF
|
||||
$this: download ${NAME} from ${REPO}
|
||||
|
||||
Usage: $this [-b bindir] [-d] [-q] [-n] [tag]
|
||||
-b sets bindir or installation directory, Defaults to ${BINSTALLER_BIN:-${HOME}/.local/bin}
|
||||
-d turns on debug logging
|
||||
-q turns on quiet mode (errors only)
|
||||
-n turns on dry run mode
|
||||
[tag] is a tag from
|
||||
https://github.com/tofuutils/tenv/releases
|
||||
If tag is missing, then latest will be used.
|
||||
|
||||
Environment variables:
|
||||
BINSTALLER_NO_PROGRESS=1 Disable progress indicators
|
||||
BINSTALLER_OS=... Override OS detection
|
||||
BINSTALLER_ARCH=... Override architecture detection
|
||||
|
||||
Generated by binstaller
|
||||
https://github.com/binary-install/binstaller
|
||||
EOF
|
||||
exit 2
|
||||
}
|
||||
|
||||
cat /dev/null <<EOF
|
||||
------------------------------------------------------------------------
|
||||
https://github.com/client9/shlib - portable posix shell functions
|
||||
Public domain - http://unlicense.org
|
||||
https://github.com/client9/shlib/blob/master/LICENSE.md
|
||||
but credit (and pull requests) appreciated.
|
||||
------------------------------------------------------------------------
|
||||
EOF
|
||||
is_command() {
|
||||
command -v "$1" >/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 <<EOF
|
||||
------------------------------------------------------------------------
|
||||
End of functions from https://github.com/client9/shlib
|
||||
------------------------------------------------------------------------
|
||||
EOF
|
||||
|
||||
|
||||
hash_sha256() {
|
||||
TARGET=${1:-/dev/stdin}
|
||||
if is_command gsha256sum; then
|
||||
hash=$(gsha256sum "$TARGET") || return 1
|
||||
echo "$hash" | cut -d ' ' -f 1
|
||||
elif is_command sha256sum; then
|
||||
hash=$(sha256sum "$TARGET") || return 1
|
||||
echo "$hash" | cut -d ' ' -f 1
|
||||
elif is_command shasum; then
|
||||
hash=$(shasum -a 256 "$TARGET" 2>/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; <doubled ESC sequence> 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: "<hash> <filename>" or "<hash> *<filename>"
|
||||
# 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}/atmos"
|
||||
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
|
||||
Reference in New Issue
Block a user