Skip to content

Commit

Permalink
Improve updating behaviour
Browse files Browse the repository at this point in the history
- Rename use of "preinstall" to "auto update". The original "preinstall"
  naming came from the fact that we used to only auto-update before
  `brew install` but now that it's many commands: this is more confusing
  than useful.
- Add `HOMEBREW_NO_UPDATE_REPORT_ONLY_INSTALLED` and remove
  `HOMEBREW_UPDATE_REPORT_ONLY_INSTALLED`; the latter is now the default
  and the prior provides an opt-out for better output, performance and
  avoiding reading potentially untrusted formulae.
- Add `HOMEBREW_UPDATE_FORMULA_VERSION_CHECKS` and don't check formula
  versions by default for better performance by default.

Co-authored-by: Eric Knibbe <3324775+EricFromCanada@users.noreply.github.com>
Co-authored-by: Sam Ford <1584702+samford@users.noreply.github.com>
  • Loading branch information
3 people committed May 19, 2022
1 parent 7384a5e commit c597a12
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 66 deletions.
18 changes: 9 additions & 9 deletions Library/Homebrew/brew.sh
Expand Up @@ -226,13 +226,13 @@ EOS
fi
}

# Let user know we're still updating Homebrew if brew update --preinstall
# Let user know we're still updating Homebrew if brew update --auto-update
# exceeds 3 seconds.
update-preinstall-timer() {
auto-update-timer() {
sleep 3
# Outputting a command but don't want to run it, hence single quotes.
# shellcheck disable=SC2016
echo 'Running `brew update --preinstall`...' >&2
echo 'Running `brew update --auto-update`...' >&2
if [[ -z "${HOMEBREW_NO_ENV_HINTS}" && -z "${HOMEBREW_AUTO_UPDATE_SECS}" ]]
then
# shellcheck disable=SC2016
Expand All @@ -244,11 +244,11 @@ update-preinstall-timer() {

# These variables are set from various Homebrew scripts.
# shellcheck disable=SC2154
update-preinstall() {
auto-update() {
[[ -z "${HOMEBREW_HELP}" ]] || return
[[ -z "${HOMEBREW_NO_AUTO_UPDATE}" ]] || return
[[ -z "${HOMEBREW_AUTO_UPDATING}" ]] || return
[[ -z "${HOMEBREW_UPDATE_PREINSTALL}" ]] || return
[[ -z "${HOMEBREW_UPDATE_AUTO}" ]] || return
[[ -z "${HOMEBREW_AUTO_UPDATE_CHECKED}" ]] || return

# If we've checked for updates, we don't need to check again.
Expand Down Expand Up @@ -280,11 +280,11 @@ update-preinstall() {

if [[ -z "${HOMEBREW_VERBOSE}" ]]
then
update-preinstall-timer &
auto-update-timer &
timer_pid=$!
fi

brew update --preinstall
brew update --auto-update

if [[ -n "${timer_pid}" ]]
then
Expand Down Expand Up @@ -842,7 +842,7 @@ then
source "${HOMEBREW_BASH_COMMAND}"

{
update-preinstall "$@"
auto-update "$@"
"homebrew-${HOMEBREW_COMMAND}" "$@"
exit $?
}
Expand All @@ -856,7 +856,7 @@ else
# HOMEBREW_RUBY_PATH set by utils/ruby.sh
# shellcheck disable=SC2154
{
update-preinstall "$@"
auto-update "$@"
exec "${HOMEBREW_RUBY_PATH}" "${HOMEBREW_RUBY_WARNINGS}" "${RUBY_DISABLE_OPTIONS}" \
"${HOMEBREW_LIBRARY}/Homebrew/brew.rb" "$@"
}
Expand Down
43 changes: 24 additions & 19 deletions Library/Homebrew/cmd/update-report.rb
Expand Up @@ -16,9 +16,9 @@ module Homebrew

module_function

def update_preinstall_header(args:)
@update_preinstall_header ||= begin
ohai "Auto-updated Homebrew!" if args.preinstall?
def auto_update_header(args:)
@auto_update_header ||= begin
ohai "Auto-updated Homebrew!" if args.auto_update?
true
end
end
Expand All @@ -29,7 +29,7 @@ def update_report_args
description <<~EOS
The Ruby implementation of `brew update`. Never called manually.
EOS
switch "--preinstall",
switch "--auto-update", "--preinstall",
description: "Run in 'auto-update' mode (faster, less output)."
switch "-f", "--force",
description: "Treat installed and updated formulae as if they are from "\
Expand Down Expand Up @@ -79,7 +79,7 @@ def output_update_report
FileUtils.rm_f HOMEBREW_LOCKS/"update"

update_args = []
update_args << "--preinstall" if args.preinstall?
update_args << "--auto-update" if args.auto_update?
update_args << "--force" if args.force?
exec HOMEBREW_BREW_FILE, "update", *update_args
end
Expand Down Expand Up @@ -123,7 +123,7 @@ def output_update_report
odie "update-report should not be called directly!" if initial_revision.empty? || current_revision.empty?

if initial_revision != current_revision
update_preinstall_header args: args
auto_update_header args: args

updated = true

Expand All @@ -150,7 +150,7 @@ def output_update_report
updated_taps = []
Tap.each do |tap|
next unless tap.git?
next if (tap.core_tap? || tap == "homebrew/cask") && Homebrew::EnvConfig.install_from_api? && args.preinstall?
next if (tap.core_tap? || tap == "homebrew/cask") && Homebrew::EnvConfig.install_from_api? && args.auto_update?

if ENV["HOMEBREW_MIGRATE_LINUXBREW_FORMULAE"].present? && tap.core_tap? &&
Settings.read("linuxbrewmigrated") != "true"
Expand Down Expand Up @@ -182,12 +182,12 @@ def output_update_report
end
if reporter.updated?
updated_taps << tap.name
hub.add(reporter, preinstall: args.preinstall?)
hub.add(reporter, auto_update: args.auto_update?)
end
end

unless updated_taps.empty?
update_preinstall_header args: args
auto_update_header args: args
puts "Updated #{updated_taps.count} #{"tap".pluralize(updated_taps.count)} (#{updated_taps.to_sentence})."
updated = true
end
Expand All @@ -196,7 +196,12 @@ def output_update_report
if hub.empty?
puts "No changes to formulae." unless args.quiet?
else
hub.dump(updated_formula_report: !args.preinstall?) unless args.quiet?
if ENV.fetch("HOMEBREW_UPDATE_REPORT_ONLY_INSTALLED", false)
opoo "HOMEBREW_UPDATE_REPORT_ONLY_INSTALLED is now the default behaviour, " \
"so you can unset it from your environment."
end

hub.dump(updated_formula_report: !args.auto_update?) unless args.quiet?
hub.reporters.each(&:migrate_tap_migration)
hub.reporters.each { |r| r.migrate_formula_rename(force: args.force?, verbose: args.verbose?) }
CacheStoreDatabase.use(:descriptions) do |db|
Expand All @@ -208,7 +213,7 @@ def output_update_report
.update_from_report!(hub)
end

if !args.preinstall? && !args.quiet?
if !args.auto_update? && !args.quiet?
outdated_formulae = Formula.installed.count(&:outdated?)
outdated_casks = Cask::Caskroom.casks.count(&:outdated?)
update_pronoun = if (outdated_formulae + outdated_casks) == 1
Expand All @@ -234,8 +239,8 @@ def output_update_report
end
end
end
puts if args.preinstall?
elsif !args.preinstall? && !ENV["HOMEBREW_UPDATE_FAILED"] && !ENV["HOMEBREW_MIGRATE_LINUXBREW_FORMULAE"]
puts if args.auto_update?
elsif !args.auto_update? && !ENV["HOMEBREW_UPDATE_FAILED"] && !ENV["HOMEBREW_MIGRATE_LINUXBREW_FORMULAE"]
puts "Already up-to-date." unless args.quiet?
end

Expand Down Expand Up @@ -326,7 +331,7 @@ def initialize(tap)
raise ReporterRevisionUnsetError, current_revision_var if @current_revision.empty?
end

def report(preinstall: false)
def report(auto_update: false)
return @report if @report

@report = Hash.new { |h, k| h[k] = [] }
Expand Down Expand Up @@ -364,8 +369,8 @@ def report(preinstall: false)
when "M"
name = tap.formula_file_to_name(src)

# Skip reporting updated formulae to speed up automatic updates.
if preinstall
# Skip reporting updated formulae by default (as it's slow).
unless Homebrew::EnvConfig.update_formula_version_checks?
@report[:M] << name
next
end
Expand Down Expand Up @@ -570,9 +575,9 @@ def select_formula(key)
@hash.fetch(key, [])
end

def add(reporter, preinstall: false)
def add(reporter, auto_update: false)
@reporters << reporter
report = reporter.report(preinstall: preinstall).delete_if { |_k, v| v.empty? }
report = reporter.report(auto_update: auto_update).delete_if { |_k, v| v.empty? }
@hash.update(report) { |_key, oldval, newval| oldval.concat(newval) }
end

Expand Down Expand Up @@ -603,7 +608,7 @@ def dump(updated_formula_report: true)
private

def dump_formula_report(key, title)
only_installed = Homebrew::EnvConfig.update_report_only_installed?
only_installed = !Homebrew::EnvConfig.no_update_report_only_installed?

formulae = select_formula(key).sort.map do |name, new_name|
# Format list items of renamed formulae
Expand Down
22 changes: 11 additions & 11 deletions Library/Homebrew/cmd/update.sh
Expand Up @@ -3,7 +3,7 @@
#: Fetch the newest version of Homebrew and all formulae from GitHub using `git`(1) and perform any necessary migrations.
#:
#: --merge Use `git merge` to apply updates (rather than `git rebase`).
#: --preinstall Run on auto-updates (e.g. before `brew install`). Skips some slower steps.
#: --auto-update Run on auto-updates (e.g. before `brew install`). Skips some slower steps.
#: -f, --force Always do a slower, full update check (even if unnecessary).
#: -q, --quiet Make some output more quiet
#: -v, --verbose Print the directories checked and `git` operations performed.
Expand Down Expand Up @@ -337,7 +337,7 @@ homebrew-update() {
--merge) HOMEBREW_MERGE=1 ;;
--force) HOMEBREW_UPDATE_FORCE=1 ;;
--simulate-from-current-branch) HOMEBREW_SIMULATE_FROM_CURRENT_BRANCH=1 ;;
--preinstall) export HOMEBREW_UPDATE_PREINSTALL=1 ;;
--auto-update) export HOMEBREW_UPDATE_AUTO=1 ;;
--*) ;;
-*)
[[ "${option}" == *v* ]] && HOMEBREW_VERBOSE=1
Expand Down Expand Up @@ -547,7 +547,7 @@ EOS
for DIR in "${HOMEBREW_REPOSITORY}" "${HOMEBREW_LIBRARY}"/Taps/*/*
do
if [[ -n "${HOMEBREW_INSTALL_FROM_API}" ]] &&
[[ -n "${HOMEBREW_UPDATE_PREINSTALL}" ]] &&
[[ -n "${HOMEBREW_UPDATE_AUTO}" ]] &&
[[ "${DIR}" == "${HOMEBREW_CORE_REPOSITORY}" ]]
then
continue
Expand Down Expand Up @@ -591,7 +591,7 @@ EOS
(
UPSTREAM_REPOSITORY_URL="$(git config remote.origin.url)"

# HOMEBREW_UPDATE_FORCE and HOMEBREW_UPDATE_PREINSTALL aren't modified here so ignore subshell warning.
# HOMEBREW_UPDATE_FORCE and HOMEBREW_UPDATE_AUTO aren't modified here so ignore subshell warning.
# shellcheck disable=SC2030
if [[ "${UPSTREAM_REPOSITORY_URL}" == "https://github.com/"* ]]
then
Expand Down Expand Up @@ -630,7 +630,7 @@ EOS
# Touch FETCH_HEAD to confirm we've checked for an update.
[[ -f "${DIR}/.git/FETCH_HEAD" ]] && touch "${DIR}/.git/FETCH_HEAD"
[[ -z "${HOMEBREW_UPDATE_FORCE}" ]] && [[ "${UPSTREAM_SHA_HTTP_CODE}" == "304" ]] && exit
elif [[ -n "${HOMEBREW_UPDATE_PREINSTALL}" ]]
elif [[ -n "${HOMEBREW_UPDATE_AUTO}" ]]
then
FORCE_AUTO_UPDATE="$(git config homebrew.forceautoupdate 2>/dev/null || echo "false")"
if [[ "${FORCE_AUTO_UPDATE}" != "true" ]]
Expand All @@ -650,7 +650,7 @@ EOS
local tmp_failure_file="${HOMEBREW_REPOSITORY}/.git/TMP_FETCH_FAILURES"
rm -f "${tmp_failure_file}"

if [[ -n "${HOMEBREW_UPDATE_PREINSTALL}" ]]
if [[ -n "${HOMEBREW_UPDATE_AUTO}" ]]
then
git fetch --tags --force "${QUIET_ARGS[@]}" origin \
"refs/heads/${UPSTREAM_BRANCH_DIR}:refs/remotes/origin/${UPSTREAM_BRANCH_DIR}" 2>/dev/null
Expand Down Expand Up @@ -701,10 +701,10 @@ EOS

for DIR in "${HOMEBREW_REPOSITORY}" "${HOMEBREW_LIBRARY}"/Taps/*/*
do
# HOMEBREW_UPDATE_PREINSTALL wasn't modified in subshell.
# HOMEBREW_UPDATE_AUTO wasn't modified in subshell.
# shellcheck disable=SC2031
if [[ -n "${HOMEBREW_INSTALL_FROM_API}" ]] &&
[[ -n "${HOMEBREW_UPDATE_PREINSTALL}" ]] &&
[[ -n "${HOMEBREW_UPDATE_AUTO}" ]] &&
[[ "${DIR}" == "${HOMEBREW_CORE_REPOSITORY}" ||
"${DIR}" == "${HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-cask" ]]
then
Expand Down Expand Up @@ -747,7 +747,7 @@ EOS

