Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 1 | #!/bin/bash -e |
| 2 | |
| 3 | # Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 4 | # Use of this source code is governed by a BSD-style license that can be |
| 5 | # found in the LICENSE file. |
| 6 | |
Dan Jacques | e82c0de | 2017-07-05 18:10:23 -0700 | [diff] [blame] | 7 | set -e -o pipefail |
| 8 | |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 9 | MYPATH=$(dirname "${BASH_SOURCE[0]}") |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 10 | CYGWIN=false |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 11 | |
| 12 | UNAME=`uname -s | tr '[:upper:]' '[:lower:]'` |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 13 | case "${UNAME}" in |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 14 | linux) |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 15 | OS=linux |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 16 | ;; |
Brian White | 361822c | 2018-04-04 15:21:45 -0400 | [diff] [blame] | 17 | cygwin*) |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 18 | OS=windows |
Brian White | 361822c | 2018-04-04 15:21:45 -0400 | [diff] [blame] | 19 | CYGWIN=true |
| 20 | ;; |
| 21 | msys*|mingw*) |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 22 | OS=windows |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 23 | ;; |
| 24 | darwin) |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 25 | OS=mac |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 26 | ;; |
| 27 | *) |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 28 | >&2 echo "CIPD not supported on ${UNAME}" |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 29 | exit 1 |
| 30 | esac |
| 31 | |
| 32 | UNAME=`uname -m | tr '[:upper:]' '[:lower:]'` |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 33 | case "${UNAME}" in |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 34 | x86_64|amd64) |
| 35 | ARCH=amd64 |
| 36 | ;; |
Robert Iannucci | ff2bf09 | 2017-09-11 16:27:26 -0700 | [diff] [blame] | 37 | s390x) # best-effort support for IBM s390x: crbug.com/764087 |
| 38 | ARCH=s390x |
| 39 | ;; |
Dan Jacques | 6342128 | 2017-10-16 15:05:59 -0400 | [diff] [blame] | 40 | ppc64) # best-effort support for 64-bit PowerPC: crbug.com/773857 |
| 41 | ARCH=ppc64 |
| 42 | ;; |
Dan Jacques | 1e0b7a5 | 2017-10-17 11:19:18 -0400 | [diff] [blame] | 43 | ppc64le) # best-effort support for 64-bit PowerPC/LE: crbug.com/773857 |
Dan Jacques | 6342128 | 2017-10-16 15:05:59 -0400 | [diff] [blame] | 44 | ARCH=ppc64le |
| 45 | ;; |
William Hesse | 6fd2484 | 2017-10-10 13:55:22 +0200 | [diff] [blame] | 46 | aarch64) |
| 47 | ARCH=arm64 |
| 48 | ;; |
Benjamin Pastene | e346e41 | 2017-10-20 12:57:43 -0700 | [diff] [blame] | 49 | armv7l) |
| 50 | ARCH=armv6l |
| 51 | ;; |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 52 | arm*) |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 53 | ARCH="${UNAME}" |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 54 | ;; |
| 55 | *86) |
| 56 | ARCH=386 |
| 57 | ;; |
Wang Qing | 254538b | 2018-07-26 02:23:53 +0000 | [diff] [blame] | 58 | mips*) |
Wang Qing | 82bb756 | 2018-08-03 21:45:46 +0000 | [diff] [blame] | 59 | # detect mips64le vs mips64. |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 60 | ARCH="${UNAME}" |
Wang Qing | 82bb756 | 2018-08-03 21:45:46 +0000 | [diff] [blame] | 61 | if lscpu | grep -q "Little Endian"; then |
| 62 | ARCH+=le |
| 63 | fi |
Wang Qing | 254538b | 2018-07-26 02:23:53 +0000 | [diff] [blame] | 64 | ;; |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 65 | *) |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 66 | >&2 echo "UNKNOWN Machine architecture: ${UNAME}" |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 67 | exit 1 |
| 68 | esac |
| 69 | |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 70 | # CIPD_BACKEND can be changed to ...-dev for manual testing. |
| 71 | CIPD_BACKEND="https://chrome-infra-packages.appspot.com" |
| 72 | VERSION_FILE="${MYPATH}/cipd_client_version" |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 73 | |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 74 | CLIENT="${MYPATH}/.cipd_client" |
| 75 | VERSION=`cat "${VERSION_FILE}"` |
| 76 | PLATFORM="${OS}-${ARCH}" |
| 77 | |
| 78 | URL="${CIPD_BACKEND}/client?platform=${PLATFORM}&version=${VERSION}" |
| 79 | USER_AGENT="depot_tools/$(git -C ${MYPATH} rev-parse HEAD 2>/dev/null || echo "???")" |
| 80 | |
| 81 | |
| 82 | # calc_sha256 is "portable" variant of sha256sum. It uses sha256sum when |
| 83 | # available (most Linuxes and cygwin) and falls back to openssl otherwise |
| 84 | # (mostly for OSX sake). |
| 85 | # |
| 86 | # Args: |
| 87 | # Path to a file. |
| 88 | # Stdout: |
| 89 | # Lowercase SHA256 hex digest of the file. |
| 90 | function calc_sha256() { |
| 91 | if hash sha256sum 2> /dev/null ; then |
| 92 | sha256sum "$1" | cut -d' ' -f1 |
| 93 | elif hash openssl 2> /dev/null ; then |
| 94 | cat "$1" | openssl dgst -sha256 |
| 95 | else |
| 96 | >&2 echo -n "[31;1m" |
| 97 | >&2 echo -n "Don't know how to calculate SHA256 on your platform. " |
| 98 | >&2 echo -n "Please use your package manager to install one before continuing:" |
| 99 | >&2 echo |
| 100 | >&2 echo " sha256sum" |
| 101 | >&2 echo -n " openssl" |
| 102 | >&2 echo "[0m" |
| 103 | return 1 |
| 104 | fi |
| 105 | } |
| 106 | |
| 107 | |
| 108 | # expected_sha256 reads the expected SHA256 hex digest from *.digests file. |
| 109 | # |
| 110 | # Args: |
| 111 | # Name of the platform to get client's digest for. |
| 112 | # Stdout: |
| 113 | # Lowercase SHA256 hex digest. |
| 114 | function expected_sha256() { |
| 115 | local line |
| 116 | while read -r line; do |
| 117 | if [[ "${line}" =~ ^([0-9a-z\-]+)[[:blank:]]+sha256[[:blank:]]+([0-9a-f]+)$ ]] ; then |
| 118 | local plat="${BASH_REMATCH[1]}" |
| 119 | local hash="${BASH_REMATCH[2]}" |
| 120 | if [ "${plat}" == "$1" ]; then |
| 121 | echo "${hash}" |
| 122 | return 0 |
| 123 | fi |
| 124 | fi |
| 125 | done < "${VERSION_FILE}.digests" |
| 126 | |
| 127 | >&2 echo -n "[31;1m" |
| 128 | >&2 echo -n "Platform $1 is not supported by the CIPD client bootstrap: " |
| 129 | >&2 echo -n "there's no pinned SHA256 hash for it in the *.digests file." |
| 130 | >&2 echo "[0m" |
| 131 | |
| 132 | return 1 |
| 133 | } |
| 134 | |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 135 | |
Vadim Shtayura | 7e50ee3 | 2018-07-26 17:43:51 +0000 | [diff] [blame] | 136 | # clean_bootstrap bootstraps the client from scratch using 'curl' or 'wget'. |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 137 | # |
| 138 | # It checks that the SHA256 of the downloaded file is known. Exits the script |
| 139 | # if the client can't be downloaded or its hash doesn't match the expected one. |
Vadim Shtayura | 7e50ee3 | 2018-07-26 17:43:51 +0000 | [diff] [blame] | 140 | function clean_bootstrap() { |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 141 | local expected_hash=$(expected_sha256 "${PLATFORM}") |
| 142 | if [ -z "${expected_hash}" ] ; then |
| 143 | exit 1 |
| 144 | fi |
Pawel Hajdan, Jr | 8c8a0a5 | 2017-09-06 19:40:18 +0000 | [diff] [blame] | 145 | |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 146 | # Download the client into a temporary file, check its hash, then move it into |
| 147 | # the final location. |
Pawel Hajdan, Jr | 8c8a0a5 | 2017-09-06 19:40:18 +0000 | [diff] [blame] | 148 | # |
| 149 | # This wonky tempdir method works on Linux and Mac. |
Vadim Shtayura | 7e50ee3 | 2018-07-26 17:43:51 +0000 | [diff] [blame] | 150 | local CIPD_CLIENT_TMP=$(\ |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 151 | mktemp -p "${MYPATH}" 2>/dev/null || \ |
| 152 | mktemp "${MYPATH}/.cipd_client.XXXXXXX") |
Pawel Hajdan, Jr | 8c8a0a5 | 2017-09-06 19:40:18 +0000 | [diff] [blame] | 153 | |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 154 | if hash curl 2> /dev/null ; then |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 155 | curl "${URL}" -s --show-error -f -A "${USER_AGENT}" -L -o "${CIPD_CLIENT_TMP}" |
Pawel Hajdan, Jr | 8c8a0a5 | 2017-09-06 19:40:18 +0000 | [diff] [blame] | 156 | elif hash wget 2> /dev/null ; then |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 157 | wget "${URL}" -q -U "${USER_AGENT}" -O "${CIPD_CLIENT_TMP}" |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 158 | else |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 159 | >&2 echo -n "[31;1m" |
| 160 | >&2 echo -n "Your platform is missing a supported fetch command. " |
| 161 | >&2 echo "Please use your package manager to install one before continuing:" |
| 162 | >&2 echo |
| 163 | >&2 echo " curl" |
| 164 | >&2 echo " wget" |
| 165 | >&2 echo |
| 166 | >&2 echo "Alternately, manually download:" |
| 167 | >&2 echo " ${URL}" |
| 168 | >&2 echo -n "To ${CLIENT}, and then re-run this command." |
| 169 | >&2 echo "[0m" |
Pawel Hajdan, Jr | 8c8a0a5 | 2017-09-06 19:40:18 +0000 | [diff] [blame] | 170 | rm "${CIPD_CLIENT_TMP}" |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 171 | exit 1 |
| 172 | fi |
Pawel Hajdan, Jr | 8c8a0a5 | 2017-09-06 19:40:18 +0000 | [diff] [blame] | 173 | |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 174 | local actual_hash=$(calc_sha256 "${CIPD_CLIENT_TMP}") |
| 175 | if [ -z "${actual_hash}" ] ; then |
| 176 | rm "${CIPD_CLIENT_TMP}" |
| 177 | exit 1 |
| 178 | fi |
| 179 | |
| 180 | if [ "${actual_hash}" != "${expected_hash}" ]; then |
| 181 | >&2 echo -n "[31;1m" |
| 182 | >&2 echo "SHA256 digest of the downloaded CIPD client is incorrect:" |
| 183 | >&2 echo " Expecting ${expected_hash}" |
| 184 | >&2 echo " Got ${actual_hash}" |
| 185 | >&2 echo -n "Refusing to run it. Check that *.digests file is up-to-date." |
| 186 | >&2 echo "[0m" |
| 187 | rm "${CIPD_CLIENT_TMP}" |
| 188 | exit 1 |
| 189 | fi |
Pawel Hajdan, Jr | 8c8a0a5 | 2017-09-06 19:40:18 +0000 | [diff] [blame] | 190 | |
| 191 | set +e |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 192 | chmod +x "${CIPD_CLIENT_TMP}" |
| 193 | mv "${CIPD_CLIENT_TMP}" "${CLIENT}" |
Pawel Hajdan, Jr | 8c8a0a5 | 2017-09-06 19:40:18 +0000 | [diff] [blame] | 194 | set -e |
Vadim Shtayura | 7e50ee3 | 2018-07-26 17:43:51 +0000 | [diff] [blame] | 195 | } |
| 196 | |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 197 | |
| 198 | # self_update launches CIPD client's built-in selfupdate mechanism. |
| 199 | # |
| 200 | # It is more efficient that redownloading the binary all the time. |
Vadim Shtayura | 7e50ee3 | 2018-07-26 17:43:51 +0000 | [diff] [blame] | 201 | function self_update() { |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 202 | "${CLIENT}" selfupdate -version-file "${VERSION_FILE}" -service-url "${CIPD_BACKEND}" |
Vadim Shtayura | 7e50ee3 | 2018-07-26 17:43:51 +0000 | [diff] [blame] | 203 | } |
| 204 | |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 205 | |
| 206 | if [ ! -x "${CLIENT}" ]; then |
Vadim Shtayura | 7e50ee3 | 2018-07-26 17:43:51 +0000 | [diff] [blame] | 207 | clean_bootstrap |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 208 | fi |
| 209 | |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 210 | export CIPD_HTTP_USER_AGENT_PREFIX="${USER_AGENT}" |
| 211 | if ! self_update 2> /dev/null ; then |
| 212 | >&2 echo -n "[31;1m" |
| 213 | >&2 echo -n "CIPD selfupdate failed. " |
| 214 | >&2 echo -n "Trying to bootstrap the CIPD client from scratch..." |
| 215 | >&2 echo "[0m" |
Vadim Shtayura | 7e50ee3 | 2018-07-26 17:43:51 +0000 | [diff] [blame] | 216 | clean_bootstrap |
| 217 | if ! self_update ; then # need to run it again to setup .cipd_version file |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 218 | >&2 echo -n "[31;1m" |
| 219 | >&2 echo -n "Bootstrap from scratch failed, something is seriously broken. " |
| 220 | >&2 echo "Run the following commands to diagnose if this is repeating:" |
| 221 | >&2 echo " export CIPD_HTTP_USER_AGENT_PREFIX=${USER_AGENT}/manual" |
| 222 | >&2 echo -n " ${CLIENT} selfupdate -version-file ${VERSION_FILE}" |
| 223 | >&2 echo "[0m" |
| 224 | exit 1 |
Vadim Shtayura | 7e50ee3 | 2018-07-26 17:43:51 +0000 | [diff] [blame] | 225 | fi |
Robert Iannucci | 2188fe9 | 2016-12-02 11:15:57 -0800 | [diff] [blame] | 226 | fi |
| 227 | |
Brian White | 361822c | 2018-04-04 15:21:45 -0400 | [diff] [blame] | 228 | # CygWin requires changing absolute paths to Windows form. Relative paths |
| 229 | # are typically okay as Windows generally accepts both forward and back |
| 230 | # slashes. This could possibly be constrained to only /tmp/ and /cygdrive/. |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 231 | if ${CYGWIN}; then |
Brian White | 361822c | 2018-04-04 15:21:45 -0400 | [diff] [blame] | 232 | args=("$@") |
| 233 | for i in `seq 2 $#`; do |
| 234 | arg="${@:$i:1}" |
| 235 | if [ "${arg:0:1}" == "/" ]; then |
| 236 | last=$((i-1)) |
| 237 | next=$((i+1)) |
| 238 | set -- "${@:1:$last}" `cygpath -w "$arg"` "${@:$next}" |
| 239 | fi |
| 240 | done |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 241 | echo "${CLIENT}" "${@}" |
Brian White | 361822c | 2018-04-04 15:21:45 -0400 | [diff] [blame] | 242 | fi |
| 243 | |
Vadim Shtayura | eebc3d8 | 2018-08-14 20:39:46 +0000 | [diff] [blame^] | 244 | exec "${CLIENT}" "${@}" |