...

Text file src/github.com/palantir/go-baseapp/godelw

Documentation: github.com/palantir/go-baseapp

     1#!/bin/bash
     2
     3set -euo pipefail
     4
     5# Version and checksums for godel. Values are populated by the godel "dist" task.
     6VERSION=2.40.0
     7DARWIN_AMD64_CHECKSUM=c0ddf9c67b8bbad9bb362687f79437ca1bf9e9076bc36b212d1be2b659bf23bd
     8DARWIN_ARM64_CHECKSUM=2de3ff5e61ebba985e2ab80fbc4ca0add0db34cac5fa4b7776c1b50d1e53463b
     9LINUX_AMD64_CHECKSUM=d489cd497218e68a5bd26ad6efa73ff6775e94b653b232585061ad07efdbd684
    10LINUX_ARM64_CHECKSUM=c1e03926e7f032e895b25e320f490c3ea696e505b44b27cb5b9014bcd24c4d16
    11
    12# Downloads file at URL to destination path using wget or curl. Prints an error and exits if wget or curl is not present.
    13function download {
    14    local url=$1
    15    local dst=$2
    16
    17    # determine whether wget, curl or both are present
    18    set +e
    19    command -v wget >/dev/null 2>&1
    20    local wget_exists=$?
    21    command -v curl >/dev/null 2>&1
    22    local curl_exists=$?
    23    set -e
    24
    25    # if one of wget or curl is not present, exit with error
    26    if [ "$wget_exists" -ne 0 -a "$curl_exists" -ne 0 ]; then
    27        echo "wget or curl must be present to download distribution. Install one of these programs and try again or install the distribution manually."
    28        exit 1
    29    fi
    30
    31    if [ "$wget_exists" -eq 0 ]; then
    32        # attempt download using wget
    33        echo "Downloading $url to $dst..."
    34        local progress_opt=""
    35        if wget --help | grep -q '\--show-progress'; then
    36            progress_opt="-q --show-progress"
    37        fi
    38        set +e
    39        wget -O "$dst" $progress_opt "$url"
    40        rv=$?
    41        set -e
    42        if [ "$rv" -eq 0 ]; then
    43            # success
    44            return
    45        fi
    46
    47        echo "Download failed using command: wget -O $dst $progress_opt $url"
    48
    49        # curl does not exist, so nothing more to try: exit
    50        if [ "$curl_exists" -ne 0 ]; then
    51            echo "Download failed using wget and curl was not found. Verify that the distribution URL is correct and try again or install the distribution manually."
    52            exit 1
    53        fi
    54        # curl exists, notify that download will be attempted using curl
    55        echo "Attempting download using curl..."
    56    fi
    57
    58    # attempt download using curl
    59    echo "Downloading $url to $dst..."
    60    set +e
    61    curl -f -L -o "$dst" "$url"
    62    rv=$?
    63    set -e
    64    if [ "$rv" -ne 0 ]; then
    65        echo "Download failed using command: curl -f -L -o $dst $url"
    66        if [ "$wget_exists" -eq 0 ]; then
    67            echo "Download failed using wget and curl. Verify that the distribution URL is correct and try again or install the distribution manually."
    68        else
    69            echo "Download failed using curl and wget was not found. Verify that the distribution URL is correct and try again or install the distribution manually."
    70        fi
    71        exit 1
    72    fi
    73}
    74
    75# verifies that the provided checksum matches the computed SHA-256 checksum of the specified file. If not, echoes an
    76# error and exits.
    77function verify_checksum {
    78    local file=$1
    79    local expected_checksum=$2
    80    local computed_checksum=$(compute_sha256 $file)
    81    if [ "$expected_checksum" != "$computed_checksum" ]; then
    82        echo "SHA-256 checksum for $file did not match expected value."
    83        echo "Expected: $expected_checksum"
    84        echo "Actual:   $computed_checksum"
    85        exit 1
    86    fi
    87}
    88
    89# computes the SHA-256 hash of the provided file. Uses openssl, shasum or sha1sum program.
    90function compute_sha256 {
    91    local file=$1
    92    if command -v openssl >/dev/null 2>&1; then
    93        # print SHA-256 hash using openssl
    94        openssl dgst -sha256 "$file" | sed -E 's/SHA256\(.*\)= //'
    95    elif command -v shasum >/dev/null 2>&1; then
    96        # Darwin systems ship with "shasum" utility
    97        shasum -a 256 "$file" | sed -E 's/[[:space:]]+.+//'
    98    elif command -v sha256sum >/dev/null 2>&1; then
    99        # Most Linux systems ship with sha256sum utility
   100        sha256sum "$file" | sed -E 's/[[:space:]]+.+//'
   101    else
   102        echo "Could not find program to calculate SHA-256 checksum for file"
   103        exit 1
   104    fi
   105}
   106
   107# Verifies that the tgz file at the provided path contains the paths/files that would be expected in a valid gödel
   108# distribution with the provided version.
   109function verify_dist_tgz_valid {
   110    local tgz_path=$1
   111    local version=$2
   112
   113    local expected_paths=("godel-$version/" "godel-$version/bin/darwin-amd64/godel" "godel-$version/bin/darwin-arm64/godel" "godel-$version/bin/linux-amd64/godel" "godel-$version/bin/linux-arm64/godel" "godel-$version/wrapper/godelw" "godel-$version/wrapper/godel/config/")
   114    local files=($(tar -tf "$tgz_path"))
   115
   116    # this is a double-for loop, but fine since $expected_paths is small and bash doesn't have good primitives for set/map/list manipulation
   117    for curr_line in "${files[@]}"; do
   118        # if all expected paths have been found, terminate
   119        if [[ ${#expected_paths[*]} == 0 ]]; then
   120            break
   121        fi
   122
   123        # check for expected path and splice out if match is found
   124        idx=0
   125        for curr_expected in "${expected_paths[@]}"; do
   126            if [ "$curr_expected" = "$curr_line" ]; then
   127                expected_paths=(${expected_paths[@]:0:idx} ${expected_paths[@]:$(($idx + 1))})
   128                break
   129            fi
   130            idx=$idx+1
   131        done
   132    done
   133
   134    # if any expected paths still remain, raise error and exit
   135    if [[ ${#expected_paths[*]} > 0 ]]; then
   136        echo "Required paths were not present in $tgz_path: ${expected_paths[@]}"
   137        exit 1
   138    fi
   139}
   140
   141# Verifies that the gödel binary in the distribution reports the expected version when called with the "version"
   142# argument. Assumes that a valid gödel distribution directory for the given version exists in the provided directory.
   143function verify_godel_version {
   144    local base_dir=$1
   145    local version=$2
   146    local os=$3
   147    local arch=$4
   148
   149    local expected_output="godel version $version"
   150    local version_output=$($base_dir/godel-$version/bin/$os-$arch/godel version)
   151
   152    if [ "$expected_output" != "$version_output" ]; then
   153        echo "Version reported by godel executable did not match expected version: expected \"$expected_output\", was \"$version_output\""
   154        exit 1
   155    fi
   156}
   157
   158# directory of godelw script
   159SCRIPT_HOME=$(cd "$(dirname "$0")" && pwd)
   160
   161# use $GODEL_HOME or default value
   162GODEL_BASE_DIR=${GODEL_HOME:-$HOME/.godel}
   163
   164# determine OS
   165OS=""
   166EXPECTED_CHECKSUM=""
   167case "$(uname)-$(uname -m)" in
   168    Darwin-x86_64)
   169        OS=darwin
   170        ARCH=amd64
   171        EXPECTED_CHECKSUM=$DARWIN_AMD64_CHECKSUM
   172        ;;
   173    Darwin-arm64)
   174        OS=darwin
   175        ARCH=arm64
   176        EXPECTED_CHECKSUM=$DARWIN_ARM64_CHECKSUM
   177        ;;
   178    Linux-x86_64)
   179        OS=linux
   180        ARCH=amd64
   181        EXPECTED_CHECKSUM=$LINUX_AMD64_CHECKSUM
   182        ;;
   183    Linux-aarch64)
   184        OS=linux
   185        ARCH=arm64
   186        EXPECTED_CHECKSUM=$LINUX_ARM64_CHECKSUM
   187        ;;
   188    *)
   189        echo "Unsupported operating system-architecture: $(uname)-$(uname -m)"
   190        exit 1
   191        ;;
   192esac
   193
   194# path to godel binary
   195CMD=$GODEL_BASE_DIR/dists/godel-$VERSION/bin/$OS-$ARCH/godel
   196
   197# godel binary is not present -- download distribution
   198if [ ! -f "$CMD" ]; then
   199    # get download URL
   200    PROPERTIES_FILE=$SCRIPT_HOME/godel/config/godel.properties
   201    if [ ! -f "$PROPERTIES_FILE" ]; then
   202        echo "Properties file must exist at $PROPERTIES_FILE"
   203        exit 1
   204    fi
   205    DOWNLOAD_URL=$(cat "$PROPERTIES_FILE" | sed -E -n "s/^distributionURL=//p")
   206    if [ -z "$DOWNLOAD_URL" ]; then
   207        echo "Value for property \"distributionURL\" was empty in $PROPERTIES_FILE"
   208        exit 1
   209    fi
   210    DOWNLOAD_CHECKSUM=$(cat "$PROPERTIES_FILE" | sed -E -n "s/^distributionSHA256=//p")
   211
   212    # create downloads directory if it does not already exist
   213    mkdir -p "$GODEL_BASE_DIR/downloads"
   214
   215    # download tgz and verify its contents
   216    # Download to unique location that includes PID ($$) and use trap ensure that temporary download file is cleaned up
   217    # if script is terminated before the file is moved to its destination.
   218    DOWNLOAD_DST=$GODEL_BASE_DIR/downloads/godel-$VERSION-$$.tgz
   219    download "$DOWNLOAD_URL" "$DOWNLOAD_DST"
   220    trap 'rm -rf "$DOWNLOAD_DST"' EXIT
   221    if [ -n "$DOWNLOAD_CHECKSUM" ]; then
   222        verify_checksum "$DOWNLOAD_DST" "$DOWNLOAD_CHECKSUM"
   223    fi
   224    verify_dist_tgz_valid "$DOWNLOAD_DST" "$VERSION"
   225
   226    # create temporary directory for unarchiving, unarchive downloaded file and verify directory
   227    TMP_DIST_DIR=$(mktemp -d "$GODEL_BASE_DIR/tmp_XXXXXX" 2>/dev/null || mktemp -d -t "$GODEL_BASE_DIR/tmp_XXXXXX")
   228    trap 'rm -rf "$TMP_DIST_DIR"' EXIT
   229    tar zxvf "$DOWNLOAD_DST" -C "$TMP_DIST_DIR" >/dev/null 2>&1
   230    verify_godel_version "$TMP_DIST_DIR" "$VERSION" "$OS" "$ARCH"
   231
   232    # rename downloaded file to remove PID portion
   233    mv "$DOWNLOAD_DST" "$GODEL_BASE_DIR/downloads/godel-$VERSION.tgz"
   234
   235    # if destination directory for distribution already exists, remove it
   236    if [ -d "$GODEL_BASE_DIR/dists/godel-$VERSION" ]; then
   237        rm -rf "$GODEL_BASE_DIR/dists/godel-$VERSION"
   238    fi
   239
   240    # ensure that parent directory of destination exists
   241    mkdir -p "$GODEL_BASE_DIR/dists"
   242
   243    # move expanded distribution directory to destination location. The location of the unarchived directory is known to
   244    # be in the same directory tree as the destination, so "mv" should always work.
   245    mv "$TMP_DIST_DIR/godel-$VERSION" "$GODEL_BASE_DIR/dists/godel-$VERSION"
   246
   247    # edge case cleanup: if the destination directory "$GODEL_BASE_DIR/dists/godel-$VERSION" was created prior to the
   248    # "mv" operation above, then the move operation will move the source directory into the destination directory. In
   249    # this case, remove the directory. It should always be safe to remove this directory because if the directory
   250    # existed in the distribution and was non-empty, then the move operation would fail (because non-empty directories
   251    # cannot be overwritten by mv). All distributions of a given version are also assumed to be identical. The only
   252    # instance in which this would not work is if the distribution purposely contained an empty directory that matched
   253    # the name "godel-$VERSION", and this is assumed to never be true.
   254    if [ -d "$GODEL_BASE_DIR/dists/godel-$VERSION/godel-$VERSION" ]; then
   255        rm -rf "$GODEL_BASE_DIR/dists/godel-$VERSION/godel-$VERSION"
   256    fi
   257fi
   258
   259verify_checksum "$CMD" "$EXPECTED_CHECKSUM"
   260
   261# execute command
   262$CMD --wrapper "$SCRIPT_HOME/$(basename "$0")" "$@"

View as plain text