@ -6,34 +6,31 @@
set -e -o pipefail
CYGWIN=false
MYPATH=$(dirname "${BASH_SOURCE[0]}")
: ${CIPD_CLIENT_VER:=`cat $MYPATH/cipd_client_version`}
: ${CIPD_CLIENT_SRV:='https://chrome-infra-packages.appspot.com'}
CYGWIN=false
UNAME=`uname -s | tr '[:upper:]' '[:lower:]'`
case $UNAME in
case " ${ UNAME}" in
linux)
PLAT =linux
OS =linux
;;
cygwin*)
PLAT =windows
OS =windows
CYGWIN=true
;;
msys*|mingw*)
PLAT =windows
OS =windows
;;
darwin)
PLAT =mac
OS =mac
;;
*)
echo "cipd not supported on $UNAME "
>&2 echo "CIPD not supported on ${UNAME} "
exit 1
esac
UNAME=`uname -m | tr '[:upper:]' '[:lower:]'`
case $UNAME in
case " ${ UNAME}" in
x86_64|amd64)
ARCH=amd64
;;
@ -53,89 +50,184 @@ case $UNAME in
ARCH=armv6l
;;
arm*)
ARCH=$UNAME
ARCH=" ${ UNAME}"
;;
*86)
ARCH=386
;;
mips*)
# detect mips64le vs mips64.
ARCH=$UNAME
ARCH=" ${ UNAME}"
if lscpu | grep -q "Little Endian"; then
ARCH+=le
fi
;;
*)
echo "UNKNOWN Machine architecture: $UNAME"
>&2 echo "UNKNOWN Machine architecture: ${ UNAME} "
exit 1
esac
URL="$CIPD_CLIENT_SRV/client?platform=${PLAT}-${ARCH}&version=$CIPD_CLIENT_VER"
CLIENT="$MYPATH/.cipd_client"
# 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}"
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
}
USER_AGENT="depot_tools/$(git -C $MYPATH rev-parse HEAD 2>/dev/null || echo "???")"
# 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() {
echo "Bootstrapping cipd client for ${PLAT}-${ARCH} from ${URL}..."
local expected_hash=$(expected_sha256 "${PLATFORM}")
if [ -z "${expected_hash}" ] ; then
exit 1
fi
# Download the client into a temporary file, then move it into the final
# location atomically.
# 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")
mktemp -p "${ MYPATH} " 2>/dev/null || \
mktemp "${ MYPATH} /.cipd_client.XXXXXXX")
if hash curl 2> /dev/null ; then
curl "$URL" -s --show-error -f -A "$USER_AGENT" -L -o "$CIPD_CLIENT_TMP"
curl "${ URL} " -s --show-error -f -A "${ USER_AGENT} " -L -o "${ CIPD_CLIENT_TMP} "
elif hash wget 2> /dev/null ; then
wget "$URL" -q -U "${USER_AGENT}" -O "${CIPD_CLIENT_TMP}"
wget "${ URL} " -q -U "${USER_AGENT}" -O "${CIPD_CLIENT_TMP}"
else
echo Your platform is missing a supported fetch command. Please use your package
echo manager to install one before continuing:
echo
echo curl
echo wget
echo
echo Alternately, manually download:
echo "$URL"
echo To $CLIENT, and then re-run this command.
>&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
chmod +x "$CIPD_CLIENT_TMP"
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
mv "$CIPD_CLIENT_TMP" "$CLIENT"
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 "$CIPD_CLIENT_VER" -service-url "$CIPD_CLIENT_SRV"
"${CLIENT}" selfupdate -version-file "${VERSION_FILE}" -service-url "${CIPD_BACKEND} "
}
if [ ! -x "$CLIENT" ]; then
if [ ! -x "${CLIENT}" ]; then
clean_bootstrap
fi
export CIPD_HTTP_USER_AGENT_PREFIX=$USER_AGENT
if ! self_update ; then
echo -n " [31;1mCIPD selfupdate failed. " 1>&2
echo "Trying to bootstrap the CIPD client from scratch... [0m" 1>&2
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
echo -n " [31;1mBootstrap from scratch failed, something is seriously broken [0m " 1>&2
echo "run \`CIPD_HTTP_USER_AGENT_PREFIX=$USER_AGENT/manual $CLIENT selfupdate -version '$CIPD_CLIENT_VER'\` to diagnose if this is repeating." 1>&2
echo " [0m" 1>&2
>&2 echo -n " [31;1m"
>&2 echo -n "Bootstrap from scratch failed, something is seriously broken. "
>&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
if ${ CYGWIN} ; then
args=("$@")
for i in `seq 2 $#`; do
arg="${@:$i:1}"
@ -145,7 +237,7 @@ if $CYGWIN; then
set -- "${@:1:$last}" `cygpath -w "$arg"` "${@:$next}"
fi
done
echo "$CLIENT" "${@}"
echo "${ CLIENT} " "${@}"
fi
exec "$CLIENT" "${@}"
exec "${ CLIENT} " "${@}"