代码拉取完成,页面将自动刷新
# Library to cache downloaded and locally-built Homebrew bottles in Travis OSX build.
#Should be in Travis' cache
BREW_LOCAL_BOTTLE_METADATA="$HOME/local_bottle_metadata"
#FIXME: temporary fix to enable the build, should be replaced with the proper path to the cache dir
mkdir -p $BREW_LOCAL_BOTTLE_METADATA
# Starting reference point for elapsed build time; seconds since the epoch.
#TRAVIS_TIMER_START_TIME is set at the start of a log fold, in nanoseconds since the epoch
BREW_TIME_START=$(($TRAVIS_TIMER_START_TIME/10**9))
# If after a package is built, elapsed time is more than this many seconds, fail the build but save Travis cache
# The cutoff moment should leave enough time till Travis' job time limit to process the main project.
# Since we have moved deps into a separate stage, we don't need to leave time for the project any more
BREW_TIME_LIMIT=$((42*60))
# If a slow-building package is about to be built and the projected build end moment is beyond this many seconds,
# skip that build, fail the Travis job and save Travis cache.
# This cutoff should leave enough time for before_cache and cache save.
BREW_TIME_HARD_LIMIT=$((43*60))
# Auto cleanup can delete locally-built bottles
# when the caching logic isn't prepared for that
export HOMEBREW_NO_INSTALL_CLEANUP=1
# Don't query analytical info online on `brew info`,
# this takes several seconds and we don't need it
# see https://docs.brew.sh/Manpage , "info formula" section
export HOMEBREW_NO_GITHUB_API=1
#Packages already installed in the current session to avoid checking them again
_BREW_ALREADY_INSTALLED='$' #$ = illegal package name; a blank line would cause macos grep to swallow everything
#Public functions
function brew_install_and_cache_within_time_limit {
# Install the package and its dependencies one by one;
# use bottle if available, build and cache bottle if not.
# Terminate and exit with status 1 if this takes too long.
# Exit with status 2 on any other error.
_brew_install_and_cache_within_time_limit $@ \
|| if test $? -eq 1; then brew_go_bootstrap_mode; return 1; else return 2; fi
}
function brew_add_local_bottles {
# Should be called after `brew update` at startup.
# Adds metadata for cached locally-built bottles to local formulas
# so that `brew` commands can find them.
# If the package was updated, removes the corresponding files
# and the bottle's entry in the formula, if any.
# Bottle entry in formula:
# bottle do
# <...>
# sha256 "<sha256>" => :<os_codename>
# <...>
# end
echo "Cached bottles:"
ls "$(brew --cache)/downloads" || true #may not exist initially since it's "$(brew --cache)" that is in Travis cache
echo "Saved .json's and links:"
ls "$BREW_LOCAL_BOTTLE_METADATA"
for JSON in "$BREW_LOCAL_BOTTLE_METADATA"/*.json; do
[ -e "$JSON" ] || break # OSX 10.11 bash has no nullglob
local PACKAGE JSON_VERSION JSON_REBUILD OS_CODENAME BOTTLE_HASH
_brew_parse_bottle_json "$JSON" PACKAGE JSON_VERSION JSON_REBUILD OS_CODENAME BOTTLE_HASH
echo "Adding local bottle: $PACKAGE ${JSON_VERSION}_${JSON_REBUILD}"
local FORMULA_VERSION FORMULA_REBUILD FORMULA_BOTTLE_HASH
_brew_parse_package_info "$PACKAGE" "$OS_CODENAME" FORMULA_VERSION FORMULA_REBUILD FORMULA_BOTTLE_HASH
local FORMULA_HAS_BOTTLE; [ -n "$FORMULA_BOTTLE_HASH" ] && FORMULA_HAS_BOTTLE=1 || true
local BOTTLE_LINK BOTTLE=""; BOTTLE_LINK="${JSON}.bottle.lnk";
local BOTTLE_EXISTS= BOTTLE_MISMATCH= VERSION_MISMATCH=
# Check that the bottle file exists and is still appropriate for the formula
if [[ "$FORMULA_VERSION" != "$JSON_VERSION" || "$JSON_REBUILD" != "$FORMULA_REBUILD" ]]; then
VERSION_MISMATCH=1;
echo "The cached bottle is obsolete: formula ${FORMULA_VERSION}_${FORMULA_REBUILD}"
fi
if [ -f "$BOTTLE_LINK" ]; then
BOTTLE=$(cat "$BOTTLE_LINK");
BOTTLE=$(cd "$(dirname "$BOTTLE")"; pwd)/$(basename "$BOTTLE")
if [ -e "$BOTTLE" ]; then
BOTTLE_EXISTS=1;
# The hash in `brew --cache $PACKAGE` entry is generated from download URL,
# which itself is generated from base URL and version
# (see Homebrew/Library/Homebrew/download_strategy.rb:cached_location).
# So if version changes, hashes will always mismatch anyway
# and we don't need a separate message about this.
# XXX: OSX doesn't have `realpath` so can't compare the entire paths
if [ -n "$FORMULA_HAS_BOTTLE" -a -z "$VERSION_MISMATCH" -a \
"$(basename "$(brew --cache "$PACKAGE")")" != "$(basename "$BOTTLE")" ]; then
BOTTLE_MISMATCH=1;
echo "Cached bottle file doesn't correspond to formula's cache entry!" \
"This can happen if download URL has changed." >&2
fi
else
echo "Cached bottle file is missing!" >&2
fi
else
echo "Link file is missing or of invalid type!" >&2
fi
# Delete cached bottle and all metadata if invalid
if [[ -z "$BOTTLE_EXISTS" || -n "$VERSION_MISMATCH" || -n "$BOTTLE_MISMATCH" ]]; then
echo "Deleting the cached bottle and all metadata"
if [ "$FORMULA_BOTTLE_HASH" == "$BOTTLE_HASH" ]; then
echo "A bottle block for the cached bottle was merged into the updated formula. Removing..."
local FORMULA; FORMULA=$(brew formula "$PACKAGE")
perl -wpe 'BEGIN { our $IN_BLOCK=0; }
if ( ($IN_BLOCK==0) && /^\s*bottle\s+do\s*$/ ) { $IN_BLOCK=1; next; }
if ( ($IN_BLOCK==1) && /^\s*end\s*$/ ) { $IN_BLOCK=-1; next; }
if ( ($IN_BLOCK==1) && /^\s*sha256\s+"(\w+)"\s+=>\s+:\w+\s*$/ )
{ if ( $1 eq "'"$BOTTLE_HASH"'" ) {$_="";}; next; }
' <"$FORMULA" >"${FORMULA}.new"
# Depending on diff version, 1 may mean differences found
# https://stackoverflow.com/questions/6971284/what-are-the-error-exit-values-for-diff
diff -u "$FORMULA" "${FORMULA}.new" || test $? -le 1
( cd $(dirname "$FORMULA")
FORMULA=$(basename "$FORMULA")
mv -v "${FORMULA}.new" "$FORMULA"
git commit -m "Removed obsolete local bottle ${JSON_VERSION}_${JSON_REBUILD} :${OS_CODENAME}" "$FORMULA"
)
fi
if [ -n "$BOTTLE" -a -n "$BOTTLE_EXISTS" ]; then rm "$BOTTLE"; fi
rm -f "$BOTTLE_LINK"
rm "$JSON"
#(Re)add metadata to the formula otherwise
else
if [ "$FORMULA_BOTTLE_HASH" == "$BOTTLE_HASH" ]; then
echo "The cached bottle is already present in the formula"
else
brew bottle --merge --write "$JSON"
fi
fi
done
}
function brew_cache_cleanup {
#Cleanup caching directories
# Is supposed to be called in before_cache
#Lefovers from some failure probably
rm -f "$BREW_LOCAL_BOTTLE_METADATA"/*.tar.gz
#`brew cleanup` may delete locally-built bottles that weren't needed this time
# so we're saving and restoring them
local BOTTLE_LINK BOTTLE
for BOTTLE_LINK in "$BREW_LOCAL_BOTTLE_METADATA"/*.lnk; do
[ -e "$BOTTLE_LINK" ] || break
BOTTLE=$(cat "$BOTTLE_LINK")
ln "$BOTTLE" "$BREW_LOCAL_BOTTLE_METADATA/"
done
brew cleanup
local BOTTLE_BASENAME
for BOTTLE_LINK in "$BREW_LOCAL_BOTTLE_METADATA"/*.lnk; do
[ -e "$BOTTLE_LINK" ] || break
BOTTLE=$(cat "$BOTTLE_LINK")
BOTTLE_BASENAME=$(basename "$BOTTLE")
if test ! -e "$BOTTLE"; then
echo "Restoring: $BOTTLE_BASENAME"
mv "$BREW_LOCAL_BOTTLE_METADATA/$BOTTLE_BASENAME" "$BOTTLE"
else
rm "$BREW_LOCAL_BOTTLE_METADATA/$BOTTLE_BASENAME"
fi
done
}
function brew_go_bootstrap_mode {
# Can be overridden
# Terminate the build but ensure saving the cache
local EXIT_CODE=${1:-1}
echo "Going into cache bootstrap mode"
BREW_BOOTSTRAP_MODE=1
#Can't just `exit` because that would terminate the build without saving the cache
#Have to replace further actions with no-ops
local MESSAGE=""; if [ "$EXIT_CODE" -ne 0 ]; then
MESSAGE='Building dependencies took too long. Restart the build in Travis UI to continue from cache.';
fi
eval '
function '"$cmd"' { return 0; }
function repair_wheelhouse { return 0; }
function install_run {'\
"$(if [ -n "$MESSAGE" ]; then
echo \
' echo -e "\n'"$MESSAGE"'\n"'
fi)"\
'
# Travis runs user scripts via `eval` i.e. in the same shell process.
# So have to unset errexit in order to get to cache save stage
set +e; return '"$EXIT_CODE"'
}'
}
#Internal functions
function _brew_install_and_cache_within_time_limit {
# This fn is run with || so errexit can't be enabled
local PACKAGE TIME_LIMIT TIME_HARD_LIMIT TIME_START MARKED_INSTALLED
PACKAGE="${1:?}" || return 2
TIME_LIMIT=${2:-$BREW_TIME_LIMIT} || return 2
TIME_HARD_LIMIT=${3:-$BREW_TIME_HARD_LIMIT} || return 2
TIME_START=${4:-$BREW_TIME_START} || return 2
if grep -qxFf <(cat <<<"$_BREW_ALREADY_INSTALLED") <<<"$PACKAGE"; then
MARKED_INSTALLED=1
fi
if [ -n "$MARKED_INSTALLED" ] || (brew list --versions "$PACKAGE" >/dev/null && ! (brew outdated | grep -qxF "$PACKAGE")); then
echo "Already installed and the latest version: $PACKAGE"
if [ -z "$MARKED_INSTALLED" ]; then _brew_mark_installed "$PACKAGE"; fi
return 0
fi
local BUILD_FROM_SOURCE INCLUDE_BUILD KEG_ONLY
_brew_is_bottle_available "$PACKAGE" KEG_ONLY || BUILD_FROM_SOURCE=1
[ -n "$BUILD_FROM_SOURCE" ] && INCLUDE_BUILD="--include-build" || true
# Whitespace is illegal in package names so converting all whitespace into single spaces due to no quotes is okay.
DEPS=`brew deps "$PACKAGE" $INCLUDE_BUILD` || return 2
DEPS=`grep -vxF <(cat <<<"$_BREW_ALREADY_INSTALLED") <<<"$DEPS"` || test $? -eq 1 || return 2
for dep in $DEPS; do
#TIME_LIMIT only has to be met if we'll be actually building the main project this iteration, i.e. after the "root" module installation
#While we don't know that yet, we can make better use of Travis-given time with a laxer limit
#We still can't overrun TIME_HARD_LIMIT as that wouldn't leave time to save the cache
_brew_install_and_cache_within_time_limit "$dep" $(((TIME_LIMIT+TIME_HARD_LIMIT)/2)) "$TIME_HARD_LIMIT" "$TIME_START" || return $?
done
_brew_check_slow_building_ahead "$PACKAGE" "$TIME_START" "$TIME_HARD_LIMIT" || return $?
_brew_install_and_cache "$PACKAGE" "$([[ -z "$BUILD_FROM_SOURCE" ]] && echo 1 || echo 0)" "$KEG_ONLY" || return 2
_brew_check_elapsed_build_time "$TIME_START" "$TIME_LIMIT" || return $?
}
function _brew_parse_bottle_json {
# Parse JSON file resulting from `brew bottle --json`
# and save data into specified variables
local JSON; JSON="${1:?}"; shift
local JSON_DATA; JSON_DATA=$(python2.7 -c 'if True:
import sys,json; j=json.load(open(sys.argv[1],"rb")); [name]=j.keys(); [pdata]=j.values()
print name
print pdata["formula"]["pkg_version"]
print pdata["bottle"]["rebuild"]
[(tag_name, tag_dict)]=pdata["bottle"]["tags"].items()
print tag_name
print tag_dict["sha256"]
' "$JSON")
unset JSON
{ local i v; for i in {1..5}; do
read -r v
eval "${1:?}=\"$v\""
shift
done } <<< "$JSON_DATA"
}
function _brew_parse_package_info {
# Get and parse `brew info --json` about a package
# and save data into specified variables
local PACKAGE OS_CODENAME
PACKAGE="${1:?}"; shift
OS_CODENAME="${1:?}"; shift
local JSON_DATA; JSON_DATA=$(python2.7 -c 'if True:
import sys, json, subprocess; j=json.loads(subprocess.check_output(("brew","info","--json=v1",sys.argv[1])))
data=j[0]
revision=data["revision"]
# in bottle''s json, revision is included into version; here, they are separate
print data["versions"]["stable"]+("_"+str(revision) if revision else "")
bottle_data=data["bottle"].get("stable",{"rebuild":"","files":{}})
print bottle_data["rebuild"]
print bottle_data["files"].get(sys.argv[2],{"sha256":"!?"})["sha256"] #prevent losing trailing blank line to command substitution
' \
"$PACKAGE" "$OS_CODENAME"); JSON_DATA="${JSON_DATA%\!\?}" #!? can't occur in a hash
unset PACKAGE OS_CODENAME
{ local i v; for i in {1..3}; do
read -r v
eval "${1:?}=\"$v\""
shift
done } <<< "$JSON_DATA"
}
function _brew_is_bottle_available {
local PACKAGE;PACKAGE="${1:?}"
local VAR_KEG_ONLY="$2"
# `brew info` prints "Error: Broken pipe" if piped directly to `head` and the info is long
# 141 = 128 + SIGPIPE
local INFO;INFO="$((brew info "$PACKAGE" | cat || test $? -eq 141) | head -n 1)"
if [ -n "$VAR_KEG_ONLY" ]; then
if grep -qwF '[keg-only]' <<<"$INFO"; then
eval "${VAR_KEG_ONLY}=1"
else
eval "${VAR_KEG_ONLY}=0"
fi
fi
if grep -qxEe '[[:space:]]*bottle :unneeded' $(brew formula "$PACKAGE"); then
echo "Bottle disabled: $PACKAGE"
return 0
fi
if grep -qwF '(bottled)' <<<"$INFO"; then
echo "Bottle available: $INFO"
return 0
else
echo "Bottle not available: $INFO"
return 1
fi
}
function _brew_install_and_cache {
# Install bottle or make and cache bottle.
# assumes that deps were already installed
# and not already the latest version
local PACKAGE USE_BOTTLE KEG_ONLY
PACKAGE="${1:?}"
USE_BOTTLE="${2:?}"
KEG_ONLY="${3:?}"
local VERB
if brew list --versions "$PACKAGE"; then
# Install alongside the old version to avoid to have to update "runtime dependents"
# https://discourse.brew.sh/t/can-i-install-a-new-version-without-having-to-upgrade-runtime-dependents/4443
VERB="install --force"
if [ "$KEG_ONLY" -eq 0 ]; then
brew unlink "$PACKAGE"
fi
else
VERB=install
fi
if [[ "$USE_BOTTLE" -gt 0 ]]; then
echo "Installing bottle for: $PACKAGE"
brew $VERB "$PACKAGE"
else
echo "Building bottle for: $PACKAGE"
brew $VERB --build-bottle "$PACKAGE"
exec 3>&1
local OUT=$(brew bottle --json "$PACKAGE" | tee /dev/fd/3)
exec 3>&-
ls "$PACKAGE"*
# doesn't seem to be a documented way to get file names
local BOTTLE; BOTTLE=$(grep -Ee '^./' <<<"$OUT")
#proper procedure as per https://discourse.brew.sh/t/how-are-bottle-and-postinstall-related-is-it-safe-to-run-bottle-after-postinstall/3410/4
brew uninstall --ignore-dependencies "$PACKAGE"
brew $VERB "$BOTTLE"
local JSON; JSON=$(sed -E 's/bottle(.[[:digit:]]+)?\.tar\.gz$/bottle.json/' <<<"$BOTTLE")
#`brew bottle --merge` doesn't return nonzero on nonexisting json file
test -f "$JSON" -a -f "$BOTTLE"
brew bottle --merge --write "$JSON"
local CACHED_BOTTLE; CACHED_BOTTLE="$(brew --cache "$PACKAGE")"
mv "$BOTTLE" "$CACHED_BOTTLE";
local CACHED_JSON; CACHED_JSON="${BREW_LOCAL_BOTTLE_METADATA}/$(basename "$JSON")"
mv "$JSON" "$CACHED_JSON"
#Symlinks aren't cached by Travis. Will just save paths in files then.
local BOTTLE_LINK; BOTTLE_LINK="${CACHED_JSON}.bottle.lnk"
echo "$CACHED_BOTTLE" >"$BOTTLE_LINK"
fi
_brew_mark_installed "$PACKAGE"
}
function _brew_mark_installed {
_BREW_ALREADY_INSTALLED="$_BREW_ALREADY_INSTALLED"$'\n'"${1:?}"
}
function _brew_check_elapsed_build_time {
# If time limit has been reached,
# arrange for further build to be skipped and return 1
local TIME_START TIME_LIMIT ELAPSED_TIME
TIME_START="${1:?}"
TIME_LIMIT="${2:?}"
ELAPSED_TIME=$(($(date +%s) - $TIME_START))
echo "Elapsed time: "$(($ELAPSED_TIME/60))"m (${ELAPSED_TIME}s)"
if [[ "$ELAPSED_TIME" -gt $TIME_LIMIT ]]; then
brew_go_bootstrap_mode
return 1
fi
return 0
}
function _brew_check_slow_building_ahead {
#If the package's projected build completion is higher than hard limit,
# skip it and arrange for further build to be skipped and return 1
local PACKAGE TIME_START TIME_HARD_LIMIT
PACKAGE="${1:?}"
TIME_START="${2:?}"
TIME_HARD_LIMIT="${3:?}"
local PROJECTED_BUILD_TIME
PROJECTED_BUILD_TIME=$(echo "$BREW_SLOW_BUILIDING_PACKAGES" | awk '$1=="'"$PACKAGE"'"{print $2}')
[ -z "$PROJECTED_BUILD_TIME" ] && return 0 || true
local PROJECTED_BUILD_END_ELAPSED_TIME
PROJECTED_BUILD_END_ELAPSED_TIME=$(( $(date +%s) - TIME_START + PROJECTED_BUILD_TIME * 60))
if [[ "$PROJECTED_BUILD_END_ELAPSED_TIME" -ge "$TIME_HARD_LIMIT" ]]; then
echo -e "\nProjected build end elapsed time for $PACKAGE: $((PROJECTED_BUILD_END_ELAPSED_TIME/60))m ($PROJECTED_BUILD_END_ELAPSED_TIMEs)"
brew_go_bootstrap_mode
return 1
fi
return 0
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。