Files
brave-core/rewrite/chrome/updater/mac/.install.sh.toml
T

112 lines
5.3 KiB
TOML

# Copyright (c) 2026 The Brave Authors. All rights reserved.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at https://mozilla.org/MPL/2.0/.
# Upstream's variable `update_app` contains the path to the new browser
# version's .app directory. As of this writing, it is computed as:
# update_app="${update_dmg_mount_point}/${APP_DIR}"
# where
# APP_DIR="$(basename "${installed_app_path}")"
# This fails when the browser's installation directory has a non-standard name.
# For example: If the browser is installed in /Applications/Brave.app instead of
# /Applications/Brave Browser.app, then `update_app` tries to read Brave.app
# from the DMG, when it should read Brave Browser.app. The substitution below
# fixes this.
[[substitution]]
description = 'Use PRODUCT_NAME instead of APP_DIR for update app path'
pattern = '${update_dmg_mount_point}/${APP_DIR}'
replace = '${update_dmg_mount_point}/${PRODUCT_NAME}.app'
# There are two installs scripts for updates in upstream: keystone_install.sh
# and .install.sh. Chrome uses the former but it has legacy code related to
# Keystone. The more modern alternative is .install.sh. But it lacks a fix
# from Chromium CL 5866112. This substitution applies it.
[[substitution]]
description = 'Omit perms, link and dir times when non-root'
pattern = 'RSYNC_FLAGS="--ignore-times --links --perms --recursive --times"'
replace = 'RSYNC_FLAGS="--ignore-times --links $(if [[ ${EUID} -eq 0 ]]; then echo "--perms --recursive --times"; else echo "--no-perms --executability --chmod=u=rwX,go=rX --recursive"; fi)"'
# install_from_archive.mm executes .install.sh with a timeout of 15 minutes. The
# versioned-dir rsync normally takes only a few seconds. But there was one
# reported case where it took 16 minutes. (It seems likely that there was some
# interference; either the computer went to sleep or the OS was blocking on a
# prompt.) This case bricked the browser because install_from_archive.mm then
# interrupted the later rsyncing of the app directory mid-execution.
# The following substitution runs rsync with its own, lower timeout. This gives
# the script a chance to put the browser back into a usable state when the
# parent timeout would have likely been exceeded.
[[substitution]]
description = 'Cap versioned-dir rsync at 10 minutes, capture status'
re_pattern = '''if ! rsync (.*? "\$\{update_versioned_dir\}/" .*?); then'''
re_flags = ['DOTALL']
replace = '''if ! perl -e 'alarm shift; exec @ARGV' "${RSYNC_TIMEOUT:-600}" rsync \1; then
local rsync_status=${PIPESTATUS[0]}
# The assignment we just made set PIPESTATUS[0] to 0. Restore it. The
# leading `!` keeps `set -e` from terminating the script.
! (exit "${rsync_status}")'''
[[substitution]]
description = '''Try various fixes for exit code 12 failures.
We anchor on upstream's `exit 12` because it is expected to remain unchanged.
The reasons are:
1. The numeric value gets used in telemetry.
2. It is documented at the top of the script.
3. Other numeric error values in //chrome/updater are treated as unchangeable.
We start our custom codes at 70 in order to not clash with upstream's, even in
case they add new ones beyond the current maximum 16.
'''
pattern = 'exit 12'
replace = '''if [[ ${rsync_status} -eq 142 ]]; then
# rsync timed out.
exit 80
fi
# Try various remedies; Report in exit code what would have worked.
local mkdir_stderr
if ! mkdir_stderr="$(mkdir -p "${new_versioned_dir}" 2>&1 1>/dev/null)"
then
# If `mkdir` fails, then other remedies won't work either; Exit with a
# code that tells us the cause.
case "${mkdir_stderr}" in
*"Read-only file system"*)
exit 70 ;;
*"No space left on device"*|*"Disc quota exceeded"*)
exit 71 ;;
*"Operation not permitted"*)
exit 72 ;;
*"Permission denied"*)
exit 73 ;;
*"File exists"*|*"Not a directory"*)
exit 74 ;;
*)
exit 75 ;;
esac
fi
# `mkdir` succeeded. Retry the original rsync. If it succeeds, then clean
# up and return an exit code that tells us that this fix is worth keeping.
if rsync ${RSYNC_FLAGS} --delete-before "${update_versioned_dir}/" \
"${new_versioned_dir}"; then
rm -rf "${new_versioned_dir}"
exit 76
fi
# Another potential remedy is to rsync into the parent directory. As
# before, if this succeeds, clean up and return a unique exit code that
# tells us that this workaround is worth keeping.
if rsync ${RSYNC_FLAGS} --delete-before "${update_versioned_dir}" \
"${installed_versions_dir}"; then
rm -rf "${new_versioned_dir}"
exit 77
fi
# Try the same rsync-into-parent, but from a clean slate.
rm -rf "${new_versioned_dir}"
if rsync ${RSYNC_FLAGS} --delete-before "${update_versioned_dir}" \
"${installed_versions_dir}"; then
rm -rf "${new_versioned_dir}"
exit 78
fi
# None of the attempted remedies worked.
rm -rf "${new_versioned_dir}"
exit 79'''