Philipp Wollermann | 19f3413 | 2015-06-12 08:39:25 +0000 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | |
Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 3 | # Copyright 2015 The Bazel Authors. All rights reserved. |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | |
| 17 | # General purpose method and values for bootstrapping bazel. |
| 18 | |
| 19 | set -o errexit |
| 20 | |
Laszlo Csomor | 5586fc1 | 2019-04-11 05:02:42 -0700 | [diff] [blame] | 21 | # Check if all necessary tools are available. |
| 22 | # List: https://github.com/bazelbuild/bazel/issues/7641#issuecomment-472344261 |
| 23 | for tool in basename cat chmod comm cp dirname find grep ln ls mkdir mktemp \ |
| 24 | readlink rm sed sort tail touch tr uname unzip which; do |
| 25 | if ! hash "$tool" >/dev/null; then |
| 26 | echo >&2 "ERROR: cannot find \"$tool\"; check your PATH." |
| 27 | echo >&2 " You may need to run the following command or similar:" |
| 28 | echo >&2 " export PATH=\"/bin:/usr/bin:\$PATH\"" |
| 29 | exit 1 |
| 30 | fi |
| 31 | done |
| 32 | |
| 33 | # Ensure Python is on the PATH on Windows, otherwise we would see |
| 34 | # "LAUNCHER ERROR" messages from py_binary exe launchers. |
| 35 | case "$(uname -s | tr "[:upper:]" "[:lower:]")" in |
| 36 | msys*|mingw*|cygwin*) |
| 37 | # Ensure Python is on the PATH, otherwise the bootstrapping fails later. |
| 38 | if ! hash python.exe >/dev/null; then |
| 39 | echo >&2 "ERROR: cannot locate python.exe; check your PATH." |
| 40 | echo >&2 " You may need to run the following command, or something" |
| 41 | echo >&2 " similar, depending on where you installed Python:" |
| 42 | echo >&2 " export PATH=\"/c/Python27:\$PATH\"" |
| 43 | exit 1 |
| 44 | fi |
| 45 | # Ensure TMPDIR uses the user-specified TMPDIR or TMP or TEMP. |
| 46 | # This is necessary to avoid overly longs paths during bootstrapping, see for |
| 47 | # example https://github.com/bazelbuild/bazel/issues/4536 |
| 48 | export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-}}}" |
| 49 | esac |
| 50 | |
Klaus Aehlig | 276a8cd | 2016-07-11 12:06:07 +0000 | [diff] [blame] | 51 | # If BAZEL_WRKDIR is set, default all variables to point into |
| 52 | # that directory |
| 53 | |
| 54 | if [ -n "${BAZEL_WRKDIR}" ] ; then |
| 55 | mkdir -p "${BAZEL_WRKDIR}/tmp" |
| 56 | mkdir -p "${BAZEL_WRKDIR}/user_root" |
| 57 | : ${TMPDIR:=${BAZEL_WRKDIR}/tmp} |
| 58 | export TMPDIR |
| 59 | : ${BAZEL_DIR_STARTUP_OPTIONS:="--output_user_root=${BAZEL_WRKDIR}/user_root"} |
| 60 | fi |
| 61 | |
| 62 | |
dmarting | 511c35b | 2017-05-05 14:12:29 +0200 | [diff] [blame] | 63 | # We define the fail function early so we can use it when detecting the JDK |
| 64 | # See https://github.com/bazelbuild/bazel/issues/2949, |
| 65 | function fail() { |
| 66 | local exitCode=$? |
| 67 | if [[ "$exitCode" = "0" ]]; then |
| 68 | exitCode=1 |
| 69 | fi |
| 70 | echo >&2 |
Androbin | ef381e5 | 2017-12-14 07:24:27 -0800 | [diff] [blame] | 71 | echo "ERROR: $*" >&2 |
dmarting | 511c35b | 2017-05-05 14:12:29 +0200 | [diff] [blame] | 72 | exit $exitCode |
| 73 | } |
| 74 | |
| 75 | |
Klaus Aehlig | 276a8cd | 2016-07-11 12:06:07 +0000 | [diff] [blame] | 76 | # Set standard variables |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 77 | DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) |
Andrew Johnson | 1fccb31 | 2016-12-05 18:27:27 +0000 | [diff] [blame] | 78 | WORKSPACE_DIR="$(dirname "$(dirname "${DIR}")")" |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 79 | |
Damien Martin-Guillerez | 9c5deb6 | 2015-09-15 07:38:26 +0000 | [diff] [blame] | 80 | JAVA_VERSION=${JAVA_VERSION:-1.8} |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 81 | BAZELRC=${BAZELRC:-"/dev/null"} |
| 82 | PLATFORM="$(uname -s | tr 'A-Z' 'a-z')" |
| 83 | |
László Csomor | 3c0c262 | 2017-02-13 15:46:28 +0000 | [diff] [blame] | 84 | PATHSEP=":" |
Lukacs T. Berki | b70343f | 2017-01-23 11:57:42 +0000 | [diff] [blame] | 85 | case "${PLATFORM}" in |
| 86 | linux) |
| 87 | # JAVA_HOME must point to a Java installation. |
| 88 | JAVA_HOME="${JAVA_HOME:-$(readlink -f $(which javac) | sed 's_/bin/javac__')}" |
| 89 | ;; |
| 90 | |
| 91 | freebsd) |
| 92 | # JAVA_HOME must point to a Java installation. |
| 93 | JAVA_HOME="${JAVA_HOME:-/usr/local/openjdk8}" |
| 94 | ;; |
| 95 | |
| 96 | darwin) |
| 97 | if [[ -z "$JAVA_HOME" ]]; then |
| 98 | JAVA_HOME="$(/usr/libexec/java_home -v ${JAVA_VERSION}+ 2> /dev/null)" \ |
| 99 | || fail "Could not find JAVA_HOME, please ensure a JDK (version ${JAVA_VERSION}+) is installed." |
| 100 | fi |
| 101 | ;; |
| 102 | |
Laszlo Csomor | d0d7ef0 | 2017-04-26 10:48:00 +0200 | [diff] [blame] | 103 | msys*|mingw*|cygwin*) |
Lukacs T. Berki | b70343f | 2017-01-23 11:57:42 +0000 | [diff] [blame] | 104 | # Use a simplified platform string. |
Laszlo Csomor | d0d7ef0 | 2017-04-26 10:48:00 +0200 | [diff] [blame] | 105 | PLATFORM="windows" |
Lukacs T. Berki | b70343f | 2017-01-23 11:57:42 +0000 | [diff] [blame] | 106 | PATHSEP=";" |
| 107 | # Find the latest available version of the SDK. |
Laszlo Csomor | d0d7ef0 | 2017-04-26 10:48:00 +0200 | [diff] [blame] | 108 | JAVA_HOME="${JAVA_HOME:-$(ls -d C:/Program\ Files/Java/jdk* | sort | tail -n 1)}" |
László Csomor | 3c0c262 | 2017-02-13 15:46:28 +0000 | [diff] [blame] | 109 | # Replace backslashes with forward slashes. |
| 110 | JAVA_HOME="${JAVA_HOME//\\//}" |
Lukacs T. Berki | b70343f | 2017-01-23 11:57:42 +0000 | [diff] [blame] | 111 | esac |
| 112 | |
Dmitry Lomov | 9d40a60 | 2016-02-15 16:15:03 +0000 | [diff] [blame] | 113 | EXE_EXT="" |
Laszlo Csomor | d0d7ef0 | 2017-04-26 10:48:00 +0200 | [diff] [blame] | 114 | if [ "${PLATFORM}" == "windows" ]; then |
Laszlo Csomor | f5525e8 | 2017-01-30 18:11:58 +0000 | [diff] [blame] | 115 | # Extension for executables. |
Dmitry Lomov | 9d40a60 | 2016-02-15 16:15:03 +0000 | [diff] [blame] | 116 | EXE_EXT=".exe" |
Dmitry Lomov | 9d40a60 | 2016-02-15 16:15:03 +0000 | [diff] [blame] | 117 | |
Laszlo Csomor | d0d7ef0 | 2017-04-26 10:48:00 +0200 | [diff] [blame] | 118 | # Fix TMPDIR on windows |
Laszlo Csomor | f5525e8 | 2017-01-30 18:11:58 +0000 | [diff] [blame] | 119 | default_tmp=${TMP:-$(cygpath -mO)/Temp} |
Laszlo Csomor | 57db509 | 2016-09-05 07:37:44 +0000 | [diff] [blame] | 120 | TMPDIR=$(cygpath -ml "${TMPDIR:-$default_tmp}") |
Laszlo Csomor | f5525e8 | 2017-01-30 18:11:58 +0000 | [diff] [blame] | 121 | fi |
Dmitry Lomov | 19fd76f | 2016-06-24 11:52:50 +0000 | [diff] [blame] | 122 | |
Julio Merino | 5909d9d | 2016-02-25 21:44:31 +0000 | [diff] [blame] | 123 | # Whether we display build messages or not. We set this conditionally because |
| 124 | # the file including us or the user may already have defined VERBOSE to their |
| 125 | # liking. |
| 126 | : ${VERBOSE:=yes} |
| 127 | |
Julio Merino | 63e8d63 | 2016-02-25 18:17:53 +0000 | [diff] [blame] | 128 | # List of functions to invoke on exit. |
| 129 | ATEXIT_HANDLERS= |
| 130 | |
| 131 | # Registers a function to be invoked on exit. |
| 132 | # |
| 133 | # The handlers will be invoked at exit time in the order they were registered. |
| 134 | # See comments in run_atexit for more details. |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 135 | function atexit() { |
Julio Merino | 63e8d63 | 2016-02-25 18:17:53 +0000 | [diff] [blame] | 136 | local handler="${1}"; shift |
| 137 | |
| 138 | [ -n "${ATEXIT_HANDLERS}" ] || trap 'run_atexit_handlers $?' EXIT |
| 139 | ATEXIT_HANDLERS="${ATEXIT_HANDLERS} ${handler}" |
| 140 | } |
| 141 | |
| 142 | # Exit routine to run all registered atexit handlers. |
| 143 | # |
| 144 | # If the program exited with an error, this exit routine will also exit with the |
| 145 | # same error. However, if the program exited successfully, this exit routine |
| 146 | # will only exit successfully if the atexit handlers succeed. |
| 147 | function run_atexit_handlers() { |
| 148 | local exit_code="$?" |
| 149 | |
| 150 | local failed=no |
| 151 | for handler in ${ATEXIT_HANDLERS}; do |
| 152 | eval "${handler}" || failed=yes |
| 153 | done |
| 154 | |
| 155 | trap - EXIT # Reset exit handler to prevent double execution. |
| 156 | if [ ${exit_code} -ne 0 ]; then |
| 157 | exit ${exit_code} |
| 158 | else |
| 159 | if [ "${failed}" = yes ]; then |
| 160 | echo "Program tried to exit successfully but atexit routines failed" 1>&2 |
| 161 | exit 1 |
| 162 | else |
| 163 | exit 0 |
| 164 | fi |
| 165 | fi |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | function tempdir() { |
| 169 | local tmp=${TMPDIR:-/tmp} |
Alexander Chung | fc07142 | 2017-02-07 12:48:26 +0000 | [diff] [blame] | 170 | mkdir -p "${tmp}" |
| 171 | local DIR="$(mktemp -d "${tmp%%/}/bazel_XXXXXXXX")" |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 172 | mkdir -p "${DIR}" |
Klaus Aehlig | f47fd83 | 2016-07-01 13:58:09 +0000 | [diff] [blame] | 173 | local DIRBASE=$(basename "${DIR}") |
László Csomor | aa02990 | 2017-10-09 09:11:08 +0200 | [diff] [blame] | 174 | eval "cleanup_tempdir_${DIRBASE}() { rm -rf '${DIR}' >&/dev/null || true ; }" |
Klaus Aehlig | f47fd83 | 2016-07-01 13:58:09 +0000 | [diff] [blame] | 175 | atexit cleanup_tempdir_${DIRBASE} |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 176 | NEW_TMPDIR="${DIR}" |
| 177 | } |
| 178 | tempdir |
| 179 | OUTPUT_DIR=${NEW_TMPDIR} |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 180 | phasefile=${OUTPUT_DIR}/phase |
Lukacs Berki | 7da21b1 | 2016-08-04 12:18:07 +0000 | [diff] [blame] | 181 | function cleanup_phasefile() { |
| 182 | if [ -f "${phasefile}" ]; then |
| 183 | echo 1>&2; |
| 184 | cat "${phasefile}" 1>&2; |
| 185 | fi; |
| 186 | } |
| 187 | |
Julio Merino | 63e8d63 | 2016-02-25 18:17:53 +0000 | [diff] [blame] | 188 | atexit cleanup_phasefile |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 189 | |
Julio Merino | 5909d9d | 2016-02-25 21:44:31 +0000 | [diff] [blame] | 190 | # Excutes a command respecting the current verbosity settings. |
| 191 | # |
| 192 | # If VERBOSE is yes, the command itself and its output are printed. |
| 193 | # If VERBOSE is no, the command's output is only displayed in case of failure. |
| 194 | # |
| 195 | # Exits the script if the command fails. |
| 196 | function run() { |
| 197 | if [ "${VERBOSE}" = yes ]; then |
| 198 | echo "${@}" |
| 199 | "${@}" || exit $? |
| 200 | else |
Lukacs Berki | 7da21b1 | 2016-08-04 12:18:07 +0000 | [diff] [blame] | 201 | local errfile="${OUTPUT_DIR}/errors" |
| 202 | |
Julio Merino | 5909d9d | 2016-02-25 21:44:31 +0000 | [diff] [blame] | 203 | echo "${@}" >"${errfile}" |
Lukacs Berki | 7da21b1 | 2016-08-04 12:18:07 +0000 | [diff] [blame] | 204 | if ! "${@}" >>"${errfile}" 2>&1; then |
| 205 | local exitcode=$? |
| 206 | cat "${errfile}" 1>&2 |
| 207 | exit $exitcode |
| 208 | fi |
Julio Merino | 5909d9d | 2016-02-25 21:44:31 +0000 | [diff] [blame] | 209 | fi |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 210 | } |
| 211 | |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 212 | function display() { |
| 213 | if [[ -z "${QUIETMODE}" ]]; then |
| 214 | echo -e "$@" >&2 |
| 215 | fi |
| 216 | } |
| 217 | |
| 218 | function log() { |
| 219 | echo -n "." >&2 |
| 220 | echo "$1" >${phasefile} |
| 221 | } |
| 222 | |
| 223 | function clear_log() { |
| 224 | echo >&2 |
| 225 | rm -f ${phasefile} |
| 226 | } |
| 227 | |
| 228 | LEAVES="\xF0\x9F\x8D\x83" |
| 229 | INFO="\033[32mINFO\033[0m:" |
Damien Martin-Guillerez | 338dc56 | 2015-06-23 17:15:12 +0000 | [diff] [blame] | 230 | WARNING="\033[31mWARN\033[0m:" |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 231 | |
| 232 | first_step=1 |
| 233 | function new_step() { |
| 234 | rm -f ${phasefile} |
| 235 | local new_line= |
| 236 | if [ -n "${first_step}" ]; then |
| 237 | first_step= |
| 238 | else |
| 239 | new_line="\n" |
| 240 | fi |
Dmitry Lomov | 8d58ec1 | 2017-10-24 14:43:07 +0200 | [diff] [blame] | 241 | if [ -t 2 ]; then |
| 242 | display -n "$new_line$LEAVES $1" |
| 243 | else |
| 244 | display -n "$new_line$1" |
| 245 | fi |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | function git_sha1() { |
Laszlo Csomor | d0d7ef0 | 2017-04-26 10:48:00 +0200 | [diff] [blame] | 249 | if [ -x "$(which git 2>/dev/null)" ] && [ -d .git ]; then |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 250 | git rev-parse --short HEAD 2>/dev/null || true |
| 251 | fi |
| 252 | } |
| 253 | |
Damien Martin-Guillerez | 28e67b5 | 2016-03-14 11:01:31 +0000 | [diff] [blame] | 254 | function git_date() { |
Laszlo Csomor | d0d7ef0 | 2017-04-26 10:48:00 +0200 | [diff] [blame] | 255 | if [ -x "$(which git 2>/dev/null)" ] && [ -d .git ]; then |
Damien Martin-Guillerez | 28e67b5 | 2016-03-14 11:01:31 +0000 | [diff] [blame] | 256 | git log -1 --pretty=%ai | cut -d " " -f 1 || true |
| 257 | fi |
| 258 | } |
| 259 | |
| 260 | # Get the latest release version and append the date of |
| 261 | # the last commit if any. |
| 262 | function get_last_version() { |
Damien Martin-Guillerez | b7e1b82 | 2016-03-17 20:52:36 +0000 | [diff] [blame] | 263 | if [ -f "CHANGELOG.md" ]; then |
| 264 | local version="$(fgrep -m 1 '## Release' CHANGELOG.md \ |
| 265 | | sed -E 's|.*Release (.*) \(.*\)|\1|')" |
| 266 | else |
| 267 | local version="" |
| 268 | fi |
| 269 | |
Damien Martin-Guillerez | 28e67b5 | 2016-03-14 11:01:31 +0000 | [diff] [blame] | 270 | local date="$(git_date)" |
| 271 | if [ -z "${version-}" ]; then |
| 272 | version="unknown" |
| 273 | fi |
| 274 | if [ -n "${date-}" ]; then |
| 275 | date="$(date +%Y-%m-%d)" |
| 276 | fi |
| 277 | echo "${version}-${date}" |
| 278 | } |
| 279 | |
Damien Martin-Guillerez | d47a8ef | 2015-06-10 11:54:50 +0000 | [diff] [blame] | 280 | if [[ ${PLATFORM} == "darwin" ]]; then |
| 281 | function md5_file() { |
| 282 | echo $(cat $1 | md5) $1 |
| 283 | } |
| 284 | else |
| 285 | function md5_file() { |
| 286 | md5sum $1 |
| 287 | } |
| 288 | fi |
Damien Martin-Guillerez | 338dc56 | 2015-06-23 17:15:12 +0000 | [diff] [blame] | 289 | |
| 290 | # Gets the java version from JAVA_HOME |
| 291 | # Sets JAVAC and JAVAC_VERSION with respectively the path to javac and |
| 292 | # the version of javac. |
| 293 | function get_java_version() { |
| 294 | test -z "$JAVA_HOME" && fail "JDK not found, please set \$JAVA_HOME." |
| 295 | JAVAC="${JAVA_HOME}/bin/javac" |
| 296 | [[ -x "${JAVAC}" ]] \ |
| 297 | || fail "JAVA_HOME ($JAVA_HOME) is not a path to a working JDK." |
| 298 | |
| 299 | JAVAC_VERSION=$("${JAVAC}" -version 2>&1) |
Bernhard M. Wiedemann | 5d3f4f1 | 2017-11-08 19:46:14 +0100 | [diff] [blame] | 300 | if [[ "$JAVAC_VERSION" =~ javac\ ((1\.)?([789]|[1-9][0-9])).*$ ]]; then |
| 301 | JAVAC_VERSION=1.${BASH_REMATCH[3]} |
Damien Martin-Guillerez | 338dc56 | 2015-06-23 17:15:12 +0000 | [diff] [blame] | 302 | else |
John Cater | 6a87a7e | 2016-08-23 18:49:56 +0000 | [diff] [blame] | 303 | fail \ |
| 304 | "Cannot determine JDK version, please set \$JAVA_HOME.\n" \ |
| 305 | "\$JAVAC_VERSION is \"${JAVAC_VERSION}\"" |
Damien Martin-Guillerez | 338dc56 | 2015-06-23 17:15:12 +0000 | [diff] [blame] | 306 | fi |
| 307 | } |
Damien Martin-Guillerez | dbf5cad | 2015-09-04 12:46:23 +0000 | [diff] [blame] | 308 | |
| 309 | # Return the target that a bind point to, using Bazel query. |
| 310 | function get_bind_target() { |
Klaus Aehlig | 276a8cd | 2016-07-11 12:06:07 +0000 | [diff] [blame] | 311 | $BAZEL --bazelrc=${BAZELRC} --nomaster_bazelrc ${BAZEL_DIR_STARTUP_OPTIONS} \ |
Damien Martin-Guillerez | dbf5cad | 2015-09-04 12:46:23 +0000 | [diff] [blame] | 312 | query "deps($1, 1) - $1" |
| 313 | } |
John Cater | 32c5add | 2018-03-19 08:51:46 -0700 | [diff] [blame] | 314 | |
| 315 | # Create a link for a directory on the filesystem |
| 316 | function link_dir() { |
| 317 | local source=$1 |
| 318 | local dest=$2 |
| 319 | |
| 320 | if [[ "${PLATFORM}" == "windows" ]]; then |
philwo | f24768b | 2019-07-16 07:12:54 -0700 | [diff] [blame] | 321 | local -r s="$(cygpath -w "$source")" |
| 322 | local -r d="$(cygpath -w "$dest")" |
| 323 | powershell -command "New-Item -ItemType Junction -Path '$d' -Value '$s'" |
John Cater | 32c5add | 2018-03-19 08:51:46 -0700 | [diff] [blame] | 324 | else |
| 325 | ln -s "${source}" "${dest}" |
| 326 | fi |
| 327 | } |
Laszlo Csomor | 3eec3fe | 2018-09-03 06:40:28 -0700 | [diff] [blame] | 328 | |
| 329 | function link_file() { |
| 330 | local source=$1 |
| 331 | local dest=$2 |
| 332 | |
| 333 | if [[ "${PLATFORM}" == "windows" ]]; then |
| 334 | # Attempt creating a symlink to the file. This is supported without |
| 335 | # elevation (Administrator privileges) on Windows 10 version 1709 when |
| 336 | # Developer Mode is enabled. |
philwo | f24768b | 2019-07-16 07:12:54 -0700 | [diff] [blame] | 337 | local -r s="$(cygpath -w "$source")" |
| 338 | local -r d="$(cygpath -w "$dest")" |
| 339 | if ! powershell -command "New-Item -ItemType SymbolicLink -Path '$d' -Value '$s'"; then |
Laszlo Csomor | 3eec3fe | 2018-09-03 06:40:28 -0700 | [diff] [blame] | 340 | # If the previous call failed to create a symlink, just copy the file. |
| 341 | cp "$source" "$dest" |
| 342 | fi |
| 343 | else |
| 344 | ln -s "${source}" "${dest}" |
| 345 | fi |
| 346 | } |
| 347 | |
| 348 | # Link direct children (subdirectories and files) of a directory. |
| 349 | # Usage: |
| 350 | # link_children "$PWD" "tools" "${BAZEL_TOOLS_REPO}" |
| 351 | # This creates: |
| 352 | # ${BAZEL_TOOLS_REPO}/tools/android -> $PWD/tools/android |
| 353 | # ${BAZEL_TOOLS_REPO}/tools/bash -> $PWD/tools/bash |
| 354 | # ... and so on for all files and directories directly under "tools". |
| 355 | function link_children() { |
| 356 | local -r source_dir=${1%/} |
| 357 | local -r source_subdir=${2%/} |
| 358 | local -r dest_dir=${3%/} |
| 359 | |
| 360 | for e in $(find "${source_dir}/${source_subdir}" -mindepth 1 -maxdepth 1 -type d); do |
| 361 | local dest_path="${dest_dir}/${e#$source_dir/}" |
| 362 | if [[ ! -d "$dest_path" ]]; then |
| 363 | link_dir "$e" "$dest_path" |
| 364 | fi |
| 365 | done |
| 366 | for e in $(find "${source_dir}/${source_subdir}" -mindepth 1 -maxdepth 1 -type f); do |
| 367 | local dest_path="${dest_dir}/${e#$source_dir/}" |
| 368 | if [[ ! -f "$dest_path" ]]; then |
| 369 | link_file "$e" "$dest_path" |
| 370 | fi |
| 371 | done |
| 372 | } |