Merge branch 'mlh-outdated-packages' of github.com:MLH-Fellowship/brew into mlh-outdated-packages
This commit is contained in:
commit
0402f0c95e
8
.github/codecov.yml
vendored
Normal file
8
.github/codecov.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fixes:
|
||||||
|
- "::Library/Homebrew/"
|
||||||
|
coverage:
|
||||||
|
round: nearest
|
||||||
|
status:
|
||||||
|
project:
|
||||||
|
default:
|
||||||
|
threshold: 0.05%
|
||||||
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
|
||||||
|
|||||||
6
.gitignore
vendored
6
.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,9 @@
|
|||||||
**/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/thor-*/
|
**/vendor/bundle/ruby/*/gems/thor-*/
|
||||||
**/vendor/bundle/ruby/*/gems/tins-*/
|
**/vendor/bundle/ruby/*/gems/url-*/
|
||||||
**/vendor/bundle/ruby/*/gems/unf_ext-*/
|
**/vendor/bundle/ruby/*/gems/unf_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)
|
||||||
@ -26,7 +24,7 @@ GEM
|
|||||||
domain_name (~> 0.5)
|
domain_name (~> 0.5)
|
||||||
i18n (1.8.3)
|
i18n (1.8.3)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
json (2.3.0)
|
json (2.3.1)
|
||||||
mechanize (2.7.6)
|
mechanize (2.7.6)
|
||||||
domain_name (~> 0.5, >= 0.5.1)
|
domain_name (~> 0.5, >= 0.5.1)
|
||||||
http-cookie (~> 1.0)
|
http-cookie (~> 1.0)
|
||||||
@ -95,28 +93,22 @@ GEM
|
|||||||
parser (>= 2.7.0.1)
|
parser (>= 2.7.0.1)
|
||||||
rubocop-performance (1.6.1)
|
rubocop-performance (1.6.1)
|
||||||
rubocop (>= 0.71.0)
|
rubocop (>= 0.71.0)
|
||||||
rubocop-rspec (1.40.0)
|
rubocop-rspec (1.41.0)
|
||||||
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
|
||||||
|
|||||||
@ -36,9 +36,11 @@ module Homebrew
|
|||||||
# Reset cache values reliant on named_args
|
# Reset cache values reliant on named_args
|
||||||
@formulae = nil
|
@formulae = nil
|
||||||
@resolved_formulae = nil
|
@resolved_formulae = nil
|
||||||
|
@resolved_formulae_casks = nil
|
||||||
@formulae_paths = nil
|
@formulae_paths = nil
|
||||||
@casks = nil
|
@casks = nil
|
||||||
@kegs = nil
|
@kegs = nil
|
||||||
|
@kegs_casks = nil
|
||||||
|
|
||||||
self[:named_args] = named_args
|
self[:named_args] = named_args
|
||||||
self[:named_args].freeze
|
self[:named_args].freeze
|
||||||
@ -96,6 +98,25 @@ module Homebrew
|
|||||||
end.uniq(&:name).freeze
|
end.uniq(&:name).freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def resolved_formulae_casks
|
||||||
|
@resolved_formulae_casks ||= begin
|
||||||
|
resolved_formulae = []
|
||||||
|
casks = []
|
||||||
|
|
||||||
|
downcased_unique_named.each do |name|
|
||||||
|
resolved_formulae << Formulary.resolve(name, spec: spec(nil))
|
||||||
|
rescue FormulaUnavailableError
|
||||||
|
begin
|
||||||
|
casks << Cask::CaskLoader.load(name)
|
||||||
|
rescue Cask::CaskUnavailableError
|
||||||
|
raise "No available formula or cask with the name \"#{name}\""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
[resolved_formulae.freeze, casks.freeze].freeze
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def formulae_paths
|
def formulae_paths
|
||||||
@formulae_paths ||= (downcased_unique_named - casks).map do |name|
|
@formulae_paths ||= (downcased_unique_named - casks).map do |name|
|
||||||
Formulary.path(name)
|
Formulary.path(name)
|
||||||
@ -108,57 +129,35 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
def kegs
|
def kegs
|
||||||
require "keg"
|
|
||||||
require "formula"
|
|
||||||
require "missing_formula"
|
|
||||||
|
|
||||||
@kegs ||= downcased_unique_named.map do |name|
|
@kegs ||= downcased_unique_named.map do |name|
|
||||||
raise UsageError if name.empty?
|
resolve_keg name
|
||||||
|
rescue NoSuchKegError => e
|
||||||
rack = Formulary.to_rack(name.downcase)
|
if (reason = Homebrew::MissingFormula.suggest_command(name, "uninstall"))
|
||||||
|
$stderr.puts reason
|
||||||
dirs = rack.directory? ? rack.subdirs : []
|
|
||||||
|
|
||||||
if dirs.empty?
|
|
||||||
if (reason = Homebrew::MissingFormula.suggest_command(name, "uninstall"))
|
|
||||||
$stderr.puts reason
|
|
||||||
end
|
|
||||||
raise NoSuchKegError, rack.basename
|
|
||||||
end
|
|
||||||
|
|
||||||
linked_keg_ref = HOMEBREW_LINKED_KEGS/rack.basename
|
|
||||||
opt_prefix = HOMEBREW_PREFIX/"opt/#{rack.basename}"
|
|
||||||
|
|
||||||
begin
|
|
||||||
if opt_prefix.symlink? && opt_prefix.directory?
|
|
||||||
Keg.new(opt_prefix.resolved_path)
|
|
||||||
elsif linked_keg_ref.symlink? && linked_keg_ref.directory?
|
|
||||||
Keg.new(linked_keg_ref.resolved_path)
|
|
||||||
elsif dirs.length == 1
|
|
||||||
Keg.new(dirs.first)
|
|
||||||
else
|
|
||||||
f = if name.include?("/") || File.exist?(name)
|
|
||||||
Formulary.factory(name)
|
|
||||||
else
|
|
||||||
Formulary.from_rack(rack)
|
|
||||||
end
|
|
||||||
|
|
||||||
unless (prefix = f.installed_prefix).directory?
|
|
||||||
raise MultipleVersionsInstalledError, rack.basename
|
|
||||||
end
|
|
||||||
|
|
||||||
Keg.new(prefix)
|
|
||||||
end
|
|
||||||
rescue FormulaUnavailableError
|
|
||||||
raise <<~EOS
|
|
||||||
Multiple kegs installed to #{rack}
|
|
||||||
However we don't know which one you refer to.
|
|
||||||
Please delete (with rm -rf!) all but one and then try again.
|
|
||||||
EOS
|
|
||||||
end
|
end
|
||||||
|
raise e
|
||||||
end.freeze
|
end.freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def kegs_casks
|
||||||
|
@kegs_casks ||= begin
|
||||||
|
kegs = []
|
||||||
|
casks = []
|
||||||
|
|
||||||
|
downcased_unique_named.each do |name|
|
||||||
|
kegs << resolve_keg(name)
|
||||||
|
rescue NoSuchKegError
|
||||||
|
begin
|
||||||
|
casks << Cask::CaskLoader.load(name)
|
||||||
|
rescue Cask::CaskUnavailableError
|
||||||
|
raise "No installed keg or cask with the name \"#{name}\""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
[kegs.freeze, casks.freeze].freeze
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def build_stable?
|
def build_stable?
|
||||||
!(HEAD? || devel?)
|
!(HEAD? || devel?)
|
||||||
end
|
end
|
||||||
@ -241,6 +240,50 @@ module Homebrew
|
|||||||
default
|
default
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def resolve_keg(name)
|
||||||
|
require "keg"
|
||||||
|
require "formula"
|
||||||
|
require "missing_formula"
|
||||||
|
|
||||||
|
raise UsageError if name.blank?
|
||||||
|
|
||||||
|
rack = Formulary.to_rack(name.downcase)
|
||||||
|
|
||||||
|
dirs = rack.directory? ? rack.subdirs : []
|
||||||
|
raise NoSuchKegError, rack.basename if dirs.empty?
|
||||||
|
|
||||||
|
linked_keg_ref = HOMEBREW_LINKED_KEGS/rack.basename
|
||||||
|
opt_prefix = HOMEBREW_PREFIX/"opt/#{rack.basename}"
|
||||||
|
|
||||||
|
begin
|
||||||
|
if opt_prefix.symlink? && opt_prefix.directory?
|
||||||
|
Keg.new(opt_prefix.resolved_path)
|
||||||
|
elsif linked_keg_ref.symlink? && linked_keg_ref.directory?
|
||||||
|
Keg.new(linked_keg_ref.resolved_path)
|
||||||
|
elsif dirs.length == 1
|
||||||
|
Keg.new(dirs.first)
|
||||||
|
else
|
||||||
|
f = if name.include?("/") || File.exist?(name)
|
||||||
|
Formulary.factory(name)
|
||||||
|
else
|
||||||
|
Formulary.from_rack(rack)
|
||||||
|
end
|
||||||
|
|
||||||
|
unless (prefix = f.installed_prefix).directory?
|
||||||
|
raise MultipleVersionsInstalledError, "#{rack.basename} has multiple installed versions"
|
||||||
|
end
|
||||||
|
|
||||||
|
Keg.new(prefix)
|
||||||
|
end
|
||||||
|
rescue FormulaUnavailableError
|
||||||
|
raise MultipleVersionsInstalledError, <<~EOS
|
||||||
|
Multiple kegs installed to #{rack}
|
||||||
|
However we don't know which one you refer to.
|
||||||
|
Please delete (with rm -rf!) all but one and then try again.
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
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
|
||||||
|
|||||||
@ -6,6 +6,10 @@ require "messages"
|
|||||||
require "reinstall"
|
require "reinstall"
|
||||||
require "cli/parser"
|
require "cli/parser"
|
||||||
require "cleanup"
|
require "cleanup"
|
||||||
|
require "cask/cmd"
|
||||||
|
require "cask/utils"
|
||||||
|
require "cask/macos"
|
||||||
|
require "upgrade"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module_function
|
||||||
@ -56,7 +60,8 @@ module Homebrew
|
|||||||
|
|
||||||
Install.perform_preinstall_checks
|
Install.perform_preinstall_checks
|
||||||
|
|
||||||
args.resolved_formulae.each do |f|
|
resolved_formulae, casks = args.resolved_formulae_casks
|
||||||
|
resolved_formulae.each do |f|
|
||||||
if f.pinned?
|
if f.pinned?
|
||||||
onoe "#{f.full_name} is pinned. You must unpin it to reinstall."
|
onoe "#{f.full_name} is pinned. You must unpin it to reinstall."
|
||||||
next
|
next
|
||||||
@ -65,6 +70,16 @@ 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.blank?
|
||||||
|
|
||||||
|
reinstall_cmd = Cask::Cmd::Reinstall.new(casks)
|
||||||
|
reinstall_cmd.verbose = args.verbose?
|
||||||
|
reinstall_cmd.force = args.force?
|
||||||
|
reinstall_cmd.run
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -5,6 +5,9 @@ require "formula"
|
|||||||
require "diagnostic"
|
require "diagnostic"
|
||||||
require "migrator"
|
require "migrator"
|
||||||
require "cli/parser"
|
require "cli/parser"
|
||||||
|
require "cask/all"
|
||||||
|
require "cask/cmd"
|
||||||
|
require "cask/cask_loader"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module_function
|
||||||
@ -29,15 +32,26 @@ module Homebrew
|
|||||||
def uninstall
|
def uninstall
|
||||||
uninstall_args.parse
|
uninstall_args.parse
|
||||||
|
|
||||||
kegs_by_rack = if args.force?
|
if args.force?
|
||||||
Hash[args.named.map do |name|
|
casks = []
|
||||||
rack = Formulary.to_rack(name)
|
kegs_by_rack = {}
|
||||||
next unless rack.directory?
|
|
||||||
|
|
||||||
[rack, rack.subdirs.map { |d| Keg.new(d) }]
|
args.named.each do |name|
|
||||||
end]
|
rack = Formulary.to_rack(name)
|
||||||
|
|
||||||
|
if rack.directory?
|
||||||
|
kegs_by_rack[rack] = rack.subdirs.map { |d| Keg.new(d) }
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
casks << Cask::CaskLoader.load(name)
|
||||||
|
rescue Cask::CaskUnavailableError
|
||||||
|
# Since the uninstall was forced, ignore any unavailable casks
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
args.kegs.group_by(&:rack)
|
all_kegs, casks = args.kegs_casks
|
||||||
|
kegs_by_rack = all_kegs.group_by(&:rack)
|
||||||
end
|
end
|
||||||
|
|
||||||
handle_unsatisfied_dependents(kegs_by_rack)
|
handle_unsatisfied_dependents(kegs_by_rack)
|
||||||
@ -108,6 +122,13 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return if casks.blank?
|
||||||
|
|
||||||
|
cask_uninstall = Cask::Cmd::Uninstall.new(casks)
|
||||||
|
cask_uninstall.force = args.force?
|
||||||
|
cask_uninstall.verbose = args.verbose?
|
||||||
|
cask_uninstall.run
|
||||||
rescue MultipleVersionsInstalledError => e
|
rescue MultipleVersionsInstalledError => e
|
||||||
ofail e
|
ofail e
|
||||||
puts "Run `brew uninstall --force #{e.name}` to remove all versions."
|
puts "Run `brew uninstall --force #{e.name}` to remove all versions."
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -148,8 +148,7 @@ module Commands
|
|||||||
cmds = internal_commands + internal_developer_commands + internal_commands_aliases
|
cmds = internal_commands + internal_developer_commands + internal_commands_aliases
|
||||||
|
|
||||||
file = HOMEBREW_REPOSITORY/"completions/internal_commands_list.txt"
|
file = HOMEBREW_REPOSITORY/"completions/internal_commands_list.txt"
|
||||||
file.delete if file.exist?
|
file.atomic_write(cmds.sort.join("\n") + "\n")
|
||||||
file.write(cmds.sort.join("\n") + "\n")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def rebuild_commands_completion_list
|
def rebuild_commands_completion_list
|
||||||
@ -157,7 +156,6 @@ module Commands
|
|||||||
HOMEBREW_CACHE.mkpath
|
HOMEBREW_CACHE.mkpath
|
||||||
|
|
||||||
file = HOMEBREW_CACHE/"all_commands_list.txt"
|
file = HOMEBREW_CACHE/"all_commands_list.txt"
|
||||||
file.delete if file.exist?
|
file.atomic_write(commands(aliases: true).sort.join("\n") + "\n")
|
||||||
file.write(commands(aliases: true).sort.join("\n") + "\n")
|
|
||||||
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 && [formula.license, "NOASSERTION"].include?(github_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
|
||||||
@ -554,6 +580,7 @@ module Homebrew
|
|||||||
"aws-sdk-cpp" => "10",
|
"aws-sdk-cpp" => "10",
|
||||||
"awscli@1" => "10",
|
"awscli@1" => "10",
|
||||||
"balena-cli" => "10",
|
"balena-cli" => "10",
|
||||||
|
"gatsby-cli" => "10",
|
||||||
"quicktype" => "10",
|
"quicktype" => "10",
|
||||||
"vim" => "50",
|
"vim" => "50",
|
||||||
}.freeze
|
}.freeze
|
||||||
@ -721,11 +748,11 @@ module Homebrew
|
|||||||
current_revision = formula.revision
|
current_revision = formula.revision
|
||||||
|
|
||||||
previous_version = nil
|
previous_version = nil
|
||||||
previous_checksum = nil
|
|
||||||
previous_version_scheme = nil
|
previous_version_scheme = nil
|
||||||
previous_revision = nil
|
previous_revision = nil
|
||||||
|
|
||||||
newest_committed_version = nil
|
newest_committed_version = nil
|
||||||
|
newest_committed_checksum = nil
|
||||||
newest_committed_revision = nil
|
newest_committed_revision = nil
|
||||||
|
|
||||||
fv.rev_list("origin/master") do |rev|
|
fv.rev_list("origin/master") do |rev|
|
||||||
@ -739,6 +766,7 @@ module Homebrew
|
|||||||
previous_revision = f.revision
|
previous_revision = f.revision
|
||||||
|
|
||||||
newest_committed_version ||= previous_version
|
newest_committed_version ||= previous_version
|
||||||
|
newest_committed_checksum ||= previous_checksum
|
||||||
newest_committed_revision ||= previous_revision
|
newest_committed_revision ||= previous_revision
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -746,7 +774,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
if current_version == previous_version &&
|
if current_version == previous_version &&
|
||||||
current_checksum != previous_checksum
|
current_checksum != newest_committed_checksum
|
||||||
problem(
|
problem(
|
||||||
"stable sha256 changed without the version also changing; " \
|
"stable sha256 changed without the version also changing; " \
|
||||||
"please create an issue upstream to rule out malicious " \
|
"please create an issue upstream to rule out malicious " \
|
||||||
@ -845,15 +873,6 @@ module Homebrew
|
|||||||
# TODO: check could be in RuboCop
|
# TODO: check could be in RuboCop
|
||||||
problem "`env :userpaths` in formulae is deprecated" if line.include?("env :userpaths")
|
problem "`env :userpaths` in formulae is deprecated" if line.include?("env :userpaths")
|
||||||
|
|
||||||
if line =~ /system ((["'])[^"' ]*(?:\s[^"' ]*)+\2)/
|
|
||||||
bad_system = Regexp.last_match(1)
|
|
||||||
unless %w[| < > & ; *].any? { |c| bad_system.include? c }
|
|
||||||
good_system = bad_system.gsub(" ", "\", \"")
|
|
||||||
# TODO: check could be in RuboCop
|
|
||||||
problem "Use `system #{good_system}` instead of `system #{bad_system}` "
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# TODO: check could be in RuboCop
|
# TODO: check could be in RuboCop
|
||||||
problem "`#{Regexp.last_match(1)}` is now unnecessary" if line =~ /(require ["']formula["'])/
|
problem "`#{Regexp.last_match(1)}` is now unnecessary" if line =~ /(require ["']formula["'])/
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
59
Library/Homebrew/dev-cmd/sponsors.rb
Normal file
59
Library/Homebrew/dev-cmd/sponsors.rb
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "cli/parser"
|
||||||
|
require "utils/github"
|
||||||
|
|
||||||
|
module Homebrew
|
||||||
|
module_function
|
||||||
|
|
||||||
|
def sponsors_args
|
||||||
|
Homebrew::CLI::Parser.new do
|
||||||
|
usage_banner <<~EOS
|
||||||
|
`sponsors`
|
||||||
|
|
||||||
|
Print a Markdown summary of Homebrew's GitHub Sponsors, suitable for pasting into a README.
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def sponsors
|
||||||
|
sponsors_args.parse
|
||||||
|
|
||||||
|
sponsors = {
|
||||||
|
"named" => [],
|
||||||
|
"users" => 0,
|
||||||
|
"orgs" => 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
GitHub.sponsors_by_tier("Homebrew").each do |tier|
|
||||||
|
sponsors["named"] += tier["sponsors"] if tier["tier"] >= 100
|
||||||
|
sponsors["users"] += tier["count"]
|
||||||
|
sponsors["orgs"] += tier["sponsors"].count { |s| s["type"] == "organization" }
|
||||||
|
end
|
||||||
|
|
||||||
|
items = []
|
||||||
|
items += sponsors["named"].map { |s| "[#{s["name"]}](https://github.com/#{s["login"]})" }
|
||||||
|
|
||||||
|
anon_users = sponsors["users"] - sponsors["named"].length - sponsors["orgs"]
|
||||||
|
|
||||||
|
items << if items.length > 1
|
||||||
|
"#{anon_users} other users"
|
||||||
|
else
|
||||||
|
"#{anon_users} users"
|
||||||
|
end
|
||||||
|
|
||||||
|
if sponsors["orgs"] == 1
|
||||||
|
items << "#{sponsors["orgs"]} organization"
|
||||||
|
elsif sponsors["orgs"] > 1
|
||||||
|
items << "#{sponsors["orgs"]} organizations"
|
||||||
|
end
|
||||||
|
|
||||||
|
sponsor_text = if items.length > 2
|
||||||
|
items[0..-2].join(", ") + " and #{items.last}"
|
||||||
|
else
|
||||||
|
items.join(" and ")
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Homebrew is generously supported by #{sponsor_text} via [GitHub Sponsors](https://github.com/sponsors/Homebrew)."
|
||||||
|
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
|
||||||
@ -29,14 +29,7 @@ class KegUnspecifiedError < UsageError
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class MultipleVersionsInstalledError < RuntimeError
|
class MultipleVersionsInstalledError < RuntimeError; end
|
||||||
attr_reader :name
|
|
||||||
|
|
||||||
def initialize(name)
|
|
||||||
@name = name
|
|
||||||
super "#{name} has multiple installed versions"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class NotAKegError < RuntimeError; end
|
class NotAKegError < RuntimeError; 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=
|
||||||
@ -1109,13 +1112,14 @@ class Formula
|
|||||||
return false if tab_tap.nil?
|
return false if tab_tap.nil?
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Formulary.factory(keg.name)
|
f = Formulary.factory(keg.name)
|
||||||
rescue FormulaUnavailableError
|
rescue FormulaUnavailableError
|
||||||
# formula for this keg is deleted, so defer to allowlist
|
# formula for this keg is deleted, so defer to allowlist
|
||||||
rescue TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
|
rescue TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
|
||||||
return false # this keg belongs to another formula
|
return false # this keg belongs to another formula
|
||||||
else
|
else
|
||||||
return false # this keg belongs to another formula
|
# this keg belongs to another unrelated formula
|
||||||
|
return false unless (f.aliases + f.oldname).include?(keg.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
to_check = path.relative_path_from(HOMEBREW_PREFIX).to_s
|
to_check = path.relative_path_from(HOMEBREW_PREFIX).to_s
|
||||||
@ -1687,6 +1691,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 +2216,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 +2660,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
|
||||||
|
|
||||||
|
|||||||
@ -167,7 +167,7 @@ module Language
|
|||||||
def needs_python?(python)
|
def needs_python?(python)
|
||||||
return true if build.with?(python)
|
return true if build.with?(python)
|
||||||
|
|
||||||
(requirements.to_a | deps).any? { |r| r.name == python && r.required? }
|
(requirements.to_a | deps).any? { |r| r.name.split("/").last == python && r.required? }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Helper method for the common case of installing a Python application.
|
# Helper method for the common case of installing a Python application.
|
||||||
|
|||||||
@ -85,6 +85,10 @@ module Homebrew
|
|||||||
cargo is part of the rust formula:
|
cargo is part of the rust formula:
|
||||||
brew install rust
|
brew install rust
|
||||||
EOS
|
EOS
|
||||||
|
when "cargo-completion" then <<~EOS
|
||||||
|
cargo-completion is part of the rust formula:
|
||||||
|
brew install rust
|
||||||
|
EOS
|
||||||
when "uconv" then <<~EOS
|
when "uconv" then <<~EOS
|
||||||
uconv is part of the icu4c formula:
|
uconv is part of the icu4c formula:
|
||||||
brew install icu4c
|
brew install icu4c
|
||||||
|
|||||||
@ -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 }],
|
||||||
|
|||||||
@ -22,18 +22,28 @@ module RuboCop
|
|||||||
Firefox
|
Firefox
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
reason = string_content(parameters(keg_only_node).first)
|
reason = parameters(keg_only_node).first
|
||||||
|
offending_node(reason)
|
||||||
name = Regexp.new(@formula_name, Regexp::IGNORECASE)
|
name = Regexp.new(@formula_name, Regexp::IGNORECASE)
|
||||||
reason = reason.sub(name, "")
|
reason = string_content(reason).sub(name, "")
|
||||||
first_word = reason.split.first
|
first_word = reason.split.first
|
||||||
|
|
||||||
if reason =~ /\A[A-Z]/ && !reason.start_with?(*allowlist)
|
if reason =~ /\A[A-Z]/ && !reason.start_with?(*allowlist)
|
||||||
problem "'#{first_word}' from the keg_only reason should be '#{first_word.downcase}'."
|
problem "'#{first_word}' from the `keg_only` reason should be '#{first_word.downcase}'."
|
||||||
end
|
end
|
||||||
|
|
||||||
return unless reason.end_with?(".")
|
return unless reason.end_with?(".")
|
||||||
|
|
||||||
problem "keg_only reason should not end with a period."
|
problem "`keg_only` reason should not end with a period."
|
||||||
|
end
|
||||||
|
|
||||||
|
def autocorrect(node)
|
||||||
|
lambda do |corrector|
|
||||||
|
reason = string_content(node)
|
||||||
|
reason[0] = reason[0].downcase
|
||||||
|
reason = reason.delete_suffix(".")
|
||||||
|
corrector.replace(node.source_range, "\"#{reason}\"")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -555,6 +555,55 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class ShellCommands < FormulaCop
|
||||||
|
def audit_formula(_node, _class_node, _parent_class_node, body_node)
|
||||||
|
# Match shell commands separated by spaces in the same string
|
||||||
|
shell_cmd_with_spaces_regex = /[^"' ]*(?:\s[^"' ]*)+/
|
||||||
|
|
||||||
|
popen_commands = [
|
||||||
|
:popen_read,
|
||||||
|
:safe_popen_read,
|
||||||
|
:popen_write,
|
||||||
|
:safe_popen_write,
|
||||||
|
]
|
||||||
|
|
||||||
|
shell_metacharacters = %w[> < < | ; : & * $ ? : ~ + @ !` ( ) [ ]]
|
||||||
|
|
||||||
|
find_every_method_call_by_name(body_node, :system).each do |method|
|
||||||
|
# Only separate when no shell metacharacters are present
|
||||||
|
next if shell_metacharacters.any? { |meta| string_content(parameters(method).first).include?(meta) }
|
||||||
|
|
||||||
|
next unless match = regex_match_group(parameters(method).first, shell_cmd_with_spaces_regex)
|
||||||
|
|
||||||
|
good_args = match[0].gsub(" ", "\", \"")
|
||||||
|
offending_node(parameters(method).first)
|
||||||
|
problem "Separate `system` commands into `\"#{good_args}\"`"
|
||||||
|
end
|
||||||
|
|
||||||
|
popen_commands.each do |command|
|
||||||
|
find_instance_method_call(body_node, "Utils", command) do |method|
|
||||||
|
index = parameters(method).first.hash_type? ? 1 : 0
|
||||||
|
|
||||||
|
# Only separate when no shell metacharacters are present
|
||||||
|
next if shell_metacharacters.any? { |meta| string_content(parameters(method)[index]).include?(meta) }
|
||||||
|
|
||||||
|
next unless match = regex_match_group(parameters(method)[index], shell_cmd_with_spaces_regex)
|
||||||
|
|
||||||
|
good_args = match[0].gsub(" ", "\", \"")
|
||||||
|
offending_node(parameters(method)[index])
|
||||||
|
problem "Separate `Utils.#{command}` commands into `\"#{good_args}\"`"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def autocorrect(node)
|
||||||
|
lambda do |corrector|
|
||||||
|
good_args = node.source.gsub(" ", "\", \"")
|
||||||
|
corrector.replace(node.source_range, good_args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -47,12 +47,12 @@ class Sandbox
|
|||||||
end
|
end
|
||||||
|
|
||||||
def allow_cvs
|
def allow_cvs
|
||||||
allow_write_path "/Users/#{ENV["USER"]}/.cvspass"
|
allow_write_path "#{ENV["HOME"]}/.cvspass"
|
||||||
end
|
end
|
||||||
|
|
||||||
def allow_fossil
|
def allow_fossil
|
||||||
allow_write_path "/Users/#{ENV["USER"]}/.fossil"
|
allow_write_path "#{ENV["HOME"]}/.fossil"
|
||||||
allow_write_path "/Users/#{ENV["USER"]}/.fossil-journal"
|
allow_write_path "#{ENV["HOME"]}/.fossil-journal"
|
||||||
end
|
end
|
||||||
|
|
||||||
def allow_write_cellar(formula)
|
def allow_write_cellar(formula)
|
||||||
@ -63,7 +63,7 @@ class Sandbox
|
|||||||
|
|
||||||
# Xcode projects expect access to certain cache/archive dirs.
|
# Xcode projects expect access to certain cache/archive dirs.
|
||||||
def allow_write_xcode
|
def allow_write_xcode
|
||||||
allow_write_path "/Users/#{ENV["USER"]}/Library/Developer"
|
allow_write_path "#{ENV["HOME"]}/Library/Developer"
|
||||||
end
|
end
|
||||||
|
|
||||||
def allow_write_log(formula)
|
def allow_write_log(formula)
|
||||||
|
|||||||
@ -168,6 +168,7 @@ false:
|
|||||||
- ./dev-cmd/test.rb
|
- ./dev-cmd/test.rb
|
||||||
- ./dev-cmd/tests.rb
|
- ./dev-cmd/tests.rb
|
||||||
- ./dev-cmd/unpack.rb
|
- ./dev-cmd/unpack.rb
|
||||||
|
- ./dev-cmd/update-license-data.rb
|
||||||
- ./dev-cmd/update-test.rb
|
- ./dev-cmd/update-test.rb
|
||||||
- ./dev-cmd/vendor-gems.rb
|
- ./dev-cmd/vendor-gems.rb
|
||||||
- ./development_tools.rb
|
- ./development_tools.rb
|
||||||
@ -185,6 +186,7 @@ false:
|
|||||||
- ./extend/os/linux/hardware/cpu.rb
|
- ./extend/os/linux/hardware/cpu.rb
|
||||||
- ./extend/os/linux/install.rb
|
- ./extend/os/linux/install.rb
|
||||||
- ./extend/os/linux/keg_relocate.rb
|
- ./extend/os/linux/keg_relocate.rb
|
||||||
|
- ./extend/os/linux/readall.rb
|
||||||
- ./extend/os/linux/requirements/osxfuse_requirement.rb
|
- ./extend/os/linux/requirements/osxfuse_requirement.rb
|
||||||
- ./extend/os/linux/system_config.rb
|
- ./extend/os/linux/system_config.rb
|
||||||
- ./extend/os/linux/tap.rb
|
- ./extend/os/linux/tap.rb
|
||||||
@ -348,6 +350,7 @@ false:
|
|||||||
- ./test/dev-cmd/audit_spec.rb
|
- ./test/dev-cmd/audit_spec.rb
|
||||||
- ./test/dev-cmd/create_spec.rb
|
- ./test/dev-cmd/create_spec.rb
|
||||||
- ./test/dev-cmd/extract_spec.rb
|
- ./test/dev-cmd/extract_spec.rb
|
||||||
|
- ./test/dev-cmd/update-license-data_spec.rb
|
||||||
- ./test/diagnostic_checks_spec.rb
|
- ./test/diagnostic_checks_spec.rb
|
||||||
- ./test/download_strategies_spec.rb
|
- ./test/download_strategies_spec.rb
|
||||||
- ./test/error_during_execution_spec.rb
|
- ./test/error_during_execution_spec.rb
|
||||||
@ -443,9 +446,9 @@ false:
|
|||||||
- ./unpack_strategy/xar.rb
|
- ./unpack_strategy/xar.rb
|
||||||
- ./unpack_strategy/xz.rb
|
- ./unpack_strategy/xz.rb
|
||||||
- ./unpack_strategy/zip.rb
|
- ./unpack_strategy/zip.rb
|
||||||
|
- ./upgrade.rb
|
||||||
- ./utils.rb
|
- ./utils.rb
|
||||||
- ./utils/analytics.rb
|
- ./utils/analytics.rb
|
||||||
- ./utils/bottles.rb
|
|
||||||
- ./utils/curl.rb
|
- ./utils/curl.rb
|
||||||
- ./utils/fork.rb
|
- ./utils/fork.rb
|
||||||
- ./utils/formatter.rb
|
- ./utils/formatter.rb
|
||||||
@ -453,7 +456,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:
|
||||||
@ -848,8 +850,6 @@ false:
|
|||||||
- ./utils/inreplace.rb
|
- ./utils/inreplace.rb
|
||||||
- ./utils/link.rb
|
- ./utils/link.rb
|
||||||
- ./utils/shebang.rb
|
- ./utils/shebang.rb
|
||||||
- ./utils/shell.rb
|
|
||||||
- ./utils/svn.rb
|
|
||||||
- ./version.rb
|
- ./version.rb
|
||||||
|
|
||||||
true:
|
true:
|
||||||
@ -889,6 +889,10 @@ 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/bottles.rb
|
||||||
|
- ./utils/shell.rb
|
||||||
|
- ./utils/svn.rb
|
||||||
|
- ./utils/tty.rb
|
||||||
- ./version/null.rb
|
- ./version/null.rb
|
||||||
|
|
||||||
strict:
|
strict:
|
||||||
@ -920,6 +924,7 @@ strict:
|
|||||||
- ./extend/os/mac/formula_support.rb
|
- ./extend/os/mac/formula_support.rb
|
||||||
- ./extend/os/missing_formula.rb
|
- ./extend/os/missing_formula.rb
|
||||||
- ./extend/os/pathname.rb
|
- ./extend/os/pathname.rb
|
||||||
|
- ./extend/os/readall.rb
|
||||||
- ./extend/os/requirements/java_requirement.rb
|
- ./extend/os/requirements/java_requirement.rb
|
||||||
- ./extend/os/requirements/osxfuse_requirement.rb
|
- ./extend/os/requirements/osxfuse_requirement.rb
|
||||||
- ./extend/os/requirements/x11_requirement.rb
|
- ./extend/os/requirements/x11_requirement.rb
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
|
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
|
||||||
# tapioca sync
|
# tapioca sync --exclude json
|
||||||
|
|
||||||
# typed: true
|
# typed: true
|
||||||
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
|
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
|
||||||
# tapioca sync
|
# tapioca sync --exclude json
|
||||||
|
|
||||||
# typed: true
|
# typed: true
|
||||||
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
|
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
|
||||||
# tapioca sync
|
# tapioca sync --exclude json
|
||||||
|
|
||||||
# typed: true
|
# typed: true
|
||||||
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
|
|
||||||
# tapioca sync
|
|
||||||
|
|
||||||
# typed: true
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
|
|
||||||
# tapioca sync
|
|
||||||
|
|
||||||
# typed: true
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
|
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
|
||||||
# tapioca sync
|
# tapioca sync --exclude json
|
||||||
|
|
||||||
# typed: true
|
# typed: true
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
38
Library/Homebrew/sorbet/rbi/utils/shell.rbi
Normal file
38
Library/Homebrew/sorbet/rbi/utils/shell.rbi
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# typed: strict
|
||||||
|
|
||||||
|
module Utils::Shell
|
||||||
|
include Kernel
|
||||||
|
|
||||||
|
sig{ params(path: String).returns(T.nilable(Symbol)) }
|
||||||
|
def from_path(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
sig{ returns(T.nilable(Symbol)) }
|
||||||
|
def preferred
|
||||||
|
end
|
||||||
|
|
||||||
|
def parent
|
||||||
|
end
|
||||||
|
|
||||||
|
def export_value(key, value, shell = preferred)
|
||||||
|
end
|
||||||
|
|
||||||
|
sig{ returns(String) }
|
||||||
|
def profile
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_variable_in_profile(variable, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
sig{ params(path: String).returns(T.nilable(String)) }
|
||||||
|
def prepend_path_in_profile(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
sig{ params(str: String).returns(T.nilable(String)) }
|
||||||
|
def csh_quote(str)
|
||||||
|
end
|
||||||
|
|
||||||
|
sig{ params(str: String).returns(T.nilable(String)) }
|
||||||
|
def sh_quote(str)
|
||||||
|
end
|
||||||
|
end
|
||||||
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
|
||||||
8
Library/Homebrew/sorbet/rbi/utils/utils.rbi
Normal file
8
Library/Homebrew/sorbet/rbi/utils/utils.rbi
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# typed: strict
|
||||||
|
|
||||||
|
module Utils
|
||||||
|
include Kernel
|
||||||
|
|
||||||
|
class Bottles
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -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
|
||||||
@ -277,6 +363,7 @@ module Homebrew
|
|||||||
origin_formula_path.write <<~RUBY
|
origin_formula_path.write <<~RUBY
|
||||||
class Foo#{foo_version} < Formula
|
class Foo#{foo_version} < Formula
|
||||||
url "https://brew.sh/foo-1.0.tar.gz"
|
url "https://brew.sh/foo-1.0.tar.gz"
|
||||||
|
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
|
||||||
revision 2
|
revision 2
|
||||||
version_scheme 1
|
version_scheme 1
|
||||||
end
|
end
|
||||||
@ -302,7 +389,7 @@ module Homebrew
|
|||||||
formula_path.write text
|
formula_path.write text
|
||||||
end
|
end
|
||||||
|
|
||||||
def formula_gsub_commit(before, after = "")
|
def formula_gsub_origin_commit(before, after = "")
|
||||||
text = origin_formula_path.read
|
text = origin_formula_path.read
|
||||||
text.gsub!(before, after)
|
text.gsub!(before, after)
|
||||||
origin_formula_path.unlink
|
origin_formula_path.unlink
|
||||||
@ -318,19 +405,48 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "checksums" do
|
||||||
|
context "should not change with the same version" do
|
||||||
|
before do
|
||||||
|
formula_gsub(
|
||||||
|
'sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"',
|
||||||
|
'sha256 "3622d2a53236ed9ca62de0616a7e80fd477a9a3f862ba09d503da188f53ca523"',
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to match("stable sha256 changed without the version also changing") }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "can change with the different version" do
|
||||||
|
before do
|
||||||
|
formula_gsub_origin_commit(
|
||||||
|
'sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"',
|
||||||
|
'sha256 "3622d2a53236ed9ca62de0616a7e80fd477a9a3f862ba09d503da188f53ca523"',
|
||||||
|
)
|
||||||
|
formula_gsub "foo-1.0.tar.gz", "foo-1.1.tar.gz"
|
||||||
|
formula_gsub_origin_commit(
|
||||||
|
'sha256 "3622d2a53236ed9ca62de0616a7e80fd477a9a3f862ba09d503da188f53ca523"',
|
||||||
|
'sha256 "e048c5e6144f5932d8672c2fade81d9073d5b3ca1517b84df006de3d25414fc1"',
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "revisions" do
|
context "revisions" do
|
||||||
context "should not be removed when first committed above 0" do
|
context "should not be removed when first committed above 0" do
|
||||||
it { is_expected.to be_nil }
|
it { is_expected.to be_nil }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "should not decrease with the same version" do
|
context "should not decrease with the same version" do
|
||||||
before { formula_gsub_commit "revision 2", "revision 1" }
|
before { formula_gsub_origin_commit "revision 2", "revision 1" }
|
||||||
|
|
||||||
it { is_expected.to match("revision should not decrease (from 2 to 1)") }
|
it { is_expected.to match("revision should not decrease (from 2 to 1)") }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "should not be removed with the same version" do
|
context "should not be removed with the same version" do
|
||||||
before { formula_gsub_commit "revision 2" }
|
before { formula_gsub_origin_commit "revision 2" }
|
||||||
|
|
||||||
it { is_expected.to match("revision should not decrease (from 2 to 0)") }
|
it { is_expected.to match("revision should not decrease (from 2 to 0)") }
|
||||||
end
|
end
|
||||||
@ -342,15 +458,15 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
context "should be removed with a newer version" do
|
context "should be removed with a newer version" do
|
||||||
before { formula_gsub_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz" }
|
before { formula_gsub_origin_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz" }
|
||||||
|
|
||||||
it { is_expected.to match("'revision 2' should be removed") }
|
it { is_expected.to match("'revision 2' should be removed") }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "should not warn on an newer version revision removal" do
|
context "should not warn on an newer version revision removal" do
|
||||||
before do
|
before do
|
||||||
formula_gsub_commit "revision 2", ""
|
formula_gsub_origin_commit "revision 2", ""
|
||||||
formula_gsub_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
|
formula_gsub_origin_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to be_nil }
|
it { is_expected.to be_nil }
|
||||||
@ -367,9 +483,9 @@ module Homebrew
|
|||||||
|
|
||||||
context "should not warn on past increment by more than 1" do
|
context "should not warn on past increment by more than 1" do
|
||||||
before do
|
before do
|
||||||
formula_gsub_commit "revision 2", "# no revision"
|
formula_gsub_origin_commit "revision 2", "# no revision"
|
||||||
formula_gsub_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
|
formula_gsub_origin_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
|
||||||
formula_gsub_commit "# no revision", "revision 3"
|
formula_gsub_origin_commit "# no revision", "revision 3"
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to be_nil }
|
it { is_expected.to be_nil }
|
||||||
@ -378,16 +494,16 @@ module Homebrew
|
|||||||
|
|
||||||
context "version_schemes" do
|
context "version_schemes" do
|
||||||
context "should not decrease with the same version" do
|
context "should not decrease with the same version" do
|
||||||
before { formula_gsub_commit "version_scheme 1" }
|
before { formula_gsub_origin_commit "version_scheme 1" }
|
||||||
|
|
||||||
it { is_expected.to match("version_scheme should not decrease (from 1 to 0)") }
|
it { is_expected.to match("version_scheme should not decrease (from 1 to 0)") }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "should not decrease with a new version" do
|
context "should not decrease with a new version" do
|
||||||
before do
|
before do
|
||||||
formula_gsub_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
|
formula_gsub_origin_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
|
||||||
formula_gsub_commit "version_scheme 1", ""
|
formula_gsub_origin_commit "version_scheme 1", ""
|
||||||
formula_gsub_commit "revision 2", ""
|
formula_gsub_origin_commit "revision 2", ""
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to match("version_scheme should not decrease (from 1 to 0)") }
|
it { is_expected.to match("version_scheme should not decrease (from 1 to 0)") }
|
||||||
@ -395,10 +511,10 @@ module Homebrew
|
|||||||
|
|
||||||
context "should only increment by 1" do
|
context "should only increment by 1" do
|
||||||
before do
|
before do
|
||||||
formula_gsub_commit "version_scheme 1", "# no version_scheme"
|
formula_gsub_origin_commit "version_scheme 1", "# no version_scheme"
|
||||||
formula_gsub_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
|
formula_gsub_origin_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
|
||||||
formula_gsub_commit "revision 2", ""
|
formula_gsub_origin_commit "revision 2", ""
|
||||||
formula_gsub_commit "# no version_scheme", "version_scheme 3"
|
formula_gsub_origin_commit "# no version_scheme", "version_scheme 3"
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to match("version_schemes should only increment by 1") }
|
it { is_expected.to match("version_schemes should only increment by 1") }
|
||||||
@ -414,8 +530,8 @@ module Homebrew
|
|||||||
|
|
||||||
context "committed can decrease" do
|
context "committed can decrease" do
|
||||||
before do
|
before do
|
||||||
formula_gsub_commit "revision 2"
|
formula_gsub_origin_commit "revision 2"
|
||||||
formula_gsub_commit "foo-1.0.tar.gz", "foo-0.9.tar.gz"
|
formula_gsub_origin_commit "foo-1.0.tar.gz", "foo-0.9.tar.gz"
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to be_nil }
|
it { is_expected.to be_nil }
|
||||||
|
|||||||
7
Library/Homebrew/test/dev-cmd/sponsors_spec.rb
Normal file
7
Library/Homebrew/test/dev-cmd/sponsors_spec.rb
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "cmd/shared_examples/args_parse"
|
||||||
|
|
||||||
|
describe "Homebrew.sponsors_args" do
|
||||||
|
it_behaves_like "parseable arguments"
|
||||||
|
end
|
||||||
@ -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
|
||||||
@ -3,7 +3,7 @@
|
|||||||
require "exceptions"
|
require "exceptions"
|
||||||
|
|
||||||
describe MultipleVersionsInstalledError do
|
describe MultipleVersionsInstalledError do
|
||||||
subject { described_class.new("foo") }
|
subject { described_class.new("foo has multiple installed versions") }
|
||||||
|
|
||||||
its(:to_s) { is_expected.to eq("foo has multiple installed versions") }
|
its(:to_s) { is_expected.to eq("foo has multiple installed versions") }
|
||||||
end
|
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
|
||||||
|
|||||||
@ -13,7 +13,7 @@ describe RuboCop::Cop::FormulaAudit::KegOnly do
|
|||||||
homepage "https://brew.sh"
|
homepage "https://brew.sh"
|
||||||
|
|
||||||
keg_only "Because why not"
|
keg_only "Because why not"
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^ 'Because' from the keg_only reason should be 'because'.
|
^^^^^^^^^^^^^^^^^ 'Because' from the `keg_only` reason should be 'because'.
|
||||||
end
|
end
|
||||||
RUBY
|
RUBY
|
||||||
end
|
end
|
||||||
@ -25,11 +25,53 @@ describe RuboCop::Cop::FormulaAudit::KegOnly do
|
|||||||
homepage "https://brew.sh"
|
homepage "https://brew.sh"
|
||||||
|
|
||||||
keg_only "ending with a period."
|
keg_only "ending with a period."
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ keg_only reason should not end with a period.
|
^^^^^^^^^^^^^^^^^^^^^^^ `keg_only` reason should not end with a period.
|
||||||
end
|
end
|
||||||
RUBY
|
RUBY
|
||||||
end
|
end
|
||||||
|
|
||||||
|
specify "keg_only_autocorrects_downcasing" do
|
||||||
|
source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
url "https://brew.sh/foo-1.0.tgz"
|
||||||
|
homepage "https://brew.sh"
|
||||||
|
keg_only "Because why not"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
corrected_source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
url "https://brew.sh/foo-1.0.tgz"
|
||||||
|
homepage "https://brew.sh"
|
||||||
|
keg_only "because why not"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
new_source = autocorrect_source(source)
|
||||||
|
expect(new_source).to eq(corrected_source)
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "keg_only_autocorrects_redundant_period" do
|
||||||
|
source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
url "https://brew.sh/foo-1.0.tgz"
|
||||||
|
homepage "https://brew.sh"
|
||||||
|
keg_only "ending with a period."
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
corrected_source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
url "https://brew.sh/foo-1.0.tgz"
|
||||||
|
homepage "https://brew.sh"
|
||||||
|
keg_only "ending with a period"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
new_source = autocorrect_source(source)
|
||||||
|
expect(new_source).to eq(corrected_source)
|
||||||
|
end
|
||||||
|
|
||||||
specify "keg_only_handles_block_correctly" do
|
specify "keg_only_handles_block_correctly" do
|
||||||
expect_no_offenses(<<~RUBY)
|
expect_no_offenses(<<~RUBY)
|
||||||
class Foo < Formula
|
class Foo < Formula
|
||||||
|
|||||||
@ -1096,3 +1096,252 @@ describe RuboCop::Cop::FormulaAuditStrict::MakeCheck do
|
|||||||
|
|
||||||
include_examples "formulae exist", described_class::MAKE_CHECK_ALLOWLIST
|
include_examples "formulae exist", described_class::MAKE_CHECK_ALLOWLIST
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe RuboCop::Cop::FormulaAuditStrict::ShellCommands do
|
||||||
|
subject(:cop) { described_class.new }
|
||||||
|
|
||||||
|
context "When auditing shell commands" do
|
||||||
|
it "system arguments should be separated" do
|
||||||
|
expect_offense(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
system "foo bar"
|
||||||
|
^^^^^^^^^ Separate `system` commands into `\"foo\", \"bar\"`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "system arguments with string interpolation should be separated" do
|
||||||
|
expect_offense(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
system "\#{bin}/foo bar"
|
||||||
|
^^^^^^^^^^^^^^^^ Separate `system` commands into `\"\#{bin}/foo\", \"bar\"`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "system arguments with metacharacters should not be separated" do
|
||||||
|
expect_no_offenses(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
system "foo bar > baz"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "only the first system argument should be separated" do
|
||||||
|
expect_no_offenses(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
system "foo", "bar baz"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Utils.popen arguments should not be separated" do
|
||||||
|
expect_no_offenses(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen("foo bar")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Utils.popen_read arguments should be separated" do
|
||||||
|
expect_offense(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read("foo bar")
|
||||||
|
^^^^^^^^^ Separate `Utils.popen_read` commands into `\"foo\", \"bar\"`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Utils.safe_popen_read arguments should be separated" do
|
||||||
|
expect_offense(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.safe_popen_read("foo bar")
|
||||||
|
^^^^^^^^^ Separate `Utils.safe_popen_read` commands into `\"foo\", \"bar\"`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Utils.popen_write arguments should be separated" do
|
||||||
|
expect_offense(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_write("foo bar")
|
||||||
|
^^^^^^^^^ Separate `Utils.popen_write` commands into `\"foo\", \"bar\"`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Utils.safe_popen_write arguments should be separated" do
|
||||||
|
expect_offense(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.safe_popen_write("foo bar")
|
||||||
|
^^^^^^^^^ Separate `Utils.safe_popen_write` commands into `\"foo\", \"bar\"`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Utils.popen_read arguments with string interpolation should be separated" do
|
||||||
|
expect_offense(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read("\#{bin}/foo bar")
|
||||||
|
^^^^^^^^^^^^^^^^ Separate `Utils.popen_read` commands into `\"\#{bin}/foo\", \"bar\"`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Utils.popen_read arguments with metacharacters should not be separated" do
|
||||||
|
expect_no_offenses(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read("foo bar > baz")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "only the first Utils.popen_read argument should be separated" do
|
||||||
|
expect_no_offenses(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read("foo", "bar baz")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Utils.popen_read arguments should be separated following a shell variable" do
|
||||||
|
expect_offense(<<~RUBY)
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read({ "SHELL" => "bash"}, "foo bar")
|
||||||
|
^^^^^^^^^ Separate `Utils.popen_read` commands into `\"foo\", \"bar\"`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
it "separates shell commands in system" do
|
||||||
|
source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
system "foo bar"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
corrected_source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
system "foo", "bar"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
new_source = autocorrect_source(source)
|
||||||
|
expect(new_source).to eq(corrected_source)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "separates shell commands with string interpolation in system" do
|
||||||
|
source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
system "\#{foo}/bar baz"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
corrected_source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
system "\#{foo}/bar", "baz"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
new_source = autocorrect_source(source)
|
||||||
|
expect(new_source).to eq(corrected_source)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "separates shell commands in Utils.popen_read" do
|
||||||
|
source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read("foo bar")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
corrected_source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read("foo", "bar")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
new_source = autocorrect_source(source)
|
||||||
|
expect(new_source).to eq(corrected_source)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "separates shell commands with string interpolation in Utils.popen_read" do
|
||||||
|
source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read("\#{foo}/bar baz")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
corrected_source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read("\#{foo}/bar", "baz")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
new_source = autocorrect_source(source)
|
||||||
|
expect(new_source).to eq(corrected_source)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "separates shell commands following a shell variable in Utils.popen_read" do
|
||||||
|
source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read({ "SHELL" => "bash" }, "foo bar")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
corrected_source = <<~RUBY
|
||||||
|
class Foo < Formula
|
||||||
|
def install
|
||||||
|
Utils.popen_read({ "SHELL" => "bash" }, "foo", "bar")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
new_source = autocorrect_source(source)
|
||||||
|
expect(new_source).to eq(corrected_source)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@ -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,21 @@ 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 "::sponsors_by_tier", :needs_network do
|
||||||
|
it "errors on an unauthenticated token" do
|
||||||
|
expect {
|
||||||
|
subject.sponsors_by_tier("Homebrew")
|
||||||
|
}.to raise_error(/INSUFFICIENT_SCOPES|FORBIDDEN/)
|
||||||
|
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|
|
||||||
|
installed_formulae.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
|
||||||
|
|||||||
@ -231,6 +231,15 @@ module GitHub
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def open_graphql(query, scopes: [].freeze)
|
||||||
|
data = { query: query }
|
||||||
|
result = open_api("https://api.github.com/graphql", scopes: scopes, data: data, request_method: "POST")
|
||||||
|
|
||||||
|
raise Error, result["errors"].map { |e| "#{e["type"]}: #{e["message"]}" }.join("\n") if result["errors"].present?
|
||||||
|
|
||||||
|
result["data"]
|
||||||
|
end
|
||||||
|
|
||||||
def raise_api_error(output, errors, http_code, headers, scopes)
|
def raise_api_error(output, errors, http_code, headers, scopes)
|
||||||
json = begin
|
json = begin
|
||||||
JSON.parse(output)
|
JSON.parse(output)
|
||||||
@ -429,6 +438,48 @@ 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)
|
||||||
|
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_graphql(query, scopes: ["user:email"])
|
||||||
|
reviews = result["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 },
|
||||||
@ -484,20 +535,21 @@ module GitHub
|
|||||||
end
|
end
|
||||||
|
|
||||||
def sponsors_by_tier(user)
|
def sponsors_by_tier(user)
|
||||||
url = "https://api.github.com/graphql"
|
query = <<~EOS
|
||||||
data = {
|
{ organization(login: "#{user}") {
|
||||||
query: <<~EOS,
|
sponsorsListing {
|
||||||
{
|
tiers(first: 10, orderBy: {field: MONTHLY_PRICE_IN_CENTS, direction: DESC}) {
|
||||||
organization(login: "#{user}") {
|
nodes {
|
||||||
sponsorsListing {
|
monthlyPriceInDollars
|
||||||
tiers(first: 100) {
|
adminInfo {
|
||||||
nodes {
|
sponsorships(first: 100, includePrivate: true) {
|
||||||
monthlyPriceInDollars
|
totalCount
|
||||||
adminInfo {
|
nodes {
|
||||||
sponsorships(first: 100) {
|
privacyLevel
|
||||||
totalCount
|
sponsorEntity {
|
||||||
nodes {
|
__typename
|
||||||
sponsor { login }
|
... on Organization { login name }
|
||||||
|
... on User { login name }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,9 +558,44 @@ module GitHub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOS
|
}
|
||||||
}
|
EOS
|
||||||
open_api(url, scopes: ["admin:org", "user"], data: data, request_method: "POST")
|
result = open_graphql(query, scopes: ["admin:org", "user"])
|
||||||
|
|
||||||
|
tiers = result["organization"]["sponsorsListing"]["tiers"]["nodes"]
|
||||||
|
|
||||||
|
tiers.map do |t|
|
||||||
|
tier = t["monthlyPriceInDollars"]
|
||||||
|
raise Error, "Your token needs the 'admin:org' scope to access this API" if t["adminInfo"].nil?
|
||||||
|
|
||||||
|
sponsorships = t["adminInfo"]["sponsorships"]
|
||||||
|
count = sponsorships["totalCount"]
|
||||||
|
sponsors = sponsorships["nodes"].map do |sponsor|
|
||||||
|
next unless sponsor["privacyLevel"] == "PUBLIC"
|
||||||
|
|
||||||
|
se = sponsor["sponsorEntity"]
|
||||||
|
{
|
||||||
|
"name" => se["name"].presence || sponsor["login"],
|
||||||
|
"login" => se["login"],
|
||||||
|
"type" => se["__typename"].downcase,
|
||||||
|
}
|
||||||
|
end.compact
|
||||||
|
|
||||||
|
{
|
||||||
|
"tier" => tier,
|
||||||
|
"count" => count,
|
||||||
|
"sponsors" => sponsors,
|
||||||
|
}
|
||||||
|
end.compact
|
||||||
|
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
|
end
|
||||||
|
|
||||||
def api_errors
|
def api_errors
|
||||||
|
|||||||
21
Library/Homebrew/vendor/bundle/bundler/setup.rb
vendored
21
Library/Homebrew/vendor/bundle/bundler/setup.rb
vendored
@ -14,18 +14,15 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.1/lib"
|
|||||||
$:.unshift "#{path}/"
|
$:.unshift "#{path}/"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/byebug-11.1.3"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/byebug-11.1.3"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/byebug-11.1.3/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/byebug-11.1.3/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/connection_pool-2.2.3/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/json-2.3.1"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/json-2.3.0"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/json-2.3.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/json-2.3.0/lib"
|
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/docile-1.3.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/docile-1.3.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/simplecov-html-0.10.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/simplecov-html-0.12.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/simplecov-0.16.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/simplecov-0.18.5/lib"
|
||||||
$:.unshift "#{path}/../../../../../../../../Library/Ruby/Gems/2.6.0/gems/sync-0.5.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/url-0.3.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tins-1.25.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/codecov-0.1.17/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/term-ansicolor-1.7.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/connection_pool-2.2.3/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.0.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/diff-lcs-1.4.4/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/coveralls-0.8.23/lib"
|
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/diff-lcs-1.4.2/lib"
|
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/unf_ext-0.0.7.7"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/unf_ext-0.0.7.7"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf_ext-0.0.7.7/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf_ext-0.0.7.7/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf-0.1.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf-0.1.4/lib"
|
||||||
@ -67,5 +64,5 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10
|
|||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.86.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.86.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.6.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.6.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.40.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.41.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.0/lib"
|
||||||
|
|||||||
@ -1,87 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module RSpec
|
|
||||||
# Wrapper for RSpec example groups
|
|
||||||
class ExampleGroup < Concept
|
|
||||||
# @!method scope_change?(node)
|
|
||||||
#
|
|
||||||
# Detect if the node is an example group or shared example
|
|
||||||
#
|
|
||||||
# Selectors which indicate that we should stop searching
|
|
||||||
#
|
|
||||||
def_node_matcher :scope_change?, (
|
|
||||||
ExampleGroups::ALL + SharedGroups::ALL + Includes::ALL
|
|
||||||
).block_pattern
|
|
||||||
|
|
||||||
def subjects
|
|
||||||
subjects_in_scope(node)
|
|
||||||
end
|
|
||||||
|
|
||||||
def examples
|
|
||||||
examples_in_scope(node).map(&Example.public_method(:new))
|
|
||||||
end
|
|
||||||
|
|
||||||
def hooks
|
|
||||||
hooks_in_scope(node).map(&Hook.public_method(:new))
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def subjects_in_scope(node)
|
|
||||||
node.each_child_node.flat_map do |child|
|
|
||||||
find_subjects(child)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_subjects(node)
|
|
||||||
return [] if scope_change?(node)
|
|
||||||
|
|
||||||
if subject?(node)
|
|
||||||
[node]
|
|
||||||
else
|
|
||||||
subjects_in_scope(node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def hooks_in_scope(node)
|
|
||||||
node.each_child_node.flat_map do |child|
|
|
||||||
find_hooks(child)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_hooks(node)
|
|
||||||
return [] if scope_change?(node) || example?(node)
|
|
||||||
|
|
||||||
if hook?(node)
|
|
||||||
[node]
|
|
||||||
else
|
|
||||||
hooks_in_scope(node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def examples_in_scope(node, &blk)
|
|
||||||
node.each_child_node.flat_map do |child|
|
|
||||||
find_examples(child, &blk)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Recursively search for examples within the current scope
|
|
||||||
#
|
|
||||||
# Searches node for examples and halts when a scope change is detected
|
|
||||||
#
|
|
||||||
# @param node [RuboCop::Node] node to recursively search for examples
|
|
||||||
#
|
|
||||||
# @return [Array<RuboCop::Node>] discovered example nodes
|
|
||||||
def find_examples(node)
|
|
||||||
return [] if scope_change?(node)
|
|
||||||
|
|
||||||
if example?(node)
|
|
||||||
[node]
|
|
||||||
else
|
|
||||||
examples_in_scope(node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -13,6 +13,7 @@ require_relative 'rubocop/rspec/top_level_describe'
|
|||||||
require_relative 'rubocop/rspec/wording'
|
require_relative 'rubocop/rspec/wording'
|
||||||
require_relative 'rubocop/rspec/language'
|
require_relative 'rubocop/rspec/language'
|
||||||
require_relative 'rubocop/rspec/language/node_pattern'
|
require_relative 'rubocop/rspec/language/node_pattern'
|
||||||
|
require_relative 'rubocop/rspec/top_level_group'
|
||||||
require_relative 'rubocop/rspec/concept'
|
require_relative 'rubocop/rspec/concept'
|
||||||
require_relative 'rubocop/rspec/example_group'
|
require_relative 'rubocop/rspec/example_group'
|
||||||
require_relative 'rubocop/rspec/example'
|
require_relative 'rubocop/rspec/example'
|
||||||
@ -43,12 +43,14 @@ module RuboCop
|
|||||||
def_node_matcher :rails_metadata?, <<-PATTERN
|
def_node_matcher :rails_metadata?, <<-PATTERN
|
||||||
(pair
|
(pair
|
||||||
(sym :type)
|
(sym :type)
|
||||||
(sym {:request :feature :system :routing :view})
|
(sym {
|
||||||
|
:channel :controller :helper :job :mailer :model :request
|
||||||
|
:routing :view :feature :system :mailbox
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def_node_matcher :shared_group?, SharedGroups::ALL.block_pattern
|
|
||||||
|
|
||||||
def on_top_level_describe(node, (described_value, _))
|
def on_top_level_describe(node, (described_value, _))
|
||||||
return if shared_group?(root_node)
|
return if shared_group?(root_node)
|
||||||
return if valid_describe?(node)
|
return if valid_describe?(node)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user