112 lines
5.3 KiB
TOML
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'''
|