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
|
- name: Run brew man
|
||||||
run: brew man --fail-if-changed
|
run: brew man --fail-if-changed
|
||||||
|
|
||||||
|
- name: Check for outdated license data
|
||||||
|
run: brew update-license-data --fail-if-changed
|
||||||
|
|
||||||
- name: Run brew tests
|
- name: Run brew tests
|
||||||
run: |
|
run: |
|
||||||
# brew tests doesn't like world writable directories
|
# brew tests doesn't like world writable directories
|
||||||
@ -136,8 +139,7 @@ jobs:
|
|||||||
HOMEBREW_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
HOMEBREW_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
# set variables for coverage reporting
|
# set variables for coverage reporting
|
||||||
HOMEBREW_CI_NAME: github-actions
|
HOMEBREW_CODECOV_TOKEN: 3ea0364c-80ce-47a3-9fba-93a940d4b5d7
|
||||||
HOMEBREW_COVERALLS_REPO_TOKEN: 3F6U6ZqctoNJwKyREremsqMgpU3qYgxFk
|
|
||||||
|
|
||||||
# These cannot be queried at the macOS level on GitHub Actions.
|
# These cannot be queried at the macOS level on GitHub Actions.
|
||||||
HOMEBREW_LANGUAGES: en-GB
|
HOMEBREW_LANGUAGES: en-GB
|
||||||
|
|||||||
7
.gitignore
vendored
7
.gitignore
vendored
@ -86,7 +86,7 @@
|
|||||||
**/vendor/bundle/ruby/*/gems/byebug-*/
|
**/vendor/bundle/ruby/*/gems/byebug-*/
|
||||||
**/vendor/bundle/ruby/*/gems/coderay-*/
|
**/vendor/bundle/ruby/*/gems/coderay-*/
|
||||||
**/vendor/bundle/ruby/*/gems/connection_pool-*/
|
**/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/diff-lcs-*/
|
||||||
**/vendor/bundle/ruby/*/gems/docile-*/
|
**/vendor/bundle/ruby/*/gems/docile-*/
|
||||||
**/vendor/bundle/ruby/*/gems/domain_name-*/
|
**/vendor/bundle/ruby/*/gems/domain_name-*/
|
||||||
@ -127,11 +127,8 @@
|
|||||||
**/vendor/bundle/ruby/*/gems/ruby-prof-*/
|
**/vendor/bundle/ruby/*/gems/ruby-prof-*/
|
||||||
**/vendor/bundle/ruby/*/gems/ruby-progressbar-*/
|
**/vendor/bundle/ruby/*/gems/ruby-progressbar-*/
|
||||||
**/vendor/bundle/ruby/*/gems/simplecov-*/
|
**/vendor/bundle/ruby/*/gems/simplecov-*/
|
||||||
**/vendor/bundle/ruby/*/gems/simplecov-cobertura-*/
|
|
||||||
**/vendor/bundle/ruby/*/gems/simplecov-html-*/
|
**/vendor/bundle/ruby/*/gems/simplecov-html-*/
|
||||||
**/vendor/bundle/ruby/*/gems/term-ansicolor-*/
|
**/vendor/bundle/ruby/*/gems/url-*/
|
||||||
**/vendor/bundle/ruby/*/gems/thor-*/
|
|
||||||
**/vendor/bundle/ruby/*/gems/tins-*/
|
|
||||||
**/vendor/bundle/ruby/*/gems/unf_ext-*/
|
**/vendor/bundle/ruby/*/gems/unf_ext-*/
|
||||||
**/vendor/bundle/ruby/*/gems/unf-*/
|
**/vendor/bundle/ruby/*/gems/unf-*/
|
||||||
**/vendor/bundle/ruby/*/gems/unicode-display_width-*/
|
**/vendor/bundle/ruby/*/gems/unicode-display_width-*/
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "English"
|
require "English"
|
||||||
|
|
||||||
@ -20,7 +21,8 @@ SimpleCov.start do
|
|||||||
|
|
||||||
# Just save result, but don't write formatted output.
|
# Just save result, but don't write formatted output.
|
||||||
coverage_result = Coverage.result
|
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_result = SimpleCov::Result.new(coverage_result)
|
||||||
SimpleCov::ResultMerger.store_result(simplecov_result)
|
SimpleCov::ResultMerger.store_result(simplecov_result)
|
||||||
|
|
||||||
@ -50,8 +52,8 @@ SimpleCov.start do
|
|||||||
|
|
||||||
require "rbconfig"
|
require "rbconfig"
|
||||||
host_os = RbConfig::CONFIG["host_os"]
|
host_os = RbConfig::CONFIG["host_os"]
|
||||||
add_filter %r{/os/mac} if host_os !~ /darwin/
|
add_filter %r{/os/mac} unless /darwin/.match?(host_os)
|
||||||
add_filter %r{/os/linux} if host_os !~ /linux/
|
add_filter %r{/os/linux} unless /linux/.match?(host_os)
|
||||||
|
|
||||||
# Add groups and the proper project name to the output.
|
# Add groups and the proper project name to the output.
|
||||||
project_name "Homebrew"
|
project_name "Homebrew"
|
||||||
|
|||||||
@ -4,7 +4,7 @@ source "https://rubygems.org"
|
|||||||
|
|
||||||
# installed gems
|
# installed gems
|
||||||
gem "byebug"
|
gem "byebug"
|
||||||
gem "coveralls", "~> 0.8", require: false
|
gem "codecov", require: false
|
||||||
gem "parallel_tests"
|
gem "parallel_tests"
|
||||||
gem "ronn", require: false
|
gem "ronn", require: false
|
||||||
gem "rspec"
|
gem "rspec"
|
||||||
|
|||||||
@ -9,15 +9,13 @@ GEM
|
|||||||
zeitwerk (~> 2.2, >= 2.2.2)
|
zeitwerk (~> 2.2, >= 2.2.2)
|
||||||
ast (2.4.1)
|
ast (2.4.1)
|
||||||
byebug (11.1.3)
|
byebug (11.1.3)
|
||||||
|
codecov (0.1.17)
|
||||||
|
json
|
||||||
|
simplecov
|
||||||
|
url
|
||||||
concurrent-ruby (1.1.6)
|
concurrent-ruby (1.1.6)
|
||||||
connection_pool (2.2.3)
|
connection_pool (2.2.3)
|
||||||
coveralls (0.8.23)
|
diff-lcs (1.4.4)
|
||||||
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)
|
|
||||||
docile (1.3.2)
|
docile (1.3.2)
|
||||||
domain_name (0.5.20190701)
|
domain_name (0.5.20190701)
|
||||||
unf (>= 0.0.5, < 1.0.0)
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
@ -99,24 +97,18 @@ GEM
|
|||||||
rubocop (>= 0.68.1)
|
rubocop (>= 0.68.1)
|
||||||
ruby-macho (2.2.0)
|
ruby-macho (2.2.0)
|
||||||
ruby-progressbar (1.10.1)
|
ruby-progressbar (1.10.1)
|
||||||
simplecov (0.16.1)
|
simplecov (0.18.5)
|
||||||
docile (~> 1.1)
|
docile (~> 1.1)
|
||||||
json (>= 1.8, < 3)
|
simplecov-html (~> 0.11)
|
||||||
simplecov-html (~> 0.10.0)
|
simplecov-html (0.12.2)
|
||||||
simplecov-html (0.10.2)
|
|
||||||
sync (0.5.0)
|
|
||||||
term-ansicolor (1.7.1)
|
|
||||||
tins (~> 1.0)
|
|
||||||
thor (1.0.1)
|
|
||||||
thread_safe (0.3.6)
|
thread_safe (0.3.6)
|
||||||
tins (1.25.0)
|
|
||||||
sync
|
|
||||||
tzinfo (1.2.7)
|
tzinfo (1.2.7)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.7.7)
|
unf_ext (0.0.7.7)
|
||||||
unicode-display_width (1.7.0)
|
unicode-display_width (1.7.0)
|
||||||
|
url (0.3.2)
|
||||||
webrobots (0.1.2)
|
webrobots (0.1.2)
|
||||||
zeitwerk (2.3.1)
|
zeitwerk (2.3.1)
|
||||||
|
|
||||||
@ -126,8 +118,8 @@ PLATFORMS
|
|||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
activesupport
|
activesupport
|
||||||
byebug
|
byebug
|
||||||
|
codecov
|
||||||
concurrent-ruby
|
concurrent-ruby
|
||||||
coveralls (~> 0.8)
|
|
||||||
mechanize
|
mechanize
|
||||||
parallel_tests
|
parallel_tests
|
||||||
plist
|
plist
|
||||||
@ -143,4 +135,4 @@ DEPENDENCIES
|
|||||||
simplecov
|
simplecov
|
||||||
|
|
||||||
BUNDLED WITH
|
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)
|
def upload(local_file, repo:, package:, version:, remote_file:, sha256: nil)
|
||||||
url = "#{API_URL}/content/#{@bintray_org}/#{repo}/#{package}/#{version}/#{remote_file}"
|
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?
|
args += ["--header", "X-Checksum-Sha2: #{sha256}"] unless sha256.blank?
|
||||||
result = open_api url, *args
|
result = open_api url, *args
|
||||||
json = JSON.parse(result.stdout)
|
json = JSON.parse(result.stdout)
|
||||||
@ -50,12 +50,15 @@ class Bintray
|
|||||||
result
|
result
|
||||||
end
|
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"
|
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)
|
json = JSON.parse(result.stdout)
|
||||||
if file_count.present? && json["files"] != file_count
|
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
|
end
|
||||||
|
|
||||||
odebug "Published #{json["files"]} bottles"
|
odebug "Published #{json["files"]} bottles"
|
||||||
@ -143,7 +146,7 @@ class Bintray
|
|||||||
end
|
end
|
||||||
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|
|
bottles_hash = json_files.reduce({}) do |hash, json_file|
|
||||||
hash.deep_merge(JSON.parse(IO.read(json_file)))
|
hash.deep_merge(JSON.parse(IO.read(json_file)))
|
||||||
end
|
end
|
||||||
@ -161,14 +164,19 @@ class Bintray
|
|||||||
|
|
||||||
odebug "Checking remote file #{@bintray_org}/#{bintray_repo}/#{filename}"
|
odebug "Checking remote file #{@bintray_org}/#{bintray_repo}/#{filename}"
|
||||||
if file_published? repo: bintray_repo, remote_file: filename
|
if file_published? repo: bintray_repo, remote_file: filename
|
||||||
raise Error, <<~EOS
|
already_published = "#{filename} is already published."
|
||||||
#{filename} is already published.
|
failed_message = <<~EOS
|
||||||
|
#{already_published}
|
||||||
Please remove it manually from:
|
Please remove it manually from:
|
||||||
https://bintray.com/#{@bintray_org}/#{bintray_repo}/#{bintray_package}/view#files
|
https://bintray.com/#{@bintray_org}/#{bintray_repo}/#{bintray_package}/view#files
|
||||||
Or run:
|
Or run:
|
||||||
curl -X DELETE -u $HOMEBREW_BINTRAY_USER:$HOMEBREW_BINTRAY_KEY \\
|
curl -X DELETE -u $HOMEBREW_BINTRAY_USER:$HOMEBREW_BINTRAY_KEY \\
|
||||||
https://api.bintray.com/content/#{@bintray_org}/#{bintray_repo}/#{filename}
|
https://api.bintray.com/content/#{@bintray_org}/#{bintray_repo}/#{filename}
|
||||||
EOS
|
EOS
|
||||||
|
raise Error, failed_message unless warn_on_error
|
||||||
|
|
||||||
|
opoo already_published
|
||||||
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
if !formula_packaged[formula_name] && !package_exists?(repo: bintray_repo, package: bintray_package)
|
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
|
bottle_count = bottle_hash["bottle"]["tags"].length
|
||||||
odebug "Publishing #{@bintray_org}/#{bintray_repo}/#{bintray_package}/#{version}"
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -211,6 +211,8 @@ module Homebrew
|
|||||||
|
|
||||||
puts "From: #{Formatter.url(github_info(f))}"
|
puts "From: #{Formatter.url(github_info(f))}"
|
||||||
|
|
||||||
|
puts "License: #{f.license}" if f.license
|
||||||
|
|
||||||
unless f.deps.empty?
|
unless f.deps.empty?
|
||||||
ohai "Dependencies"
|
ohai "Dependencies"
|
||||||
%w[build required recommended optional].map do |type|
|
%w[build required recommended optional].map do |type|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ require "install"
|
|||||||
require "search"
|
require "search"
|
||||||
require "cleanup"
|
require "cleanup"
|
||||||
require "cli/parser"
|
require "cli/parser"
|
||||||
|
require "upgrade"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module_function
|
||||||
@ -261,6 +262,9 @@ module Homebrew
|
|||||||
install_formula(f)
|
install_formula(f)
|
||||||
Cleanup.install_formula_clean!(f)
|
Cleanup.install_formula_clean!(f)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
check_installed_dependents
|
||||||
|
|
||||||
Homebrew.messages.display_messages
|
Homebrew.messages.display_messages
|
||||||
rescue FormulaUnreadableError, FormulaClassUnavailableError,
|
rescue FormulaUnreadableError, FormulaClassUnavailableError,
|
||||||
TapFormulaUnreadableError, TapFormulaClassUnavailableError => e
|
TapFormulaUnreadableError, TapFormulaClassUnavailableError => e
|
||||||
|
|||||||
@ -11,10 +11,10 @@ module Homebrew
|
|||||||
usage_banner <<~EOS
|
usage_banner <<~EOS
|
||||||
`readall` [<options>] [<tap>]
|
`readall` [<options>] [<tap>]
|
||||||
|
|
||||||
Import all formulae from the specified <tap>, or from all installed taps if none is provided.
|
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 formulae when making
|
This can be useful for debugging issues across all items when making
|
||||||
significant changes to `formula.rb`, testing the performance of loading
|
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
|
EOS
|
||||||
switch "--aliases",
|
switch "--aliases",
|
||||||
description: "Verify any alias symlinks in each tap."
|
description: "Verify any alias symlinks in each tap."
|
||||||
@ -30,7 +30,7 @@ module Homebrew
|
|||||||
|
|
||||||
if args.syntax?
|
if args.syntax?
|
||||||
scan_files = "#{HOMEBREW_LIBRARY_PATH}/**/*.rb"
|
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)
|
Homebrew.failed = true unless Readall.valid_ruby_syntax?(ruby_files)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -9,6 +9,7 @@ require "cleanup"
|
|||||||
require "cask/cmd"
|
require "cask/cmd"
|
||||||
require "cask/utils"
|
require "cask/utils"
|
||||||
require "cask/macos"
|
require "cask/macos"
|
||||||
|
require "upgrade"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module_function
|
||||||
@ -69,6 +70,9 @@ module Homebrew
|
|||||||
reinstall_formula(f)
|
reinstall_formula(f)
|
||||||
Cleanup.install_formula_clean!(f)
|
Cleanup.install_formula_clean!(f)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
check_installed_dependents
|
||||||
|
|
||||||
Homebrew.messages.display_messages
|
Homebrew.messages.display_messages
|
||||||
|
|
||||||
return if casks.empty?
|
return if casks.empty?
|
||||||
|
|||||||
@ -1,12 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "install"
|
|
||||||
require "reinstall"
|
|
||||||
require "formula_installer"
|
|
||||||
require "development_tools"
|
|
||||||
require "messages"
|
|
||||||
require "cleanup"
|
|
||||||
require "cli/parser"
|
require "cli/parser"
|
||||||
|
require "formula_installer"
|
||||||
|
require "install"
|
||||||
|
require "upgrade"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module_function
|
||||||
@ -114,241 +111,8 @@ module Homebrew
|
|||||||
|
|
||||||
upgrade_formulae(formulae_to_install)
|
upgrade_formulae(formulae_to_install)
|
||||||
|
|
||||||
check_dependents(formulae_to_install)
|
check_installed_dependents
|
||||||
|
|
||||||
Homebrew.messages.display_messages
|
Homebrew.messages.display_messages
|
||||||
end
|
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
|
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 "missing_formula"
|
||||||
require "digest"
|
require "digest"
|
||||||
require "cli/parser"
|
require "cli/parser"
|
||||||
|
require "json"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module_function
|
||||||
@ -109,7 +110,9 @@ module Homebrew
|
|||||||
|
|
||||||
# Check style in a single batch run up front for performance
|
# Check style in a single batch run up front for performance
|
||||||
style_results = Style.check_style_json(style_files, options) if style_files
|
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 = []
|
new_formula_problem_lines = []
|
||||||
audit_formulae.sort.each do |f|
|
audit_formulae.sort.each do |f|
|
||||||
only = only_cops ? ["style"] : args.only
|
only = only_cops ? ["style"] : args.only
|
||||||
@ -120,6 +123,7 @@ module Homebrew
|
|||||||
git: git,
|
git: git,
|
||||||
only: only,
|
only: only,
|
||||||
except: args.except,
|
except: args.except,
|
||||||
|
spdx_data: spdx_data,
|
||||||
}
|
}
|
||||||
options[:style_offenses] = style_results.file_offenses(f.path) if style_results
|
options[:style_offenses] = style_results.file_offenses(f.path) if style_results
|
||||||
options[:display_cop_names] = args.display_cop_names?
|
options[:display_cop_names] = args.display_cop_names?
|
||||||
@ -215,6 +219,7 @@ module Homebrew
|
|||||||
@new_formula_problems = []
|
@new_formula_problems = []
|
||||||
@text = FormulaText.new(formula.path)
|
@text = FormulaText.new(formula.path)
|
||||||
@specs = %w[stable devel head].map { |s| formula.send(s) }.compact
|
@specs = %w[stable devel head].map { |s| formula.send(s) }.compact
|
||||||
|
@spdx_data = options[:spdx_data]
|
||||||
end
|
end
|
||||||
|
|
||||||
def audit_style
|
def audit_style
|
||||||
@ -327,6 +332,27 @@ module Homebrew
|
|||||||
openssl@1.1
|
openssl@1.1
|
||||||
].freeze
|
].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
|
def audit_deps
|
||||||
@specs.each do |spec|
|
@specs.each do |spec|
|
||||||
# Check for things we don't like to depend on.
|
# Check for things we don't like to depend on.
|
||||||
@ -502,8 +528,9 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
def audit_github_repository
|
def audit_github_repository
|
||||||
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*})
|
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @new_formula
|
||||||
return if user.nil?
|
|
||||||
|
return if user.blank?
|
||||||
|
|
||||||
warning = SharedAudits.github(user, repo)
|
warning = SharedAudits.github(user, repo)
|
||||||
return if warning.nil?
|
return if warning.nil?
|
||||||
@ -512,8 +539,8 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
def audit_gitlab_repository
|
def audit_gitlab_repository
|
||||||
user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*})
|
user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) if @new_formula
|
||||||
return if user.nil?
|
return if user.blank?
|
||||||
|
|
||||||
warning = SharedAudits.gitlab(user, repo)
|
warning = SharedAudits.gitlab(user, repo)
|
||||||
return if warning.nil?
|
return if warning.nil?
|
||||||
@ -522,8 +549,8 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
def audit_bitbucket_repository
|
def audit_bitbucket_repository
|
||||||
user, repo = get_repo_data(%r{https?://bitbucket\.org/([^/]+)/([^/]+)/?.*})
|
user, repo = get_repo_data(%r{https?://bitbucket\.org/([^/]+)/([^/]+)/?.*}) if @new_formula
|
||||||
return if user.nil?
|
return if user.blank?
|
||||||
|
|
||||||
warning = SharedAudits.bitbucket(user, repo)
|
warning = SharedAudits.bitbucket(user, repo)
|
||||||
return if warning.nil?
|
return if warning.nil?
|
||||||
@ -534,7 +561,6 @@ module Homebrew
|
|||||||
def get_repo_data(regex)
|
def get_repo_data(regex)
|
||||||
return unless @core_tap
|
return unless @core_tap
|
||||||
return unless @online
|
return unless @online
|
||||||
return unless @new_formula
|
|
||||||
|
|
||||||
_, user, repo = *regex.match(formula.stable.url) if formula.stable
|
_, user, repo = *regex.match(formula.stable.url) if formula.stable
|
||||||
_, user, repo = *regex.match(formula.homepage) unless user
|
_, 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?
|
odie "--keep-old was passed but there was no existing bottle block!" if args.keep_old?
|
||||||
puts output
|
puts output
|
||||||
update_or_add = "add"
|
update_or_add = "add"
|
||||||
if s.include? "stable do"
|
pattern = /(
|
||||||
indent = s.slice(/^( +)stable do/, 1).length
|
(\ {2}\#[^\n]*\n)* # comments
|
||||||
string = s.sub!(/^ {#{indent}}stable do(.|\n)+?^ {#{indent}}end\n/m, '\0' + output + "\n")
|
\ {2}( # two spaces at the beginning
|
||||||
else
|
(url|head)\ ['"][\S\ ]+['"] # url or head with a string
|
||||||
pattern = /(
|
(
|
||||||
(\ {2}\#[^\n]*\n)* # comments
|
,[\S\ ]*$ # url may have options
|
||||||
\ {2}( # two spaces at the beginning
|
(\n^\ {3}[\S\ ]+$)* # options can be in multiple lines
|
||||||
(url|head)\ ['"][\S\ ]+['"] # url or head with a string
|
)?|
|
||||||
(
|
(homepage|desc|sha256|version|mirror|license)\ ['"][\S\ ]+['"]| # specs with a string
|
||||||
,[\S\ ]*$ # url may have options
|
(revision|version_scheme)\ \d+| # revision with a number
|
||||||
(\n^\ {3}[\S\ ]+$)* # options can be in multiple lines
|
(stable|livecheck)\ do(\n+^\ {4}[\S\ ]+$)*\n+^\ {2}end # components with blocks
|
||||||
)?|
|
)\n+ # multiple empty lines
|
||||||
(homepage|desc|sha1|sha256|version|mirror)\ ['"][\S\ ]+['"]| # specs with a string
|
)+
|
||||||
(revision|version_scheme)\ \d+ # revision with a number
|
/mx
|
||||||
)\n+ # multiple empty lines
|
string = s.sub!(pattern, '\0' + output + "\n")
|
||||||
)+
|
|
||||||
/mx
|
|
||||||
string = s.sub!(pattern, '\0' + output + "\n")
|
|
||||||
end
|
|
||||||
odie "Bottle block addition failed!" unless string
|
odie "Bottle block addition failed!" unless string
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -47,6 +47,8 @@ module Homebrew
|
|||||||
description: "Explicitly set the <name> of the new formula."
|
description: "Explicitly set the <name> of the new formula."
|
||||||
flag "--set-version=",
|
flag "--set-version=",
|
||||||
description: "Explicitly set the <version> of the new formula."
|
description: "Explicitly set the <version> of the new formula."
|
||||||
|
flag "--set-license=",
|
||||||
|
description: "Explicitly set the <license> of the new formula."
|
||||||
flag "--tap=",
|
flag "--tap=",
|
||||||
description: "Generate the new formula within the given tap, specified as <user>`/`<repo>."
|
description: "Generate the new formula within the given tap, specified as <user>`/`<repo>."
|
||||||
switch :force
|
switch :force
|
||||||
@ -68,11 +70,13 @@ module Homebrew
|
|||||||
|
|
||||||
version = args.set_version
|
version = args.set_version
|
||||||
name = args.set_name
|
name = args.set_name
|
||||||
|
license = args.set_license
|
||||||
tap = args.tap
|
tap = args.tap
|
||||||
|
|
||||||
fc = FormulaCreator.new
|
fc = FormulaCreator.new
|
||||||
fc.name = name
|
fc.name = name
|
||||||
fc.version = version
|
fc.version = version
|
||||||
|
fc.license = license
|
||||||
fc.tap = Tap.fetch(tap || "homebrew/core")
|
fc.tap = Tap.fetch(tap || "homebrew/core")
|
||||||
raise TapUnavailableError, tap unless fc.tap.installed?
|
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
|
# Remove any existing version suffixes, as a new one will be added later
|
||||||
name.sub!(/\b@(.*)\z\b/i, "")
|
name.sub!(/\b@(.*)\z\b/i, "")
|
||||||
versioned_name = Formulary.class_s("#{name}@#{version}")
|
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"
|
path = destination_tap.path/"Formula/#{name}@#{version}.rb"
|
||||||
if path.exist?
|
if path.exist?
|
||||||
@ -205,7 +208,8 @@ module Homebrew
|
|||||||
odebug "Overwriting existing formula at #{path}"
|
odebug "Overwriting existing formula at #{path}"
|
||||||
path.delete
|
path.delete
|
||||||
end
|
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
|
path.write result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,9 @@ module Homebrew
|
|||||||
switch "--resolve",
|
switch "--resolve",
|
||||||
description: "When a patch fails to apply, leave in progress and allow user to resolve, "\
|
description: "When a patch fails to apply, leave in progress and allow user to resolve, "\
|
||||||
"instead of aborting."
|
"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=",
|
flag "--workflow=",
|
||||||
description: "Retrieve artifacts from the specified workflow (default: `tests.yml`)."
|
description: "Retrieve artifacts from the specified workflow (default: `tests.yml`)."
|
||||||
flag "--artifact=",
|
flag "--artifact=",
|
||||||
@ -73,13 +76,18 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def signoff!(pr, path: ".")
|
def signoff!(pr, tap:)
|
||||||
message = Utils.popen_read "git", "-C", path, "log", "-1", "--pretty=%B"
|
message = Utils.popen_read "git", "-C", tap.path, "log", "-1", "--pretty=%B"
|
||||||
subject = message.lines.first.strip
|
subject = message.lines.first.strip
|
||||||
|
|
||||||
# Skip the subject and separate lines that look like trailers (e.g. "Co-authored-by")
|
# Skip the subject and separate lines that look like trailers (e.g. "Co-authored-by")
|
||||||
# from lines that look like regular body text.
|
# from lines that look like regular body text.
|
||||||
trailers, body = message.lines.drop(1).partition { |s| s.match?(/^[a-z-]+-by:/i) }
|
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
|
trailers = trailers.uniq.join.strip
|
||||||
body = body.join.strip.gsub(/\n{3,}/, "\n\n")
|
body = body.join.strip.gsub(/\n{3,}/, "\n\n")
|
||||||
|
|
||||||
@ -90,7 +98,7 @@ module Homebrew
|
|||||||
if Homebrew.args.dry_run?
|
if Homebrew.args.dry_run?
|
||||||
puts "git commit --amend --signoff -m $message"
|
puts "git commit --amend --signoff -m $message"
|
||||||
else
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -232,7 +240,7 @@ module Homebrew
|
|||||||
cd dir do
|
cd dir do
|
||||||
original_commit = Utils.popen_read("git", "-C", tap.path, "rev-parse", "HEAD").chomp
|
original_commit = Utils.popen_read("git", "-C", tap.path, "rev-parse", "HEAD").chomp
|
||||||
cherry_pick_pr! pr, path: tap.path
|
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?
|
unless args.no_upload?
|
||||||
mirror_formulae(tap, original_commit, org: bintray_org, repo: mirror_repo, publish: !args.no_publish?)
|
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 << "--verbose" if Homebrew.args.verbose?
|
||||||
upload_args << "--no-publish" if args.no_publish?
|
upload_args << "--no-publish" if args.no_publish?
|
||||||
upload_args << "--dry-run" if args.dry_run?
|
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 << "--root_url=#{args.root_url}" if args.root_url
|
||||||
upload_args << "--bintray-org=#{bintray_org}"
|
upload_args << "--bintray-org=#{bintray_org}"
|
||||||
system HOMEBREW_BREW_FILE, *upload_args
|
safe_system HOMEBREW_BREW_FILE, *upload_args
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -17,6 +17,9 @@ module Homebrew
|
|||||||
description: "Apply the bottle commit and upload the bottles, but don't publish them."
|
description: "Apply the bottle commit and upload the bottles, but don't publish them."
|
||||||
switch "-n", "--dry-run",
|
switch "-n", "--dry-run",
|
||||||
description: "Print what would be done rather than doing it."
|
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=",
|
flag "--bintray-org=",
|
||||||
description: "Upload to the specified Bintray organisation (default: `homebrew`)."
|
description: "Upload to the specified Bintray organisation (default: `homebrew`)."
|
||||||
flag "--root-url=",
|
flag "--root-url=",
|
||||||
@ -42,13 +45,15 @@ module Homebrew
|
|||||||
if args.dry_run?
|
if args.dry_run?
|
||||||
puts "brew #{bottle_args.join " "}"
|
puts "brew #{bottle_args.join " "}"
|
||||||
else
|
else
|
||||||
system HOMEBREW_BREW_FILE, *bottle_args
|
safe_system HOMEBREW_BREW_FILE, *bottle_args
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.dry_run?
|
if args.dry_run?
|
||||||
puts "Upload bottles described by these JSON files to Bintray:\n #{Dir["*.json"].join("\n ")}"
|
puts "Upload bottles described by these JSON files to Bintray:\n #{Dir["*.json"].join("\n ")}"
|
||||||
else
|
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
|
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_xcode_minimum_version
|
||||||
check_clt_minimum_version
|
check_clt_minimum_version
|
||||||
check_if_xcode_needs_clt_installed
|
check_if_xcode_needs_clt_installed
|
||||||
|
check_if_supported_sdk_available
|
||||||
].freeze
|
].freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -357,6 +358,34 @@ module Homebrew
|
|||||||
Untap them with `brew untap`.
|
Untap them with `brew untap`.
|
||||||
EOS
|
EOS
|
||||||
end
|
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
|
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=
|
# @see .desc=
|
||||||
delegate desc: :"self.class"
|
delegate desc: :"self.class"
|
||||||
|
|
||||||
|
# The SPDX ID of the software license.
|
||||||
|
delegate license: :"self.class"
|
||||||
|
|
||||||
# The homepage for the software.
|
# The homepage for the software.
|
||||||
# @method homepage
|
# @method homepage
|
||||||
# @see .homepage=
|
# @see .homepage=
|
||||||
@ -1687,6 +1690,7 @@ class Formula
|
|||||||
"aliases" => aliases.sort,
|
"aliases" => aliases.sort,
|
||||||
"versioned_formulae" => versioned_formulae.map(&:name),
|
"versioned_formulae" => versioned_formulae.map(&:name),
|
||||||
"desc" => desc,
|
"desc" => desc,
|
||||||
|
"license" => license,
|
||||||
"homepage" => homepage,
|
"homepage" => homepage,
|
||||||
"versions" => {
|
"versions" => {
|
||||||
"stable" => stable&.version&.to_s,
|
"stable" => stable&.version&.to_s,
|
||||||
@ -2211,6 +2215,13 @@ class Formula
|
|||||||
# <pre>desc "Example formula"</pre>
|
# <pre>desc "Example formula"</pre>
|
||||||
attr_rw :desc
|
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
|
# @!attribute [w] homepage
|
||||||
# The homepage for the software. Used by users to get more information
|
# The homepage for the software. Used by users to get more information
|
||||||
# about the software and Homebrew maintainers as a point of contact for
|
# 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.
|
# 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
|
# We want tests that don't require any user input
|
||||||
# and building the software was OK.
|
# and test the basic functionality of the application.
|
||||||
# <pre>system bin/"foobar", "--version"</pre>
|
# 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
|
# <pre>(testpath/"test.file").write <<~EOS
|
||||||
# writing some test file, if you need to
|
# writing some test file, if you need to
|
||||||
|
|||||||
@ -6,7 +6,7 @@ require "erb"
|
|||||||
module Homebrew
|
module Homebrew
|
||||||
class FormulaCreator
|
class FormulaCreator
|
||||||
attr_reader :url, :sha256, :desc, :homepage
|
attr_reader :url, :sha256, :desc, :homepage
|
||||||
attr_accessor :name, :version, :tap, :path, :mode
|
attr_accessor :name, :version, :tap, :path, :mode, :license
|
||||||
|
|
||||||
def url=(url)
|
def url=(url)
|
||||||
@url = url
|
@url = url
|
||||||
@ -100,6 +100,7 @@ module Homebrew
|
|||||||
<% end %>
|
<% end %>
|
||||||
sha256 "#{sha256}"
|
sha256 "#{sha256}"
|
||||||
<% end %>
|
<% end %>
|
||||||
|
license "#{license}"
|
||||||
|
|
||||||
<% if mode == :cmake %>
|
<% if mode == :cmake %>
|
||||||
depends_on "cmake" => :build
|
depends_on "cmake" => :build
|
||||||
|
|||||||
@ -77,6 +77,14 @@ class FormulaInstaller
|
|||||||
@attempted = Set.new
|
@attempted = Set.new
|
||||||
end
|
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,
|
# 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
|
# it's necessary to interrupt the user before any sort of installation
|
||||||
# can proceed. Only invoked when the user has no developer tools.
|
# can proceed. Only invoked when the user has no developer tools.
|
||||||
@ -292,7 +300,7 @@ class FormulaInstaller
|
|||||||
|
|
||||||
self.class.attempted << formula
|
self.class.attempted << formula
|
||||||
|
|
||||||
if pour_bottle?(warn: true)
|
if pour_bottle?
|
||||||
begin
|
begin
|
||||||
pour
|
pour
|
||||||
rescue Exception => e # rubocop:disable Lint/RescueException
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
||||||
@ -700,6 +708,8 @@ class FormulaInstaller
|
|||||||
|
|
||||||
ohai "Summary" if verbose? || show_summary_heading?
|
ohai "Summary" if verbose? || show_summary_heading?
|
||||||
puts summary
|
puts summary
|
||||||
|
|
||||||
|
self.class.installed << formula
|
||||||
ensure
|
ensure
|
||||||
unlock
|
unlock
|
||||||
end
|
end
|
||||||
@ -983,11 +993,24 @@ class FormulaInstaller
|
|||||||
|
|
||||||
return if only_deps?
|
return if only_deps?
|
||||||
|
|
||||||
unless pour_bottle?
|
if pour_bottle?(warn: true)
|
||||||
formula.fetch_patches
|
begin
|
||||||
formula.resources.each(&:fetch)
|
downloader.fetch
|
||||||
end
|
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
|
downloader.fetch
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -97,14 +97,16 @@ module OS
|
|||||||
# If no specific SDK is requested, the SDK matching the OS version is returned,
|
# If no specific SDK is requested, the SDK matching the OS version is returned,
|
||||||
# if available. Otherwise, the latest SDK is returned.
|
# if available. Otherwise, the latest SDK is returned.
|
||||||
|
|
||||||
def sdk(v = nil)
|
def sdk_locator
|
||||||
@locator ||= if CLT.installed? && CLT.provides_sdk?
|
if CLT.installed? && CLT.provides_sdk?
|
||||||
CLTSDKLocator.new
|
CLT.sdk_locator
|
||||||
else
|
else
|
||||||
XcodeSDKLocator.new
|
Xcode.sdk_locator
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@locator.sdk_if_applicable(v)
|
def sdk(v = nil)
|
||||||
|
sdk_locator.sdk_if_applicable(v)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sdk_for_formula(f, v = nil)
|
def sdk_for_formula(f, v = nil)
|
||||||
|
|||||||
@ -31,6 +31,10 @@ module OS
|
|||||||
SDK.new v, path, source
|
SDK.new v, path, source
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def all_sdks
|
||||||
|
sdk_paths.map { |v, p| SDK.new v, p, source }
|
||||||
|
end
|
||||||
|
|
||||||
def sdk_if_applicable(v = nil)
|
def sdk_if_applicable(v = nil)
|
||||||
sdk = begin
|
sdk = begin
|
||||||
if v.nil?
|
if v.nil?
|
||||||
@ -47,15 +51,11 @@ module OS
|
|||||||
sdk
|
sdk
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def source
|
def source
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def source_version
|
private
|
||||||
OS::Mac::Version::NULL
|
|
||||||
end
|
|
||||||
|
|
||||||
def sdk_prefix
|
def sdk_prefix
|
||||||
""
|
""
|
||||||
@ -81,15 +81,11 @@ module OS
|
|||||||
end
|
end
|
||||||
|
|
||||||
class XcodeSDKLocator < BaseSDKLocator
|
class XcodeSDKLocator < BaseSDKLocator
|
||||||
private
|
|
||||||
|
|
||||||
def source
|
def source
|
||||||
:xcode
|
:xcode
|
||||||
end
|
end
|
||||||
|
|
||||||
def source_version
|
private
|
||||||
OS::Mac::Xcode.version
|
|
||||||
end
|
|
||||||
|
|
||||||
def sdk_prefix
|
def sdk_prefix
|
||||||
@sdk_prefix ||= begin
|
@sdk_prefix ||= begin
|
||||||
@ -105,15 +101,11 @@ module OS
|
|||||||
end
|
end
|
||||||
|
|
||||||
class CLTSDKLocator < BaseSDKLocator
|
class CLTSDKLocator < BaseSDKLocator
|
||||||
private
|
|
||||||
|
|
||||||
def source
|
def source
|
||||||
:clt
|
:clt
|
||||||
end
|
end
|
||||||
|
|
||||||
def source_version
|
private
|
||||||
OS::Mac::CLT.version
|
|
||||||
end
|
|
||||||
|
|
||||||
# While CLT SDKs existed prior to Xcode 10, those packages also
|
# While CLT SDKs existed prior to Xcode 10, those packages also
|
||||||
# installed a traditional Unix-style header layout and we prefer
|
# installed a traditional Unix-style header layout and we prefer
|
||||||
|
|||||||
@ -107,10 +107,12 @@ module OS
|
|||||||
!prefix.nil?
|
!prefix.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def sdk(v = nil)
|
def sdk_locator
|
||||||
@locator ||= XcodeSDKLocator.new
|
@sdk_locator ||= XcodeSDKLocator.new
|
||||||
|
end
|
||||||
|
|
||||||
@locator.sdk_if_applicable(v)
|
def sdk(v = nil)
|
||||||
|
sdk_locator.sdk_if_applicable(v)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sdk_path(v = nil)
|
def sdk_path(v = nil)
|
||||||
@ -219,10 +221,12 @@ module OS
|
|||||||
version >= "8"
|
version >= "8"
|
||||||
end
|
end
|
||||||
|
|
||||||
def sdk(v = nil)
|
def sdk_locator
|
||||||
@locator ||= CLTSDKLocator.new
|
@sdk_locator ||= CLTSDKLocator.new
|
||||||
|
end
|
||||||
|
|
||||||
@locator.sdk_if_applicable(v)
|
def sdk(v = nil)
|
||||||
|
sdk_locator.sdk_if_applicable(v)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sdk_path(v = nil)
|
def sdk_path(v = nil)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "formula"
|
require "formula"
|
||||||
|
require "cask/cask_loader"
|
||||||
|
|
||||||
module Readall
|
module Readall
|
||||||
class << self
|
class << self
|
||||||
@ -35,28 +36,43 @@ module Readall
|
|||||||
end
|
end
|
||||||
|
|
||||||
def valid_formulae?(formulae)
|
def valid_formulae?(formulae)
|
||||||
failed = false
|
success = true
|
||||||
formulae.each do |file|
|
formulae.each do |file|
|
||||||
Formulary.factory(file)
|
Formulary.factory(file)
|
||||||
rescue Interrupt
|
rescue Interrupt
|
||||||
raise
|
raise
|
||||||
rescue Exception => e # rubocop:disable Lint/RescueException
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
||||||
onoe "Invalid formula: #{file}"
|
onoe "Invalid formula: #{file}"
|
||||||
puts e
|
$stderr.puts e
|
||||||
failed = true
|
success = false
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def valid_tap?(tap, options = {})
|
def valid_tap?(tap, options = {})
|
||||||
failed = false
|
success = true
|
||||||
if options[:aliases]
|
if options[:aliases]
|
||||||
valid_aliases = valid_aliases?(tap.alias_dir, tap.formula_dir)
|
valid_aliases = valid_aliases?(tap.alias_dir, tap.formula_dir)
|
||||||
failed = true unless valid_aliases
|
success = false unless valid_aliases
|
||||||
end
|
end
|
||||||
valid_formulae = valid_formulae?(tap.formula_files)
|
valid_formulae = valid_formulae?(tap.formula_files)
|
||||||
failed = true unless valid_formulae
|
valid_casks = valid_casks?(tap.cask_files)
|
||||||
!failed
|
success = false if !valid_formulae || !valid_casks
|
||||||
|
success
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -79,3 +95,5 @@ module Readall
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require "extend/os/readall"
|
||||||
|
|||||||
@ -24,7 +24,8 @@ module RuboCop
|
|||||||
[{ name: :mirror, type: :method_call }],
|
[{ name: :mirror, type: :method_call }],
|
||||||
[{ name: :version, type: :method_call }],
|
[{ name: :version, type: :method_call }],
|
||||||
[{ name: :sha256, 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: :version_scheme, type: :method_call }],
|
||||||
[{ name: :head, type: :method_call }],
|
[{ name: :head, type: :method_call }],
|
||||||
[{ name: :stable, type: :block_call }],
|
[{ name: :stable, type: :block_call }],
|
||||||
|
|||||||
@ -453,7 +453,6 @@ false:
|
|||||||
- ./utils/github.rb
|
- ./utils/github.rb
|
||||||
- ./utils/notability.rb
|
- ./utils/notability.rb
|
||||||
- ./utils/popen.rb
|
- ./utils/popen.rb
|
||||||
- ./utils/tty.rb
|
|
||||||
- ./utils/user.rb
|
- ./utils/user.rb
|
||||||
|
|
||||||
false:
|
false:
|
||||||
@ -889,6 +888,7 @@ true:
|
|||||||
- ./tap_constants.rb
|
- ./tap_constants.rb
|
||||||
- ./test/support/helper/fixtures.rb
|
- ./test/support/helper/fixtures.rb
|
||||||
- ./test/support/lib/config.rb
|
- ./test/support/lib/config.rb
|
||||||
|
- ./utils/tty.rb
|
||||||
- ./version/null.rb
|
- ./version/null.rb
|
||||||
|
|
||||||
strict:
|
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
|
end
|
||||||
|
|
||||||
describe "brew search", :integration_test do
|
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_test_formula "testball"
|
||||||
setup_remote_tap "homebrew/cask"
|
setup_remote_tap "homebrew/cask"
|
||||||
|
|
||||||
@ -16,4 +16,13 @@ describe "brew search", :integration_test do
|
|||||||
.to output(/firefox/).to_stdout
|
.to output(/firefox/).to_stdout
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
@ -79,6 +79,92 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
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
|
describe "#audit_file" do
|
||||||
specify "no issue" do
|
specify "no issue" do
|
||||||
fa = formula_auditor "foo", <<~RUBY
|
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
|
RUBY
|
||||||
end
|
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
|
it "When `bottle` precedes `livecheck`" do
|
||||||
expect_offense(<<~RUBY)
|
expect_offense(<<~RUBY)
|
||||||
class Foo < Formula
|
class Foo < Formula
|
||||||
|
|||||||
@ -4,12 +4,10 @@ if ENV["HOMEBREW_TESTS_COVERAGE"]
|
|||||||
require "simplecov"
|
require "simplecov"
|
||||||
|
|
||||||
formatters = [SimpleCov::Formatter::HTMLFormatter]
|
formatters = [SimpleCov::Formatter::HTMLFormatter]
|
||||||
if ENV["HOMEBREW_COVERALLS_REPO_TOKEN"] && RUBY_PLATFORM[/darwin/]
|
if ENV["HOMEBREW_CODECOV_TOKEN"] && RUBY_PLATFORM[/darwin/]
|
||||||
require "coveralls"
|
require "codecov"
|
||||||
|
|
||||||
Coveralls::Output.no_color if !ENV["HOMEBREW_COLOR"] && (ENV["HOMEBREW_NO_COLOR"] || !$stdout.tty?)
|
formatters << SimpleCov::Formatter::Codecov
|
||||||
|
|
||||||
formatters << Coveralls::SimpleCov::Formatter
|
|
||||||
|
|
||||||
if ENV["TEST_ENV_NUMBER"]
|
if ENV["TEST_ENV_NUMBER"]
|
||||||
SimpleCov.at_exit do
|
SimpleCov.at_exit do
|
||||||
@ -18,16 +16,7 @@ if ENV["HOMEBREW_TESTS_COVERAGE"]
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ENV["CI_NAME"] = ENV["HOMEBREW_CI_NAME"]
|
ENV["CODECOV_TOKEN"] = ENV["HOMEBREW_CODECOV_TOKEN"]
|
||||||
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"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(formatters)
|
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(formatters)
|
||||||
@ -174,6 +163,7 @@ RSpec.configure do |config|
|
|||||||
Keg.clear_cache
|
Keg.clear_cache
|
||||||
Tab.clear_cache
|
Tab.clear_cache
|
||||||
FormulaInstaller.clear_attempted
|
FormulaInstaller.clear_attempted
|
||||||
|
FormulaInstaller.clear_installed
|
||||||
|
|
||||||
TEST_DIRECTORIES.each(&:mkpath)
|
TEST_DIRECTORIES.each(&:mkpath)
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@ RSpec.shared_context "integration test" do
|
|||||||
|
|
||||||
example.run
|
example.run
|
||||||
ensure
|
ensure
|
||||||
FileUtils.rm_r HOMEBREW_PREFIX/"bin"
|
FileUtils.rm_rf HOMEBREW_PREFIX/"bin"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Generate unique ID to be able to
|
# Generate unique ID to be able to
|
||||||
|
|||||||
@ -42,6 +42,13 @@ describe GitHub do
|
|||||||
end
|
end
|
||||||
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
|
describe "::get_artifact_url", :needs_network do
|
||||||
it "fails to find a nonexistant workflow" do
|
it "fails to find a nonexistant workflow" do
|
||||||
expect {
|
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
|
secrets: secrets
|
||||||
end
|
end
|
||||||
|
|
||||||
def curl_download(*args, to: nil, **options)
|
def curl_download(*args, to: nil, partial: true, **options)
|
||||||
destination = Pathname(to)
|
destination = Pathname(to)
|
||||||
destination.dirname.mkpath
|
destination.dirname.mkpath
|
||||||
|
|
||||||
range_stdout = curl_output("--location", "--range", "0-1",
|
if partial
|
||||||
"--dump-header", "-",
|
range_stdout = curl_output("--location", "--range", "0-1",
|
||||||
"--write-out", "%\{http_code}",
|
"--dump-header", "-",
|
||||||
"--output", "/dev/null", *args, **options).stdout
|
"--write-out", "%\{http_code}",
|
||||||
headers, _, http_status = range_stdout.partition("\r\n\r\n")
|
"--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
|
supports_partial_download = http_status.to_i == 206 # Partial Content
|
||||||
if supports_partial_download &&
|
if supports_partial_download &&
|
||||||
destination.exist? &&
|
destination.exist? &&
|
||||||
destination.size == %r{^.*Content-Range: bytes \d+-\d+/(\d+)\r\n.*$}m.match(headers)&.[](1)&.to_i
|
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
|
return # We've already downloaded all the bytes
|
||||||
|
end
|
||||||
|
else
|
||||||
|
supports_partial_download = false
|
||||||
end
|
end
|
||||||
|
|
||||||
continue_at = if destination.exist? && supports_partial_download
|
continue_at = if destination.exist? && supports_partial_download
|
||||||
|
|||||||
@ -392,6 +392,52 @@ module GitHub
|
|||||||
open_api(uri) { |json| json.fetch("items", []) }
|
open_api(uri) { |json| json.fetch("items", []) }
|
||||||
end
|
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)
|
def dispatch_event(user, repo, event, **payload)
|
||||||
url = "#{API_URL}/repos/#{user}/#{repo}/dispatches"
|
url = "#{API_URL}/repos/#{user}/#{repo}/dispatches"
|
||||||
open_api(url, data: { event_type: event, client_payload: payload },
|
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")
|
open_api(url, scopes: ["admin:org", "user"], data: data, request_method: "POST")
|
||||||
end
|
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
|
def api_errors
|
||||||
[GitHub::AuthenticationFailedError, GitHub::HTTPNotFoundError,
|
[GitHub::AuthenticationFailedError, GitHub::HTTPNotFoundError,
|
||||||
GitHub::RateLimitExceededError, GitHub::Error, JSON::ParserError].freeze
|
GitHub::RateLimitExceededError, GitHub::Error, JSON::ParserError].freeze
|
||||||
|
|||||||
@ -86,6 +86,7 @@ unpin
|
|||||||
untap
|
untap
|
||||||
up
|
up
|
||||||
update
|
update
|
||||||
|
update-license-data
|
||||||
update-report
|
update-report
|
||||||
update-reset
|
update-reset
|
||||||
update-test
|
update-test
|
||||||
|
|||||||
@ -6,6 +6,13 @@ This is a page for maintainers to diagnose certain build errors.
|
|||||||
|
|
||||||
## Issues
|
## 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`
|
### `ld: internal error: atom not found in symbolIndex(__ZN10SQInstance3GetERK11SQObjectPtrRS0_) for architecture x86_64`
|
||||||
|
|
||||||
The exact atom may be different.
|
The exact atom may be different.
|
||||||
|
|||||||
@ -369,10 +369,10 @@ Rerun the post-install steps for *`formula`*.
|
|||||||
|
|
||||||
### `readall` [*`options`*] [*`tap`*]
|
### `readall` [*`options`*] [*`tap`*]
|
||||||
|
|
||||||
Import all formulae from the specified *`tap`*, or from all installed taps if none
|
Import all items from the specified *`tap`*, or from all installed taps if none is
|
||||||
is provided. This can be useful for debugging issues across all formulae when
|
provided. This can be useful for debugging issues across all items when making
|
||||||
making significant changes to `formula.rb`, testing the performance of loading
|
significant changes to `formula.rb`, testing the performance of loading all
|
||||||
all formulae or checking if any current formulae have Ruby issues.
|
items or checking if any current formulae/casks have Ruby issues.
|
||||||
|
|
||||||
* `--aliases`:
|
* `--aliases`:
|
||||||
Verify any alias symlinks in each tap.
|
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.
|
Explicitly set the *`name`* of the new formula.
|
||||||
* `--set-version`:
|
* `--set-version`:
|
||||||
Explicitly set the *`version`* of the new formula.
|
Explicitly set the *`version`* of the new formula.
|
||||||
|
* `--set-license`:
|
||||||
|
Explicitly set the *`license`* of the new formula.
|
||||||
* `--tap`:
|
* `--tap`:
|
||||||
Generate the new formula within the given tap, specified as *`user`*`/`*`repo`*.
|
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).
|
Do not warn if pulling to a branch besides master (useful for testing).
|
||||||
* `--resolve`:
|
* `--resolve`:
|
||||||
When a patch fails to apply, leave in progress and allow user to resolve, instead of aborting.
|
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`:
|
* `--workflow`:
|
||||||
Retrieve artifacts from the specified workflow (default: `tests.yml`).
|
Retrieve artifacts from the specified workflow (default: `tests.yml`).
|
||||||
* `--artifact`:
|
* `--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.
|
Apply the bottle commit and upload the bottles, but don't publish them.
|
||||||
* `-n`, `--dry-run`:
|
* `-n`, `--dry-run`:
|
||||||
Print what would be done rather than doing it.
|
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`:
|
* `--bintray-org`:
|
||||||
Upload to the specified Bintray organisation (default: `homebrew`).
|
Upload to the specified Bintray organisation (default: `homebrew`).
|
||||||
* `--root-url`:
|
* `--root-url`:
|
||||||
@ -1028,6 +1034,13 @@ directory.
|
|||||||
* `-g`, `--git`:
|
* `-g`, `--git`:
|
||||||
Initialise a Git repository in the unpacked source. This is useful for creating patches for the software.
|
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`*]
|
### `update-test` [*`options`*]
|
||||||
|
|
||||||
Run a test of `brew update` with a new repository clone. If no options are
|
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
|
.\" generated with Ronn/v0.7.3
|
||||||
.\" http://github.com/rtomayko/ronn/tree/0.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"
|
.SH "NAME"
|
||||||
\fBbrew\-cask\fR \- a friendly binary installer for macOS
|
\fBbrew\-cask\fR \- a friendly binary installer for macOS
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
.\" generated with Ronn/v0.7.3
|
.\" generated with Ronn/v0.7.3
|
||||||
.\" http://github.com/rtomayko/ronn/tree/0.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"
|
.SH "NAME"
|
||||||
\fBbrew\fR \- The Missing Package Manager for macOS
|
\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\.
|
Rerun the post\-install steps for \fIformula\fR\.
|
||||||
.
|
.
|
||||||
.SS "\fBreadall\fR [\fIoptions\fR] [\fItap\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
|
.TP
|
||||||
\fB\-\-aliases\fR
|
\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\.
|
Explicitly set the \fIversion\fR of the new formula\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-set\-license\fR
|
||||||
|
Explicitly set the \fIlicense\fR of the new formula\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
\fB\-\-tap\fR
|
\fB\-\-tap\fR
|
||||||
Generate the new formula within the given tap, specified as \fIuser\fR\fB/\fR\fIrepo\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\.
|
When a patch fails to apply, leave in progress and allow user to resolve, instead of aborting\.
|
||||||
.
|
.
|
||||||
.TP
|
.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
|
\fB\-\-workflow\fR
|
||||||
Retrieve artifacts from the specified workflow (default: \fBtests\.yml\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\.
|
Print what would be done rather than doing it\.
|
||||||
.
|
.
|
||||||
.TP
|
.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
|
\fB\-\-bintray\-org\fR
|
||||||
Upload to the specified Bintray organisation (default: \fBhomebrew\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
|
\fB\-g\fR, \fB\-\-git\fR
|
||||||
Initialise a Git repository in the unpacked source\. This is useful for creating patches for the software\.
|
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]"
|
.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\.
|
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