mirror of
https://chromium.googlesource.com/chromium/tools/depot_tools.git
synced 2026-01-11 18:51:29 +00:00
Signed-off-by: Rebecca Chang Swee Fun <rebecca.chang@starfivetech.com> Bug: 1331190 Change-Id: I7c751e5cf02f088f2145c3c701547f0412f2bd69 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/3686858 Reviewed-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Robbie Iannucci <iannucci@chromium.org> Commit-Queue: Robbie Iannucci <iannucci@chromium.org>
280 lines
7.8 KiB
Bash
Executable File
280 lines
7.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
|
||
# Copyright (c) 2016 The Chromium Authors. All rights reserved.
|
||
# Use of this source code is governed by a BSD-style license that can be
|
||
# found in the LICENSE file.
|
||
|
||
set -e -o pipefail
|
||
|
||
MYPATH=$(dirname "${BASH_SOURCE[0]}")
|
||
CYGWIN=false
|
||
|
||
# Make sure this starts empty
|
||
ARCH=
|
||
|
||
UNAME=`uname -s | tr '[:upper:]' '[:lower:]'`
|
||
case "${UNAME}" in
|
||
aix)
|
||
OS="${UNAME}"
|
||
ARCH="ppc64" # apparently 'uname -m' returns something very different
|
||
;;
|
||
linux)
|
||
OS="${UNAME}"
|
||
;;
|
||
cygwin*)
|
||
OS=windows
|
||
CYGWIN=true
|
||
;;
|
||
msys*|mingw*)
|
||
OS=windows
|
||
;;
|
||
darwin)
|
||
OS=mac
|
||
;;
|
||
*)
|
||
>&2 echo "CIPD not supported on ${UNAME}"
|
||
exit 1
|
||
esac
|
||
|
||
|
||
if [ -z $ARCH ]; then
|
||
UNAME=`uname -m | tr '[:upper:]' '[:lower:]'`
|
||
case "${UNAME}" in
|
||
x86_64|amd64)
|
||
ARCH=amd64
|
||
# Check if Mac ARM running under Rosetta
|
||
if [ $OS == 'mac' ]; then
|
||
TRANSLATED=`/usr/sbin/sysctl -n sysctl.proc_translated 2> /dev/null || echo 0`
|
||
if [ $TRANSLATED == "1" ]; then
|
||
ARCH="arm64"
|
||
fi
|
||
fi
|
||
;;
|
||
s390x|ppc64|ppc64le) # best-effort support
|
||
ARCH="${UNAME}"
|
||
;;
|
||
aarch64)
|
||
ARCH=arm64
|
||
;;
|
||
armv7l)
|
||
ARCH=armv6l
|
||
;;
|
||
arm*)
|
||
ARCH="${UNAME}"
|
||
;;
|
||
*86)
|
||
ARCH=386
|
||
;;
|
||
mips*)
|
||
# detect mips64le vs mips64.
|
||
ARCH="${UNAME}"
|
||
if lscpu | grep -q "Little Endian"; then
|
||
ARCH+=le
|
||
fi
|
||
;;
|
||
riscv64)
|
||
ARCH=riscv64
|
||
;;
|
||
*)
|
||
>&2 echo "UNKNOWN Machine architecture: ${UNAME}"
|
||
exit 1
|
||
esac
|
||
fi
|
||
|
||
# CIPD_BACKEND can be changed to ...-dev for manual testing.
|
||
CIPD_BACKEND="https://chrome-infra-packages.appspot.com"
|
||
VERSION_FILE="${MYPATH}/cipd_client_version"
|
||
|
||
CLIENT="${MYPATH}/.cipd_client"
|
||
VERSION=`cat "${VERSION_FILE}"`
|
||
PLATFORM="${OS}-${ARCH}"
|
||
|
||
# A value in .cipd_client_platform overrides the "guessed" platform.
|
||
PLATFORM_OVERRIDE_FILE="${MYPATH}/.cipd_client_platform"
|
||
if [ -f "${PLATFORM_OVERRIDE_FILE}" ]; then
|
||
PLATFORM=`cat ${PLATFORM_OVERRIDE_FILE}`
|
||
fi
|
||
|
||
URL="${CIPD_BACKEND}/client?platform=${PLATFORM}&version=${VERSION}"
|
||
USER_AGENT="depot_tools/$(git -C ${MYPATH} rev-parse HEAD 2>/dev/null || echo "???")"
|
||
|
||
|
||
# calc_sha256 is "portable" variant of sha256sum. It uses sha256sum when
|
||
# available (most Linuxes and cygwin) and 'shasum -a 256' otherwise (for OSX).
|
||
#
|
||
# Args:
|
||
# Path to a file.
|
||
# Stdout:
|
||
# Lowercase SHA256 hex digest of the file.
|
||
function calc_sha256() {
|
||
if hash sha256sum 2> /dev/null ; then
|
||
sha256sum "$1" | cut -d' ' -f1
|
||
elif hash shasum 2> /dev/null ; then
|
||
shasum -a 256 "$1" | cut -d' ' -f1
|
||
else
|
||
>&2 echo -n "[31;1m"
|
||
>&2 echo -n "Don't know how to calculate SHA256 on your platform. "
|
||
>&2 echo -n "Please use your package manager to install one before continuing:"
|
||
>&2 echo
|
||
>&2 echo " sha256sum"
|
||
>&2 echo -n " shasum"
|
||
>&2 echo "[0m"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
|
||
# expected_sha256 reads the expected SHA256 hex digest from *.digests file.
|
||
#
|
||
# Args:
|
||
# Name of the platform to get client's digest for.
|
||
# Stdout:
|
||
# Lowercase SHA256 hex digest.
|
||
function expected_sha256() {
|
||
local line
|
||
while read -r line; do
|
||
if [[ "${line}" =~ ^([0-9a-z\-]+)[[:blank:]]+sha256[[:blank:]]+([0-9a-f]+)$ ]] ; then
|
||
local plat="${BASH_REMATCH[1]}"
|
||
local hash="${BASH_REMATCH[2]}"
|
||
if [ "${plat}" == "$1" ]; then
|
||
echo "${hash}"
|
||
return 0
|
||
fi
|
||
fi
|
||
done < "${VERSION_FILE}.digests"
|
||
|
||
>&2 echo -n "[31;1m"
|
||
>&2 echo -n "Platform $1 is not supported by the CIPD client bootstrap: "
|
||
>&2 echo -n "there's no pinned SHA256 hash for it in the *.digests file."
|
||
>&2 echo "[0m"
|
||
|
||
return 1
|
||
}
|
||
|
||
|
||
# clean_bootstrap bootstraps the client from scratch using 'curl' or 'wget'.
|
||
#
|
||
# It checks that the SHA256 of the downloaded file is known. Exits the script
|
||
# if the client can't be downloaded or its hash doesn't match the expected one.
|
||
function clean_bootstrap() {
|
||
local expected_hash=$(expected_sha256 "${PLATFORM}")
|
||
if [ -z "${expected_hash}" ] ; then
|
||
exit 1
|
||
fi
|
||
|
||
# Download the client into a temporary file, check its hash, then move it into
|
||
# the final location.
|
||
#
|
||
# This wonky tempdir method works on Linux and Mac.
|
||
local CIPD_CLIENT_TMP=$(\
|
||
mktemp -p "${MYPATH}" 2>/dev/null || \
|
||
mktemp "${MYPATH}/.cipd_client.XXXXXXX")
|
||
|
||
if hash curl 2> /dev/null ; then
|
||
curl "${URL}" -s --show-error -f --retry 3 --retry-delay 5 -A "${USER_AGENT}" -L -o "${CIPD_CLIENT_TMP}"
|
||
elif hash wget 2> /dev/null ; then
|
||
wget "${URL}" -q -t 3 -w 5 --retry-connrefused -U "${USER_AGENT}" -O "${CIPD_CLIENT_TMP}"
|
||
else
|
||
>&2 echo -n "[31;1m"
|
||
>&2 echo -n "Your platform is missing a supported fetch command. "
|
||
>&2 echo "Please use your package manager to install one before continuing:"
|
||
>&2 echo
|
||
>&2 echo " curl"
|
||
>&2 echo " wget"
|
||
>&2 echo
|
||
>&2 echo "Alternately, manually download:"
|
||
>&2 echo " ${URL}"
|
||
>&2 echo -n "To ${CLIENT}, and then re-run this command."
|
||
>&2 echo "[0m"
|
||
rm "${CIPD_CLIENT_TMP}"
|
||
exit 1
|
||
fi
|
||
|
||
local actual_hash=$(calc_sha256 "${CIPD_CLIENT_TMP}")
|
||
if [ -z "${actual_hash}" ] ; then
|
||
rm "${CIPD_CLIENT_TMP}"
|
||
exit 1
|
||
fi
|
||
|
||
if [ "${actual_hash}" != "${expected_hash}" ]; then
|
||
>&2 echo -n "[31;1m"
|
||
>&2 echo "SHA256 digest of the downloaded CIPD client is incorrect:"
|
||
>&2 echo " Expecting ${expected_hash}"
|
||
>&2 echo " Got ${actual_hash}"
|
||
>&2 echo -n "Refusing to run it. Check that *.digests file is up-to-date."
|
||
>&2 echo "[0m"
|
||
rm "${CIPD_CLIENT_TMP}"
|
||
exit 1
|
||
fi
|
||
|
||
set +e
|
||
chmod +x "${CIPD_CLIENT_TMP}"
|
||
mv "${CIPD_CLIENT_TMP}" "${CLIENT}"
|
||
set -e
|
||
}
|
||
|
||
|
||
# self_update launches CIPD client's built-in selfupdate mechanism.
|
||
#
|
||
# It is more efficient that redownloading the binary all the time.
|
||
function self_update() {
|
||
"${CLIENT}" selfupdate -version-file "${VERSION_FILE}" -service-url "${CIPD_BACKEND}"
|
||
}
|
||
|
||
|
||
# Nuke the existing client if its platform doesn't match what we want now. We
|
||
# crudely search for a CIPD client package name in the .cipd_version JSON file.
|
||
# It has only "instance_id" as the other field (looking like a base64 string),
|
||
# so mismatches are very unlikely.
|
||
INSTALLED_VERSION_FILE="${MYPATH}/.versions/.cipd_client.cipd_version"
|
||
if [ -f "${INSTALLED_VERSION_FILE}" ]; then
|
||
JSON_BODY=`cat "${INSTALLED_VERSION_FILE}"`
|
||
if [[ "$JSON_BODY" != *"infra/tools/cipd/${PLATFORM}"* ]]; then
|
||
>&2 echo "Detected CIPD client platform change to ${PLATFORM}."
|
||
>&2 echo "Deleting the existing client to trigger the bootstrap..."
|
||
rm -f "${CLIENT}" "${INSTALLED_VERSION_FILE}"
|
||
fi
|
||
fi
|
||
|
||
# If the client binary doesn't exist, do the bootstrap from scratch.
|
||
if [ ! -x "${CLIENT}" ]; then
|
||
clean_bootstrap
|
||
fi
|
||
|
||
# If the client binary exists, ask it to self-update.
|
||
export CIPD_HTTP_USER_AGENT_PREFIX="${USER_AGENT}"
|
||
if ! self_update 2> /dev/null ; then
|
||
>&2 echo -n "[31;1m"
|
||
>&2 echo -n "CIPD selfupdate failed. "
|
||
>&2 echo -n "Trying to bootstrap the CIPD client from scratch..."
|
||
>&2 echo "[0m"
|
||
clean_bootstrap
|
||
if ! self_update ; then # need to run it again to setup .cipd_version file
|
||
>&2 echo -n "[31;1m"
|
||
>&2 echo -n "Bootstrap from scratch for ${PLATFORM} failed! "
|
||
>&2 echo "Run the following commands to diagnose if this is repeating:"
|
||
>&2 echo " export CIPD_HTTP_USER_AGENT_PREFIX=${USER_AGENT}/manual"
|
||
>&2 echo -n " ${CLIENT} selfupdate -version-file ${VERSION_FILE}"
|
||
>&2 echo "[0m"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# CygWin requires changing absolute paths to Windows form. Relative paths
|
||
# are typically okay as Windows generally accepts both forward and back
|
||
# slashes. This could possibly be constrained to only /tmp/ and /cygdrive/.
|
||
if ${CYGWIN}; then
|
||
args=("$@")
|
||
for i in `seq 2 $#`; do
|
||
arg="${@:$i:1}"
|
||
if [ "${arg:0:1}" == "/" ]; then
|
||
last=$((i-1))
|
||
next=$((i+1))
|
||
set -- "${@:1:$last}" `cygpath -w "$arg"` "${@:$next}"
|
||
fi
|
||
done
|
||
echo "${CLIENT}" "${@}"
|
||
fi
|
||
|
||
exec "${CLIENT}" "${@}"
|