Merge branch 'master' into integrate-uninstall-reinstall
This commit is contained in:
commit
3459931a8d
6
.github/workflows/tests.yml
vendored
6
.github/workflows/tests.yml
vendored
@ -114,6 +114,9 @@ jobs:
|
||||
- name: Run brew man
|
||||
run: brew man --fail-if-changed
|
||||
|
||||
- name: Check for outdated license data
|
||||
run: brew update-license-data --fail-if-changed
|
||||
|
||||
- name: Run brew tests
|
||||
run: |
|
||||
# brew tests doesn't like world writable directories
|
||||
@ -136,8 +139,7 @@ jobs:
|
||||
HOMEBREW_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# set variables for coverage reporting
|
||||
HOMEBREW_CI_NAME: github-actions
|
||||
HOMEBREW_COVERALLS_REPO_TOKEN: 3F6U6ZqctoNJwKyREremsqMgpU3qYgxFk
|
||||
HOMEBREW_CODECOV_TOKEN: 3ea0364c-80ce-47a3-9fba-93a940d4b5d7
|
||||
|
||||
# These cannot be queried at the macOS level on GitHub Actions.
|
||||
HOMEBREW_LANGUAGES: en-GB
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@ -86,7 +86,7 @@
|
||||
**/vendor/bundle/ruby/*/gems/byebug-*/
|
||||
**/vendor/bundle/ruby/*/gems/coderay-*/
|
||||
**/vendor/bundle/ruby/*/gems/connection_pool-*/
|
||||
**/vendor/bundle/ruby/*/gems/coveralls-*/
|
||||
**/vendor/bundle/ruby/*/gems/codecov-*/
|
||||
**/vendor/bundle/ruby/*/gems/diff-lcs-*/
|
||||
**/vendor/bundle/ruby/*/gems/docile-*/
|
||||
**/vendor/bundle/ruby/*/gems/domain_name-*/
|
||||
@ -127,11 +127,8 @@
|
||||
**/vendor/bundle/ruby/*/gems/ruby-prof-*/
|
||||
**/vendor/bundle/ruby/*/gems/ruby-progressbar-*/
|
||||
**/vendor/bundle/ruby/*/gems/simplecov-*/
|
||||
**/vendor/bundle/ruby/*/gems/simplecov-cobertura-*/
|
||||
**/vendor/bundle/ruby/*/gems/simplecov-html-*/
|
||||
**/vendor/bundle/ruby/*/gems/term-ansicolor-*/
|
||||
**/vendor/bundle/ruby/*/gems/thor-*/
|
||||
**/vendor/bundle/ruby/*/gems/tins-*/
|
||||
**/vendor/bundle/ruby/*/gems/url-*/
|
||||
**/vendor/bundle/ruby/*/gems/unf_ext-*/
|
||||
**/vendor/bundle/ruby/*/gems/unf-*/
|
||||
**/vendor/bundle/ruby/*/gems/unicode-display_width-*/
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "English"
|
||||
|
||||
@ -20,7 +21,8 @@ SimpleCov.start do
|
||||
|
||||
# Just save result, but don't write formatted output.
|
||||
coverage_result = Coverage.result
|
||||
SimpleCov.add_not_loaded_files(coverage_result)
|
||||
# TODO: this method is private, find a better way.
|
||||
SimpleCov.send(:add_not_loaded_files, coverage_result)
|
||||
simplecov_result = SimpleCov::Result.new(coverage_result)
|
||||
SimpleCov::ResultMerger.store_result(simplecov_result)
|
||||
|
||||
@ -50,8 +52,8 @@ SimpleCov.start do
|
||||
|
||||
require "rbconfig"
|
||||
host_os = RbConfig::CONFIG["host_os"]
|
||||
add_filter %r{/os/mac} if host_os !~ /darwin/
|
||||
add_filter %r{/os/linux} if host_os !~ /linux/
|
||||
add_filter %r{/os/mac} unless /darwin/.match?(host_os)
|
||||
add_filter %r{/os/linux} unless /linux/.match?(host_os)
|
||||
|
||||
# Add groups and the proper project name to the output.
|
||||
project_name "Homebrew"
|
||||
|
||||
@ -4,7 +4,7 @@ source "https://rubygems.org"
|
||||
|
||||
# installed gems
|
||||
gem "byebug"
|
||||
gem "coveralls", "~> 0.8", require: false
|
||||
gem "codecov", require: false
|
||||
gem "parallel_tests"
|
||||
gem "ronn", require: false
|
||||
gem "rspec"
|
||||
|
||||
@ -9,15 +9,13 @@ GEM
|
||||
zeitwerk (~> 2.2, >= 2.2.2)
|
||||
ast (2.4.1)
|
||||
byebug (11.1.3)
|
||||
codecov (0.1.17)
|
||||
json
|
||||
simplecov
|
||||
url
|
||||
concurrent-ruby (1.1.6)
|
||||
connection_pool (2.2.3)
|
||||
coveralls (0.8.23)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov (~> 0.16.1)
|
||||
term-ansicolor (~> 1.3)
|
||||
thor (>= 0.19.4, < 2.0)
|
||||
tins (~> 1.6)
|
||||
diff-lcs (1.4.3)
|
||||
diff-lcs (1.4.4)
|
||||
docile (1.3.2)
|
||||
domain_name (0.5.20190701)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
@ -99,24 +97,18 @@ GEM
|
||||
rubocop (>= 0.68.1)
|
||||
ruby-macho (2.2.0)
|
||||
ruby-progressbar (1.10.1)
|
||||
simplecov (0.16.1)
|
||||
simplecov (0.18.5)
|
||||
docile (~> 1.1)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.2)
|
||||
sync (0.5.0)
|
||||
term-ansicolor (1.7.1)
|
||||
tins (~> 1.0)
|
||||
thor (1.0.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov-html (0.12.2)
|
||||
thread_safe (0.3.6)
|
||||
tins (1.25.0)
|
||||
sync
|
||||
tzinfo (1.2.7)
|
||||
thread_safe (~> 0.1)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.7)
|
||||
unicode-display_width (1.7.0)
|
||||
url (0.3.2)
|
||||
webrobots (0.1.2)
|
||||
zeitwerk (2.3.1)
|
||||
|
||||
@ -126,8 +118,8 @@ PLATFORMS
|
||||
DEPENDENCIES
|
||||
activesupport
|
||||
byebug
|
||||
codecov
|
||||
concurrent-ruby
|
||||
coveralls (~> 0.8)
|
||||
mechanize
|
||||
parallel_tests
|
||||
plist
|
||||
@ -143,4 +135,4 @@ DEPENDENCIES
|
||||
simplecov
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.2
|
||||
1.17.3
|
||||
|
||||
@ -41,7 +41,7 @@ class Bintray
|
||||
|
||||
def upload(local_file, repo:, package:, version:, remote_file:, sha256: nil)
|
||||
url = "#{API_URL}/content/#{@bintray_org}/#{repo}/#{package}/#{version}/#{remote_file}"
|
||||
args = ["--upload-file", local_file]
|
||||
args = ["--fail", "--upload-file", local_file]
|
||||
args += ["--header", "X-Checksum-Sha2: #{sha256}"] unless sha256.blank?
|
||||
result = open_api url, *args
|
||||
json = JSON.parse(result.stdout)
|
||||
@ -50,12 +50,15 @@ class Bintray
|
||||
result
|
||||
end
|
||||
|
||||
def publish(repo:, package:, version:, file_count:)
|
||||
def publish(repo:, package:, version:, file_count:, warn_on_error: false)
|
||||
url = "#{API_URL}/content/#{@bintray_org}/#{repo}/#{package}/#{version}/publish"
|
||||
result = open_api url, "--request", "POST"
|
||||
result = open_api url, "--request", "POST", "--fail"
|
||||
json = JSON.parse(result.stdout)
|
||||
if file_count.present? && json["files"] != file_count
|
||||
raise "Bottle publish failed: expected #{file_count} bottles, but published #{json["files"]} instead."
|
||||
message = "Bottle publish failed: expected #{file_count} bottles, but published #{json["files"]} instead."
|
||||
raise message unless warn_on_error
|
||||
|
||||
opoo message
|
||||
end
|
||||
|
||||
odebug "Published #{json["files"]} bottles"
|
||||
@ -143,7 +146,7 @@ class Bintray
|
||||
end
|
||||
end
|
||||
|
||||
def upload_bottle_json(json_files, publish_package: false)
|
||||
def upload_bottle_json(json_files, publish_package: false, warn_on_error: false)
|
||||
bottles_hash = json_files.reduce({}) do |hash, json_file|
|
||||
hash.deep_merge(JSON.parse(IO.read(json_file)))
|
||||
end
|
||||
@ -161,14 +164,19 @@ class Bintray
|
||||
|
||||
odebug "Checking remote file #{@bintray_org}/#{bintray_repo}/#{filename}"
|
||||
if file_published? repo: bintray_repo, remote_file: filename
|
||||
raise Error, <<~EOS
|
||||
#{filename} is already published.
|
||||
already_published = "#{filename} is already published."
|
||||
failed_message = <<~EOS
|
||||
#{already_published}
|
||||
Please remove it manually from:
|
||||
https://bintray.com/#{@bintray_org}/#{bintray_repo}/#{bintray_package}/view#files
|
||||
Or run:
|
||||
curl -X DELETE -u $HOMEBREW_BINTRAY_USER:$HOMEBREW_BINTRAY_KEY \\
|
||||
https://api.bintray.com/content/#{@bintray_org}/#{bintray_repo}/#{filename}
|
||||
EOS
|
||||
raise Error, failed_message unless warn_on_error
|
||||
|
||||
opoo already_published
|
||||
next
|
||||
end
|
||||
|
||||
if !formula_packaged[formula_name] && !package_exists?(repo: bintray_repo, package: bintray_package)
|
||||
@ -189,7 +197,11 @@ class Bintray
|
||||
|
||||
bottle_count = bottle_hash["bottle"]["tags"].length
|
||||
odebug "Publishing #{@bintray_org}/#{bintray_repo}/#{bintray_package}/#{version}"
|
||||
publish repo: bintray_repo, package: bintray_package, version: version, file_count: bottle_count
|
||||
publish(repo: bintray_repo,
|
||||
package: bintray_package,
|
||||
version: version,
|
||||
file_count: bottle_count,
|
||||
warn_on_error: warn_on_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -211,6 +211,8 @@ module Homebrew
|
||||
|
||||
puts "From: #{Formatter.url(github_info(f))}"
|
||||
|
||||
puts "License: #{f.license}" if f.license
|
||||
|
||||
unless f.deps.empty?
|
||||
ohai "Dependencies"
|
||||
%w[build required recommended optional].map do |type|
|
||||
|
||||
@ -7,6 +7,7 @@ require "install"
|
||||
require "search"
|
||||
require "cleanup"
|
||||
require "cli/parser"
|
||||
require "upgrade"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
@ -261,6 +262,9 @@ module Homebrew
|
||||
install_formula(f)
|
||||
Cleanup.install_formula_clean!(f)
|
||||
end
|
||||
|
||||
check_installed_dependents
|
||||
|
||||
Homebrew.messages.display_messages
|
||||
rescue FormulaUnreadableError, FormulaClassUnavailableError,
|
||||
TapFormulaUnreadableError, TapFormulaClassUnavailableError => e
|
||||
|
||||
@ -11,10 +11,10 @@ module Homebrew
|
||||
usage_banner <<~EOS
|
||||
`readall` [<options>] [<tap>]
|
||||
|
||||
Import all formulae from the specified <tap>, or from all installed taps if none is provided.
|
||||
This can be useful for debugging issues across all formulae when making
|
||||
Import all items from the specified <tap>, or from all installed taps if none is provided.
|
||||
This can be useful for debugging issues across all items when making
|
||||
significant changes to `formula.rb`, testing the performance of loading
|
||||
all formulae or checking if any current formulae have Ruby issues.
|
||||
all items or checking if any current formulae/casks have Ruby issues.
|
||||
EOS
|
||||
switch "--aliases",
|
||||
description: "Verify any alias symlinks in each tap."
|
||||
@ -30,7 +30,7 @@ module Homebrew
|
||||
|
||||
if args.syntax?
|
||||
scan_files = "#{HOMEBREW_LIBRARY_PATH}/**/*.rb"
|
||||
ruby_files = Dir.glob(scan_files).reject { |file| file =~ %r{/(vendor|cask)/} }
|
||||
ruby_files = Dir.glob(scan_files).reject { |file| file =~ %r{/(vendor)/} }
|
||||
|
||||
Homebrew.failed = true unless Readall.valid_ruby_syntax?(ruby_files)
|
||||
end
|
||||
|
||||
@ -9,6 +9,7 @@ require "cleanup"
|
||||
require "cask/cmd"
|
||||
require "cask/utils"
|
||||
require "cask/macos"
|
||||
require "upgrade"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
@ -69,6 +70,9 @@ module Homebrew
|
||||
reinstall_formula(f)
|
||||
Cleanup.install_formula_clean!(f)
|
||||
end
|
||||
|
||||
check_installed_dependents
|
||||
|
||||
Homebrew.messages.display_messages
|
||||
|
||||
return if casks.empty?
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "install"
|
||||
require "reinstall"
|
||||
require "formula_installer"
|
||||
require "development_tools"
|
||||
require "messages"
|
||||
require "cleanup"
|
||||
require "cli/parser"
|
||||
require "formula_installer"
|
||||
require "install"
|
||||
require "upgrade"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
@ -114,241 +111,8 @@ module Homebrew
|
||||
|
||||
upgrade_formulae(formulae_to_install)
|
||||
|
||||
check_dependents(formulae_to_install)
|
||||
check_installed_dependents
|
||||
|
||||
Homebrew.messages.display_messages
|
||||
end
|
||||
|
||||
def upgrade_formulae(formulae_to_install)
|
||||
return if formulae_to_install.empty?
|
||||
return if args.dry_run?
|
||||
|
||||
# Sort keg-only before non-keg-only formulae to avoid any needless conflicts
|
||||
# with outdated, non-keg-only versions of formulae being upgraded.
|
||||
formulae_to_install.sort! do |a, b|
|
||||
if !a.keg_only? && b.keg_only?
|
||||
1
|
||||
elsif a.keg_only? && !b.keg_only?
|
||||
-1
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
formulae_to_install.each do |f|
|
||||
Migrator.migrate_if_needed(f)
|
||||
begin
|
||||
upgrade_formula(f)
|
||||
Cleanup.install_formula_clean!(f)
|
||||
rescue UnsatisfiedRequirements => e
|
||||
Homebrew.failed = true
|
||||
onoe "#{f}: #{e}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def upgrade_formula(f)
|
||||
return if args.dry_run?
|
||||
|
||||
if f.opt_prefix.directory?
|
||||
keg = Keg.new(f.opt_prefix.resolved_path)
|
||||
keg_had_linked_opt = true
|
||||
keg_was_linked = keg.linked?
|
||||
end
|
||||
|
||||
formulae_maybe_with_kegs = [f] + f.old_installed_formulae
|
||||
outdated_kegs = formulae_maybe_with_kegs
|
||||
.map(&:linked_keg)
|
||||
.select(&:directory?)
|
||||
.map { |k| Keg.new(k.resolved_path) }
|
||||
linked_kegs = outdated_kegs.select(&:linked?)
|
||||
|
||||
if f.opt_prefix.directory?
|
||||
keg = Keg.new(f.opt_prefix.resolved_path)
|
||||
tab = Tab.for_keg(keg)
|
||||
end
|
||||
|
||||
build_options = BuildOptions.new(Options.create(args.flags_only), f.options)
|
||||
options = build_options.used_options
|
||||
options |= f.build.used_options
|
||||
options &= f.options
|
||||
|
||||
fi = FormulaInstaller.new(f)
|
||||
fi.options = options
|
||||
fi.build_bottle = args.build_bottle?
|
||||
fi.installed_on_request = args.named.present?
|
||||
fi.link_keg ||= keg_was_linked if keg_had_linked_opt
|
||||
if tab
|
||||
fi.build_bottle ||= tab.built_bottle?
|
||||
fi.installed_as_dependency = tab.installed_as_dependency
|
||||
fi.installed_on_request ||= tab.installed_on_request
|
||||
end
|
||||
|
||||
upgrade_version = if f.optlinked?
|
||||
"#{Keg.new(f.opt_prefix).version} -> #{f.pkg_version}"
|
||||
else
|
||||
"-> #{f.pkg_version}"
|
||||
end
|
||||
oh1 "Upgrading #{Formatter.identifier(f.full_specified_name)} #{upgrade_version} #{fi.options.to_a.join(" ")}"
|
||||
|
||||
fi.prelude
|
||||
fi.fetch
|
||||
|
||||
# first we unlink the currently active keg for this formula otherwise it is
|
||||
# possible for the existing build to interfere with the build we are about to
|
||||
# do! Seriously, it happens!
|
||||
outdated_kegs.each(&:unlink)
|
||||
|
||||
fi.install
|
||||
fi.finish
|
||||
rescue FormulaInstallationAlreadyAttemptedError
|
||||
# We already attempted to upgrade f as part of the dependency tree of
|
||||
# another formula. In that case, don't generate an error, just move on.
|
||||
nil
|
||||
rescue CannotInstallFormulaError => e
|
||||
ofail e
|
||||
rescue BuildError => e
|
||||
e.dump
|
||||
puts
|
||||
Homebrew.failed = true
|
||||
rescue DownloadError => e
|
||||
ofail e
|
||||
ensure
|
||||
# restore previous installation state if build failed
|
||||
begin
|
||||
linked_kegs.each(&:link) unless f.latest_version_installed?
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# @private
|
||||
def depends_on(a, b)
|
||||
if a.opt_or_installed_prefix_keg
|
||||
&.runtime_dependencies
|
||||
&.any? { |d| d["full_name"] == b.full_name }
|
||||
1
|
||||
else
|
||||
a <=> b
|
||||
end
|
||||
end
|
||||
|
||||
def check_dependents(formulae_to_install)
|
||||
return if formulae_to_install.empty?
|
||||
|
||||
oh1 "Checking for dependents of upgraded formulae..." unless args.dry_run?
|
||||
outdated_dependents =
|
||||
formulae_to_install.flat_map(&:runtime_installed_formula_dependents)
|
||||
.select(&:outdated?)
|
||||
if outdated_dependents.blank?
|
||||
ohai "No dependents found!" unless args.dry_run?
|
||||
return
|
||||
end
|
||||
outdated_dependents -= formulae_to_install if args.dry_run?
|
||||
|
||||
upgradeable_dependents =
|
||||
outdated_dependents.reject(&:pinned?)
|
||||
.sort { |a, b| depends_on(a, b) }
|
||||
pinned_dependents =
|
||||
outdated_dependents.select(&:pinned?)
|
||||
.sort { |a, b| depends_on(a, b) }
|
||||
|
||||
if pinned_dependents.present?
|
||||
plural = "dependent".pluralize(pinned_dependents.count)
|
||||
ohai "Not upgrading #{pinned_dependents.count} pinned #{plural}:"
|
||||
puts(pinned_dependents.map do |f|
|
||||
"#{f.full_specified_name} #{f.pkg_version}"
|
||||
end.join(", "))
|
||||
end
|
||||
|
||||
# Print the upgradable dependents.
|
||||
if upgradeable_dependents.blank?
|
||||
ohai "No outdated dependents to upgrade!" unless args.dry_run?
|
||||
else
|
||||
plural = "dependent".pluralize(upgradeable_dependents.count)
|
||||
verb = args.dry_run? ? "Would upgrade" : "Upgrading"
|
||||
ohai "#{verb} #{upgradeable_dependents.count} #{plural}:"
|
||||
formulae_upgrades = upgradeable_dependents.map do |f|
|
||||
name = f.full_specified_name
|
||||
if f.optlinked?
|
||||
"#{name} #{Keg.new(f.opt_prefix).version} -> #{f.pkg_version}"
|
||||
else
|
||||
"#{name} #{f.pkg_version}"
|
||||
end
|
||||
end
|
||||
puts formulae_upgrades.join(", ")
|
||||
end
|
||||
|
||||
upgrade_formulae(upgradeable_dependents)
|
||||
|
||||
# Assess the dependents tree again now we've upgraded.
|
||||
oh1 "Checking for dependents of upgraded formulae..." unless args.dry_run?
|
||||
broken_dependents = CacheStoreDatabase.use(:linkage) do |db|
|
||||
formulae_to_install.flat_map(&:runtime_installed_formula_dependents)
|
||||
.select do |f|
|
||||
keg = f.opt_or_installed_prefix_keg
|
||||
next unless keg
|
||||
|
||||
LinkageChecker.new(keg, cache_db: db)
|
||||
.broken_library_linkage?
|
||||
end.compact
|
||||
end
|
||||
if broken_dependents.blank?
|
||||
if args.dry_run?
|
||||
ohai "No currently broken dependents found!"
|
||||
opoo "If they are broken by the upgrade they will also be upgraded or reinstalled."
|
||||
else
|
||||
ohai "No broken dependents found!"
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
reinstallable_broken_dependents =
|
||||
broken_dependents.reject(&:outdated?)
|
||||
.reject(&:pinned?)
|
||||
.sort { |a, b| depends_on(a, b) }
|
||||
outdated_pinned_broken_dependents =
|
||||
broken_dependents.select(&:outdated?)
|
||||
.select(&:pinned?)
|
||||
.sort { |a, b| depends_on(a, b) }
|
||||
|
||||
# Print the pinned dependents.
|
||||
if outdated_pinned_broken_dependents.present?
|
||||
count = outdated_pinned_broken_dependents.count
|
||||
plural = "dependent".pluralize(outdated_pinned_broken_dependents.count)
|
||||
onoe "Not reinstalling #{count} broken and outdated, but pinned #{plural}:"
|
||||
$stderr.puts(outdated_pinned_broken_dependents.map do |f|
|
||||
"#{f.full_specified_name} #{f.pkg_version}"
|
||||
end.join(", "))
|
||||
end
|
||||
|
||||
# Print the broken dependents.
|
||||
if reinstallable_broken_dependents.blank?
|
||||
ohai "No broken dependents to reinstall!"
|
||||
else
|
||||
count = reinstallable_broken_dependents.count
|
||||
plural = "dependent".pluralize(reinstallable_broken_dependents.count)
|
||||
ohai "Reinstalling #{count} broken #{plural} from source:"
|
||||
puts reinstallable_broken_dependents.map(&:full_specified_name)
|
||||
.join(", ")
|
||||
end
|
||||
|
||||
return if args.dry_run?
|
||||
|
||||
reinstallable_broken_dependents.each do |f|
|
||||
reinstall_formula(f, build_from_source: true)
|
||||
rescue FormulaInstallationAlreadyAttemptedError
|
||||
# We already attempted to reinstall f as part of the dependency tree of
|
||||
# another formula. In that case, don't generate an error, just move on.
|
||||
nil
|
||||
rescue CannotInstallFormulaError => e
|
||||
ofail e
|
||||
rescue BuildError => e
|
||||
e.dump
|
||||
puts
|
||||
Homebrew.failed = true
|
||||
rescue DownloadError => e
|
||||
ofail e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
5454
Library/Homebrew/data/spdx.json
Normal file
5454
Library/Homebrew/data/spdx.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -12,6 +12,7 @@ require "date"
|
||||
require "missing_formula"
|
||||
require "digest"
|
||||
require "cli/parser"
|
||||
require "json"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
@ -109,7 +110,9 @@ module Homebrew
|
||||
|
||||
# Check style in a single batch run up front for performance
|
||||
style_results = Style.check_style_json(style_files, options) if style_files
|
||||
|
||||
# load licenses
|
||||
spdx = HOMEBREW_LIBRARY_PATH/"data/spdx.json"
|
||||
spdx_data = JSON.parse(spdx.read)
|
||||
new_formula_problem_lines = []
|
||||
audit_formulae.sort.each do |f|
|
||||
only = only_cops ? ["style"] : args.only
|
||||
@ -120,6 +123,7 @@ module Homebrew
|
||||
git: git,
|
||||
only: only,
|
||||
except: args.except,
|
||||
spdx_data: spdx_data,
|
||||
}
|
||||
options[:style_offenses] = style_results.file_offenses(f.path) if style_results
|
||||
options[:display_cop_names] = args.display_cop_names?
|
||||
@ -215,6 +219,7 @@ module Homebrew
|
||||
@new_formula_problems = []
|
||||
@text = FormulaText.new(formula.path)
|
||||
@specs = %w[stable devel head].map { |s| formula.send(s) }.compact
|
||||
@spdx_data = options[:spdx_data]
|
||||
end
|
||||
|
||||
def audit_style
|
||||
@ -327,6 +332,27 @@ module Homebrew
|
||||
openssl@1.1
|
||||
].freeze
|
||||
|
||||
def audit_license
|
||||
if formula.license.present?
|
||||
if @spdx_data["licenses"].any? { |lic| lic["licenseId"] == formula.license }
|
||||
return unless @online
|
||||
|
||||
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @new_formula
|
||||
return if user.blank?
|
||||
|
||||
github_license = GitHub.get_repo_license(user, repo)
|
||||
return if github_license && (github_license == formula.license)
|
||||
|
||||
problem "License mismatch - GitHub license is: #{github_license}, "\
|
||||
"but Formulae license states: #{formula.license}."
|
||||
else
|
||||
problem "#{formula.license} is not a standard SPDX license."
|
||||
end
|
||||
elsif @new_formula
|
||||
problem "No license specified for package."
|
||||
end
|
||||
end
|
||||
|
||||
def audit_deps
|
||||
@specs.each do |spec|
|
||||
# Check for things we don't like to depend on.
|
||||
@ -502,8 +528,9 @@ module Homebrew
|
||||
end
|
||||
|
||||
def audit_github_repository
|
||||
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*})
|
||||
return if user.nil?
|
||||
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @new_formula
|
||||
|
||||
return if user.blank?
|
||||
|
||||
warning = SharedAudits.github(user, repo)
|
||||
return if warning.nil?
|
||||
@ -512,8 +539,8 @@ module Homebrew
|
||||
end
|
||||
|
||||
def audit_gitlab_repository
|
||||
user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*})
|
||||
return if user.nil?
|
||||
user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) if @new_formula
|
||||
return if user.blank?
|
||||
|
||||
warning = SharedAudits.gitlab(user, repo)
|
||||
return if warning.nil?
|
||||
@ -522,8 +549,8 @@ module Homebrew
|
||||
end
|
||||
|
||||
def audit_bitbucket_repository
|
||||
user, repo = get_repo_data(%r{https?://bitbucket\.org/([^/]+)/([^/]+)/?.*})
|
||||
return if user.nil?
|
||||
user, repo = get_repo_data(%r{https?://bitbucket\.org/([^/]+)/([^/]+)/?.*}) if @new_formula
|
||||
return if user.blank?
|
||||
|
||||
warning = SharedAudits.bitbucket(user, repo)
|
||||
return if warning.nil?
|
||||
@ -534,7 +561,6 @@ module Homebrew
|
||||
def get_repo_data(regex)
|
||||
return unless @core_tap
|
||||
return unless @online
|
||||
return unless @new_formula
|
||||
|
||||
_, user, repo = *regex.match(formula.stable.url) if formula.stable
|
||||
_, user, repo = *regex.match(formula.homepage) unless user
|
||||
|
||||
@ -531,25 +531,21 @@ module Homebrew
|
||||
odie "--keep-old was passed but there was no existing bottle block!" if args.keep_old?
|
||||
puts output
|
||||
update_or_add = "add"
|
||||
if s.include? "stable do"
|
||||
indent = s.slice(/^( +)stable do/, 1).length
|
||||
string = s.sub!(/^ {#{indent}}stable do(.|\n)+?^ {#{indent}}end\n/m, '\0' + output + "\n")
|
||||
else
|
||||
pattern = /(
|
||||
(\ {2}\#[^\n]*\n)* # comments
|
||||
\ {2}( # two spaces at the beginning
|
||||
(url|head)\ ['"][\S\ ]+['"] # url or head with a string
|
||||
(
|
||||
,[\S\ ]*$ # url may have options
|
||||
(\n^\ {3}[\S\ ]+$)* # options can be in multiple lines
|
||||
)?|
|
||||
(homepage|desc|sha1|sha256|version|mirror)\ ['"][\S\ ]+['"]| # specs with a string
|
||||
(revision|version_scheme)\ \d+ # revision with a number
|
||||
)\n+ # multiple empty lines
|
||||
)+
|
||||
/mx
|
||||
string = s.sub!(pattern, '\0' + output + "\n")
|
||||
end
|
||||
pattern = /(
|
||||
(\ {2}\#[^\n]*\n)* # comments
|
||||
\ {2}( # two spaces at the beginning
|
||||
(url|head)\ ['"][\S\ ]+['"] # url or head with a string
|
||||
(
|
||||
,[\S\ ]*$ # url may have options
|
||||
(\n^\ {3}[\S\ ]+$)* # options can be in multiple lines
|
||||
)?|
|
||||
(homepage|desc|sha256|version|mirror|license)\ ['"][\S\ ]+['"]| # specs with a string
|
||||
(revision|version_scheme)\ \d+| # revision with a number
|
||||
(stable|livecheck)\ do(\n+^\ {4}[\S\ ]+$)*\n+^\ {2}end # components with blocks
|
||||
)\n+ # multiple empty lines
|
||||
)+
|
||||
/mx
|
||||
string = s.sub!(pattern, '\0' + output + "\n")
|
||||
odie "Bottle block addition failed!" unless string
|
||||
end
|
||||
end
|
||||
|
||||
@ -47,6 +47,8 @@ module Homebrew
|
||||
description: "Explicitly set the <name> of the new formula."
|
||||
flag "--set-version=",
|
||||
description: "Explicitly set the <version> of the new formula."
|
||||
flag "--set-license=",
|
||||
description: "Explicitly set the <license> of the new formula."
|
||||
flag "--tap=",
|
||||
description: "Generate the new formula within the given tap, specified as <user>`/`<repo>."
|
||||
switch :force
|
||||
@ -68,11 +70,13 @@ module Homebrew
|
||||
|
||||
version = args.set_version
|
||||
name = args.set_name
|
||||
license = args.set_license
|
||||
tap = args.tap
|
||||
|
||||
fc = FormulaCreator.new
|
||||
fc.name = name
|
||||
fc.version = version
|
||||
fc.license = license
|
||||
fc.tap = Tap.fetch(tap || "homebrew/core")
|
||||
raise TapUnavailableError, tap unless fc.tap.installed?
|
||||
|
||||
|
||||
@ -191,7 +191,10 @@ module Homebrew
|
||||
# Remove any existing version suffixes, as a new one will be added later
|
||||
name.sub!(/\b@(.*)\z\b/i, "")
|
||||
versioned_name = Formulary.class_s("#{name}@#{version}")
|
||||
result.gsub!("class #{class_name} < Formula", "class #{versioned_name} < Formula")
|
||||
result.sub!("class #{class_name} < Formula", "class #{versioned_name} < Formula")
|
||||
|
||||
# Remove bottle blocks, they won't work.
|
||||
result.sub!(/ bottle do.+?end\n\n/m, "") if destination_tap != source_tap
|
||||
|
||||
path = destination_tap.path/"Formula/#{name}@#{version}.rb"
|
||||
if path.exist?
|
||||
@ -205,7 +208,8 @@ module Homebrew
|
||||
odebug "Overwriting existing formula at #{path}"
|
||||
path.delete
|
||||
end
|
||||
ohai "Writing formula for #{name} from revision #{rev} to #{path}"
|
||||
ohai "Writing formula for #{name} from revision #{rev} to:"
|
||||
puts path
|
||||
path.write result
|
||||
end
|
||||
|
||||
|
||||
@ -33,6 +33,9 @@ module Homebrew
|
||||
switch "--resolve",
|
||||
description: "When a patch fails to apply, leave in progress and allow user to resolve, "\
|
||||
"instead of aborting."
|
||||
switch "--warn-on-upload-failure",
|
||||
description: "Warn instead of raising an error if the bottle upload fails. "\
|
||||
"Useful for repairing bottle uploads that previously failed."
|
||||
flag "--workflow=",
|
||||
description: "Retrieve artifacts from the specified workflow (default: `tests.yml`)."
|
||||
flag "--artifact=",
|
||||
@ -73,13 +76,18 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
def signoff!(pr, path: ".")
|
||||
message = Utils.popen_read "git", "-C", path, "log", "-1", "--pretty=%B"
|
||||
def signoff!(pr, tap:)
|
||||
message = Utils.popen_read "git", "-C", tap.path, "log", "-1", "--pretty=%B"
|
||||
subject = message.lines.first.strip
|
||||
|
||||
# Skip the subject and separate lines that look like trailers (e.g. "Co-authored-by")
|
||||
# from lines that look like regular body text.
|
||||
trailers, body = message.lines.drop(1).partition { |s| s.match?(/^[a-z-]+-by:/i) }
|
||||
|
||||
# Approving reviewers also sign-off on merge
|
||||
trailers += GitHub.approved_reviews(tap.user, "homebrew-#{tap.repo}", pr).map do |r|
|
||||
"Signed-off-by: #{r["name"]} <#{r["email"]}>\n"
|
||||
end
|
||||
trailers = trailers.uniq.join.strip
|
||||
body = body.join.strip.gsub(/\n{3,}/, "\n\n")
|
||||
|
||||
@ -90,7 +98,7 @@ module Homebrew
|
||||
if Homebrew.args.dry_run?
|
||||
puts "git commit --amend --signoff -m $message"
|
||||
else
|
||||
safe_system "git", "-C", path, "commit", "--amend", "--signoff", "--allow-empty", "-q", "-m", new_message
|
||||
safe_system "git", "-C", tap.path, "commit", "--amend", "--signoff", "--allow-empty", "-q", "-m", new_message
|
||||
end
|
||||
end
|
||||
|
||||
@ -232,7 +240,7 @@ module Homebrew
|
||||
cd dir do
|
||||
original_commit = Utils.popen_read("git", "-C", tap.path, "rev-parse", "HEAD").chomp
|
||||
cherry_pick_pr! pr, path: tap.path
|
||||
signoff! pr, path: tap.path unless args.clean?
|
||||
signoff! pr, tap: tap unless args.clean?
|
||||
|
||||
unless args.no_upload?
|
||||
mirror_formulae(tap, original_commit, org: bintray_org, repo: mirror_repo, publish: !args.no_publish?)
|
||||
@ -253,9 +261,10 @@ module Homebrew
|
||||
upload_args << "--verbose" if Homebrew.args.verbose?
|
||||
upload_args << "--no-publish" if args.no_publish?
|
||||
upload_args << "--dry-run" if args.dry_run?
|
||||
upload_args << "--warn-on-upload-failure" if args.warn_on_upload_failure?
|
||||
upload_args << "--root_url=#{args.root_url}" if args.root_url
|
||||
upload_args << "--bintray-org=#{bintray_org}"
|
||||
system HOMEBREW_BREW_FILE, *upload_args
|
||||
safe_system HOMEBREW_BREW_FILE, *upload_args
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -17,6 +17,9 @@ module Homebrew
|
||||
description: "Apply the bottle commit and upload the bottles, but don't publish them."
|
||||
switch "-n", "--dry-run",
|
||||
description: "Print what would be done rather than doing it."
|
||||
switch "--warn-on-upload-failure",
|
||||
description: "Warn instead of raising an error if the bottle upload fails. "\
|
||||
"Useful for repairing bottle uploads that previously failed."
|
||||
flag "--bintray-org=",
|
||||
description: "Upload to the specified Bintray organisation (default: `homebrew`)."
|
||||
flag "--root-url=",
|
||||
@ -42,13 +45,15 @@ module Homebrew
|
||||
if args.dry_run?
|
||||
puts "brew #{bottle_args.join " "}"
|
||||
else
|
||||
system HOMEBREW_BREW_FILE, *bottle_args
|
||||
safe_system HOMEBREW_BREW_FILE, *bottle_args
|
||||
end
|
||||
|
||||
if args.dry_run?
|
||||
puts "Upload bottles described by these JSON files to Bintray:\n #{Dir["*.json"].join("\n ")}"
|
||||
else
|
||||
bintray.upload_bottle_json Dir["*.json"], publish_package: !args.no_publish?
|
||||
bintray.upload_bottle_json(Dir["*.json"],
|
||||
publish_package: !args.no_publish?,
|
||||
warn_on_error: args.warn_on_upload_failure?)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
39
Library/Homebrew/dev-cmd/update-license-data.rb
Normal file
39
Library/Homebrew/dev-cmd/update-license-data.rb
Normal file
@ -0,0 +1,39 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "commands"
|
||||
require "cli/parser"
|
||||
require "json"
|
||||
require "net/http"
|
||||
require "open-uri"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
|
||||
SPDX_PATH = (HOMEBREW_LIBRARY_PATH/"data/spdx.json").freeze
|
||||
SPDX_DATA_URL = "https://raw.githubusercontent.com/spdx/license-list-data/HEAD/json/licenses.json"
|
||||
|
||||
def update_license_data_args
|
||||
Homebrew::CLI::Parser.new do
|
||||
usage_banner <<~EOS
|
||||
`update_license_data` <cmd>
|
||||
|
||||
Update SPDX license data in the Homebrew repository.
|
||||
EOS
|
||||
switch "--fail-if-changed",
|
||||
description: "Return a failing status code if current license data's version is different from " \
|
||||
"the upstream. This can be used to notify CI when the SPDX license data is out of date."
|
||||
|
||||
max_named 0
|
||||
end
|
||||
end
|
||||
|
||||
def update_license_data
|
||||
update_license_data_args.parse
|
||||
ohai "Updating SPDX license data..."
|
||||
curl_download(SPDX_DATA_URL, to: SPDX_PATH, partial: false)
|
||||
|
||||
return unless args.fail_if_changed?
|
||||
|
||||
safe_system "git", "diff", "--stat", "--exit-code", SPDX_PATH
|
||||
end
|
||||
end
|
||||
9
Library/Homebrew/extend/os/linux/readall.rb
Normal file
9
Library/Homebrew/extend/os/linux/readall.rb
Normal file
@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Readall
|
||||
class << self
|
||||
def valid_casks?(*)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -12,6 +12,7 @@ module Homebrew
|
||||
check_xcode_minimum_version
|
||||
check_clt_minimum_version
|
||||
check_if_xcode_needs_clt_installed
|
||||
check_if_supported_sdk_available
|
||||
].freeze
|
||||
end
|
||||
|
||||
@ -357,6 +358,34 @@ module Homebrew
|
||||
Untap them with `brew untap`.
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_if_supported_sdk_available
|
||||
return unless MacOS.sdk_root_needed?
|
||||
return if MacOS.sdk
|
||||
|
||||
locator = MacOS.sdk_locator
|
||||
|
||||
source = if locator.source == :clt
|
||||
"CLT"
|
||||
else
|
||||
"Xcode"
|
||||
end
|
||||
|
||||
all_sdks = locator.all_sdks
|
||||
sdks_found_msg = unless all_sdks.empty?
|
||||
<<~EOS
|
||||
Homebrew found the following SDKs in the #{source} install:
|
||||
#{locator.all_sdks.map(&:version).join("\n ")}
|
||||
EOS
|
||||
end
|
||||
|
||||
<<~EOS
|
||||
Could not find an SDK that supports macOS #{MacOS.version}.
|
||||
You may have have an outdated or incompatible #{source}.
|
||||
#{sdks_found_msg}
|
||||
Please update #{source} or uninstall it if no updates are available.
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
3
Library/Homebrew/extend/os/readall.rb
Normal file
3
Library/Homebrew/extend/os/readall.rb
Normal file
@ -0,0 +1,3 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "extend/os/linux/readall" if OS.linux?
|
||||
@ -351,6 +351,9 @@ class Formula
|
||||
# @see .desc=
|
||||
delegate desc: :"self.class"
|
||||
|
||||
# The SPDX ID of the software license.
|
||||
delegate license: :"self.class"
|
||||
|
||||
# The homepage for the software.
|
||||
# @method homepage
|
||||
# @see .homepage=
|
||||
@ -1687,6 +1690,7 @@ class Formula
|
||||
"aliases" => aliases.sort,
|
||||
"versioned_formulae" => versioned_formulae.map(&:name),
|
||||
"desc" => desc,
|
||||
"license" => license,
|
||||
"homepage" => homepage,
|
||||
"versions" => {
|
||||
"stable" => stable&.version&.to_s,
|
||||
@ -2211,6 +2215,13 @@ class Formula
|
||||
# <pre>desc "Example formula"</pre>
|
||||
attr_rw :desc
|
||||
|
||||
# @!attribute [w]
|
||||
# The SPDX ID of the open-source license that the formula uses.
|
||||
# Shows when running `brew info`.
|
||||
#
|
||||
# <pre>license "BSD-2-Clause"</pre>
|
||||
attr_rw :license
|
||||
|
||||
# @!attribute [w] homepage
|
||||
# The homepage for the software. Used by users to get more information
|
||||
# about the software and Homebrew maintainers as a point of contact for
|
||||
@ -2648,9 +2659,13 @@ class Formula
|
||||
#
|
||||
# The block will create, run in and delete a temporary directory.
|
||||
#
|
||||
# We are fine if the executable does not error out, so we know linking
|
||||
# and building the software was OK.
|
||||
# <pre>system bin/"foobar", "--version"</pre>
|
||||
# We want tests that don't require any user input
|
||||
# and test the basic functionality of the application.
|
||||
# For example foo build-foo input.foo is a good test
|
||||
# and foo --version and foo --help are bad tests.
|
||||
# However, a bad test is better than no test at all.
|
||||
#
|
||||
# See: https://docs.brew.sh/Formula-Cookbook#add-a-test-to-the-formula
|
||||
#
|
||||
# <pre>(testpath/"test.file").write <<~EOS
|
||||
# writing some test file, if you need to
|
||||
|
||||
@ -6,7 +6,7 @@ require "erb"
|
||||
module Homebrew
|
||||
class FormulaCreator
|
||||
attr_reader :url, :sha256, :desc, :homepage
|
||||
attr_accessor :name, :version, :tap, :path, :mode
|
||||
attr_accessor :name, :version, :tap, :path, :mode, :license
|
||||
|
||||
def url=(url)
|
||||
@url = url
|
||||
@ -100,6 +100,7 @@ module Homebrew
|
||||
<% end %>
|
||||
sha256 "#{sha256}"
|
||||
<% end %>
|
||||
license "#{license}"
|
||||
|
||||
<% if mode == :cmake %>
|
||||
depends_on "cmake" => :build
|
||||
|
||||
@ -77,6 +77,14 @@ class FormulaInstaller
|
||||
@attempted = Set.new
|
||||
end
|
||||
|
||||
def self.installed
|
||||
@installed ||= Set.new
|
||||
end
|
||||
|
||||
def self.clear_installed
|
||||
@installed = Set.new
|
||||
end
|
||||
|
||||
# When no build tools are available and build flags are passed through ARGV,
|
||||
# it's necessary to interrupt the user before any sort of installation
|
||||
# can proceed. Only invoked when the user has no developer tools.
|
||||
@ -292,7 +300,7 @@ class FormulaInstaller
|
||||
|
||||
self.class.attempted << formula
|
||||
|
||||
if pour_bottle?(warn: true)
|
||||
if pour_bottle?
|
||||
begin
|
||||
pour
|
||||
rescue Exception => e # rubocop:disable Lint/RescueException
|
||||
@ -700,6 +708,8 @@ class FormulaInstaller
|
||||
|
||||
ohai "Summary" if verbose? || show_summary_heading?
|
||||
puts summary
|
||||
|
||||
self.class.installed << formula
|
||||
ensure
|
||||
unlock
|
||||
end
|
||||
@ -983,11 +993,24 @@ class FormulaInstaller
|
||||
|
||||
return if only_deps?
|
||||
|
||||
unless pour_bottle?
|
||||
formula.fetch_patches
|
||||
formula.resources.each(&:fetch)
|
||||
end
|
||||
if pour_bottle?(warn: true)
|
||||
begin
|
||||
downloader.fetch
|
||||
rescue Exception => e # rubocop:disable Lint/RescueException
|
||||
raise if Homebrew::EnvConfig.developer? ||
|
||||
Homebrew::EnvConfig.no_bottle_source_fallback? ||
|
||||
e.is_a?(Interrupt)
|
||||
|
||||
@pour_failed = true
|
||||
onoe e.message
|
||||
opoo "Bottle installation failed: building from source."
|
||||
fetch_dependencies
|
||||
end
|
||||
end
|
||||
return if pour_bottle?
|
||||
|
||||
formula.fetch_patches
|
||||
formula.resources.each(&:fetch)
|
||||
downloader.fetch
|
||||
end
|
||||
|
||||
|
||||
@ -97,14 +97,16 @@ module OS
|
||||
# If no specific SDK is requested, the SDK matching the OS version is returned,
|
||||
# if available. Otherwise, the latest SDK is returned.
|
||||
|
||||
def sdk(v = nil)
|
||||
@locator ||= if CLT.installed? && CLT.provides_sdk?
|
||||
CLTSDKLocator.new
|
||||
def sdk_locator
|
||||
if CLT.installed? && CLT.provides_sdk?
|
||||
CLT.sdk_locator
|
||||
else
|
||||
XcodeSDKLocator.new
|
||||
Xcode.sdk_locator
|
||||
end
|
||||
end
|
||||
|
||||
@locator.sdk_if_applicable(v)
|
||||
def sdk(v = nil)
|
||||
sdk_locator.sdk_if_applicable(v)
|
||||
end
|
||||
|
||||
def sdk_for_formula(f, v = nil)
|
||||
|
||||
@ -31,6 +31,10 @@ module OS
|
||||
SDK.new v, path, source
|
||||
end
|
||||
|
||||
def all_sdks
|
||||
sdk_paths.map { |v, p| SDK.new v, p, source }
|
||||
end
|
||||
|
||||
def sdk_if_applicable(v = nil)
|
||||
sdk = begin
|
||||
if v.nil?
|
||||
@ -47,15 +51,11 @@ module OS
|
||||
sdk
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def source
|
||||
nil
|
||||
end
|
||||
|
||||
def source_version
|
||||
OS::Mac::Version::NULL
|
||||
end
|
||||
private
|
||||
|
||||
def sdk_prefix
|
||||
""
|
||||
@ -81,15 +81,11 @@ module OS
|
||||
end
|
||||
|
||||
class XcodeSDKLocator < BaseSDKLocator
|
||||
private
|
||||
|
||||
def source
|
||||
:xcode
|
||||
end
|
||||
|
||||
def source_version
|
||||
OS::Mac::Xcode.version
|
||||
end
|
||||
private
|
||||
|
||||
def sdk_prefix
|
||||
@sdk_prefix ||= begin
|
||||
@ -105,15 +101,11 @@ module OS
|
||||
end
|
||||
|
||||
class CLTSDKLocator < BaseSDKLocator
|
||||
private
|
||||
|
||||
def source
|
||||
:clt
|
||||
end
|
||||
|
||||
def source_version
|
||||
OS::Mac::CLT.version
|
||||
end
|
||||
private
|
||||
|
||||
# While CLT SDKs existed prior to Xcode 10, those packages also
|
||||
# installed a traditional Unix-style header layout and we prefer
|
||||
|
||||
@ -107,10 +107,12 @@ module OS
|
||||
!prefix.nil?
|
||||
end
|
||||
|
||||
def sdk(v = nil)
|
||||
@locator ||= XcodeSDKLocator.new
|
||||
def sdk_locator
|
||||
@sdk_locator ||= XcodeSDKLocator.new
|
||||
end
|
||||
|
||||
@locator.sdk_if_applicable(v)
|
||||
def sdk(v = nil)
|
||||
sdk_locator.sdk_if_applicable(v)
|
||||
end
|
||||
|
||||
def sdk_path(v = nil)
|
||||
@ -219,10 +221,12 @@ module OS
|
||||
version >= "8"
|
||||
end
|
||||
|
||||
def sdk(v = nil)
|
||||
@locator ||= CLTSDKLocator.new
|
||||
def sdk_locator
|
||||
@sdk_locator ||= CLTSDKLocator.new
|
||||
end
|
||||
|
||||
@locator.sdk_if_applicable(v)
|
||||
def sdk(v = nil)
|
||||
sdk_locator.sdk_if_applicable(v)
|
||||
end
|
||||
|
||||
def sdk_path(v = nil)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "formula"
|
||||
require "cask/cask_loader"
|
||||
|
||||
module Readall
|
||||
class << self
|
||||
@ -35,28 +36,43 @@ module Readall
|
||||
end
|
||||
|
||||
def valid_formulae?(formulae)
|
||||
failed = false
|
||||
success = true
|
||||
formulae.each do |file|
|
||||
Formulary.factory(file)
|
||||
rescue Interrupt
|
||||
raise
|
||||
rescue Exception => e # rubocop:disable Lint/RescueException
|
||||
onoe "Invalid formula: #{file}"
|
||||
puts e
|
||||
failed = true
|
||||
$stderr.puts e
|
||||
success = false
|
||||
end
|
||||
!failed
|
||||
success
|
||||
end
|
||||
|
||||
def valid_casks?(casks)
|
||||
success = true
|
||||
casks.each do |file|
|
||||
Cask::CaskLoader.load(file)
|
||||
rescue Interrupt
|
||||
raise
|
||||
rescue Exception => e # rubocop:disable Lint/RescueException
|
||||
onoe "Invalid cask: #{file}"
|
||||
$stderr.puts e
|
||||
success = false
|
||||
end
|
||||
success
|
||||
end
|
||||
|
||||
def valid_tap?(tap, options = {})
|
||||
failed = false
|
||||
success = true
|
||||
if options[:aliases]
|
||||
valid_aliases = valid_aliases?(tap.alias_dir, tap.formula_dir)
|
||||
failed = true unless valid_aliases
|
||||
success = false unless valid_aliases
|
||||
end
|
||||
valid_formulae = valid_formulae?(tap.formula_files)
|
||||
failed = true unless valid_formulae
|
||||
!failed
|
||||
valid_casks = valid_casks?(tap.cask_files)
|
||||
success = false if !valid_formulae || !valid_casks
|
||||
success
|
||||
end
|
||||
|
||||
private
|
||||
@ -79,3 +95,5 @@ module Readall
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "extend/os/readall"
|
||||
|
||||
@ -24,7 +24,8 @@ module RuboCop
|
||||
[{ name: :mirror, type: :method_call }],
|
||||
[{ name: :version, type: :method_call }],
|
||||
[{ name: :sha256, type: :method_call }],
|
||||
[{ name: :revision, type: :method_call }],
|
||||
[{ name: :license, type: :method_call }],
|
||||
[{ name: :revision, type: :method_call }],
|
||||
[{ name: :version_scheme, type: :method_call }],
|
||||
[{ name: :head, type: :method_call }],
|
||||
[{ name: :stable, type: :block_call }],
|
||||
|
||||
@ -453,7 +453,6 @@ false:
|
||||
- ./utils/github.rb
|
||||
- ./utils/notability.rb
|
||||
- ./utils/popen.rb
|
||||
- ./utils/tty.rb
|
||||
- ./utils/user.rb
|
||||
|
||||
false:
|
||||
@ -889,6 +888,7 @@ true:
|
||||
- ./tap_constants.rb
|
||||
- ./test/support/helper/fixtures.rb
|
||||
- ./test/support/lib/config.rb
|
||||
- ./utils/tty.rb
|
||||
- ./version/null.rb
|
||||
|
||||
strict:
|
||||
|
||||
36
Library/Homebrew/sorbet/rbi/utils/tty.rbi
Normal file
36
Library/Homebrew/sorbet/rbi/utils/tty.rbi
Normal file
@ -0,0 +1,36 @@
|
||||
# typed: strict
|
||||
|
||||
module Tty
|
||||
include Kernel
|
||||
|
||||
sig{ params(string: String).returns(String) }
|
||||
def strip_ansi(string)
|
||||
end
|
||||
|
||||
sig{ returns(Integer) }
|
||||
def width()
|
||||
end
|
||||
|
||||
sig{ params(string: String).returns(T.nilable(String)) }
|
||||
def truncate(string)
|
||||
end
|
||||
|
||||
def append_to_escape_sequence(code)
|
||||
end
|
||||
|
||||
sig{ returns(String) }
|
||||
def current_escape_sequence()
|
||||
end
|
||||
|
||||
sig{ void }
|
||||
def reset_escape_sequence!()
|
||||
end
|
||||
|
||||
sig{ returns(String) }
|
||||
def to_s
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def color?
|
||||
end
|
||||
end
|
||||
9
Library/Homebrew/test/.codecov.yml
Normal file
9
Library/Homebrew/test/.codecov.yml
Normal file
@ -0,0 +1,9 @@
|
||||
codecov:
|
||||
fixes:
|
||||
- "::Library/Homebrew/"
|
||||
coverage:
|
||||
round: nearest
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 0.05%
|
||||
@ -8,7 +8,7 @@ describe "Homebrew.search_args" do
|
||||
end
|
||||
|
||||
describe "brew search", :integration_test do
|
||||
it "falls back to a GitHub tap search when no formula is found", :needs_network do
|
||||
it "falls back to a GitHub tap search when no formula is found", :needs_macos, :needs_network do
|
||||
setup_test_formula "testball"
|
||||
setup_remote_tap "homebrew/cask"
|
||||
|
||||
@ -16,4 +16,13 @@ describe "brew search", :integration_test do
|
||||
.to output(/firefox/).to_stdout
|
||||
.and be_a_success
|
||||
end
|
||||
|
||||
# doesn't actually need Linux but only want one integration test per-OS.
|
||||
it "finds formula in search", :need_linux do
|
||||
setup_test_formula "testball"
|
||||
|
||||
expect { brew "search", "testball" }
|
||||
.to output(/testball/).to_stdout
|
||||
.and be_a_success
|
||||
end
|
||||
end
|
||||
|
||||
@ -79,6 +79,92 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
describe "#audit_license" do
|
||||
let(:spdx_data) {
|
||||
JSON.parse Pathname(File.join(File.dirname(__FILE__), "../../data/spdx.json")).read
|
||||
}
|
||||
|
||||
let(:custom_spdx_id) { "zzz" }
|
||||
let(:standard_mismatch_spdx_id) { "0BSD" }
|
||||
|
||||
it "does not check if the formula is not a new formula" do
|
||||
fa = formula_auditor "foo", <<~RUBY, spdx_data: spdx_data, new_formula: false
|
||||
class Foo < Formula
|
||||
url "https://brew.sh/foo-1.0.tgz"
|
||||
license ""
|
||||
end
|
||||
RUBY
|
||||
|
||||
fa.audit_license
|
||||
expect(fa.problems).to be_empty
|
||||
end
|
||||
|
||||
it "detects no license info" do
|
||||
fa = formula_auditor "foo", <<~RUBY, spdx_data: spdx_data, new_formula: true
|
||||
class Foo < Formula
|
||||
url "https://brew.sh/foo-1.0.tgz"
|
||||
license ""
|
||||
end
|
||||
RUBY
|
||||
|
||||
fa.audit_license
|
||||
expect(fa.problems.first).to match "No license specified for package."
|
||||
end
|
||||
|
||||
it "detects if license is not a standard spdx-id" do
|
||||
fa = formula_auditor "foo", <<~RUBY, spdx_data: spdx_data, new_formula: true
|
||||
class Foo < Formula
|
||||
url "https://brew.sh/foo-1.0.tgz"
|
||||
license "#{custom_spdx_id}"
|
||||
end
|
||||
RUBY
|
||||
|
||||
fa.audit_license
|
||||
expect(fa.problems.first).to match "#{custom_spdx_id} is not a standard SPDX license."
|
||||
end
|
||||
|
||||
it "verifies that a license info is a standard spdx id" do
|
||||
fa = formula_auditor "foo", <<~RUBY, spdx_data: spdx_data, new_formula: true
|
||||
class Foo < Formula
|
||||
url "https://brew.sh/foo-1.0.tgz"
|
||||
license "0BSD"
|
||||
end
|
||||
RUBY
|
||||
|
||||
fa.audit_license
|
||||
expect(fa.problems).to be_empty
|
||||
end
|
||||
|
||||
it "checks online and verifies that a standard license id is the same "\
|
||||
"as what is indicated on its Github repo" do
|
||||
fa = formula_auditor "cask", <<~RUBY, spdx_data: spdx_data, online: true, core_tap: true, new_formula: true
|
||||
class Cask < Formula
|
||||
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
|
||||
head "https://github.com/cask/cask.git"
|
||||
license "GPL-3.0"
|
||||
end
|
||||
RUBY
|
||||
|
||||
fa.audit_license
|
||||
expect(fa.problems).to be_empty
|
||||
end
|
||||
|
||||
it "checks online and detects that a formula-specified license is not "\
|
||||
"the same as what is indicated on its Github repository" do
|
||||
fa = formula_auditor "cask", <<~RUBY, online: true, spdx_data: spdx_data, core_tap: true, new_formula: true
|
||||
class Cask < Formula
|
||||
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
|
||||
head "https://github.com/cask/cask.git"
|
||||
license "#{standard_mismatch_spdx_id}"
|
||||
end
|
||||
RUBY
|
||||
|
||||
fa.audit_license
|
||||
expect(fa.problems.first).to match "License mismatch - GitHub license is: GPL-3.0, "\
|
||||
"but Formulae license states: #{standard_mismatch_spdx_id}."
|
||||
end
|
||||
end
|
||||
|
||||
describe "#audit_file" do
|
||||
specify "no issue" do
|
||||
fa = formula_auditor "foo", <<~RUBY
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "cmd/shared_examples/args_parse"
|
||||
|
||||
describe "Homebrew.update_license_data_args" do
|
||||
it_behaves_like "parseable arguments"
|
||||
end
|
||||
@ -19,6 +19,18 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "When license precedes sha256" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
homepage "https://brew.sh"
|
||||
url "https://brew.sh/foo-1.0.tgz"
|
||||
license "0BSD"
|
||||
sha256 "samplesha256"
|
||||
^^^^^^^^^^^^^^^^^^^^^ `sha256` (line 5) should be put before `license` (line 4)
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "When `bottle` precedes `livecheck`" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
|
||||
@ -4,12 +4,10 @@ if ENV["HOMEBREW_TESTS_COVERAGE"]
|
||||
require "simplecov"
|
||||
|
||||
formatters = [SimpleCov::Formatter::HTMLFormatter]
|
||||
if ENV["HOMEBREW_COVERALLS_REPO_TOKEN"] && RUBY_PLATFORM[/darwin/]
|
||||
require "coveralls"
|
||||
if ENV["HOMEBREW_CODECOV_TOKEN"] && RUBY_PLATFORM[/darwin/]
|
||||
require "codecov"
|
||||
|
||||
Coveralls::Output.no_color if !ENV["HOMEBREW_COLOR"] && (ENV["HOMEBREW_NO_COLOR"] || !$stdout.tty?)
|
||||
|
||||
formatters << Coveralls::SimpleCov::Formatter
|
||||
formatters << SimpleCov::Formatter::Codecov
|
||||
|
||||
if ENV["TEST_ENV_NUMBER"]
|
||||
SimpleCov.at_exit do
|
||||
@ -18,16 +16,7 @@ if ENV["HOMEBREW_TESTS_COVERAGE"]
|
||||
end
|
||||
end
|
||||
|
||||
ENV["CI_NAME"] = ENV["HOMEBREW_CI_NAME"]
|
||||
ENV["COVERALLS_REPO_TOKEN"] = ENV["HOMEBREW_COVERALLS_REPO_TOKEN"]
|
||||
|
||||
ENV["CI_BUILD_NUMBER"] = ENV["HOMEBREW_CI_BUILD_NUMBER"]
|
||||
ENV["CI_BRANCH"] = ENV["HOMEBREW_CI_BRANCH"]
|
||||
%r{refs/pull/(?<pr>\d+)/merge} =~ ENV["HOMEBREW_CI_BUILD_NUMBER"]
|
||||
ENV["CI_PULL_REQUEST"] = pr
|
||||
ENV["CI_BUILD_URL"] = "https://github.com/#{ENV["HOMEBREW_GITHUB_REPOSITORY"]}/pull/#{pr}/checks"
|
||||
|
||||
ENV["CI_JOB_ID"] = ENV["TEST_ENV_NUMBER"] || "1"
|
||||
ENV["CODECOV_TOKEN"] = ENV["HOMEBREW_CODECOV_TOKEN"]
|
||||
end
|
||||
|
||||
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(formatters)
|
||||
@ -174,6 +163,7 @@ RSpec.configure do |config|
|
||||
Keg.clear_cache
|
||||
Tab.clear_cache
|
||||
FormulaInstaller.clear_attempted
|
||||
FormulaInstaller.clear_installed
|
||||
|
||||
TEST_DIRECTORIES.each(&:mkpath)
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ RSpec.shared_context "integration test" do
|
||||
|
||||
example.run
|
||||
ensure
|
||||
FileUtils.rm_r HOMEBREW_PREFIX/"bin"
|
||||
FileUtils.rm_rf HOMEBREW_PREFIX/"bin"
|
||||
end
|
||||
|
||||
# Generate unique ID to be able to
|
||||
|
||||
@ -42,6 +42,13 @@ describe GitHub do
|
||||
end
|
||||
end
|
||||
|
||||
describe "::approved_reviews", :needs_network do
|
||||
it "can get reviews for a pull request" do
|
||||
reviews = subject.approved_reviews("Homebrew", "homebrew-core", 1, commit: "deadbeef")
|
||||
expect(reviews).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
describe "::get_artifact_url", :needs_network do
|
||||
it "fails to find a nonexistant workflow" do
|
||||
expect {
|
||||
|
||||
242
Library/Homebrew/upgrade.rb
Normal file
242
Library/Homebrew/upgrade.rb
Normal file
@ -0,0 +1,242 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "reinstall"
|
||||
require "formula_installer"
|
||||
require "development_tools"
|
||||
require "messages"
|
||||
require "cleanup"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
|
||||
def upgrade_formulae(formulae_to_install)
|
||||
return if formulae_to_install.empty?
|
||||
return if args.dry_run?
|
||||
|
||||
# Sort keg-only before non-keg-only formulae to avoid any needless conflicts
|
||||
# with outdated, non-keg-only versions of formulae being upgraded.
|
||||
formulae_to_install.sort! do |a, b|
|
||||
if !a.keg_only? && b.keg_only?
|
||||
1
|
||||
elsif a.keg_only? && !b.keg_only?
|
||||
-1
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
formulae_to_install.each do |f|
|
||||
Migrator.migrate_if_needed(f)
|
||||
begin
|
||||
upgrade_formula(f)
|
||||
Cleanup.install_formula_clean!(f)
|
||||
rescue UnsatisfiedRequirements => e
|
||||
Homebrew.failed = true
|
||||
onoe "#{f}: #{e}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def upgrade_formula(f)
|
||||
return if args.dry_run?
|
||||
|
||||
if f.opt_prefix.directory?
|
||||
keg = Keg.new(f.opt_prefix.resolved_path)
|
||||
keg_had_linked_opt = true
|
||||
keg_was_linked = keg.linked?
|
||||
end
|
||||
|
||||
formulae_maybe_with_kegs = [f] + f.old_installed_formulae
|
||||
outdated_kegs = formulae_maybe_with_kegs
|
||||
.map(&:linked_keg)
|
||||
.select(&:directory?)
|
||||
.map { |k| Keg.new(k.resolved_path) }
|
||||
linked_kegs = outdated_kegs.select(&:linked?)
|
||||
|
||||
if f.opt_prefix.directory?
|
||||
keg = Keg.new(f.opt_prefix.resolved_path)
|
||||
tab = Tab.for_keg(keg)
|
||||
end
|
||||
|
||||
build_options = BuildOptions.new(Options.create(args.flags_only), f.options)
|
||||
options = build_options.used_options
|
||||
options |= f.build.used_options
|
||||
options &= f.options
|
||||
|
||||
fi = FormulaInstaller.new(f)
|
||||
fi.options = options
|
||||
fi.build_bottle = args.build_bottle?
|
||||
fi.installed_on_request = args.named.present?
|
||||
fi.link_keg ||= keg_was_linked if keg_had_linked_opt
|
||||
if tab
|
||||
fi.build_bottle ||= tab.built_bottle?
|
||||
fi.installed_as_dependency = tab.installed_as_dependency
|
||||
fi.installed_on_request ||= tab.installed_on_request
|
||||
end
|
||||
|
||||
upgrade_version = if f.optlinked?
|
||||
"#{Keg.new(f.opt_prefix).version} -> #{f.pkg_version}"
|
||||
else
|
||||
"-> #{f.pkg_version}"
|
||||
end
|
||||
oh1 "Upgrading #{Formatter.identifier(f.full_specified_name)} #{upgrade_version} #{fi.options.to_a.join(" ")}"
|
||||
|
||||
fi.prelude
|
||||
fi.fetch
|
||||
|
||||
# first we unlink the currently active keg for this formula otherwise it is
|
||||
# possible for the existing build to interfere with the build we are about to
|
||||
# do! Seriously, it happens!
|
||||
outdated_kegs.each(&:unlink)
|
||||
|
||||
fi.install
|
||||
fi.finish
|
||||
rescue FormulaInstallationAlreadyAttemptedError
|
||||
# We already attempted to upgrade f as part of the dependency tree of
|
||||
# another formula. In that case, don't generate an error, just move on.
|
||||
nil
|
||||
rescue CannotInstallFormulaError => e
|
||||
ofail e
|
||||
rescue BuildError => e
|
||||
e.dump
|
||||
puts
|
||||
Homebrew.failed = true
|
||||
rescue DownloadError => e
|
||||
ofail e
|
||||
ensure
|
||||
# restore previous installation state if build failed
|
||||
begin
|
||||
linked_kegs.each(&:link) unless f.latest_version_installed?
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def check_installed_dependents
|
||||
installed_formulae = FormulaInstaller.installed.to_a
|
||||
return if installed_formulae.empty?
|
||||
|
||||
outdated_dependents =
|
||||
installed_formulae.flat_map(&:runtime_installed_formula_dependents)
|
||||
.select(&:outdated?)
|
||||
return if outdated_dependents.blank?
|
||||
|
||||
outdated_dependents -= installed_formulae if args.dry_run?
|
||||
|
||||
upgradeable_dependents =
|
||||
outdated_dependents.reject(&:pinned?)
|
||||
.sort { |a, b| depends_on(a, b) }
|
||||
pinned_dependents =
|
||||
outdated_dependents.select(&:pinned?)
|
||||
.sort { |a, b| depends_on(a, b) }
|
||||
|
||||
if pinned_dependents.present?
|
||||
plural = "dependent".pluralize(pinned_dependents.count)
|
||||
ohai "Not upgrading #{pinned_dependents.count} pinned #{plural}:"
|
||||
puts(pinned_dependents.map do |f|
|
||||
"#{f.full_specified_name} #{f.pkg_version}"
|
||||
end.join(", "))
|
||||
end
|
||||
|
||||
# Print the upgradable dependents.
|
||||
if upgradeable_dependents.blank?
|
||||
ohai "No outdated dependents to upgrade!" unless args.dry_run?
|
||||
else
|
||||
plural = "dependent".pluralize(upgradeable_dependents.count)
|
||||
verb = args.dry_run? ? "Would upgrade" : "Upgrading"
|
||||
ohai "#{verb} #{upgradeable_dependents.count} #{plural}:"
|
||||
formulae_upgrades = upgradeable_dependents.map do |f|
|
||||
name = f.full_specified_name
|
||||
if f.optlinked?
|
||||
"#{name} #{Keg.new(f.opt_prefix).version} -> #{f.pkg_version}"
|
||||
else
|
||||
"#{name} #{f.pkg_version}"
|
||||
end
|
||||
end
|
||||
puts formulae_upgrades.join(", ")
|
||||
end
|
||||
|
||||
upgrade_formulae(upgradeable_dependents)
|
||||
|
||||
# Assess the dependents tree again now we've upgraded.
|
||||
oh1 "Checking for dependents of upgraded formulae..." unless args.dry_run?
|
||||
broken_dependents = CacheStoreDatabase.use(:linkage) do |db|
|
||||
formulae_to_install.flat_map(&:runtime_installed_formula_dependents)
|
||||
.select do |f|
|
||||
keg = f.opt_or_installed_prefix_keg
|
||||
next unless keg
|
||||
|
||||
LinkageChecker.new(keg, cache_db: db)
|
||||
.broken_library_linkage?
|
||||
end.compact
|
||||
end
|
||||
if broken_dependents.blank?
|
||||
if args.dry_run?
|
||||
ohai "No currently broken dependents found!"
|
||||
opoo "If they are broken by the upgrade they will also be upgraded or reinstalled."
|
||||
else
|
||||
ohai "No broken dependents found!"
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
reinstallable_broken_dependents =
|
||||
broken_dependents.reject(&:outdated?)
|
||||
.reject(&:pinned?)
|
||||
.sort { |a, b| depends_on(a, b) }
|
||||
outdated_pinned_broken_dependents =
|
||||
broken_dependents.select(&:outdated?)
|
||||
.select(&:pinned?)
|
||||
.sort { |a, b| depends_on(a, b) }
|
||||
|
||||
# Print the pinned dependents.
|
||||
if outdated_pinned_broken_dependents.present?
|
||||
count = outdated_pinned_broken_dependents.count
|
||||
plural = "dependent".pluralize(outdated_pinned_broken_dependents.count)
|
||||
onoe "Not reinstalling #{count} broken and outdated, but pinned #{plural}:"
|
||||
$stderr.puts(outdated_pinned_broken_dependents.map do |f|
|
||||
"#{f.full_specified_name} #{f.pkg_version}"
|
||||
end.join(", "))
|
||||
end
|
||||
|
||||
# Print the broken dependents.
|
||||
if reinstallable_broken_dependents.blank?
|
||||
ohai "No broken dependents to reinstall!"
|
||||
else
|
||||
count = reinstallable_broken_dependents.count
|
||||
plural = "dependent".pluralize(reinstallable_broken_dependents.count)
|
||||
ohai "Reinstalling #{count} broken #{plural} from source:"
|
||||
puts reinstallable_broken_dependents.map(&:full_specified_name)
|
||||
.join(", ")
|
||||
end
|
||||
|
||||
return if args.dry_run?
|
||||
|
||||
reinstallable_broken_dependents.each do |f|
|
||||
reinstall_formula(f, build_from_source: true)
|
||||
rescue FormulaInstallationAlreadyAttemptedError
|
||||
# We already attempted to reinstall f as part of the dependency tree of
|
||||
# another formula. In that case, don't generate an error, just move on.
|
||||
nil
|
||||
rescue CannotInstallFormulaError => e
|
||||
ofail e
|
||||
rescue BuildError => e
|
||||
e.dump
|
||||
puts
|
||||
Homebrew.failed = true
|
||||
rescue DownloadError => e
|
||||
ofail e
|
||||
end
|
||||
end
|
||||
|
||||
# @private
|
||||
def depends_on(a, b)
|
||||
if a.opt_or_installed_prefix_keg
|
||||
&.runtime_dependencies
|
||||
&.any? { |d| d["full_name"] == b.full_name }
|
||||
1
|
||||
else
|
||||
a <=> b
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -54,21 +54,25 @@ def curl(*args, secrets: [], **options)
|
||||
secrets: secrets
|
||||
end
|
||||
|
||||
def curl_download(*args, to: nil, **options)
|
||||
def curl_download(*args, to: nil, partial: true, **options)
|
||||
destination = Pathname(to)
|
||||
destination.dirname.mkpath
|
||||
|
||||
range_stdout = curl_output("--location", "--range", "0-1",
|
||||
"--dump-header", "-",
|
||||
"--write-out", "%\{http_code}",
|
||||
"--output", "/dev/null", *args, **options).stdout
|
||||
headers, _, http_status = range_stdout.partition("\r\n\r\n")
|
||||
if partial
|
||||
range_stdout = curl_output("--location", "--range", "0-1",
|
||||
"--dump-header", "-",
|
||||
"--write-out", "%\{http_code}",
|
||||
"--output", "/dev/null", *args, **options).stdout
|
||||
headers, _, http_status = range_stdout.partition("\r\n\r\n")
|
||||
|
||||
supports_partial_download = http_status.to_i == 206 # Partial Content
|
||||
if supports_partial_download &&
|
||||
destination.exist? &&
|
||||
destination.size == %r{^.*Content-Range: bytes \d+-\d+/(\d+)\r\n.*$}m.match(headers)&.[](1)&.to_i
|
||||
return # We've already downloaded all the bytes
|
||||
supports_partial_download = http_status.to_i == 206 # Partial Content
|
||||
if supports_partial_download &&
|
||||
destination.exist? &&
|
||||
destination.size == %r{^.*Content-Range: bytes \d+-\d+/(\d+)\r\n.*$}m.match(headers)&.[](1)&.to_i
|
||||
return # We've already downloaded all the bytes
|
||||
end
|
||||
else
|
||||
supports_partial_download = false
|
||||
end
|
||||
|
||||
continue_at = if destination.exist? && supports_partial_download
|
||||
|
||||
@ -392,6 +392,52 @@ module GitHub
|
||||
open_api(uri) { |json| json.fetch("items", []) }
|
||||
end
|
||||
|
||||
def approved_reviews(user, repo, pr, commit: nil)
|
||||
url = "https://api.github.com/graphql"
|
||||
data = {
|
||||
query: <<~EOS,
|
||||
{ repository(name: "#{repo}", owner: "#{user}") {
|
||||
pullRequest(number: #{pr}) {
|
||||
reviews(states: APPROVED, first: 100) {
|
||||
nodes {
|
||||
author {
|
||||
... on User { email login name databaseId }
|
||||
... on Organization { email login name databaseId }
|
||||
}
|
||||
authorAssociation
|
||||
commit { oid }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOS
|
||||
}
|
||||
result = open_api(url, scopes: ["user:email"], data: data, request_method: "POST")
|
||||
raise Error, result["errors"] if result["errors"].present?
|
||||
|
||||
reviews = result["data"]["repository"]["pullRequest"]["reviews"]["nodes"]
|
||||
|
||||
reviews.map do |r|
|
||||
next if commit.present? && commit != r["commit"]["oid"]
|
||||
next unless %w[MEMBER OWNER].include? r["authorAssociation"]
|
||||
|
||||
email = if r["author"]["email"].blank?
|
||||
"#{r["author"]["databaseId"]}+#{r["author"]["login"]}@users.noreply.github.com"
|
||||
else
|
||||
r["author"]["email"]
|
||||
end
|
||||
|
||||
name = r["author"]["name"].presence || r["author"]["login"]
|
||||
|
||||
{
|
||||
"email" => email,
|
||||
"name" => name,
|
||||
"login" => r["author"]["login"],
|
||||
}
|
||||
end.compact
|
||||
end
|
||||
|
||||
def dispatch_event(user, repo, event, **payload)
|
||||
url = "#{API_URL}/repos/#{user}/#{repo}/dispatches"
|
||||
open_api(url, data: { event_type: event, client_payload: payload },
|
||||
@ -474,6 +520,15 @@ module GitHub
|
||||
open_api(url, scopes: ["admin:org", "user"], data: data, request_method: "POST")
|
||||
end
|
||||
|
||||
def get_repo_license(user, repo)
|
||||
response = GitHub.open_api("#{GitHub::API_URL}/repos/#{user}/#{repo}/license")
|
||||
return unless response.key?("license")
|
||||
|
||||
response["license"]["spdx_id"]
|
||||
rescue GitHub::HTTPNotFoundError
|
||||
nil
|
||||
end
|
||||
|
||||
def api_errors
|
||||
[GitHub::AuthenticationFailedError, GitHub::HTTPNotFoundError,
|
||||
GitHub::RateLimitExceededError, GitHub::Error, JSON::ParserError].freeze
|
||||
|
||||
@ -86,6 +86,7 @@ unpin
|
||||
untap
|
||||
up
|
||||
update
|
||||
update-license-data
|
||||
update-report
|
||||
update-reset
|
||||
update-test
|
||||
|
||||
@ -6,6 +6,13 @@ This is a page for maintainers to diagnose certain build errors.
|
||||
|
||||
## Issues
|
||||
|
||||
### Bottle publishes failed but the commits are correct in the git history
|
||||
|
||||
Follow these steps to fix this issue:
|
||||
* `git reset --hard <SHA>` in homebrew/core to reset to the commit before before all the commits created by `brew pr-pull`.
|
||||
* `brew pr-pull <options>` to upload the right bottles. Add the `--warn-on-upload-failure` flag if the bottles have been partially uploaded and you're certain that the bottle checksums will match the checksums already present in the `bottle do` block of the formula.
|
||||
* `git reset --hard origin/master` to return to the latest commit and discard the commits made by `brew pr-pull`.
|
||||
|
||||
### `ld: internal error: atom not found in symbolIndex(__ZN10SQInstance3GetERK11SQObjectPtrRS0_) for architecture x86_64`
|
||||
|
||||
The exact atom may be different.
|
||||
|
||||
@ -369,10 +369,10 @@ Rerun the post-install steps for *`formula`*.
|
||||
|
||||
### `readall` [*`options`*] [*`tap`*]
|
||||
|
||||
Import all formulae from the specified *`tap`*, or from all installed taps if none
|
||||
is provided. This can be useful for debugging issues across all formulae when
|
||||
making significant changes to `formula.rb`, testing the performance of loading
|
||||
all formulae or checking if any current formulae have Ruby issues.
|
||||
Import all items from the specified *`tap`*, or from all installed taps if none is
|
||||
provided. This can be useful for debugging issues across all items when making
|
||||
significant changes to `formula.rb`, testing the performance of loading all
|
||||
items or checking if any current formulae/casks have Ruby issues.
|
||||
|
||||
* `--aliases`:
|
||||
Verify any alias symlinks in each tap.
|
||||
@ -793,6 +793,8 @@ a simple example. For the complete API, see:
|
||||
Explicitly set the *`name`* of the new formula.
|
||||
* `--set-version`:
|
||||
Explicitly set the *`version`* of the new formula.
|
||||
* `--set-license`:
|
||||
Explicitly set the *`license`* of the new formula.
|
||||
* `--tap`:
|
||||
Generate the new formula within the given tap, specified as *`user`*`/`*`repo`*.
|
||||
|
||||
@ -901,6 +903,8 @@ repository.
|
||||
Do not warn if pulling to a branch besides master (useful for testing).
|
||||
* `--resolve`:
|
||||
When a patch fails to apply, leave in progress and allow user to resolve, instead of aborting.
|
||||
* `--warn-on-upload-failure`:
|
||||
Warn instead of raising an error if the bottle upload fails. Useful for repairing bottle uploads that previously failed.
|
||||
* `--workflow`:
|
||||
Retrieve artifacts from the specified workflow (default: `tests.yml`).
|
||||
* `--artifact`:
|
||||
@ -922,6 +926,8 @@ Apply the bottle commit and publish bottles to Bintray.
|
||||
Apply the bottle commit and upload the bottles, but don't publish them.
|
||||
* `-n`, `--dry-run`:
|
||||
Print what would be done rather than doing it.
|
||||
* `--warn-on-upload-failure`:
|
||||
Warn instead of raising an error if the bottle upload fails. Useful for repairing bottle uploads that previously failed.
|
||||
* `--bintray-org`:
|
||||
Upload to the specified Bintray organisation (default: `homebrew`).
|
||||
* `--root-url`:
|
||||
@ -1028,6 +1034,13 @@ directory.
|
||||
* `-g`, `--git`:
|
||||
Initialise a Git repository in the unpacked source. This is useful for creating patches for the software.
|
||||
|
||||
### `update_license_data` *`cmd`*
|
||||
|
||||
Update SPDX license data in the Homebrew repository.
|
||||
|
||||
* `--fail-if-changed`:
|
||||
Return a failing status code if current license data's version is different from the upstream. This can be used to notify CI when the SPDX license data is out of date.
|
||||
|
||||
### `update-test` [*`options`*]
|
||||
|
||||
Run a test of `brew update` with a new repository clone. If no options are
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.\" generated with Ronn/v0.7.3
|
||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||
.
|
||||
.TH "BREW\-CASK" "1" "June 2020" "Homebrew" "brew-cask"
|
||||
.TH "BREW\-CASK" "1" "July 2020" "Homebrew" "brew-cask"
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBbrew\-cask\fR \- a friendly binary installer for macOS
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.\" generated with Ronn/v0.7.3
|
||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||
.
|
||||
.TH "BREW" "1" "June 2020" "Homebrew" "brew"
|
||||
.TH "BREW" "1" "July 2020" "Homebrew" "brew"
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBbrew\fR \- The Missing Package Manager for macOS
|
||||
@ -486,7 +486,7 @@ Pin the specified \fIformula\fR, preventing them from being upgraded when issuin
|
||||
Rerun the post\-install steps for \fIformula\fR\.
|
||||
.
|
||||
.SS "\fBreadall\fR [\fIoptions\fR] [\fItap\fR]"
|
||||
Import all formulae from the specified \fItap\fR, or from all installed taps if none is provided\. This can be useful for debugging issues across all formulae when making significant changes to \fBformula\.rb\fR, testing the performance of loading all formulae or checking if any current formulae have Ruby issues\.
|
||||
Import all items from the specified \fItap\fR, or from all installed taps if none is provided\. This can be useful for debugging issues across all items when making significant changes to \fBformula\.rb\fR, testing the performance of loading all items or checking if any current formulae/casks have Ruby issues\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-aliases\fR
|
||||
@ -1047,6 +1047,10 @@ Explicitly set the \fIname\fR of the new formula\.
|
||||
Explicitly set the \fIversion\fR of the new formula\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-set\-license\fR
|
||||
Explicitly set the \fIlicense\fR of the new formula\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-tap\fR
|
||||
Generate the new formula within the given tap, specified as \fIuser\fR\fB/\fR\fIrepo\fR\.
|
||||
.
|
||||
@ -1172,6 +1176,10 @@ Do not warn if pulling to a branch besides master (useful for testing)\.
|
||||
When a patch fails to apply, leave in progress and allow user to resolve, instead of aborting\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-warn\-on\-upload\-failure\fR
|
||||
Warn instead of raising an error if the bottle upload fails\. Useful for repairing bottle uploads that previously failed\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-workflow\fR
|
||||
Retrieve artifacts from the specified workflow (default: \fBtests\.yml\fR)\.
|
||||
.
|
||||
@ -1207,6 +1215,10 @@ Apply the bottle commit and upload the bottles, but don\'t publish them\.
|
||||
Print what would be done rather than doing it\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-warn\-on\-upload\-failure\fR
|
||||
Warn instead of raising an error if the bottle upload fails\. Useful for repairing bottle uploads that previously failed\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-bintray\-org\fR
|
||||
Upload to the specified Bintray organisation (default: \fBhomebrew\fR)\.
|
||||
.
|
||||
@ -1331,6 +1343,13 @@ Patches for \fIformula\fR will be applied to the unpacked source\.
|
||||
\fB\-g\fR, \fB\-\-git\fR
|
||||
Initialise a Git repository in the unpacked source\. This is useful for creating patches for the software\.
|
||||
.
|
||||
.SS "\fBupdate_license_data\fR \fIcmd\fR"
|
||||
Update SPDX license data in the Homebrew repository\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-fail\-if\-changed\fR
|
||||
Return a failing status code if current license data\'s version is different from the upstream\. This can be used to notify CI when the SPDX license data is out of date\.
|
||||
.
|
||||
.SS "\fBupdate\-test\fR [\fIoptions\fR]"
|
||||
Run a test of \fBbrew update\fR with a new repository clone\. If no options are passed, use \fBorigin/master\fR as the start commit\.
|
||||
.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user