safe_cd "${HOMEBREW_REPOSITORY}"

# HOMEBREW_UPDATE_PREINSTALL wasn't modified in subshell.
# HOMEBREW_UPDATE_AUTO wasn't modified in subshell.
# shellcheck disable=SC2031
if [[ -n "${HOMEBREW_UPDATED}" ]] ||
[[ -n "${HOMEBREW_UPDATE_FAILED}" ]] ||
Expand All @@ -756,11 +756,11 @@ EOS
[[ -n "${HOMEBREW_MIGRATE_LINUXBREW_FORMULAE}" ]] ||
[[ -d "${HOMEBREW_LIBRARY}/LinkedKegs" ]] ||
[[ ! -f "${HOMEBREW_CACHE}/all_commands_list.txt" ]] ||
[[ -n "${HOMEBREW_DEVELOPER}" && -z "${HOMEBREW_UPDATE_PREINSTALL}" ]]
[[ -n "${HOMEBREW_DEVELOPER}" && -z "${HOMEBREW_UPDATE_AUTO}" ]]
then
brew update-report "$@"
return $?
elif [[ -z "${HOMEBREW_UPDATE_PREINSTALL}" && -z "${HOMEBREW_QUIET}" ]]
elif [[ -z "${HOMEBREW_UPDATE_AUTO}" && -z "${HOMEBREW_QUIET}" ]]
then
echo "Already up-to-date."
fi
Expand Down
9 changes: 7 additions & 2 deletions Library/Homebrew/env_config.rb
Expand Up @@ -289,6 +289,10 @@ module EnvConfig
"outdated.",
boolean: true,
},
HOMEBREW_NO_UPDATE_REPORT_ONLY_INSTALLED: {
description: "If set, `brew update` lists updates to all software.",
boolean: true,
},
HOMEBREW_PRY: {
description: "If set, use Pry for the `brew irb` command.",
boolean: true,
Expand Down Expand Up @@ -325,8 +329,9 @@ module EnvConfig
default_text: "macOS: `/private/tmp`, Linux: `/tmp`.",
default: HOMEBREW_DEFAULT_TEMP,
},
HOMEBREW_UPDATE_REPORT_ONLY_INSTALLED: {
description: "If set, `brew update` only lists updates to installed software.",
HOMEBREW_UPDATE_FORMULA_VERSION_CHECKS: {
description: "If set, `brew update` only lists updates to formulae with differing versions. " \
"Note this is slower than the default behaviour.",
boolean: true,
},
HOMEBREW_UPDATE_TO_TAG: {
Expand Down
20 changes: 10 additions & 10 deletions Library/Homebrew/test/completions_spec.rb
Expand Up @@ -195,13 +195,13 @@ def delete_completions_setting(setting: "linkcompletions")

it "returns an array of options for a shell command" do
expected_options = {
"--debug" => "Display a trace of all shell commands as they are executed.",
"--force" => "Always do a slower, full update check (even if unnecessary).",
"--help" => "Show this message.",
"--merge" => "Use `git merge` to apply updates (rather than `git rebase`).",
"--preinstall" => "Run on auto-updates (e.g. before `brew install`). Skips some slower steps.",
"--quiet" => "Make some output more quiet",
"--verbose" => "Print the directories checked and `git` operations performed.",
"--auto-update" => "Run on auto-updates (e.g. before `brew install`). Skips some slower steps.",
"--debug" => "Display a trace of all shell commands as they are executed.",
"--force" => "Always do a slower, full update check (even if unnecessary).",
"--help" => "Show this message.",
"--merge" => "Use `git merge` to apply updates (rather than `git rebase`).",
"--quiet" => "Make some output more quiet",
"--verbose" => "Print the directories checked and `git` operations performed.",
}
expect(described_class.command_options("update")).to eq expected_options
end
Expand Down Expand Up @@ -277,11 +277,11 @@ def delete_completions_setting(setting: "linkcompletions")
case "${cur}" in
-*)
__brewcomp "
--auto-update
--debug
--force
--help
--merge
--preinstall
--quiet
--verbose
"
Expand Down Expand Up @@ -342,11 +342,11 @@ def delete_completions_setting(setting: "linkcompletions")
# brew update
_brew_update() {
_arguments \\
'--auto-update[Run on auto-updates (e.g. before `brew install`). Skips some slower steps]' \\
'--debug[Display a trace of all shell commands as they are executed]' \\
'--force[Always do a slower, full update check (even if unnecessary)]' \\
'--help[Show this message]' \\
'--merge[Use `git merge` to apply updates (rather than `git rebase`)]' \\
'--preinstall[Run on auto-updates (e.g. before `brew install`). Skips some slower steps]' \\
'--quiet[Make some output more quiet]' \\
'--verbose[Print the directories checked and `git` operations performed]'
}
Expand Down Expand Up @@ -402,11 +402,11 @@ def delete_completions_setting(setting: "linkcompletions")
completion = described_class.generate_fish_subcommand_completion("update")
expect(completion).to eq <<~COMPLETION
__fish_brew_complete_cmd 'update' 'Fetch the newest version of Homebrew and all formulae from GitHub using `git`(1) and perform any necessary migrations'
__fish_brew_complete_arg 'update' -l auto-update -d 'Run on auto-updates (e.g. before `brew install`). Skips some slower steps'
__fish_brew_complete_arg 'update' -l debug -d 'Display a trace of all shell commands as they are executed'
__fish_brew_complete_arg 'update' -l force -d 'Always do a slower, full update check (even if unnecessary)'
__fish_brew_complete_arg 'update' -l help -d 'Show this message'
__fish_brew_complete_arg 'update' -l merge -d 'Use `git merge` to apply updates (rather than `git rebase`)'
__fish_brew_complete_arg 'update' -l preinstall -d 'Run on auto-updates (e.g. before `brew install`). Skips some slower steps'
__fish_brew_complete_arg 'update' -l quiet -d 'Make some output more quiet'
__fish_brew_complete_arg 'update' -l verbose -d 'Print the directories checked and `git` operations performed'
COMPLETION
Expand Down

0 comments on commit c597a12

Please sign in to comment.