Files
2024-02-15 18:55:11 +01:00

243 lines
7.5 KiB
Bash

#!/bin/bash -e
################################################################################
## File: install.sh
## Desc: Helper functions for installing tools
################################################################################
download_with_retry() {
local url=$1
local download_path=$2
if [ -z "$download_path" ]; then
download_path="/tmp/$(basename "$url")"
fi
echo "Downloading package from $url to $download_path..." >&2
interval=30
download_start_time=$(date +%s)
for ((retries=20; retries>0; retries--)); do
attempt_start_time=$(date +%s)
if http_code=$(curl -4sSLo "$download_path" "$url" -w '%{http_code}'); then
attempt_seconds=$(($(date +%s) - attempt_start_time))
if [ "$http_code" -eq 200 ]; then
echo "Package downloaded in $attempt_seconds seconds" >&2
break
else
echo "Received HTTP status code $http_code after $attempt_seconds seconds" >&2
fi
else
attempt_seconds=$(($(date +%s) - attempt_start_time))
echo "Package download failed in $attempt_seconds seconds" >&2
fi
if [ "$retries" -le 1 ]; then
total_seconds=$(($(date +%s) - download_start_time))
echo "Package download failed after $total_seconds seconds" >&2
exit 1
fi
echo "Waiting $interval seconds before retrying (retries left: $retries)..." >&2
sleep $interval
done
echo "$download_path"
}
get_toolset_value() {
local toolset_path="${INSTALLER_SCRIPT_FOLDER}/toolset.json"
local query=$1
echo "$(jq -r "$query" $toolset_path)"
}
get_github_releases_by_version() {
local repo=$1
local version=${2:-".+"}
local allow_pre_release=${3:-false}
local with_assets_only=${4:-false}
page_size="100"
json=$(curl -fsSL "https://api.github.com/repos/${repo}/releases?per_page=${page_size}")
if [[ -z "$json" ]]; then
echo "Failed to get releases" >&2
exit 1
fi
if [[ $with_assets_only == "true" ]]; then
json=$(echo $json | jq -r '.[] | select(.assets | length > 0)')
else
json=$(echo $json | jq -r '.[]')
fi
if [[ $allow_pre_release == "true" ]]; then
json=$(echo $json | jq -r '.')
else
json=$(echo $json | jq -r '. | select(.prerelease==false)')
fi
# Filter out rc/beta/etc releases, convert to numeric version and sort
json=$(echo $json | jq '. | select(.tag_name | test(".*-[a-z]|beta") | not)' | jq '.tag_name |= gsub("[^\\d.]"; "")' | jq -s 'sort_by(.tag_name | split(".") | map(tonumber))')
# Select releases matching version
if [[ $version == "latest" ]]; then
json_filtered=$(echo $json | jq .[-1])
elif [[ $version == *"+"* ]] || [[ $version == *"*"* ]]; then
json_filtered=$(echo $json | jq --arg version $version '.[] | select(.tag_name | test($version))')
else
json_filtered=$(echo $json | jq --arg version $version '.[] | select(.tag_name | contains($version))')
fi
if [[ -z "$json_filtered" ]]; then
echo "Failed to get releases from ${repo} matching version ${version}" >&2
echo "Available versions: $(echo "$json" | jq -r '.tag_name')" >&2
exit 1
fi
echo $json_filtered
}
resolve_github_release_asset_url() {
local repo=$1
local url_filter=$2
local version=${3:-".+"}
local allow_pre_release=${4:-false}
local allow_multiple_matches=${5:-false}
matching_releases=$(get_github_releases_by_version "${repo}" "${version}" "${allow_pre_release}" "true")
matched_url=$(echo $matching_releases | jq -r ".assets[].browser_download_url | select(${url_filter})")
if [[ -z "$matched_url" ]]; then
echo "Found no download urls matching pattern: ${url_filter}" >&2
echo "Available download urls: $(echo "$matching_releases" | jq -r '.assets[].browser_download_url')" >&2
exit 1
fi
if [[ "$(echo "$matched_url" | wc -l)" -gt 1 ]]; then
if [[ $allow_multiple_matches == "true" ]]; then
matched_url=$(echo "$matched_url" | tail -n 1)
else
echo "Multiple matches found for ${version} version and ${url_filter} URL filter. Please make filters more specific" >&2
exit 1
fi
fi
echo $matched_url
}
get_checksum_from_github_release() {
local repo=$1
local file_name=$2
local version=${3:-".+"}
local hash_type=$4
local allow_pre_release=${5:-false}
if [[ -z "$file_name" ]]; then
echo "File name is not specified." >&2
exit 1
fi
if [[ "$hash_type" == "SHA256" ]]; then
hash_pattern="[A-Fa-f0-9]{64}"
elif [[ "$hash_type" == "SHA512" ]]; then
hash_pattern="[A-Fa-f0-9]{128}"
else
echo "Unknown hash type: ${hash_type}" >&2
exit 1
fi
matching_releases=$(get_github_releases_by_version "${repo}" "${version}" "${allow_pre_release}" "true")
matched_line=$(printf "$(echo $matching_releases | jq '.body')\n" | grep "$file_name")
if [[ -z "$matched_line" ]]; then
echo "File name ${file_name} not found in release body" >&2
exit 1
fi
if [[ "$(echo "$matched_line" | wc -l)" -gt 1 ]]; then
echo "Multiple matches found for ${file_name} in release body: ${matched_line}" >&2
exit 1
fi
hash=$(echo $matched_line | grep -oP "$hash_pattern")
if [[ -z "$hash" ]]; then
echo "Found ${file_name} in body of release, but failed to get hash from it: ${matched_line}" >&2
exit 1
fi
echo "$hash"
}
get_checksum_from_url() {
local url=$1
local file_name=$2
local hash_type=$3
local use_custom_search_pattern=${4:-false}
local delimiter=${5:-' '}
local word_number=${6:-1}
if [[ "$hash_type" == "SHA256" ]]; then
hash_pattern="[A-Fa-f0-9]{64}"
elif [[ "$hash_type" == "SHA512" ]]; then
hash_pattern="[A-Fa-f0-9]{128}"
else
echo "Unknown hash type: ${hash_type}" >&2
exit 1
fi
checksums_file_path=$(download_with_retry "$url")
checksums=$(cat "$checksums_file_path")
rm "$checksums_file_path"
matched_line=$(printf "$checksums\n" | grep "$file_name")
if [[ "$(echo "$matched_line" | wc -l)" -gt 1 ]]; then
echo "Found multiple lines matching file name ${file_name} in checksum file." >&2
exit 1
fi
if [[ -z "$matched_line" ]]; then
echo "File name ${file_name} not found in checksum file." >&2
exit 1
fi
if [[ $use_custom_search_pattern == "true" ]]; then
hash=$(echo "$matched_line" | sed 's/ */ /g' | cut -d "$delimiter" -f "$word_number" | tr -d -c '[:alnum:]')
else
hash=$(echo $matched_line | grep -oP "$hash_pattern")
fi
if [[ -z "$hash" ]]; then
echo "Found ${file_name} in checksum file, but failed to get hash from it: ${matched_line}" >&2
exit 1
fi
echo "$hash"
}
use_checksum_comparison() {
local file_path=$1
local checksum=$2
local sha_type=${3:-"256"}
echo "Performing checksum verification"
if [[ ! -f "$file_path" ]]; then
echo "File not found: $file_path"
exit 1
fi
local_file_hash=$(shasum --algorithm "$sha_type" "$file_path" | awk '{print $1}')
if [[ "$local_file_hash" != "$checksum" ]]; then
echo "Checksum verification failed. Expected hash: $checksum; Actual hash: $local_file_hash."
exit 1
else
echo "Checksum verification passed"
fi
}