| OLD | NEW |
| (Empty) |
| 1 #!/bin/bash | |
| 2 # Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 set -o nounset | |
| 7 set -o errexit | |
| 8 | |
| 9 # Turn on/off debugging mode | |
| 10 readonly UTMAN_DEBUG=${UTMAN_DEBUG:-false} | |
| 11 | |
| 12 # True if the scripts are running on the build bots. | |
| 13 readonly UTMAN_BUILDBOT=${UTMAN_BUILDBOT:-false} | |
| 14 | |
| 15 # Dump all build output to stdout | |
| 16 readonly UTMAN_VERBOSE=${UTMAN_VERBOSE:-false} | |
| 17 | |
| 18 # Mercurial Retry settings | |
| 19 HG_MAX_RETRIES=${HG_MAX_RETRIES:-3} | |
| 20 if ${UTMAN_BUILDBOT} ; then | |
| 21 HG_RETRY_DELAY_SEC=${HG_RETRY_DELAY_SEC:-60} | |
| 22 else | |
| 23 HG_RETRY_DELAY_SEC=${HG_RETRY_DELAY_SEC:-1} | |
| 24 fi | |
| 25 | |
| 26 readonly TIME_AT_STARTUP=$(date '+%s') | |
| 27 | |
| 28 SetScriptPath() { | |
| 29 SCRIPT_PATH="$1" | |
| 30 } | |
| 31 | |
| 32 SetLogDirectory() { | |
| 33 TC_LOG="$1" | |
| 34 TC_LOG_ALL="${TC_LOG}/ALL" | |
| 35 } | |
| 36 | |
| 37 ###################################################################### | |
| 38 # Detect if we are in a ChromiumOS chroot | |
| 39 ###################################################################### | |
| 40 if [ -e /etc/debian_chroot ]; then | |
| 41 readonly UTMAN_IN_CROS_CHROOT=true | |
| 42 else | |
| 43 readonly UTMAN_IN_CROS_CHROOT=false | |
| 44 fi | |
| 45 | |
| 46 ###################################################################### | |
| 47 # Detect system type | |
| 48 ###################################################################### | |
| 49 | |
| 50 BUILD_PLATFORM=$(uname | tr '[A-Z]' '[a-z]') | |
| 51 BUILD_PLATFORM_LINUX=false | |
| 52 BUILD_PLATFORM_MAC=false | |
| 53 BUILD_PLATFORM_WIN=false | |
| 54 | |
| 55 if [ "${BUILD_PLATFORM}" == "linux" ] ; then | |
| 56 BUILD_PLATFORM_LINUX=true | |
| 57 SCONS_BUILD_PLATFORM=linux | |
| 58 SO_PREFIX=lib | |
| 59 SO_EXT=.so | |
| 60 SO_DIR=lib | |
| 61 elif [[ "${BUILD_PLATFORM}" =~ cygwin_nt ]]; then | |
| 62 BUILD_PLATFORM=windows | |
| 63 BUILD_PLATFORM_WIN=true | |
| 64 SCONS_BUILD_PLATFORM=win | |
| 65 SO_PREFIX=cyg | |
| 66 SO_EXT=.dll | |
| 67 SO_DIR=bin # On Windows, DLLs are placed in bin/ | |
| 68 # because the dynamic loader searches %PATH% | |
| 69 elif [ "${BUILD_PLATFORM}" == "darwin" ] ; then | |
| 70 BUILD_PLATFORM_MAC=true | |
| 71 SCONS_BUILD_PLATFORM=mac | |
| 72 # force 32 bit host because build is also 32 bit on mac (no 64bit nacl) | |
| 73 HOST_ARCH=${HOST_ARCH:-i386} | |
| 74 SO_PREFIX=lib | |
| 75 SO_EXT=.dylib | |
| 76 SO_DIR=lib | |
| 77 else | |
| 78 echo "Unknown system '${BUILD_PLATFORM}'" | |
| 79 exit -1 | |
| 80 fi | |
| 81 | |
| 82 readonly BUILD_PLATFORM | |
| 83 readonly BUILD_PLATFORM_LINUX | |
| 84 readonly BUILD_PLATFORM_MAC | |
| 85 readonly BUILD_PLATFORM_WIN | |
| 86 readonly SCONS_BUILD_PLATFORM | |
| 87 readonly SO_PREFIX | |
| 88 readonly SO_EXT | |
| 89 readonly SO_DIR | |
| 90 | |
| 91 BUILD_ARCH=$(uname -m) | |
| 92 BUILD_ARCH_X8632=false | |
| 93 BUILD_ARCH_X8664=false | |
| 94 if [ "${BUILD_ARCH}" == "i386" ] || | |
| 95 [ "${BUILD_ARCH}" == "i686" ] ; then | |
| 96 BUILD_ARCH_X8632=true | |
| 97 elif [ "${BUILD_ARCH}" == "x86_64" ] ; then | |
| 98 BUILD_ARCH_X8664=true | |
| 99 else | |
| 100 echo "Unknown build arch '${BUILD_ARCH}'" | |
| 101 exit -1 | |
| 102 fi | |
| 103 readonly BUILD_ARCH | |
| 104 readonly BUILD_ARCH_X8632 | |
| 105 readonly BUILD_ARCH_X8664 | |
| 106 | |
| 107 | |
| 108 HOST_ARCH=${HOST_ARCH:-${BUILD_ARCH}} | |
| 109 HOST_ARCH_X8632=false | |
| 110 HOST_ARCH_X8664=false | |
| 111 if [ "${HOST_ARCH}" == "i386" ] || | |
| 112 [ "${HOST_ARCH}" == "i686" ] ; then | |
| 113 HOST_ARCH_X8632=true | |
| 114 elif [ "${HOST_ARCH}" == "x86_64" ] ; then | |
| 115 HOST_ARCH_X8664=true | |
| 116 else | |
| 117 echo "Unknown host arch '${HOST_ARCH}'" | |
| 118 exit -1 | |
| 119 fi | |
| 120 readonly HOST_ARCH | |
| 121 readonly HOST_ARCH_X8632 | |
| 122 readonly HOST_ARCH_X8664 | |
| 123 | |
| 124 if [ "${BUILD_ARCH}" != "${HOST_ARCH}" ]; then | |
| 125 if ! { ${BUILD_ARCH_X8664} && ${HOST_ARCH_X8632}; }; then | |
| 126 echo "Cross targets other than host=i686 with build=x86_64 not supported" | |
| 127 exit -1 | |
| 128 fi | |
| 129 fi | |
| 130 | |
| 131 # On Windows, scons expects Windows-style paths (C:\foo\bar) | |
| 132 # This function converts cygwin posix paths to Windows-style paths. | |
| 133 # On all other platforms, this function does nothing to the path. | |
| 134 PosixToSysPath() { | |
| 135 local path="$1" | |
| 136 if ${BUILD_PLATFORM_WIN}; then | |
| 137 cygpath -w "$(GetAbsolutePath "${path}")" | |
| 138 else | |
| 139 echo "${path}" | |
| 140 fi | |
| 141 } | |
| 142 | |
| 143 ###################################################################### | |
| 144 # Mercurial repository tools | |
| 145 ###################################################################### | |
| 146 | |
| 147 #+ hg-pull <dir> | |
| 148 hg-pull() { | |
| 149 local dir="$1" | |
| 150 | |
| 151 assert-dir "$dir" \ | |
| 152 "Repository $(basename "${dir}") doesn't exist. First do 'hg-checkout'" | |
| 153 | |
| 154 RunWithRetry ${HG_MAX_RETRIES} ${HG_RETRY_DELAY_SEC} \ | |
| 155 hg-pull-try "${dir}" | |
| 156 } | |
| 157 | |
| 158 hg-pull-try() { | |
| 159 local dir="$1" | |
| 160 local retcode=0 | |
| 161 | |
| 162 spushd "${dir}" | |
| 163 RunWithLog "hg-pull" hg pull || retcode=$? | |
| 164 spopd | |
| 165 return ${retcode} | |
| 166 } | |
| 167 | |
| 168 #+ hg-revert <dir> | |
| 169 hg-revert() { | |
| 170 local dir="$1" | |
| 171 hg revert "${dir}" | |
| 172 } | |
| 173 | |
| 174 #+ hg-clone <url> <dir> | |
| 175 hg-clone() { | |
| 176 local url="$1" | |
| 177 local dir="$2" | |
| 178 RunWithRetry ${HG_MAX_RETRIES} ${HG_RETRY_DELAY_SEC} \ | |
| 179 hg-clone-try "${url}" "${dir}" | |
| 180 } | |
| 181 | |
| 182 hg-clone-try() { | |
| 183 local url="$1" | |
| 184 local dir="$2" | |
| 185 local retcode=0 | |
| 186 | |
| 187 rm -rf "${dir}" | |
| 188 hg clone "${url}" "${dir}" || retcode=$? | |
| 189 | |
| 190 if [ ${retcode} -ne 0 ] ; then | |
| 191 # Clean up directory after failure | |
| 192 rm -rf "${dir}" | |
| 193 fi | |
| 194 return ${retcode} | |
| 195 } | |
| 196 | |
| 197 hg-checkout() { | |
| 198 local repo=$1 | |
| 199 local dest=$2 | |
| 200 local rev=$3 | |
| 201 | |
| 202 if [ ! -d ${dest} ] ; then | |
| 203 local repobasedir=$(dirname "${dest}") | |
| 204 mkdir -p "${repobasedir}" | |
| 205 StepBanner "HG-CHECKOUT" "Checking out new repository for ${repo} @ ${rev}" | |
| 206 # Use a temporary directory just in case HG has problems | |
| 207 # with long filenames during checkout, and to make sure the | |
| 208 # repo directory only exists if the checkout was successful. | |
| 209 local TMPDIR="/tmp/hg-${rev}-$RANDOM" | |
| 210 hg-clone "https://code.google.com/p/${repo}" "${TMPDIR}" | |
| 211 hg-update "${TMPDIR}" -C ${rev} | |
| 212 mv "${TMPDIR}" "${dest}" | |
| 213 else | |
| 214 StepBanner "HG-CHECKOUT" "Using existing source for ${repo} in ${dest}" | |
| 215 fi | |
| 216 } | |
| 217 | |
| 218 #+ hg-update <dir> [extra_flags] [rev] | |
| 219 hg-update() { | |
| 220 local dir="$1" | |
| 221 shift 1 | |
| 222 | |
| 223 assert-dir "${dir}" \ | |
| 224 "HG repository $(basename "${dir}") doesn't exist. First do 'hg-checkout'" | |
| 225 | |
| 226 RunWithRetry ${HG_MAX_RETRIES} ${HG_RETRY_DELAY_SEC} \ | |
| 227 hg-update-try "${dir}" "$@" | |
| 228 } | |
| 229 | |
| 230 hg-update-try() { | |
| 231 local dir="$1" | |
| 232 shift 1 | |
| 233 local retcode=0 | |
| 234 spushd "${dir}" | |
| 235 RunWithLog "hg-update" hg update "$@" || retcode=$? | |
| 236 spopd | |
| 237 return ${retcode} | |
| 238 } | |
| 239 | |
| 240 #+ hg-push <dir> | |
| 241 hg-push() { | |
| 242 local dir="$1" | |
| 243 spushd "${dir}" | |
| 244 hg push | |
| 245 spopd | |
| 246 } | |
| 247 | |
| 248 hg-info() { | |
| 249 local dir="$1" | |
| 250 local rev="$2" | |
| 251 | |
| 252 spushd "$dir" | |
| 253 local hg_status=$(hg status -mard) | |
| 254 if [ ${#hg_status} -gt 0 ]; then | |
| 255 LOCAL_CHANGES="YES" | |
| 256 else | |
| 257 LOCAL_CHANGES="NO" | |
| 258 fi | |
| 259 | |
| 260 echo "" | |
| 261 echo "Directory: hg/$(basename ${dir})" | |
| 262 echo " Branch : $(hg branch)" | |
| 263 echo " Revision : $(hg identify)" | |
| 264 echo " Local changes : ${LOCAL_CHANGES}" | |
| 265 echo " Stable Revision: ${rev}" | |
| 266 echo "" | |
| 267 spopd | |
| 268 } | |
| 269 | |
| 270 svn-at-revision() { | |
| 271 local dir="$1" | |
| 272 local rev="$2" | |
| 273 local repo_rev=$(svn-get-revision "${dir}") | |
| 274 [ "${repo_rev}" == "${rev}" ] | |
| 275 return $? | |
| 276 } | |
| 277 | |
| 278 hg-at-revision() { | |
| 279 local dir="$1" | |
| 280 local rev="$2" | |
| 281 local repo_rev=$(hg-get-revision "${dir}") | |
| 282 [ "${repo_rev}" == "${rev}" ] | |
| 283 return $? | |
| 284 } | |
| 285 | |
| 286 #+ hg-assert-is-merge <dir> - Assert an working directory contains a merge | |
| 287 hg-assert-is-merge() { | |
| 288 local dir=$1 | |
| 289 spushd "${dir}" | |
| 290 | |
| 291 # When the working directory is a merge, hg identify -i | |
| 292 # emits "changesetid1+changesetid2+" | |
| 293 if hg identify -i | egrep -q '^[0-9a-f]+\+[0-9a-f]+\+$'; then | |
| 294 spopd | |
| 295 return | |
| 296 fi | |
| 297 local REPONAME=$(basename $(pwd)) | |
| 298 spopd | |
| 299 Banner "ERROR: Working directory of '${REPONAME}' does not have a merge." | |
| 300 exit -1 | |
| 301 } | |
| 302 | |
| 303 hg-on-branch() { | |
| 304 local dir=$1 | |
| 305 local branch=$2 | |
| 306 spushd "${dir}" | |
| 307 if hg branch | grep -q "^${branch}\$"; then | |
| 308 spopd | |
| 309 return 0 | |
| 310 else | |
| 311 spopd | |
| 312 return 1 | |
| 313 fi | |
| 314 } | |
| 315 | |
| 316 #+ hg-assert-branch <dir> <branch> - Assert hg repo in <dir> is on <branch> | |
| 317 hg-assert-branch() { | |
| 318 local dir=$1 | |
| 319 local branch=$2 | |
| 320 | |
| 321 if ! hg-on-branch "${dir}" "${branch}" ; then | |
| 322 local REPONAME=$(basename "${dir}") | |
| 323 Banner "ERROR: ${REPONAME} is not on branch '${branch}'." | |
| 324 exit -1 | |
| 325 fi | |
| 326 } | |
| 327 | |
| 328 hg-has-changes() { | |
| 329 local dir=$1 | |
| 330 spushd "${dir}" | |
| 331 local PLUS=$(hg status . | grep -v '^?') | |
| 332 spopd | |
| 333 | |
| 334 [ "${PLUS}" != "" ] | |
| 335 return $? | |
| 336 } | |
| 337 | |
| 338 #+ hg-assert-no-changes <dir> - Assert an hg repo has no local changes | |
| 339 hg-assert-no-changes() { | |
| 340 local dir="$1" | |
| 341 if hg-has-changes "${dir}" ; then | |
| 342 local REPONAME=$(basename "${dir}") | |
| 343 Banner "ERROR: Repository ${REPONAME} has local changes" | |
| 344 exit -1 | |
| 345 fi | |
| 346 } | |
| 347 | |
| 348 hg-has-untracked() { | |
| 349 local dir=$1 | |
| 350 spushd "${dir}" | |
| 351 local STATUS=$(hg status . | grep '^?') | |
| 352 spopd | |
| 353 | |
| 354 [ "${STATUS}" != "" ] | |
| 355 return $? | |
| 356 } | |
| 357 | |
| 358 hg-assert-no-untracked() { | |
| 359 local dir=$1 | |
| 360 if hg-has-untracked "${dir}"; then | |
| 361 local REPONAME=$(basename "${dir}") | |
| 362 Banner "ERROR: Repository ${REPONAME} has untracked files" | |
| 363 exit -1 | |
| 364 fi | |
| 365 } | |
| 366 | |
| 367 hg-has-outgoing() { | |
| 368 local dir=$1 | |
| 369 spushd "${dir}" | |
| 370 if hg outgoing | grep -q "^no changes found$" ; then | |
| 371 spopd | |
| 372 return 1 | |
| 373 fi | |
| 374 spopd | |
| 375 return 0 | |
| 376 } | |
| 377 | |
| 378 hg-assert-no-outgoing() { | |
| 379 local dir=$1 | |
| 380 if hg-has-outgoing "${dir}" ; then | |
| 381 local REPONAME=$(basename $(pwd)) | |
| 382 msg="ERROR: Repository ${REPONAME} has outgoing commits. Clean first." | |
| 383 Banner "${msg}" | |
| 384 exit -1 | |
| 385 fi | |
| 386 } | |
| 387 | |
| 388 ###################################################################### | |
| 389 # Subversion repository tools | |
| 390 ###################################################################### | |
| 391 | |
| 392 #+ svn-get-revision <dir> | |
| 393 svn-get-revision() { | |
| 394 local dir="$1" | |
| 395 spushd "${dir}" | |
| 396 local rev=$(svn info | grep 'Revision: ' | cut -b 11-) | |
| 397 if ! [[ "${rev}" =~ ^[0-9]+$ ]]; then | |
| 398 echo "Invalid revision number '${rev}' or invalid repository '${dir}'" 1>&2 | |
| 399 exit -1 | |
| 400 fi | |
| 401 spopd | |
| 402 echo "${rev}" | |
| 403 } | |
| 404 | |
| 405 #+ hg-get-revision <dir> | |
| 406 hg-get-revision() { | |
| 407 local dir="$1" | |
| 408 spushd "${dir}" | |
| 409 local HGREV=($(hg identify | tr -d '+')) | |
| 410 spopd | |
| 411 echo "${HGREV[0]}" | |
| 412 } | |
| 413 | |
| 414 #+ svn-checkout <url> <repodir> - Checkout an SVN repository | |
| 415 svn-checkout() { | |
| 416 local url="$1" | |
| 417 local dir="$2" | |
| 418 local rev="$3" | |
| 419 | |
| 420 if [ ! -d "${dir}" ]; then | |
| 421 StepBanner "SVN-CHECKOUT" "Checking out ${url}" | |
| 422 RunWithLog "svn-checkout" svn co "${url}" "${dir}" -r "${rev}" | |
| 423 else | |
| 424 SkipBanner "SVN-CHECKOUT" "Using existing SVN repository for ${url}" | |
| 425 fi | |
| 426 } | |
| 427 | |
| 428 #+ svn-update <dir> <rev> - Update an SVN repository | |
| 429 svn-update() { | |
| 430 local dir="$1" | |
| 431 local rev="$2" | |
| 432 | |
| 433 assert-dir "$dir" \ | |
| 434 "SVN repository $(basename "${dir}") doesn't exist." | |
| 435 | |
| 436 spushd "${dir}" | |
| 437 if [[ "$rev" == "tip" ]]; then | |
| 438 RunWithLog "svn-update" svn update | |
| 439 else | |
| 440 RunWithLog "svn-update" svn update -r ${rev} | |
| 441 fi | |
| 442 spopd | |
| 443 } | |
| 444 | |
| 445 svn-has-changes() { | |
| 446 local dir="$1" | |
| 447 spushd "${dir}" | |
| 448 local STATUS=$(svn status) | |
| 449 spopd | |
| 450 [ "${STATUS}" != "" ] | |
| 451 return $? | |
| 452 } | |
| 453 | |
| 454 #+ svn-assert-no-changes <dir> - Assert an svn repo has no local changes | |
| 455 svn-assert-no-changes() { | |
| 456 local dir="$1" | |
| 457 if svn-has-changes "${dir}" ; then | |
| 458 local name=$(basename "${dir}") | |
| 459 Banner "ERROR: Repository ${name} has local changes" | |
| 460 exit -1 | |
| 461 fi | |
| 462 } | |
| 463 | |
| 464 ###################################################################### | |
| 465 # Logging tools | |
| 466 ###################################################################### | |
| 467 | |
| 468 #@ progress - Show build progress (open in another window) | |
| 469 progress() { | |
| 470 StepBanner "PROGRESS WINDOW" | |
| 471 | |
| 472 while true; do | |
| 473 if [ -f "${TC_LOG_ALL}" ]; then | |
| 474 if tail --version > /dev/null; then | |
| 475 # GNU coreutils tail | |
| 476 tail -s 0.05 --max-unchanged-stats=20 --follow=name "${TC_LOG_ALL}" | |
| 477 else | |
| 478 # MacOS tail | |
| 479 tail -F "${TC_LOG_ALL}" | |
| 480 fi | |
| 481 fi | |
| 482 sleep 1 | |
| 483 done | |
| 484 } | |
| 485 | |
| 486 #+ clean-logs - Clean all logs | |
| 487 clean-logs() { | |
| 488 rm -rf "${TC_LOG}" | |
| 489 } | |
| 490 | |
| 491 # Logged pushd | |
| 492 spushd() { | |
| 493 LogEcho "-------------------------------------------------------------------" | |
| 494 LogEcho "ENTERING: $1" | |
| 495 pushd "$1" > /dev/null | |
| 496 } | |
| 497 | |
| 498 # Logged popd | |
| 499 spopd() { | |
| 500 LogEcho "LEAVING: $(pwd)" | |
| 501 popd > /dev/null | |
| 502 LogEcho "-------------------------------------------------------------------" | |
| 503 LogEcho "ENTERING: $(pwd)" | |
| 504 } | |
| 505 | |
| 506 LogEcho() { | |
| 507 mkdir -p "${TC_LOG}" | |
| 508 echo "$*" >> "${TC_LOG_ALL}" | |
| 509 } | |
| 510 | |
| 511 RunWithLog() { | |
| 512 local log="${TC_LOG}/$1" | |
| 513 | |
| 514 mkdir -p "${TC_LOG}" | |
| 515 | |
| 516 shift 1 | |
| 517 local ret=1 | |
| 518 if ${UTMAN_VERBOSE}; then | |
| 519 echo "RUNNING: " "$@" | tee -a "${log}" "${TC_LOG_ALL}" | |
| 520 "$@" 2>&1 | tee -a "${log}" "${TC_LOG_ALL}" | |
| 521 ret=${PIPESTATUS[0]} | |
| 522 else | |
| 523 echo "RUNNING: " "$@" | tee -a "${log}" "${TC_LOG_ALL}" &> /dev/null | |
| 524 "$@" 2>&1 | tee -a "${log}" "${TC_LOG_ALL}" &> /dev/null | |
| 525 ret=${PIPESTATUS[0]} | |
| 526 fi | |
| 527 if [ ${ret} -ne 0 ]; then | |
| 528 echo | |
| 529 Banner "ERROR" | |
| 530 echo -n "COMMAND:" | |
| 531 PrettyPrint "$@" | |
| 532 echo | |
| 533 echo "LOGFILE: ${log}" | |
| 534 echo | |
| 535 echo "PWD: $(pwd)" | |
| 536 echo | |
| 537 if ${UTMAN_BUILDBOT}; then | |
| 538 echo "BEGIN LOGFILE Contents." | |
| 539 cat "${log}" | |
| 540 echo "END LOGFILE Contents." | |
| 541 fi | |
| 542 return 1 | |
| 543 fi | |
| 544 return 0 | |
| 545 } | |
| 546 | |
| 547 PrettyPrint() { | |
| 548 # Pretty print, respecting parameter grouping | |
| 549 for I in "$@"; do | |
| 550 local has_space=$(echo "$I" | grep " ") | |
| 551 if [ ${#has_space} -gt 0 ]; then | |
| 552 echo -n ' "' | |
| 553 echo -n "$I" | |
| 554 echo -n '"' | |
| 555 else | |
| 556 echo -n " $I" | |
| 557 fi | |
| 558 done | |
| 559 echo | |
| 560 } | |
| 561 | |
| 562 assert-dir() { | |
| 563 local dir="$1" | |
| 564 local msg="$2" | |
| 565 | |
| 566 if [ ! -d "${dir}" ]; then | |
| 567 Banner "ERROR: ${msg}" | |
| 568 exit -1 | |
| 569 fi | |
| 570 } | |
| 571 | |
| 572 assert-file() { | |
| 573 local fn="$1" | |
| 574 local msg="$2" | |
| 575 | |
| 576 if [ ! -f "${fn}" ]; then | |
| 577 Banner "ERROR: ${fn} does not exist. ${msg}" | |
| 578 exit -1 | |
| 579 fi | |
| 580 } | |
| 581 | |
| 582 Usage() { | |
| 583 egrep "^#@" "${SCRIPT_PATH}" | cut -b 3- | |
| 584 } | |
| 585 | |
| 586 Usage2() { | |
| 587 egrep "^#(@|\+)" "${SCRIPT_PATH}" | cut -b 3- | |
| 588 } | |
| 589 | |
| 590 Banner() { | |
| 591 echo "" | |
| 592 echo " *********************************************************************" | |
| 593 echo " | " | |
| 594 for arg in "$@" ; do | |
| 595 echo " | ${arg}" | |
| 596 done | |
| 597 echo " | " | |
| 598 echo " *********************************************************************" | |
| 599 } | |
| 600 | |
| 601 StepBanner() { | |
| 602 local module="$1" | |
| 603 if [ $# -eq 1 ]; then | |
| 604 echo "" | |
| 605 echo "-------------------------------------------------------------------" | |
| 606 local padding=$(RepeatStr ' ' 28) | |
| 607 echo "${padding}${module}" | |
| 608 echo "-------------------------------------------------------------------" | |
| 609 else | |
| 610 shift 1 | |
| 611 local padding=$(RepeatStr ' ' $((20-${#module})) ) | |
| 612 echo "[$(TimeStamp)] ${module}${padding}" "$@" | |
| 613 fi | |
| 614 } | |
| 615 | |
| 616 TimeStamp() { | |
| 617 if date --version &> /dev/null ; then | |
| 618 # GNU 'date' | |
| 619 date -d "now - ${TIME_AT_STARTUP}sec" '+%M:%S' | |
| 620 else | |
| 621 # Other 'date' (assuming BSD for now) | |
| 622 local time_now=$(date '+%s') | |
| 623 local time_delta=$[ ${time_now} - ${TIME_AT_STARTUP} ] | |
| 624 date -j -f "%s" "${time_delta}" "+%M:%S" | |
| 625 fi | |
| 626 } | |
| 627 | |
| 628 | |
| 629 SubBanner() { | |
| 630 echo "----------------------------------------------------------------------" | |
| 631 echo " $@" | |
| 632 echo "----------------------------------------------------------------------" | |
| 633 } | |
| 634 | |
| 635 SkipBanner() { | |
| 636 StepBanner "$1" "Skipping $2, already up to date." | |
| 637 } | |
| 638 | |
| 639 RepeatStr() { | |
| 640 local str="$1" | |
| 641 local count=$2 | |
| 642 local ret="" | |
| 643 | |
| 644 while [ $count -gt 0 ]; do | |
| 645 ret="${ret}${str}" | |
| 646 count=$((count-1)) | |
| 647 done | |
| 648 echo "$ret" | |
| 649 } | |
| 650 | |
| 651 | |
| 652 Fatal() { | |
| 653 echo 1>&2 | |
| 654 echo "$@" 1>&2 | |
| 655 echo 1>&2 | |
| 656 exit -1 | |
| 657 } | |
| 658 | |
| 659 PackageCheck() { | |
| 660 assert-bin "makeinfo" "makeinfo not found. Please install 'texinfo' package." | |
| 661 assert-bin "bison" "bison not found. Please install 'bison' package." | |
| 662 assert-bin "flex" "flex not found. Please install 'flex' package." | |
| 663 assert-bin "gclient" "gclient not found in PATH. Please install depot_tools." | |
| 664 } | |
| 665 | |
| 666 assert-bin() { | |
| 667 local exe="$1" | |
| 668 local msg="$2" | |
| 669 | |
| 670 if ! which "$exe" > /dev/null; then | |
| 671 Banner "ERROR: $msg" | |
| 672 exit -1 | |
| 673 fi | |
| 674 } | |
| 675 | |
| 676 is-ELF() { | |
| 677 local F=$(file -b "$1") | |
| 678 [[ "${F}" =~ "ELF" ]] | |
| 679 } | |
| 680 | |
| 681 is-Mach() { | |
| 682 local F=$(file -b "$1") | |
| 683 [[ "${F}" =~ "Mach-O" ]] | |
| 684 } | |
| 685 | |
| 686 is-shell-script() { | |
| 687 local F=$(file -b "$1") | |
| 688 [[ "${F}" =~ "shell" ]] | |
| 689 } | |
| 690 | |
| 691 get_dir_size_in_mb() { | |
| 692 du -msc "$1" | tail -1 | egrep -o "[0-9]+" | |
| 693 } | |
| 694 | |
| 695 confirm-yes() { | |
| 696 local msg="$1" | |
| 697 while true; do | |
| 698 echo -n "${msg} [Y/N]? " | |
| 699 local YESNO | |
| 700 read YESNO | |
| 701 if [ "${YESNO}" == "N" ] || [ "${YESNO}" == "n" ]; then | |
| 702 return 1 | |
| 703 fi | |
| 704 if [ "${YESNO}" == "Y" ] || [ "${YESNO}" == "y" ]; then | |
| 705 return 0 | |
| 706 fi | |
| 707 done | |
| 708 } | |
| 709 | |
| 710 # On Linux with GNU readlink, "readlink -f" would be a quick way | |
| 711 # of getting an absolute path, but MacOS has BSD readlink. | |
| 712 GetAbsolutePath() { | |
| 713 local relpath=$1 | |
| 714 local reldir | |
| 715 local relname | |
| 716 if [ -d "${relpath}" ]; then | |
| 717 reldir="${relpath}" | |
| 718 relname="" | |
| 719 else | |
| 720 reldir="$(dirname "${relpath}")" | |
| 721 relname="/$(basename "${relpath}")" | |
| 722 fi | |
| 723 | |
| 724 local absdir="$(cd "${reldir}" && pwd)" | |
| 725 echo "${absdir}${relname}" | |
| 726 } | |
| 727 | |
| 728 | |
| 729 # The Queue* functions provide a simple way of keeping track | |
| 730 # of multiple background processes in order to ensure that: | |
| 731 # 1) they all finish successfully (with return value 0), and | |
| 732 # 2) they terminate if the master process is killed/interrupted. | |
| 733 # (This is done using a bash "trap" handler) | |
| 734 # | |
| 735 # Example Usage: | |
| 736 # command1 & | |
| 737 # QueueLastProcess | |
| 738 # command2 & | |
| 739 # QueueLastProcess | |
| 740 # command3 & | |
| 741 # QueueLastProcess | |
| 742 # echo "Waiting for commands finish..." | |
| 743 # QueueWait | |
| 744 # | |
| 745 # TODO(pdox): Right now, this abstraction is only used for | |
| 746 # paralellizing translations in the self-build. If we're going | |
| 747 # to use this for anything more complex, then throttling the | |
| 748 # number of active processes to exactly UTMAN_CONCURRENCY would | |
| 749 # be a useful feature. | |
| 750 CT_WAIT_QUEUE="" | |
| 751 QueueLastProcess() { | |
| 752 local pid=$! | |
| 753 CT_WAIT_QUEUE+=" ${pid}" | |
| 754 if ! QueueConcurrent ; then | |
| 755 QueueWait | |
| 756 fi | |
| 757 } | |
| 758 | |
| 759 QueueConcurrent() { | |
| 760 [ ${UTMAN_CONCURRENCY} -gt 1 ] | |
| 761 } | |
| 762 | |
| 763 QueueWait() { | |
| 764 for pid in ${CT_WAIT_QUEUE} ; do | |
| 765 wait ${pid} | |
| 766 done | |
| 767 CT_WAIT_QUEUE="" | |
| 768 } | |
| 769 | |
| 770 # Add a trap so that if the user Ctrl-C's or kills | |
| 771 # this script while background processes are running, | |
| 772 # the background processes don't keep going. | |
| 773 trap 'QueueKill' SIGINT SIGTERM SIGHUP | |
| 774 QueueKill() { | |
| 775 echo | |
| 776 echo "Killing queued processes: ${CT_WAIT_QUEUE}" | |
| 777 for pid in ${CT_WAIT_QUEUE} ; do | |
| 778 kill ${pid} &> /dev/null || true | |
| 779 done | |
| 780 echo | |
| 781 CT_WAIT_QUEUE="" | |
| 782 } | |
| 783 | |
| 784 QueueEmpty() { | |
| 785 [ "${CT_WAIT_QUEUE}" == "" ] | |
| 786 } | |
| 787 | |
| 788 #+ RunWithRetry <max_retries> <delay_sec> cmd [args] | |
| 789 RunWithRetry() { | |
| 790 local max_retries="$1" | |
| 791 local delay_sec="$2" | |
| 792 local cmdname=$(basename "$3") | |
| 793 shift 2 | |
| 794 | |
| 795 local retries=0 | |
| 796 while true; do | |
| 797 if "$@" ; then | |
| 798 return 0 | |
| 799 fi | |
| 800 | |
| 801 StepBanner "RUN-WITH-RETRY" "Execution of '${cmdname}' failed." | |
| 802 retries=$[retries+1] | |
| 803 if [ ${retries} -lt ${max_retries} ]; then | |
| 804 StepBanner "RUN-WITH-RETRY" "Retrying in ${delay_sec} seconds." | |
| 805 sleep ${delay_sec} | |
| 806 else | |
| 807 StepBanner "RUN-WITH-RETRY" \ | |
| 808 "'${cmdname}' failed ${max_retries} times. Aborting." | |
| 809 return 1 | |
| 810 fi | |
| 811 done | |
| 812 | |
| 813 } | |
| OLD | NEW |