Make prebuilt more self-contained by having it fetch cipd itself.

This is almost entirely copied from //buildtools/.

The main difference is I have the cipd bootstrap script copy the cipd
client binary into the tools subdirectory, which I think is useful since
most users of this repo will add that subdirectory to their PATH and
it's useful to have the cipd tool in the PATH, too.

Change-Id: I3fba8e42ea08fc19d54985157fded3085cd6ab6e
diff --git a/.cipd_version b/.cipd_version
new file mode 100644
index 0000000..c93947c
--- /dev/null
+++ b/.cipd_version
@@ -0,0 +1 @@
+git_revision:fb963f0f43e265a65fb7f1f202e17ea23e947063
diff --git a/.cipd_version.digests b/.cipd_version.digests
new file mode 100644
index 0000000..45ba466
--- /dev/null
+++ b/.cipd_version.digests
@@ -0,0 +1,21 @@
+# This file was generated by
+#
+#  cipd selfupdate-roll -version-file .cipd_version \
+#      -version git_revision:fb963f0f43e265a65fb7f1f202e17ea23e947063
+#
+# Do not modify manually. All changes will be overwritten.
+# Use 'cipd selfupdate-roll ...' to modify.
+
+linux-386       sha256  4e488d22d03e44fb1c24bbe192575970b3898ba5fc3d3ac9751545ee90b727e5
+linux-amd64     sha256  f6bd33252d7f9eb93718b2808b66db012416c0bd0b7ba4670d3f56670782f07a
+linux-arm64     sha256  233c24311443873ec14d96d0f8e3a70a533f1ee4cb36c26fad1fd127834a28d9
+linux-armv6l    sha256  1b5c6eea7fa4cabb7b82bb8666b3762b5e50bbe4ed39c1321b89927faebb4b0a
+linux-mips64    sha256  0e7863521601eb5581c2a00440797f04413c3f8da6392d3429289c06ff8aadcf
+linux-mips64le  sha256  09cabd05ce48dee62f5cb516ca1f4eca9986dcb5880f6af7dd28c324dd000b0e
+linux-mipsle    sha256  e229160b2b46cd6b8cf9d8343a85d5d00dd11e72574913353bd76c76dfee4ebd
+linux-ppc64     sha256  79c075c274b8d0be000b35bcec40f73ed50b0354ab4d99536fbb011c5dc1986b
+linux-ppc64le   sha256  32c486e6c06361b40e0c42ef6645591dd988000e4ec8f004ea43255b4c9b3628
+linux-s390x     sha256  80d990b0c69b522d563f7e367dda0987e6bb1936d6ca2ae33d985ed706cb661b
+mac-amd64       sha256  525186502934af16f8fe5c4cf35588b3886285043c269c63d937c2d780639139
+windows-386     sha256  8baf18b295cd377265e021a026b978c82833b0e62944a6050ce735a6a1652008
+windows-amd64   sha256  b7b31cfd3f6bb8e0bc3fdb1c394987ce0a2a785f4dd9b850f45b1199f9a97e72
diff --git a/cipd.sh b/cipd.sh
new file mode 100755
index 0000000..d3307e3
--- /dev/null
+++ b/cipd.sh
@@ -0,0 +1,131 @@
+#!/usr/bin/env bash
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script installs cipd in ./tools/ and then executes it, passing through
+# all arguments.
+
+set -eo pipefail; [[ "${TRACE}" ]] && set -x
+
+readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+readonly VERSION_FILE="${SCRIPT_DIR}/.cipd_version"
+readonly CIPD_BACKEND="https://chrome-infra-packages.appspot.com"
+
+declare HOST_PLATFORM="$(uname -s | tr '[:upper:]' '[:lower:]')"
+case "${HOST_PLATFORM}" in
+  linux)
+    readonly HOST_PLATFORM="linux"
+    ;;
+  darwin)
+    readonly HOST_PLATFORM="mac"
+    ;;
+  *)
+    echo "Unknown operating system." >&2
+    exit 1
+esac
+
+HOST_ARCH="$(uname -m | tr '[:upper:]' '[:lower:]')"
+case "${HOST_ARCH}" in
+  x86_64|amd64)
+    readonly HOST_ARCH="amd64"
+    ;;
+  arm*)
+    readonly HOST_ARCH="${HOST_ARCH}"
+    ;;
+  *86)
+    readonly HOST_ARCH=386
+    ;;
+  *)
+    echo "Unknown machine architecture." >&2
+    exit 1
+esac
+
+readonly PLATFORM="${HOST_PLATFORM}-${HOST_ARCH}"
+readonly VERSION="$(cat ${VERSION_FILE})"
+readonly URL="${CIPD_BACKEND}/client?platform=${PLATFORM}&version=${VERSION}"
+# Put it in tools so that users can easily get it in their PATH.
+readonly CLIENT="${SCRIPT_DIR}/tools/cipd"
+
+readonly USER_AGENT="fuchsia-infra/prebuilt/$(git -C ${SCRIPT_DIR} rev-parse HEAD 2>/dev/null || echo "???")"
+
+function actual_sha256() {
+  if type shasum >/dev/null ; then
+    shasum -a 256 "$1" | cut -d' ' -f1
+  else
+    echo "The \`shasum\` command is missing. Please use your package manager to install it." >&2
+    return 1
+  fi
+}
+
+function expected_sha256() {
+  local line
+  while read -r line; do
+    if [[ "${line}" =~ ^([0-9a-z\-]+)[[:blank:]]+sha256[[:blank:]]+([0-9a-f]+)$ ]] ; then
+      local platform="${BASH_REMATCH[1]}"
+      local hash="${BASH_REMATCH[2]}"
+      if [[ "${platform}" ==  "$1" ]]; then
+        echo "${hash}"
+        return 0
+      fi
+    fi
+  done < "${VERSION_FILE}.digests"
+
+  echo "Platform $1 is not supported by the CIPD client bootstrap. There's no pinned hash for it in the *.digests file." >&2
+
+  return 1
+}
+
+# bootstraps the client from scratch using 'curl'.
+function bootstrap() {
+  local expected_hash="$(expected_sha256 "${PLATFORM}")"
+  if [[ -z "${expected_hash}" ]] ; then
+    exit 1
+  fi
+
+  echo "Bootstrapping cipd client for ${HOST_PLATFORM}-${HOST_ARCH}..."
+  local CLIENT_TMP="$(mktemp -p "${SCRIPT_DIR}" 2>/dev/null || mktemp "${SCRIPT_DIR}/.cipd_client.XXXXXXX")"
+  if type curl >/dev/null ; then
+    curl -f --progress-bar "${URL}" -A "${USER_AGENT}"  -L -o "${CLIENT_TMP}"
+  else
+    echo "The \`curl\` command is missing. Please use your package manager to install it." >&2
+    exit 1
+  fi
+  trap "rm -f '${CLIENT_TMP}'" EXIT ERR HUP INT TERM
+
+  local actual_hash="$(actual_sha256 "${CLIENT_TMP}")"
+  if [[ -z "${actual_hash}" ]] ; then
+    exit 1
+  fi
+
+  if [[ "${actual_hash}" != "${expected_hash}" ]]; then
+    echo "SHA256 digest of the downloaded CIPD client is incorrect. Check that *.digests file is up-to-date." >&2
+    exit 1
+  fi
+
+  chmod +x "${CLIENT_TMP}"
+  mkdir -p $(dirname ${CLIENT})
+  mv -f "${CLIENT_TMP}" "${CLIENT}"
+  trap - EXIT
+}
+
+# self_update asks the existing client to update itself, if necessary.
+function self_update() {
+  "${CLIENT}" selfupdate -version-file "${VERSION_FILE}" -service-url "${CIPD_BACKEND}"
+}
+
+if [[ ! -x "${CLIENT}" ]]; then
+  bootstrap
+fi
+
+export CIPD_HTTP_USER_AGENT_PREFIX="${USER_AGENT}"
+if ! self_update ; then
+  echo "CIPD selfupdate failed. Trying to bootstrap the CIPD client from scratch..." >&2
+  bootstrap
+  if ! self_update ; then  # we need to run it again to setup .cipd_version file
+    echo "Bootstrap from scratch failed. Run \`CIPD_HTTP_USER_AGENT_PREFIX=${USER_AGENT}/manual ${CLIENT} selfupdate -version-file '${VERSION_FILE}'\` to diagnose if this is repeating." >&2
+  fi
+fi
+
+exec "${CLIENT}" "${@}"
diff --git a/update.sh b/update.sh
index c001232..041918a 100755
--- a/update.sh
+++ b/update.sh
@@ -10,11 +10,5 @@
 
 readonly SCRIPT_ROOT="$(cd $(dirname ${BASH_SOURCE[0]} ) && pwd)"
 
-if ! which cipd > /dev/null; then
-  echo "cipd must be in the PATH. See\
-  https://fuchsia.googlesource.com/infra/recipes/+/master/README.md"
-  exit 1
-fi
-
-cipd ensure -ensure-file "${SCRIPT_ROOT}/cipd.ensure" -root "${SCRIPT_ROOT}" \
+"${SCRIPT_ROOT}/cipd.sh" ensure -ensure-file "${SCRIPT_ROOT}/cipd.ensure" -root "${SCRIPT_ROOT}" \
   -log-level warning