2023-03-06 08:20:40 -08:00
|
|
|
# typed: true
|
2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-01-10 20:28:52 +00:00
|
|
|
require "migrator"
|
|
|
|
require "formulary"
|
2023-04-08 14:10:58 +02:00
|
|
|
require "cask/cask_loader"
|
2023-05-14 15:12:11 -04:00
|
|
|
require "cask/migrator"
|
2016-01-10 20:28:52 +00:00
|
|
|
require "descriptions"
|
2016-06-01 08:46:33 +01:00
|
|
|
require "cleanup"
|
2018-10-13 08:22:51 -07:00
|
|
|
require "description_cache_store"
|
2019-04-17 18:25:08 +09:00
|
|
|
require "cli/parser"
|
2021-01-12 16:27:25 -05:00
|
|
|
require "settings"
|
2021-10-07 11:16:03 +01:00
|
|
|
require "linuxbrew-core-migration"
|
2016-01-10 20:28:52 +00:00
|
|
|
|
|
|
|
module Homebrew
|
2016-09-26 01:44:51 +02:00
|
|
|
module_function
|
|
|
|
|
2022-05-19 11:04:20 -04:00
|
|
|
def auto_update_header(args:)
|
|
|
|
@auto_update_header ||= begin
|
|
|
|
ohai "Auto-updated Homebrew!" if args.auto_update?
|
2016-04-11 09:31:50 +01:00
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(CLI::Parser) }
|
2019-01-30 21:30:45 +00:00
|
|
|
def update_report_args
|
|
|
|
Homebrew::CLI::Parser.new do
|
2021-01-15 15:04:02 -05:00
|
|
|
description <<~EOS
|
2019-01-30 21:30:45 +00:00
|
|
|
The Ruby implementation of `brew update`. Never called manually.
|
|
|
|
EOS
|
2022-05-19 11:04:20 -04:00
|
|
|
switch "--auto-update", "--preinstall",
|
2019-04-30 08:44:35 +01:00
|
|
|
description: "Run in 'auto-update' mode (faster, less output)."
|
2020-07-27 03:59:52 +02:00
|
|
|
switch "-f", "--force",
|
2022-06-28 10:09:59 +01:00
|
|
|
description: "Treat installed and updated formulae as if they are from " \
|
2020-07-27 03:59:52 +02:00
|
|
|
"the same taps and migrate them anyway."
|
2020-07-30 18:40:10 +02:00
|
|
|
|
2019-01-30 21:30:45 +00:00
|
|
|
hide_from_man_page!
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-01-10 20:28:52 +00:00
|
|
|
def update_report
|
2021-11-24 00:46:02 +08:00
|
|
|
return output_update_report if $stdout.tty?
|
2021-11-23 23:55:06 +08:00
|
|
|
|
|
|
|
redirect_stdout($stderr) do
|
2021-11-24 00:46:02 +08:00
|
|
|
output_update_report
|
2021-11-23 23:55:06 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-11-24 00:46:02 +08:00
|
|
|
def output_update_report
|
2020-07-25 21:33:48 +02:00
|
|
|
args = update_report_args.parse
|
2019-01-30 21:30:45 +00:00
|
|
|
|
2021-10-20 11:01:38 +01:00
|
|
|
# Run `brew update` (again) if we've got a linuxbrew-core CoreTap
|
2021-10-25 16:52:29 +01:00
|
|
|
if CoreTap.instance.installed? && CoreTap.instance.linuxbrew_core? &&
|
|
|
|
ENV["HOMEBREW_LINUXBREW_CORE_MIGRATION"].blank?
|
2021-11-23 23:55:06 +08:00
|
|
|
ohai "Re-running `brew update` for linuxbrew-core migration"
|
2021-10-21 15:01:58 +01:00
|
|
|
|
2023-02-10 08:59:51 +00:00
|
|
|
if Homebrew::EnvConfig.core_git_remote != HOMEBREW_CORE_DEFAULT_GIT_REMOTE
|
2021-10-21 15:01:58 +01:00
|
|
|
opoo <<~EOS
|
2022-05-30 04:15:28 +01:00
|
|
|
HOMEBREW_CORE_GIT_REMOTE was set: #{Homebrew::EnvConfig.core_git_remote}.
|
2021-10-21 15:10:17 +01:00
|
|
|
It has been unset for the migration.
|
2021-10-21 15:01:58 +01:00
|
|
|
You may need to change this from a linuxbrew-core mirror to a homebrew-core one.
|
|
|
|
|
|
|
|
EOS
|
|
|
|
end
|
|
|
|
ENV.delete("HOMEBREW_CORE_GIT_REMOTE")
|
|
|
|
|
2023-02-10 08:59:51 +00:00
|
|
|
if Homebrew::EnvConfig.bottle_domain != HOMEBREW_BOTTLE_DEFAULT_DOMAIN
|
2021-10-21 15:01:58 +01:00
|
|
|
opoo <<~EOS
|
2022-05-30 04:15:28 +01:00
|
|
|
HOMEBREW_BOTTLE_DOMAIN was set: #{Homebrew::EnvConfig.bottle_domain}.
|
2021-10-21 15:10:17 +01:00
|
|
|
It has been unset for the migration.
|
|
|
|
You may need to change this from a Linuxbrew package mirror to a Homebrew one.
|
2021-10-21 15:01:58 +01:00
|
|
|
|
|
|
|
EOS
|
|
|
|
end
|
|
|
|
ENV.delete("HOMEBREW_BOTTLE_DOMAIN")
|
|
|
|
|
2021-10-20 11:01:38 +01:00
|
|
|
ENV["HOMEBREW_LINUXBREW_CORE_MIGRATION"] = "1"
|
2021-10-21 15:01:58 +01:00
|
|
|
FileUtils.rm_f HOMEBREW_LOCKS/"update"
|
|
|
|
|
2021-10-20 11:01:38 +01:00
|
|
|
update_args = []
|
2022-05-19 11:04:20 -04:00
|
|
|
update_args << "--auto-update" if args.auto_update?
|
2021-10-20 11:01:38 +01:00
|
|
|
update_args << "--force" if args.force?
|
|
|
|
exec HOMEBREW_BREW_FILE, "update", *update_args
|
|
|
|
end
|
|
|
|
|
2023-06-16 16:52:17 +01:00
|
|
|
if ENV["HOMEBREW_ADDITIONAL_GOOGLE_ANALYTICS_ID"].present?
|
|
|
|
opoo "HOMEBREW_ADDITIONAL_GOOGLE_ANALYTICS_ID is now a no-op so can be unset."
|
|
|
|
puts "All Homebrew Google Analytics code and data was destroyed."
|
2019-11-22 09:08:31 +00:00
|
|
|
end
|
|
|
|
|
2023-06-16 16:52:17 +01:00
|
|
|
if ENV["HOMEBREW_NO_GOOGLE_ANALYTICS"].present?
|
|
|
|
opoo "HOMEBREW_NO_GOOGLE_ANALYTICS is now a no-op so can be unset."
|
|
|
|
puts "All Homebrew Google Analytics code and data was destroyed."
|
|
|
|
end
|
2018-08-14 13:19:37 +01:00
|
|
|
|
2023-06-16 16:52:17 +01:00
|
|
|
unless args.quiet?
|
|
|
|
analytics_message
|
|
|
|
donation_message
|
|
|
|
install_from_api_message
|
|
|
|
untap_message
|
2016-04-25 18:05:30 -05:00
|
|
|
end
|
|
|
|
|
2016-02-26 17:39:49 +08:00
|
|
|
install_core_tap_if_necessary
|
2016-01-10 20:28:52 +00:00
|
|
|
|
2016-03-06 14:55:37 +08:00
|
|
|
updated = false
|
2022-07-04 11:03:14 -07:00
|
|
|
new_tag = nil
|
2016-02-25 16:41:34 +08:00
|
|
|
|
2016-03-06 14:55:37 +08:00
|
|
|
initial_revision = ENV["HOMEBREW_UPDATE_BEFORE"].to_s
|
|
|
|
current_revision = ENV["HOMEBREW_UPDATE_AFTER"].to_s
|
2019-02-19 13:11:32 +00:00
|
|
|
odie "update-report should not be called directly!" if initial_revision.empty? || current_revision.empty?
|
2016-02-25 16:41:34 +08:00
|
|
|
|
2016-03-06 14:55:37 +08:00
|
|
|
if initial_revision != current_revision
|
2022-05-19 11:04:20 -04:00
|
|
|
auto_update_header args: args
|
2022-04-13 11:10:04 -07:00
|
|
|
|
2016-03-06 14:55:37 +08:00
|
|
|
updated = true
|
2020-12-23 12:06:28 -05:00
|
|
|
|
2021-01-12 16:27:25 -05:00
|
|
|
old_tag = Settings.read "latesttag"
|
2020-12-25 14:08:11 -05:00
|
|
|
|
|
|
|
new_tag = Utils.popen_read(
|
2021-01-01 17:54:59 +09:00
|
|
|
"git", "-C", HOMEBREW_REPOSITORY, "tag", "--list", "--sort=-version:refname", "*.*"
|
2020-12-25 14:08:11 -05:00
|
|
|
).lines.first.chomp
|
|
|
|
|
2022-06-25 17:20:47 -07:00
|
|
|
Settings.write "latesttag", new_tag if new_tag != old_tag
|
|
|
|
|
2022-07-06 23:24:01 -07:00
|
|
|
if new_tag == old_tag
|
2022-07-07 14:17:00 -07:00
|
|
|
ohai "Updated Homebrew from #{shorten_revision(initial_revision)} to #{shorten_revision(current_revision)}."
|
2022-07-06 23:24:01 -07:00
|
|
|
elsif old_tag.blank?
|
|
|
|
ohai "Updated Homebrew from #{shorten_revision(initial_revision)} " \
|
|
|
|
"to #{new_tag} (#{shorten_revision(current_revision)})."
|
2022-04-13 11:10:04 -07:00
|
|
|
else
|
2022-07-06 23:15:38 -07:00
|
|
|
ohai "Updated Homebrew from #{old_tag} (#{shorten_revision(initial_revision)}) " \
|
2022-04-13 11:10:04 -07:00
|
|
|
"to #{new_tag} (#{shorten_revision(current_revision)})."
|
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2023-02-16 21:49:03 +00:00
|
|
|
# Check if we can parse the JSON and do any Ruby-side follow-up.
|
2023-02-24 13:25:18 +00:00
|
|
|
unless Homebrew::EnvConfig.no_install_from_api?
|
2023-02-16 21:49:03 +00:00
|
|
|
Homebrew::API::Formula.write_names_and_aliases
|
|
|
|
Homebrew::API::Cask.write_names
|
|
|
|
end
|
|
|
|
|
2020-03-27 23:50:37 +00:00
|
|
|
Homebrew.failed = true if ENV["HOMEBREW_UPDATE_FAILED"]
|
2022-05-30 04:15:28 +01:00
|
|
|
return if Homebrew::EnvConfig.disable_load_formula?
|
2020-03-27 23:50:37 +00:00
|
|
|
|
2022-08-02 23:49:05 +08:00
|
|
|
migrate_gcc_dependents_if_needed
|
|
|
|
|
2020-03-27 23:50:37 +00:00
|
|
|
hub = ReporterHub.new
|
|
|
|
|
2016-01-10 20:28:52 +00:00
|
|
|
updated_taps = []
|
|
|
|
Tap.each do |tap|
|
2023-04-30 06:43:22 +08:00
|
|
|
next if !tap.git? || tap.git_repo.origin_url.nil?
|
2023-07-13 19:28:39 +01:00
|
|
|
next if (tap.core_tap? || tap.core_cask_tap?) && !Homebrew::EnvConfig.no_install_from_api?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2021-10-07 11:16:03 +01:00
|
|
|
if ENV["HOMEBREW_MIGRATE_LINUXBREW_FORMULAE"].present? && tap.core_tap? &&
|
|
|
|
Settings.read("linuxbrewmigrated") != "true"
|
2021-11-23 23:55:06 +08:00
|
|
|
ohai "Migrating formulae from linuxbrew-core to homebrew-core"
|
2021-10-07 11:16:03 +01:00
|
|
|
|
|
|
|
LINUXBREW_CORE_MIGRATION_LIST.each do |name|
|
|
|
|
begin
|
|
|
|
formula = Formula[name]
|
|
|
|
rescue FormulaUnavailableError
|
|
|
|
next
|
|
|
|
end
|
|
|
|
next unless formula.any_version_installed?
|
|
|
|
|
|
|
|
keg = formula.installed_kegs.last
|
|
|
|
tab = Tab.for_keg(keg)
|
|
|
|
# force a `brew upgrade` from the linuxbrew-core version to the homebrew-core version (even if lower)
|
|
|
|
tab.source["versions"]["version_scheme"] = -1
|
|
|
|
tab.write
|
|
|
|
end
|
|
|
|
|
|
|
|
Settings.write "linuxbrewmigrated", true
|
|
|
|
end
|
|
|
|
|
2016-02-25 16:41:34 +08:00
|
|
|
begin
|
|
|
|
reporter = Reporter.new(tap)
|
|
|
|
rescue Reporter::ReporterRevisionUnsetError => e
|
2023-03-06 08:20:40 -08:00
|
|
|
onoe "#{e.message}\n#{e.backtrace&.join("\n")}" if Homebrew::EnvConfig.developer?
|
2016-02-25 16:41:34 +08:00
|
|
|
next
|
|
|
|
end
|
|
|
|
if reporter.updated?
|
|
|
|
updated_taps << tap.name
|
2022-05-19 11:04:20 -04:00
|
|
|
hub.add(reporter, auto_update: args.auto_update?)
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
end
|
2016-03-06 14:55:37 +08:00
|
|
|
|
2023-02-28 16:40:00 +00:00
|
|
|
# If we're installing from the API: we cannot use Git to check for #
|
|
|
|
# differences in packages so instead use {formula,cask}_names.txt to do so.
|
|
|
|
# The first time this runs: we won't yet have a base state
|
|
|
|
# ({formula,cask}_names.before.txt) to compare against so we don't output a
|
|
|
|
# anything and just copy the files for next time.
|
|
|
|
unless Homebrew::EnvConfig.no_install_from_api?
|
|
|
|
api_cache = Homebrew::API::HOMEBREW_CACHE_API
|
|
|
|
core_tap = CoreTap.instance
|
2023-07-13 19:28:39 +01:00
|
|
|
cask_tap = CoreCaskTap.instance
|
2023-02-28 16:40:00 +00:00
|
|
|
[
|
|
|
|
[:formula, core_tap, core_tap.formula_dir],
|
|
|
|
[:cask, cask_tap, cask_tap.cask_dir],
|
|
|
|
].each do |type, tap, dir|
|
|
|
|
names_txt = api_cache/"#{type}_names.txt"
|
|
|
|
next unless names_txt.exist?
|
|
|
|
|
|
|
|
names_before_txt = api_cache/"#{type}_names.before.txt"
|
|
|
|
if names_before_txt.exist?
|
|
|
|
reporter = Reporter.new(
|
|
|
|
tap,
|
|
|
|
api_names_txt: names_txt,
|
|
|
|
api_names_before_txt: names_before_txt,
|
|
|
|
api_dir_prefix: dir,
|
|
|
|
)
|
|
|
|
if reporter.updated?
|
|
|
|
updated_taps << tap.name
|
|
|
|
hub.add(reporter, auto_update: args.auto_update?)
|
|
|
|
end
|
2023-03-27 17:24:25 +01:00
|
|
|
else
|
|
|
|
FileUtils.cp names_txt, names_before_txt
|
2023-02-28 16:40:00 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-01-10 20:28:52 +00:00
|
|
|
unless updated_taps.empty?
|
2022-05-19 11:04:20 -04:00
|
|
|
auto_update_header args: args
|
2023-03-20 07:23:17 -04:00
|
|
|
puts "Updated #{Utils.pluralize("tap", updated_taps.count, include_count: true)} (#{updated_taps.to_sentence})."
|
2016-03-06 14:55:37 +08:00
|
|
|
updated = true
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
2016-01-26 09:03:28 +00:00
|
|
|
|
2020-11-09 20:09:16 +11:00
|
|
|
if updated
|
2016-09-03 19:36:34 +01:00
|
|
|
if hub.empty?
|
2023-03-27 17:24:25 +01:00
|
|
|
puts no_changes_message unless args.quiet?
|
2016-09-03 19:36:34 +01:00
|
|
|
else
|
2022-05-19 11:04:20 -04:00
|
|
|
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
|
|
|
|
|
2023-03-27 17:24:25 +01:00
|
|
|
hub.dump(auto_update: args.auto_update?) unless args.quiet?
|
2016-09-03 19:36:34 +01:00
|
|
|
hub.reporters.each(&:migrate_tap_migration)
|
2023-04-08 14:10:58 +02:00
|
|
|
hub.reporters.each(&:migrate_cask_rename)
|
2020-08-02 04:46:32 +02:00
|
|
|
hub.reporters.each { |r| r.migrate_formula_rename(force: args.force?, verbose: args.verbose?) }
|
2022-06-03 19:16:15 +01:00
|
|
|
|
2018-10-13 08:22:51 -07:00
|
|
|
CacheStoreDatabase.use(:descriptions) do |db|
|
|
|
|
DescriptionCacheStore.new(db)
|
|
|
|
.update_from_report!(hub)
|
|
|
|
end
|
2022-03-23 00:03:11 -04:00
|
|
|
CacheStoreDatabase.use(:cask_descriptions) do |db|
|
|
|
|
CaskDescriptionCacheStore.new(db)
|
|
|
|
.update_from_report!(hub)
|
|
|
|
end
|
2016-09-03 19:36:34 +01:00
|
|
|
end
|
2022-05-19 11:04:20 -04:00
|
|
|
puts if args.auto_update?
|
|
|
|
elsif !args.auto_update? && !ENV["HOMEBREW_UPDATE_FAILED"] && !ENV["HOMEBREW_MIGRATE_LINUXBREW_FORMULAE"]
|
2021-11-23 23:55:06 +08:00
|
|
|
puts "Already up-to-date." unless args.quiet?
|
2016-01-26 09:03:28 +00:00
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
|
2020-06-17 18:03:40 -04:00
|
|
|
Commands.rebuild_commands_completion_list
|
2016-09-30 18:22:53 -05:00
|
|
|
link_completions_manpages_and_docs
|
|
|
|
Tap.each(&:link_completions_and_manpages)
|
2020-12-23 12:06:28 -05:00
|
|
|
|
2021-05-06 10:03:21 +09:00
|
|
|
failed_fetch_dirs = ENV["HOMEBREW_MISSING_REMOTE_REF_DIRS"]&.split("\n")
|
2021-01-28 01:51:40 -05:00
|
|
|
if failed_fetch_dirs.present?
|
|
|
|
failed_fetch_taps = failed_fetch_dirs.map { |dir| Tap.from_path(dir) }
|
|
|
|
|
2021-02-03 13:31:24 +00:00
|
|
|
ofail <<~EOS
|
|
|
|
Some taps failed to update!
|
2021-01-28 01:51:40 -05:00
|
|
|
The following taps can not read their remote branches:
|
|
|
|
#{failed_fetch_taps.join("\n ")}
|
2021-01-28 09:10:07 -05:00
|
|
|
This is happening because the remote branch was renamed or deleted.
|
2021-01-28 01:51:40 -05:00
|
|
|
Reset taps to point to the correct remote branches by running `brew tap --repair`
|
|
|
|
EOS
|
|
|
|
end
|
|
|
|
|
2022-06-30 18:41:44 -07:00
|
|
|
return if new_tag.blank? || new_tag == old_tag || args.quiet?
|
2020-12-23 12:06:28 -05:00
|
|
|
|
2021-11-23 23:55:06 +08:00
|
|
|
puts
|
2022-07-06 23:15:38 -07:00
|
|
|
|
2022-06-28 00:02:45 -07:00
|
|
|
new_major_version, new_minor_version, new_patch_version = new_tag.split(".").map(&:to_i)
|
|
|
|
old_major_version, old_minor_version = (old_tag.split(".")[0, 2]).map(&:to_i) if old_tag.present?
|
|
|
|
if old_tag.blank? || new_major_version > old_major_version \
|
|
|
|
|| new_minor_version > old_minor_version
|
2021-11-23 23:55:06 +08:00
|
|
|
puts <<~EOS
|
2022-07-06 23:15:38 -07:00
|
|
|
The #{new_major_version}.#{new_minor_version}.0 release notes are available on the Homebrew Blog:
|
2022-06-28 00:02:45 -07:00
|
|
|
#{Formatter.url("https://brew.sh/blog/#{new_major_version}.#{new_minor_version}.0")}
|
2020-12-24 19:05:23 -05:00
|
|
|
EOS
|
|
|
|
end
|
2022-06-28 00:02:45 -07:00
|
|
|
|
|
|
|
return if new_patch_version.zero?
|
|
|
|
|
|
|
|
puts <<~EOS
|
2022-07-06 23:15:38 -07:00
|
|
|
The #{new_tag} changelog can be found at:
|
2022-06-28 00:02:45 -07:00
|
|
|
#{Formatter.url("https://github.com/Homebrew/brew/releases/tag/#{new_tag}")}
|
|
|
|
EOS
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2023-03-27 17:24:25 +01:00
|
|
|
def no_changes_message
|
|
|
|
"No changes to formulae or casks."
|
|
|
|
end
|
|
|
|
|
2016-01-10 20:28:52 +00:00
|
|
|
def shorten_revision(revision)
|
2016-02-25 16:41:34 +08:00
|
|
|
Utils.popen_read("git", "-C", HOMEBREW_REPOSITORY, "rev-parse", "--short", revision).chomp
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
2016-02-26 17:39:49 +08:00
|
|
|
|
|
|
|
def install_core_tap_if_necessary
|
2016-10-02 17:16:35 +01:00
|
|
|
return if ENV["HOMEBREW_UPDATE_TEST"]
|
2023-02-24 13:25:18 +00:00
|
|
|
return unless Homebrew::EnvConfig.no_install_from_api?
|
2023-02-14 09:54:24 +00:00
|
|
|
return if Homebrew::EnvConfig.automatically_set_no_install_from_api?
|
2023-02-28 16:40:00 +00:00
|
|
|
return if CoreTap.instance.installed?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2017-09-07 12:09:52 +01:00
|
|
|
CoreTap.ensure_installed!
|
2023-03-06 08:20:40 -08:00
|
|
|
revision = CoreTap.instance.git_head
|
2016-02-26 17:39:49 +08:00
|
|
|
ENV["HOMEBREW_UPDATE_BEFORE_HOMEBREW_HOMEBREW_CORE"] = revision
|
|
|
|
ENV["HOMEBREW_UPDATE_AFTER_HOMEBREW_HOMEBREW_CORE"] = revision
|
|
|
|
end
|
2016-06-01 08:46:33 +01:00
|
|
|
|
2016-09-30 18:22:53 -05:00
|
|
|
def link_completions_manpages_and_docs(repository = HOMEBREW_REPOSITORY)
|
2016-09-06 09:04:51 +01:00
|
|
|
command = "brew update"
|
2021-01-11 12:24:48 -05:00
|
|
|
Utils::Link.link_completions(repository, command)
|
2016-09-30 18:22:53 -05:00
|
|
|
Utils::Link.link_manpages(repository, command)
|
|
|
|
Utils::Link.link_docs(repository, command)
|
2016-09-20 08:03:06 +01:00
|
|
|
rescue => e
|
2017-10-15 02:28:32 +02:00
|
|
|
ofail <<~EOS
|
2016-09-20 08:03:06 +01:00
|
|
|
Failed to link all completions, docs and manpages:
|
|
|
|
#{e}
|
|
|
|
EOS
|
2016-08-22 11:07:15 +01:00
|
|
|
end
|
2022-08-02 23:49:05 +08:00
|
|
|
|
|
|
|
def migrate_gcc_dependents_if_needed
|
2023-01-28 21:38:40 +09:00
|
|
|
# do nothing
|
2022-08-02 23:49:05 +08:00
|
|
|
end
|
2023-06-16 16:52:17 +01:00
|
|
|
|
|
|
|
def analytics_message
|
2023-07-18 08:03:57 +01:00
|
|
|
return if Utils::Analytics.messages_displayed?
|
|
|
|
return if Utils::Analytics.no_message_output?
|
2023-06-16 16:52:17 +01:00
|
|
|
|
2023-07-18 08:03:57 +01:00
|
|
|
if Utils::Analytics.disabled? && !Utils::Analytics.influx_message_displayed?
|
|
|
|
ohai "Homebrew's analytics have entirely moved to our InfluxDB instance in the EU."
|
|
|
|
puts "We gather less data than before and have destroyed all Google Analytics data:"
|
|
|
|
puts " #{Formatter.url("https://docs.brew.sh/Analytics")}#{Tty.reset}"
|
|
|
|
puts "Please reconsider re-enabling analytics to help our volunteer maintainers with:"
|
|
|
|
puts " brew analytics on"
|
|
|
|
elsif !Utils::Analytics.disabled?
|
2023-06-16 16:52:17 +01:00
|
|
|
ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1"
|
|
|
|
# Use the shell's audible bell.
|
|
|
|
print "\a"
|
|
|
|
|
|
|
|
# Use an extra newline and bold to avoid this being missed.
|
|
|
|
ohai "Homebrew collects anonymous analytics."
|
|
|
|
puts <<~EOS
|
|
|
|
#{Tty.bold}Read the analytics documentation (and how to opt-out) here:
|
|
|
|
#{Formatter.url("https://docs.brew.sh/Analytics")}#{Tty.reset}
|
|
|
|
No analytics have been recorded yet (nor will be during this `brew` run).
|
|
|
|
|
|
|
|
EOS
|
|
|
|
end
|
2023-07-18 08:03:57 +01:00
|
|
|
|
|
|
|
# Consider the messages possibly missed if not a TTY.
|
|
|
|
Utils::Analytics.messages_displayed! if $stdout.tty?
|
2023-06-16 16:52:17 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def donation_message
|
|
|
|
return if Settings.read("donationmessage") == "true"
|
|
|
|
|
|
|
|
ohai "Homebrew is run entirely by unpaid volunteers. Please consider donating:"
|
|
|
|
puts " #{Formatter.url("https://github.com/Homebrew/brew#donations")}\n\n"
|
|
|
|
|
|
|
|
# Consider the message possibly missed if not a TTY.
|
|
|
|
Settings.write "donationmessage", true if $stdout.tty?
|
|
|
|
end
|
|
|
|
|
|
|
|
def install_from_api_message
|
|
|
|
return if Settings.read("installfromapimessage") == "true"
|
|
|
|
|
2023-07-06 13:58:24 +01:00
|
|
|
api_auto_update_secs = Homebrew::EnvConfig.api_auto_update_secs.to_i
|
|
|
|
api_auto_update_secs_default = Homebrew::EnvConfig::ENVS.fetch(:HOMEBREW_API_AUTO_UPDATE_SECS).fetch(:default)
|
|
|
|
auto_update_secs_set = api_auto_update_secs.positive? && api_auto_update_secs != api_auto_update_secs_default
|
2023-07-06 17:33:49 +01:00
|
|
|
no_auto_update_set = Homebrew::EnvConfig.no_auto_update? &&
|
|
|
|
!ENV["HOMEBREW_GITHUB_HOSTED_RUNNER"] &&
|
|
|
|
!ENV["GITHUB_ACTIONS_HOMEBREW_SELF_HOSTED"]
|
|
|
|
no_install_from_api_set = Homebrew::EnvConfig.no_install_from_api? &&
|
2023-07-27 12:36:54 +01:00
|
|
|
!Homebrew::EnvConfig.automatically_set_no_install_from_api? &&
|
|
|
|
!Homebrew::EnvConfig.install_from_api_unsupported?
|
2023-07-06 17:33:49 +01:00
|
|
|
return if !no_auto_update_set && !no_install_from_api_set && !auto_update_secs_set
|
2023-06-16 16:52:17 +01:00
|
|
|
|
|
|
|
ohai "You have set:"
|
2023-07-06 17:33:49 +01:00
|
|
|
puts " HOMEBREW_NO_AUTO_UPDATE" if no_auto_update_set
|
2023-06-16 16:52:17 +01:00
|
|
|
puts " HOMEBREW_API_AUTO_UPDATE_SECS" if auto_update_secs_set
|
2023-07-06 17:33:49 +01:00
|
|
|
puts " HOMEBREW_NO_INSTALL_FROM_API" if no_install_from_api_set
|
2023-06-16 16:52:17 +01:00
|
|
|
puts "but we have dramatically sped up and fixed many bugs in the way we do Homebrew updates since."
|
|
|
|
puts "Please consider unsetting these and tweaking the values based on the new behaviour."
|
|
|
|
puts "\n\n"
|
|
|
|
|
|
|
|
# Consider the message possibly missed if not a TTY.
|
|
|
|
Settings.write "installfromapimessage", true if $stdout.tty?
|
|
|
|
end
|
|
|
|
|
|
|
|
def untap_message
|
|
|
|
return if Homebrew::EnvConfig.no_install_from_api?
|
|
|
|
return if Homebrew::EnvConfig.developer? || ENV["HOMEBREW_DEV_CMD_RUN"]
|
2023-07-06 17:33:49 +01:00
|
|
|
return if ENV["HOMEBREW_GITHUB_HOSTED_RUNNER"] || ENV["GITHUB_ACTIONS_HOMEBREW_SELF_HOSTED"]
|
|
|
|
return if (HOMEBREW_PREFIX/".homebrewdocker").exist?
|
2023-06-16 16:52:17 +01:00
|
|
|
|
|
|
|
core_tap = CoreTap.instance
|
2023-07-13 19:28:39 +01:00
|
|
|
cask_tap = CoreCaskTap.instance
|
2023-06-16 16:52:17 +01:00
|
|
|
return if !core_tap.installed? && !cask_tap.installed?
|
|
|
|
|
|
|
|
puts "Installing from the API is now the default behaviour!"
|
|
|
|
puts "You can save space and time by running:"
|
|
|
|
puts " brew untap #{core_tap.name}" if core_tap.installed?
|
|
|
|
puts " brew untap #{cask_tap.name}" if cask_tap.installed?
|
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2023-02-21 22:12:45 -08:00
|
|
|
require "extend/os/cmd/update-report"
|
|
|
|
|
2016-01-10 20:28:52 +00:00
|
|
|
class Reporter
|
2016-02-25 15:34:11 +08:00
|
|
|
class ReporterRevisionUnsetError < RuntimeError
|
|
|
|
def initialize(var_name)
|
|
|
|
super "#{var_name} is unset!"
|
2016-01-20 19:41:42 +08:00
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2023-02-28 16:40:00 +00:00
|
|
|
def initialize(tap, api_names_txt: nil, api_names_before_txt: nil, api_dir_prefix: nil)
|
2016-02-25 15:34:11 +08:00
|
|
|
@tap = tap
|
2016-01-10 20:28:52 +00:00
|
|
|
|
2023-02-28 16:40:00 +00:00
|
|
|
# This is slightly involved/weird but all the #report logic is shared so it's worth it.
|
|
|
|
if installed_from_api?(api_names_txt, api_names_before_txt, api_dir_prefix)
|
|
|
|
@api_names_txt = api_names_txt
|
|
|
|
@api_names_before_txt = api_names_before_txt
|
|
|
|
@api_dir_prefix = api_dir_prefix
|
|
|
|
else
|
|
|
|
initial_revision_var = "HOMEBREW_UPDATE_BEFORE#{tap.repo_var}"
|
|
|
|
@initial_revision = ENV[initial_revision_var].to_s
|
|
|
|
raise ReporterRevisionUnsetError, initial_revision_var if @initial_revision.empty?
|
|
|
|
|
|
|
|
current_revision_var = "HOMEBREW_UPDATE_AFTER#{tap.repo_var}"
|
|
|
|
@current_revision = ENV[current_revision_var].to_s
|
|
|
|
raise ReporterRevisionUnsetError, current_revision_var if @current_revision.empty?
|
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2022-05-19 11:04:20 -04:00
|
|
|
def report(auto_update: false)
|
2016-02-25 15:34:11 +08:00
|
|
|
return @report if @report
|
|
|
|
|
|
|
|
@report = Hash.new { |h, k| h[k] = [] }
|
|
|
|
return @report unless updated?
|
|
|
|
|
|
|
|
diff.each_line do |line|
|
|
|
|
status, *paths = line.split
|
|
|
|
src = Pathname.new paths.first
|
|
|
|
dst = Pathname.new paths.last
|
|
|
|
|
2023-04-18 15:06:50 -07:00
|
|
|
next if dst.extname != ".rb"
|
2016-08-05 16:00:33 +01:00
|
|
|
|
|
|
|
if paths.any? { |p| tap.cask_file?(p) }
|
2020-07-13 22:48:53 +10:00
|
|
|
case status
|
2022-02-28 09:54:12 +00:00
|
|
|
when "A"
|
|
|
|
# Have a dedicated report array for new casks.
|
|
|
|
@report[:AC] << tap.formula_file_to_name(src)
|
2020-07-13 22:48:53 +10:00
|
|
|
when "D"
|
2016-08-05 16:00:33 +01:00
|
|
|
# Have a dedicated report array for deleted casks.
|
|
|
|
@report[:DC] << tap.formula_file_to_name(src)
|
2020-07-13 22:48:53 +10:00
|
|
|
when "M"
|
2020-03-02 17:08:24 -05:00
|
|
|
# Report updated casks
|
|
|
|
@report[:MC] << tap.formula_file_to_name(src)
|
2023-04-08 14:10:58 +02:00
|
|
|
when /^R\d{0,3}/
|
|
|
|
src_full_name = tap.formula_file_to_name(src)
|
|
|
|
dst_full_name = tap.formula_file_to_name(dst)
|
|
|
|
# Don't report formulae that are moved within a tap but not renamed
|
|
|
|
next if src_full_name == dst_full_name
|
|
|
|
|
|
|
|
@report[:DC] << src_full_name
|
|
|
|
@report[:AC] << dst_full_name
|
2020-03-02 17:08:24 -05:00
|
|
|
end
|
2016-08-05 16:00:33 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
next unless paths.any? { |p| tap.formula_file?(p) }
|
2016-02-25 15:34:11 +08:00
|
|
|
|
|
|
|
case status
|
|
|
|
when "A", "D"
|
2017-03-20 15:28:24 +02:00
|
|
|
full_name = tap.formula_file_to_name(src)
|
|
|
|
name = full_name.split("/").last
|
|
|
|
new_tap = tap.tap_migrations[name]
|
|
|
|
@report[status.to_sym] << full_name unless new_tap
|
2016-02-25 15:34:11 +08:00
|
|
|
when "M"
|
2020-07-20 00:21:51 +10:00
|
|
|
name = tap.formula_file_to_name(src)
|
|
|
|
|
|
|
|
@report[:M] << name
|
2016-02-25 15:34:11 +08:00
|
|
|
when /^R\d{0,3}/
|
2016-07-16 01:18:30 -04:00
|
|
|
src_full_name = tap.formula_file_to_name(src)
|
|
|
|
dst_full_name = tap.formula_file_to_name(dst)
|
|
|
|
# Don't report formulae that are moved within a tap but not renamed
|
|
|
|
next if src_full_name == dst_full_name
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-07-16 01:18:30 -04:00
|
|
|
@report[:D] << src_full_name
|
|
|
|
@report[:A] << dst_full_name
|
2016-02-25 15:34:11 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
renamed_casks = Set.new
|
|
|
|
@report[:DC].each do |old_full_name|
|
|
|
|
old_name = old_full_name.split("/").last
|
|
|
|
new_name = tap.cask_renames[old_name]
|
|
|
|
next unless new_name
|
|
|
|
|
2023-07-13 19:28:39 +01:00
|
|
|
new_full_name = if tap.core_cask_tap?
|
2023-04-08 14:10:58 +02:00
|
|
|
new_name
|
|
|
|
else
|
|
|
|
"#{tap}/#{new_name}"
|
|
|
|
end
|
|
|
|
|
|
|
|
renamed_casks << [old_full_name, new_full_name] if @report[:AC].include?(new_full_name)
|
|
|
|
end
|
|
|
|
|
|
|
|
@report[:AC].each do |new_full_name|
|
|
|
|
new_name = new_full_name.split("/").last
|
|
|
|
old_name = tap.cask_renames.key(new_name)
|
|
|
|
next unless old_name
|
|
|
|
|
2023-07-13 19:28:39 +01:00
|
|
|
old_full_name = if tap.core_cask_tap?
|
2023-04-08 14:10:58 +02:00
|
|
|
old_name
|
|
|
|
else
|
|
|
|
"#{tap}/#{old_name}"
|
|
|
|
end
|
|
|
|
|
|
|
|
renamed_casks << [old_full_name, new_full_name]
|
|
|
|
end
|
|
|
|
|
|
|
|
if renamed_casks.any?
|
|
|
|
@report[:AC] -= renamed_casks.map(&:last)
|
|
|
|
@report[:DC] -= renamed_casks.map(&:first)
|
|
|
|
@report[:RC] = renamed_casks.to_a
|
|
|
|
end
|
|
|
|
|
2017-01-02 17:24:52 +00:00
|
|
|
renamed_formulae = Set.new
|
2016-02-25 15:34:11 +08:00
|
|
|
@report[:D].each do |old_full_name|
|
|
|
|
old_name = old_full_name.split("/").last
|
|
|
|
new_name = tap.formula_renames[old_name]
|
|
|
|
next unless new_name
|
|
|
|
|
2020-03-13 21:15:06 +00:00
|
|
|
new_full_name = if tap.core_tap?
|
|
|
|
new_name
|
2016-02-25 15:34:11 +08:00
|
|
|
else
|
2020-03-13 21:15:06 +00:00
|
|
|
"#{tap}/#{new_name}"
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
2016-02-25 15:34:11 +08:00
|
|
|
|
|
|
|
renamed_formulae << [old_full_name, new_full_name] if @report[:A].include? new_full_name
|
|
|
|
end
|
|
|
|
|
2017-01-02 17:24:52 +00:00
|
|
|
@report[:A].each do |new_full_name|
|
|
|
|
new_name = new_full_name.split("/").last
|
|
|
|
old_name = tap.formula_renames.key(new_name)
|
|
|
|
next unless old_name
|
|
|
|
|
2020-03-13 21:15:06 +00:00
|
|
|
old_full_name = if tap.core_tap?
|
|
|
|
old_name
|
2017-01-02 17:24:52 +00:00
|
|
|
else
|
2020-03-13 21:15:06 +00:00
|
|
|
"#{tap}/#{old_name}"
|
2017-01-02 17:24:52 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
renamed_formulae << [old_full_name, new_full_name]
|
|
|
|
end
|
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
if renamed_formulae.any?
|
2016-02-25 15:34:11 +08:00
|
|
|
@report[:A] -= renamed_formulae.map(&:last)
|
|
|
|
@report[:D] -= renamed_formulae.map(&:first)
|
2022-02-28 09:54:12 +00:00
|
|
|
@report[:R] = renamed_formulae.to_a
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2023-08-14 19:28:56 +01:00
|
|
|
# If any formulae/casks are marked as added and deleted, remove them from
|
|
|
|
# the report as we've not detected things correctly.
|
|
|
|
if (added_and_deleted_formulae = (@report[:A] & @report[:D]).presence)
|
|
|
|
@report[:A] -= added_and_deleted_formulae
|
|
|
|
@report[:D] -= added_and_deleted_formulae
|
|
|
|
end
|
|
|
|
if (added_and_deleted_casks = (@report[:AC] & @report[:DC]).presence)
|
|
|
|
@report[:AC] -= added_and_deleted_casks
|
|
|
|
@report[:DC] -= added_and_deleted_casks
|
|
|
|
end
|
|
|
|
|
2016-02-25 15:34:11 +08:00
|
|
|
@report
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def updated?
|
2023-02-28 16:40:00 +00:00
|
|
|
if installed_from_api?
|
|
|
|
diff.present?
|
|
|
|
else
|
|
|
|
initial_revision != current_revision
|
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2016-02-25 15:34:11 +08:00
|
|
|
def migrate_tap_migration
|
2016-08-05 16:00:33 +01:00
|
|
|
(report[:D] + report[:DC]).each do |full_name|
|
2016-02-25 15:34:11 +08:00
|
|
|
name = full_name.split("/").last
|
2016-07-26 00:15:21 +03:00
|
|
|
new_tap_name = tap.tap_migrations[name]
|
|
|
|
next if new_tap_name.nil? # skip if not in tap_migrations list.
|
|
|
|
|
2016-12-18 13:18:46 -08:00
|
|
|
new_tap_user, new_tap_repo, new_tap_new_name = new_tap_name.split("/")
|
|
|
|
new_name = if new_tap_new_name
|
|
|
|
new_full_name = new_tap_new_name
|
|
|
|
new_tap_name = "#{new_tap_user}/#{new_tap_repo}"
|
|
|
|
new_tap_new_name
|
|
|
|
else
|
|
|
|
new_full_name = "#{new_tap_name}/#{name}"
|
|
|
|
name
|
|
|
|
end
|
|
|
|
|
2020-11-05 17:17:03 -05:00
|
|
|
# This means it is a cask
|
2016-08-05 16:00:33 +01:00
|
|
|
if report[:DC].include? full_name
|
2016-12-18 13:18:46 -08:00
|
|
|
next unless (HOMEBREW_PREFIX/"Caskroom"/new_name).exist?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-07-26 00:15:21 +03:00
|
|
|
new_tap = Tap.fetch(new_tap_name)
|
2023-07-13 19:45:28 +01:00
|
|
|
new_tap.ensure_installed!
|
2021-11-23 23:55:06 +08:00
|
|
|
ohai "#{name} has been moved to Homebrew.", <<~EOS
|
2021-01-26 15:21:24 -05:00
|
|
|
To uninstall the cask, run:
|
2020-11-18 08:10:21 +01:00
|
|
|
brew uninstall --cask --force #{name}
|
2016-07-26 00:15:21 +03:00
|
|
|
EOS
|
2016-12-18 13:18:46 -08:00
|
|
|
next if (HOMEBREW_CELLAR/new_name.split("/").last).directory?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2021-11-23 23:55:06 +08:00
|
|
|
ohai "Installing #{new_name}..."
|
2016-07-26 00:15:21 +03:00
|
|
|
system HOMEBREW_BREW_FILE, "install", new_full_name
|
|
|
|
begin
|
|
|
|
unless Formulary.factory(new_full_name).keg_only?
|
2016-08-02 11:48:11 +01:00
|
|
|
system HOMEBREW_BREW_FILE, "link", new_full_name, "--overwrite"
|
2016-07-26 00:15:21 +03:00
|
|
|
end
|
2017-10-07 00:31:28 +02:00
|
|
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
2023-03-06 08:20:40 -08:00
|
|
|
onoe "#{e.message}\n#{e.backtrace&.join("\n")}" if Homebrew::EnvConfig.developer?
|
2016-07-26 00:15:21 +03:00
|
|
|
end
|
|
|
|
next
|
|
|
|
end
|
|
|
|
|
2016-02-25 15:34:11 +08:00
|
|
|
next unless (dir = HOMEBREW_CELLAR/name).exist? # skip if formula is not installed.
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-02-25 15:34:11 +08:00
|
|
|
tabs = dir.subdirs.map { |d| Tab.for_keg(Keg.new(d)) }
|
2023-04-18 15:06:50 -07:00
|
|
|
next if tabs.first.tap != tap # skip if installed formula is not from this tap.
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-02-25 15:34:11 +08:00
|
|
|
new_tap = Tap.fetch(new_tap_name)
|
2016-06-22 16:36:17 +04:00
|
|
|
# For formulae migrated to cask: Auto-install cask or provide install instructions.
|
2018-05-25 18:03:16 +02:00
|
|
|
if new_tap_name.start_with?("homebrew/cask")
|
2016-11-05 15:37:28 -04:00
|
|
|
if new_tap.installed? && (HOMEBREW_PREFIX/"Caskroom").directory?
|
2021-11-23 23:55:06 +08:00
|
|
|
ohai "#{name} has been moved to Homebrew Cask."
|
|
|
|
ohai "brew unlink #{name}"
|
2017-02-17 12:34:24 -05:00
|
|
|
system HOMEBREW_BREW_FILE, "unlink", name
|
2021-11-23 23:55:06 +08:00
|
|
|
ohai "brew cleanup"
|
2019-01-02 13:21:34 +00:00
|
|
|
system HOMEBREW_BREW_FILE, "cleanup"
|
2021-11-23 23:55:06 +08:00
|
|
|
ohai "brew install --cask #{new_name}"
|
2020-11-18 08:10:21 +01:00
|
|
|
system HOMEBREW_BREW_FILE, "install", "--cask", new_name
|
2017-10-15 02:28:32 +02:00
|
|
|
ohai <<~EOS
|
2018-09-03 20:12:29 +01:00
|
|
|
#{name} has been moved to Homebrew Cask.
|
2017-02-17 12:34:24 -05:00
|
|
|
The existing keg has been unlinked.
|
|
|
|
Please uninstall the formula when convenient by running:
|
|
|
|
brew uninstall --force #{name}
|
|
|
|
EOS
|
2016-06-22 16:36:17 +04:00
|
|
|
else
|
2021-11-23 23:55:06 +08:00
|
|
|
ohai "#{name} has been moved to Homebrew Cask.", <<~EOS
|
2021-01-26 15:21:24 -05:00
|
|
|
To uninstall the formula and install the cask, run:
|
2016-06-22 16:36:17 +04:00
|
|
|
brew uninstall --force #{name}
|
2018-05-25 18:03:16 +02:00
|
|
|
brew tap #{new_tap_name}
|
2020-11-18 08:10:21 +01:00
|
|
|
brew install --cask #{new_name}
|
2016-06-22 16:36:17 +04:00
|
|
|
EOS
|
|
|
|
end
|
|
|
|
else
|
2023-07-13 19:45:28 +01:00
|
|
|
new_tap.ensure_installed!
|
2016-06-22 16:36:17 +04:00
|
|
|
# update tap for each Tab
|
|
|
|
tabs.each { |tab| tab.tap = new_tap }
|
|
|
|
tabs.each(&:write)
|
|
|
|
end
|
2016-02-25 15:34:11 +08:00
|
|
|
end
|
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
def migrate_cask_rename
|
|
|
|
Cask::Caskroom.casks.each do |cask|
|
|
|
|
Cask::Migrator.migrate_if_needed(cask)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-08-02 04:46:32 +02:00
|
|
|
def migrate_formula_rename(force:, verbose:)
|
2017-03-29 11:22:59 +01:00
|
|
|
Formula.installed.each do |formula|
|
|
|
|
next unless Migrator.needs_migration?(formula)
|
2016-02-25 15:34:11 +08:00
|
|
|
|
2023-04-27 04:09:28 +01:00
|
|
|
oldnames_to_migrate = formula.oldnames.select do |oldname|
|
|
|
|
oldname_rack = HOMEBREW_CELLAR/oldname
|
|
|
|
next false unless oldname_rack.exist?
|
2017-03-29 11:22:59 +01:00
|
|
|
|
2023-04-27 04:09:28 +01:00
|
|
|
if oldname_rack.subdirs.empty?
|
|
|
|
oldname_rack.rmdir_if_possible
|
|
|
|
next false
|
|
|
|
end
|
2017-03-20 18:10:28 +02:00
|
|
|
|
2023-04-27 04:09:28 +01:00
|
|
|
true
|
2016-02-25 15:34:11 +08:00
|
|
|
end
|
2023-04-27 04:09:28 +01:00
|
|
|
next if oldnames_to_migrate.empty?
|
2016-02-25 15:34:11 +08:00
|
|
|
|
2023-04-27 04:09:28 +01:00
|
|
|
Migrator.migrate_if_needed(formula, force: force)
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-02-25 15:34:11 +08:00
|
|
|
private
|
|
|
|
|
2023-02-28 16:40:00 +00:00
|
|
|
attr_reader :tap, :initial_revision, :current_revision, :api_names_txt, :api_names_before_txt, :api_dir_prefix
|
|
|
|
|
|
|
|
def installed_from_api?(api_names_txt = @api_names_txt, api_names_before_txt = @api_names_before_txt,
|
|
|
|
api_dir_prefix = @api_dir_prefix)
|
|
|
|
!api_names_txt.nil? && !api_names_before_txt.nil? && !api_dir_prefix.nil?
|
|
|
|
end
|
|
|
|
|
2016-01-10 20:28:52 +00:00
|
|
|
def diff
|
2023-02-28 16:40:00 +00:00
|
|
|
@diff ||= if installed_from_api?
|
|
|
|
# Hack `git diff` output with regexes to look like `git diff-tree` output.
|
|
|
|
# Yes, I know this is a bit filthy but it saves duplicating the #report logic.
|
2023-05-09 05:19:55 +01:00
|
|
|
diff_output = Utils.popen_read("git", "diff", "--no-ext-diff", api_names_before_txt, api_names_txt)
|
2023-02-28 16:40:00 +00:00
|
|
|
header_regex = /^(---|\+\+\+) /.freeze
|
|
|
|
add_delete_characters = ["+", "-"].freeze
|
|
|
|
|
|
|
|
diff_output.lines.map do |line|
|
|
|
|
next if line.match?(header_regex)
|
|
|
|
next unless add_delete_characters.include?(line[0])
|
|
|
|
|
|
|
|
line.sub(/^\+/, "A #{api_dir_prefix.basename}/")
|
|
|
|
.sub(/^-/, "D #{api_dir_prefix.basename}/")
|
|
|
|
.sub(/$/, ".rb")
|
|
|
|
.chomp
|
|
|
|
end.compact.join("\n")
|
|
|
|
else
|
|
|
|
Utils.popen_read(
|
|
|
|
"git", "-C", tap.path, "diff-tree", "-r", "--name-status", "--diff-filter=AMDR",
|
|
|
|
"-M85%", initial_revision, current_revision
|
|
|
|
)
|
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-02-25 15:43:02 +08:00
|
|
|
class ReporterHub
|
|
|
|
attr_reader :reporters
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { void }
|
2016-01-10 20:28:52 +00:00
|
|
|
def initialize
|
|
|
|
@hash = {}
|
2016-02-25 15:43:02 +08:00
|
|
|
@reporters = []
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2022-06-03 19:16:15 +01:00
|
|
|
def select_formula_or_cask(key)
|
2016-02-25 15:43:02 +08:00
|
|
|
@hash.fetch(key, [])
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2022-05-19 11:04:20 -04:00
|
|
|
def add(reporter, auto_update: false)
|
2016-02-25 15:43:02 +08:00
|
|
|
@reporters << reporter
|
2022-05-19 11:04:20 -04:00
|
|
|
report = reporter.report(auto_update: auto_update).delete_if { |_k, v| v.empty? }
|
2016-02-25 15:43:02 +08:00
|
|
|
@hash.update(report) { |_key, oldval, newval| oldval.concat(newval) }
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2023-04-27 08:13:51 -07:00
|
|
|
def empty?
|
|
|
|
@hash.empty?
|
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
|
2023-03-27 17:24:25 +01:00
|
|
|
def dump(auto_update: false)
|
2023-03-03 08:51:58 +00:00
|
|
|
report_all = ENV["HOMEBREW_UPDATE_REPORT_ALL_FORMULAE"].present?
|
|
|
|
if report_all && !Homebrew::EnvConfig.no_install_from_api?
|
2023-07-06 16:47:09 +01:00
|
|
|
odisabled "HOMEBREW_UPDATE_REPORT_ALL_FORMULAE"
|
2023-03-03 08:51:58 +00:00
|
|
|
opoo "This will not report all formulae because Homebrew cannot get this data from the API."
|
|
|
|
report_all = false
|
|
|
|
end
|
2022-02-28 09:54:12 +00:00
|
|
|
|
2023-08-07 11:34:52 +07:00
|
|
|
unless Homebrew::EnvConfig.no_update_report_new?
|
|
|
|
dump_new_formula_report
|
|
|
|
dump_new_cask_report
|
|
|
|
end
|
2023-08-08 12:06:00 +01:00
|
|
|
|
|
|
|
if report_all
|
|
|
|
dump_renamed_formula_report
|
|
|
|
dump_renamed_cask_report
|
|
|
|
end
|
|
|
|
|
2022-06-11 15:41:28 -07:00
|
|
|
dump_deleted_formula_report(report_all)
|
|
|
|
dump_deleted_cask_report(report_all)
|
2022-06-03 19:16:15 +01:00
|
|
|
|
2023-03-06 10:57:53 -08:00
|
|
|
outdated_formulae = []
|
|
|
|
outdated_casks = []
|
2022-06-03 19:16:15 +01:00
|
|
|
|
2023-08-08 12:06:00 +01:00
|
|
|
if report_all
|
|
|
|
if auto_update
|
|
|
|
if (changed_formulae = select_formula_or_cask(:M).count) && changed_formulae.positive?
|
|
|
|
ohai "Modified Formulae",
|
|
|
|
"Modified #{Utils.pluralize("formula", changed_formulae, plural: "e", include_count: true)}."
|
|
|
|
end
|
2022-06-03 19:16:15 +01:00
|
|
|
|
2023-08-08 12:06:00 +01:00
|
|
|
if (changed_casks = select_formula_or_cask(:MC).count) && changed_casks.positive?
|
|
|
|
ohai "Modified Casks", "Modified #{Utils.pluralize("cask", changed_casks, include_count: true)}."
|
|
|
|
end
|
|
|
|
else
|
|
|
|
dump_modified_formula_report
|
|
|
|
dump_modified_cask_report
|
2022-06-03 19:16:15 +01:00
|
|
|
end
|
2020-07-20 00:21:51 +10:00
|
|
|
else
|
2022-06-03 19:16:15 +01:00
|
|
|
outdated_formulae = Formula.installed.select(&:outdated?).map(&:name)
|
|
|
|
outdated_casks = Cask::Caskroom.casks.select(&:outdated?).map(&:token)
|
2023-08-08 12:06:00 +01:00
|
|
|
unless auto_update
|
|
|
|
output_dump_formula_or_cask_report "Outdated Formulae", outdated_formulae
|
|
|
|
output_dump_formula_or_cask_report "Outdated Casks", outdated_casks
|
|
|
|
end
|
2020-07-20 00:21:51 +10:00
|
|
|
end
|
2022-06-03 19:16:15 +01:00
|
|
|
|
|
|
|
return if outdated_formulae.blank? && outdated_casks.blank?
|
|
|
|
|
|
|
|
outdated_formulae = outdated_formulae.count
|
2023-03-06 10:57:53 -08:00
|
|
|
outdated_casks = outdated_casks.count
|
2022-06-03 19:16:15 +01:00
|
|
|
|
|
|
|
update_pronoun = if (outdated_formulae + outdated_casks) == 1
|
|
|
|
"it"
|
2020-12-14 19:49:35 -05:00
|
|
|
else
|
2022-06-03 19:16:15 +01:00
|
|
|
"them"
|
|
|
|
end
|
|
|
|
|
|
|
|
msg = ""
|
|
|
|
|
|
|
|
if outdated_formulae.positive?
|
2023-02-27 20:49:02 -08:00
|
|
|
noun = Utils.pluralize("formula", outdated_formulae, plural: "e")
|
|
|
|
msg += "#{Tty.bold}#{outdated_formulae}#{Tty.reset} outdated #{noun}"
|
2022-06-03 19:16:15 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
if outdated_casks.positive?
|
|
|
|
msg += " and " if msg.present?
|
2023-02-27 20:49:02 -08:00
|
|
|
msg += "#{Tty.bold}#{outdated_casks}#{Tty.reset} outdated #{Utils.pluralize("cask", outdated_casks)}"
|
2020-12-14 19:49:35 -05:00
|
|
|
end
|
2022-06-03 19:16:15 +01:00
|
|
|
|
|
|
|
return if msg.blank?
|
|
|
|
|
|
|
|
puts
|
2023-03-28 08:49:05 +01:00
|
|
|
puts "You have #{msg} installed."
|
2023-03-27 17:24:25 +01:00
|
|
|
# If we're auto-updating, don't need to suggest commands that we're perhaps
|
|
|
|
# already running.
|
|
|
|
return if auto_update
|
|
|
|
|
|
|
|
puts <<~EOS
|
2022-06-03 19:16:15 +01:00
|
|
|
You can upgrade #{update_pronoun} with #{Tty.bold}brew upgrade#{Tty.reset}
|
|
|
|
or list #{update_pronoun} with #{Tty.bold}brew outdated#{Tty.reset}.
|
|
|
|
EOS
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
2016-02-25 15:43:02 +08:00
|
|
|
private
|
2016-01-10 20:28:52 +00:00
|
|
|
|
2022-06-11 15:41:28 -07:00
|
|
|
def dump_new_formula_report
|
2022-06-17 19:53:30 +01:00
|
|
|
formulae = select_formula_or_cask(:A).sort.reject { |name| installed?(name) }
|
2022-02-28 09:54:12 +00:00
|
|
|
|
2022-06-11 15:41:28 -07:00
|
|
|
output_dump_formula_or_cask_report "New Formulae", formulae
|
|
|
|
end
|
|
|
|
|
|
|
|
def dump_new_cask_report
|
|
|
|
casks = select_formula_or_cask(:AC).sort.map do |name|
|
|
|
|
name.split("/").last unless cask_installed?(name)
|
2022-06-17 00:30:49 +01:00
|
|
|
end.compact
|
2022-06-11 15:41:28 -07:00
|
|
|
|
|
|
|
output_dump_formula_or_cask_report "New Casks", casks
|
|
|
|
end
|
|
|
|
|
|
|
|
def dump_renamed_formula_report
|
|
|
|
formulae = select_formula_or_cask(:R).sort.map do |name, new_name|
|
|
|
|
name = pretty_installed(name) if installed?(name)
|
|
|
|
new_name = pretty_installed(new_name) if installed?(new_name)
|
|
|
|
"#{name} -> #{new_name}"
|
|
|
|
end
|
|
|
|
|
|
|
|
output_dump_formula_or_cask_report "Renamed Formulae", formulae
|
|
|
|
end
|
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
def dump_renamed_cask_report
|
|
|
|
casks = select_formula_or_cask(:RC).sort.map do |name, new_name|
|
|
|
|
name = pretty_installed(name) if installed?(name)
|
|
|
|
new_name = pretty_installed(new_name) if installed?(new_name)
|
|
|
|
"#{name} -> #{new_name}"
|
|
|
|
end
|
|
|
|
|
|
|
|
output_dump_formula_or_cask_report "Renamed Casks", casks
|
|
|
|
end
|
|
|
|
|
2022-06-11 15:41:28 -07:00
|
|
|
def dump_deleted_formula_report(report_all)
|
|
|
|
formulae = select_formula_or_cask(:D).sort.map do |name|
|
|
|
|
if installed?(name)
|
|
|
|
pretty_uninstalled(name)
|
|
|
|
elsif report_all
|
|
|
|
name
|
|
|
|
end
|
|
|
|
end.compact
|
|
|
|
|
2023-08-08 12:06:00 +01:00
|
|
|
title = if report_all
|
|
|
|
"Deleted Formulae"
|
|
|
|
else
|
|
|
|
"Deleted Installed Formulae"
|
|
|
|
end
|
|
|
|
output_dump_formula_or_cask_report title, formulae
|
2022-06-11 15:41:28 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
def dump_deleted_cask_report(report_all)
|
|
|
|
casks = select_formula_or_cask(:DC).sort.map do |name|
|
|
|
|
name = name.split("/").last
|
|
|
|
if cask_installed?(name)
|
|
|
|
pretty_uninstalled(name)
|
|
|
|
elsif report_all
|
|
|
|
name
|
|
|
|
end
|
|
|
|
end.compact
|
|
|
|
|
2023-08-08 12:06:00 +01:00
|
|
|
title = if report_all
|
|
|
|
"Deleted Casks"
|
|
|
|
else
|
|
|
|
"Deleted Installed Casks"
|
|
|
|
end
|
|
|
|
output_dump_formula_or_cask_report title, casks
|
2022-06-11 15:41:28 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
def dump_modified_formula_report
|
|
|
|
formulae = select_formula_or_cask(:M).sort.map do |name|
|
|
|
|
if installed?(name)
|
|
|
|
if outdated?(name)
|
|
|
|
pretty_outdated(name)
|
|
|
|
else
|
|
|
|
pretty_installed(name)
|
2022-02-28 09:54:12 +00:00
|
|
|
end
|
2022-06-11 15:41:28 -07:00
|
|
|
else
|
|
|
|
name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
output_dump_formula_or_cask_report "Modified Formulae", formulae
|
|
|
|
end
|
|
|
|
|
|
|
|
def dump_modified_cask_report
|
|
|
|
casks = select_formula_or_cask(:MC).sort.map do |name|
|
|
|
|
name = name.split("/").last
|
|
|
|
if cask_installed?(name)
|
|
|
|
if cask_outdated?(name)
|
|
|
|
pretty_outdated(name)
|
|
|
|
else
|
|
|
|
pretty_installed(name)
|
2022-06-03 19:16:15 +01:00
|
|
|
end
|
|
|
|
else
|
2022-06-11 15:41:28 -07:00
|
|
|
name
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
2022-06-11 15:41:28 -07:00
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
|
2022-06-11 15:41:28 -07:00
|
|
|
output_dump_formula_or_cask_report "Modified Casks", casks
|
2022-06-03 19:16:15 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def output_dump_formula_or_cask_report(title, formulae_or_casks)
|
|
|
|
return if formulae_or_casks.blank?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2022-06-03 19:16:15 +01:00
|
|
|
ohai title, Formatter.columns(formulae_or_casks.sort)
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def installed?(formula)
|
|
|
|
(HOMEBREW_CELLAR/formula.split("/").last).directory?
|
|
|
|
end
|
2020-03-05 11:14:37 -05:00
|
|
|
|
2022-06-03 19:16:15 +01:00
|
|
|
def outdated?(formula)
|
|
|
|
Formula[formula].outdated?
|
|
|
|
rescue FormulaUnavailableError
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
2020-03-05 11:14:37 -05:00
|
|
|
def cask_installed?(cask)
|
|
|
|
(Cask::Caskroom.path/cask).directory?
|
|
|
|
end
|
2022-06-03 19:16:15 +01:00
|
|
|
|
|
|
|
def cask_outdated?(cask)
|
|
|
|
Cask::CaskLoader.load(cask).outdated?
|
|
|
|
rescue Cask::CaskError
|
|
|
|
false
|
|
|
|
end
|
2016-01-10 20:28:52 +00:00
|
|
|
end
|