Merge pull request #7328 from MikeMcQuaid/keg_only_tweaks

keg_only tweaks
This commit is contained in:
Mike McQuaid 2020-04-12 14:39:47 +01:00 committed by GitHub
commit 793407a2e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 163 additions and 110 deletions

View File

@ -68,10 +68,10 @@ module Homebrew
if keg_only if keg_only
if Homebrew.default_prefix? if Homebrew.default_prefix?
f = keg.to_formula f = keg.to_formula
if f.keg_only_reason.reason == :provided_by_macos if f.keg_only_reason.reason.by_macos?
caveats = Caveats.new(f) caveats = Caveats.new(f)
opoo <<~EOS opoo <<~EOS
Refusing to link macOS-provided software: #{keg.name} Refusing to link macOS provided/shadowed software: #{keg.name}
#{caveats.keg_only_text(skip_reason: true).strip} #{caveats.keg_only_text(skip_reason: true).strip}
EOS EOS
next next

View File

@ -364,6 +364,13 @@ module Homebrew
problem "Formula name conflicts with existing core formula." problem "Formula name conflicts with existing core formula."
end end
USES_FROM_MACOS_WHITELIST = %w[
apr
apr-util
openblas
openssl@1.1
].freeze
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.
@ -396,9 +403,9 @@ module Homebrew
end end
if @new_formula && if @new_formula &&
dep_f.keg_only_reason&.reason == :provided_by_macos && dep_f.keg_only_reason.provided_by_macos? &&
dep_f.keg_only_reason.valid? && dep_f.keg_only_reason.applicable? &&
!%w[apr apr-util openblas openssl openssl@1.1].include?(dep.name) !USES_FROM_MACOS_WHITELIST.include?(dep.name)
new_formula_problem( new_formula_problem(
"Dependency '#{dep.name}' is provided by macOS; " \ "Dependency '#{dep.name}' is provided by macOS; " \
"please replace 'depends_on' with 'uses_from_macos'.", "please replace 'depends_on' with 'uses_from_macos'.",
@ -502,28 +509,28 @@ module Homebrew
end end
end end
VERSIONED_KEG_ONLY_WHITELIST = %w[
autoconf@2.13
bash-completion@2
gnupg@1.4
lua@5.1
numpy@1.16
libsigc++@2
].freeze
def audit_versioned_keg_only def audit_versioned_keg_only
return unless @versioned_formula return unless @versioned_formula
return unless @core_tap return unless @core_tap
if formula.keg_only? if formula.keg_only?
return if formula.keg_only_reason.reason == :versioned_formula return if formula.keg_only_reason.versioned_formula?
if formula.name.start_with?("openssl", "libressl") && if formula.name.start_with?("openssl", "libressl") &&
formula.keg_only_reason.reason == :provided_by_macos formula.keg_only_reason.provided_by_macos?
return return
end end
end end
keg_only_whitelist = %w[ return if VERSIONED_KEG_ONLY_WHITELIST.include?(formula.name) || formula.name.start_with?("gcc@")
autoconf@2.13
bash-completion@2
gnupg@1.4
lua@5.1
numpy@1.16
libsigc++@2
].freeze
return if keg_only_whitelist.include?(formula.name) || formula.name.start_with?("gcc@")
problem "Versioned formulae in homebrew/core should use `keg_only :versioned_formula`" problem "Versioned formulae in homebrew/core should use `keg_only :versioned_formula`"
end end
@ -661,6 +668,47 @@ module Homebrew
[user, repo] [user, repo]
end end
VERSIONED_HEAD_SPEC_WHITELIST = %w[
bash-completion@2
imagemagick@6
].freeze
THROTTLED_BLACKLIST = {
"aws-sdk-cpp" => "10",
"awscli@1" => "10",
"quicktype" => "10",
"vim" => "50",
}.freeze
UNSTABLE_WHITELIST = {
"aalib" => "1.4rc",
"automysqlbackup" => "3.0-rc",
"aview" => "1.3.0rc",
"elm-format" => "0.6.0-alpha",
"ftgl" => "2.1.3-rc",
"hidapi" => "0.8.0-rc",
"libcaca" => "0.99b",
"premake" => "4.4-beta",
"pwnat" => "0.3-beta",
"recode" => "3.7-beta",
"speexdsp" => "1.2rc",
"sqoop" => "1.4.",
"tcptraceroute" => "1.5beta",
"tiny-fugue" => "5.0b",
"vbindiff" => "3.0_beta",
}.freeze
GNOME_DEVEL_WHITELIST = {
"libart" => "2.3",
"gtk-mac-integration" => "2.1",
"gtk-doc" => "1.31",
"gcab" => "1.3",
"libepoxy" => "1.5",
}.freeze
# version_prefix = stable_version_string.sub(/\d+$/, "")
# version_prefix = stable_version_string.split(".")[0..1].join(".")
def audit_specs def audit_specs
problem "Head-only (no stable download)" if head_only?(formula) problem "Head-only (no stable download)" if head_only?(formula)
problem "Devel-only (no stable download)" if devel_only?(formula) problem "Devel-only (no stable download)" if devel_only?(formula)
@ -714,60 +762,18 @@ module Homebrew
if formula.head && @versioned_formula if formula.head && @versioned_formula
head_spec_message = "Formulae should not have a `HEAD` spec" head_spec_message = "Formulae should not have a `HEAD` spec"
versioned_head_spec = %w[ problem head_spec_message unless VERSIONED_HEAD_SPEC_WHITELIST.include?(formula.name)
bash-completion@2
imagemagick@6
]
problem head_spec_message unless versioned_head_spec.include?(formula.name)
end end
throttled = %w[ THROTTLED_BLACKLIST.each do |f, v|
aws-sdk-cpp 10
awscli@1 10
quicktype 10
vim 50
]
throttled.each_slice(2).to_a.map do |a, b|
next if formula.stable.nil? next if formula.stable.nil?
version = formula.stable.version.to_s.split(".").last.to_i version = formula.stable.version.to_s.split(".").last.to_i
if a == formula.name && version.modulo(b.to_i).nonzero? if f == formula.name && version.modulo(v.to_i).nonzero?
problem "should only be updated every #{b} releases on multiples of #{b}" problem "should only be updated every #{v} releases on multiples of #{v}"
end end
end end
unstable_whitelist = %w[
aalib 1.4rc5
automysqlbackup 3.0-rc6
aview 1.3.0rc1
elm-format 0.6.0-alpha
ftgl 2.1.3-rc5
hidapi 0.8.0-rc1
libcaca 0.99b19
premake 4.4-beta5
pwnat 0.3-beta
recode 3.7-beta2
speexdsp 1.2rc3
sqoop 1.4.6
tcptraceroute 1.5beta7
tiny-fugue 5.0b8
vbindiff 3.0_beta4
].each_slice(2).to_a.map do |formula, version|
[formula, version.sub(/\d+$/, "")]
end
gnome_devel_whitelist = %w[
libart 2.3.21
pygtkglext 1.1.0
gtk-mac-integration 2.1.3
gtk-doc 1.31
gcab 1.3
libepoxy 1.5.4
].each_slice(2).to_a.map do |formula, version|
[formula, version.split(".")[0..1].join(".")]
end
stable = formula.stable stable = formula.stable
return unless stable return unless stable
return unless stable.url return unless stable.url
@ -782,12 +788,12 @@ module Homebrew
when /[\d\._-](alpha|beta|rc\d)/ when /[\d\._-](alpha|beta|rc\d)/
matched = Regexp.last_match(1) matched = Regexp.last_match(1)
version_prefix = stable_version_string.sub(/\d+$/, "") version_prefix = stable_version_string.sub(/\d+$/, "")
return if unstable_whitelist.include?([formula.name, version_prefix]) return if UNSTABLE_WHITELIST[formula.name] == version_prefix
problem "Stable version URLs should not contain #{matched}" problem "Stable version URLs should not contain #{matched}"
when %r{download\.gnome\.org/sources}, %r{ftp\.gnome\.org/pub/GNOME/sources}i when %r{download\.gnome\.org/sources}, %r{ftp\.gnome\.org/pub/GNOME/sources}i
version_prefix = stable_version_string.split(".")[0..1].join(".") version_prefix = stable_version_string.split(".")[0..1].join(".")
return if gnome_devel_whitelist.include?([formula.name, version_prefix]) return if GNOME_DEVEL_WHITELIST[formula.name] == version_prefix
return if stable_url_version < Version.create("1.0") return if stable_url_version < Version.create("1.0")
return if stable_url_minor_version.even? return if stable_url_minor_version.even?

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class KegOnlyReason class KegOnlyReason
def valid? def applicable?
true true
end end
end end

View File

@ -1045,7 +1045,7 @@ class Formula
def keg_only? def keg_only?
return false unless keg_only_reason return false unless keg_only_reason
keg_only_reason.valid? keg_only_reason.applicable?
end end
# @private # @private

View File

@ -13,24 +13,41 @@ class KegOnlyReason
@explanation = explanation @explanation = explanation
end end
def valid? def versioned_formula?
![:provided_by_macos, :provided_by_osx, :shadowed_by_macos].include?(@reason) @reason == :versioned_formula
end
def provided_by_macos?
@reason == :provided_by_macos
end
def shadowed_by_macos?
@reason == :shadowed_by_macos
end
def by_macos?
provided_by_macos? || shadowed_by_macos?
end
def applicable?
# macOS reasons aren't applicable on other OSs
# (see extend/os/mac/formula_support for override on macOS)
!by_macos?
end end
def to_s def to_s
return @explanation unless @explanation.empty? return @explanation unless @explanation.empty?
case @reason if versioned_formula?
when :versioned_formula
<<~EOS <<~EOS
this is an alternate version of another formula this is an alternate version of another formula
EOS EOS
when :provided_by_macos elsif provided_by_macos?
<<~EOS <<~EOS
macOS already provides this software and installing another version in macOS already provides this software and installing another version in
parallel can cause all kinds of trouble parallel can cause all kinds of trouble
EOS EOS
when :shadowed_by_macos elsif shadowed_by_macos?
<<~EOS <<~EOS
macOS provides similar software and installing this software in macOS provides similar software and installing this software in
parallel can cause all kinds of trouble parallel can cause all kinds of trouble

View File

@ -70,7 +70,7 @@ module RuboCop
end end
end end
module FormulaAuditStrict module FormulaAudit
# - `test do ..end` should be meaningfully defined in the formula. # - `test do ..end` should be meaningfully defined in the formula.
class Test < FormulaCop class Test < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
@ -86,8 +86,8 @@ module RuboCop
return return
end end
return unless test.body.single_line? && return unless test.body.single_line?
test.body.source.to_s == "true" return if test.body.source.to_s != "true"
problem "`test do` should contain a real test" problem "`test do` should contain a real test"
end end

View File

@ -12,13 +12,13 @@ module RuboCop
"Use `keg_only :versioned_formula` instead." "Use `keg_only :versioned_formula` instead."
WHITELIST = %w[ WHITELIST = %w[
bash-completion@ bash-completion@2
].freeze ].freeze
def audit_formula(_node, _class_node, _parent_class_node, body) def audit_formula(_node, _class_node, _parent_class_node, body)
return unless versioned_formula? return unless versioned_formula?
problem MSG if !@formula_name.start_with?(*WHITELIST) && problem MSG if !WHITELIST.include?(@formula_name) &&
method_called_ever?(body, :conflicts_with) method_called_ever?(body, :conflicts_with)
end end
end end

View File

@ -38,7 +38,7 @@ module RuboCop
end end
end end
module FormulaAuditStrict module FormulaAudit
# This cop audits `desc` in Formulae. # This cop audits `desc` in Formulae.
# #
# - Checks for leading/trailing whitespace in `desc` # - Checks for leading/trailing whitespace in `desc`

View File

@ -196,6 +196,26 @@ module RuboCop
end end
class Miscellaneous < FormulaCop class Miscellaneous < FormulaCop
MAKE_CHECK_WHITELIST = %w[
beecrypt
ccrypt
git
gmp
gnupg
gnupg@1.4
google-sparsehash
jemalloc
jpeg-turbo
mpfr
nettle
open-mpi
openssl@1.1
pcre
protobuf
wolfssl
xz
].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
# FileUtils is included in Formula # FileUtils is included in Formula
# encfs modifies a file with this name, so check for some leading characters # encfs modifies a file with this name, so check for some leading characters
@ -425,25 +445,7 @@ module RuboCop
# Avoid build-time checks in homebrew/core # Avoid build-time checks in homebrew/core
find_every_method_call_by_name(body_node, :system).each do |method| find_every_method_call_by_name(body_node, :system).each do |method|
next if @formula_name.start_with?("lib") next if @formula_name.start_with?("lib")
next if %w[ next if MAKE_CHECK_WHITELIST.include?(@formula_name)
beecrypt
ccrypt
git
gmp
gnupg
gnupg@1.4
google-sparsehash
jemalloc
jpeg-turbo
mpfr
nettle
open-mpi
openssl@1.1
pcre
protobuf
wolfssl
xz
].include?(@formula_name)
params = parameters(method) params = parameters(method)
next unless node_equals?(params[0], "make") next unless node_equals?(params[0], "make")

View File

@ -39,7 +39,7 @@ module RuboCop
" Migrate '--#{option}' with `deprecated_option`." " Migrate '--#{option}' with `deprecated_option`."
end end
return unless formula_tap == "homebrew-core" return if formula_tap != "homebrew-core"
problem DEP_OPTION if method_called_ever?(body_node, :deprecated_option) problem DEP_OPTION if method_called_ever?(body_node, :deprecated_option)
problem OPTION if method_called_ever?(body_node, :option) problem OPTION if method_called_ever?(body_node, :option)

View File

@ -12,7 +12,7 @@ module RuboCop
problem "Please set plist_options when using a formula-defined plist." problem "Please set plist_options when using a formula-defined plist."
end end
if depends_on?("openssl") && depends_on?("libressl") if (depends_on?("openssl") || depends_on?("openssl@1.1")) && depends_on?("libressl")
problem "Formulae should not depend on both OpenSSL and LibreSSL (even optionally)." problem "Formulae should not depend on both OpenSSL and LibreSSL (even optionally)."
end end
@ -61,17 +61,19 @@ module RuboCop
find_method_with_args(body_node, :system, "cargo", "build") do find_method_with_args(body_node, :system, "cargo", "build") do
problem "use \"cargo\", \"install\", \"--root\", prefix, \"--path\", \".\"" problem "use \"cargo\", \"install\", \"--root\", prefix, \"--path\", \".\""
end end
end
end
end
module FormulaAuditStrict
class Text < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
find_method_with_args(body_node, :go_resource) do find_method_with_args(body_node, :go_resource) do
problem "`go_resource`s are deprecated. Please ask upstream to implement Go vendoring" problem "`go_resource`s are deprecated. Please ask upstream to implement Go vendoring"
end end
end end
end end
end end
# Keep this (empty) module and class around in case we need it later to
# avoid deleting all the FormulaAuditStrict referencing logic.
module FormulaAuditStrict
class Text < FormulaCop
end
end
end end
end end

View File

@ -26,7 +26,7 @@ module RuboCop
m4 m4
ncurses ncurses
openldap openldap
openssl openssl@1.1
perl perl
php php
ruby ruby

View File

@ -633,5 +633,12 @@ module Homebrew
expect(fa.problems).to eq([]) expect(fa.problems).to eq([])
end end
end end
include_examples "formulae exist", described_class::VERSIONED_KEG_ONLY_WHITELIST
include_examples "formulae exist", described_class::VERSIONED_HEAD_SPEC_WHITELIST
include_examples "formulae exist", described_class::USES_FROM_MACOS_WHITELIST
include_examples "formulae exist", described_class::THROTTLED_BLACKLIST.keys
include_examples "formulae exist", described_class::UNSTABLE_WHITELIST.keys
include_examples "formulae exist", described_class::GNOME_DEVEL_WHITELIST.keys
end end
end end

View File

@ -105,7 +105,7 @@ describe RuboCop::Cop::FormulaAudit::TestCalls do
end end
end end
describe RuboCop::Cop::FormulaAuditStrict::Test do describe RuboCop::Cop::FormulaAudit::Test do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
it "reports an offense when there is no test block" do it "reports an offense when there is no test block" do

View File

@ -26,4 +26,6 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do
RUBY RUBY
end end
end end
include_examples "formulae exist", described_class::WHITELIST
end end

View File

@ -48,7 +48,7 @@ describe RuboCop::Cop::FormulaAudit::DescLength do
end end
end end
describe RuboCop::Cop::FormulaAuditStrict::Desc do describe RuboCop::Cop::FormulaAudit::Desc do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "When auditing formula desc" do context "When auditing formula desc" do

View File

@ -860,4 +860,6 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
RUBY RUBY
end end
end end
include_examples "formulae exist", described_class::MAKE_CHECK_WHITELIST
end end

View File

@ -218,6 +218,8 @@ describe RuboCop::Cop::FormulaAudit::Urls do
RUBY RUBY
end end
end end
include_examples "formulae exist", described_class::BINARY_BOOTSTRAP_FORMULA_URLS_WHITELIST
end end
describe RuboCop::Cop::FormulaAudit::PyPiUrls do describe RuboCop::Cop::FormulaAudit::PyPiUrls do

View File

@ -16,4 +16,6 @@ describe RuboCop::Cop::FormulaAudit::UsesFromMacos do
end end
RUBY RUBY
end end
include_examples "formulae exist", described_class::ALLOWED_USES_FROM_MACOS_DEPS
end end

View File

@ -52,6 +52,7 @@ require "test/support/helper/output_as_tty"
require "test/support/helper/spec/shared_context/homebrew_cask" if OS.mac? require "test/support/helper/spec/shared_context/homebrew_cask" if OS.mac?
require "test/support/helper/spec/shared_context/integration_test" require "test/support/helper/spec/shared_context/integration_test"
require "test/support/helper/spec/shared_examples/formulae_exist"
TEST_DIRECTORIES = [ TEST_DIRECTORIES = [
CoreTap.instance.path/"Formula", CoreTap.instance.path/"Formula",

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
shared_examples "formulae exist" do |array|
array.each do |f|
it "#{f} formula exists" do
formula_path = Pathname("#{HOMEBREW_LIBRARY_PATH}/../Taps/homebrew/homebrew-core/Formula/#{f}.rb")
expect(formula_path.exist?).to be true
end
end
end

View File

@ -17,7 +17,7 @@ TEST_TMPDIR = ENV.fetch("HOMEBREW_TEST_TMPDIR") do |k|
end.freeze end.freeze
# Paths pointing into the Homebrew code base that persist across test runs # Paths pointing into the Homebrew code base that persist across test runs
HOMEBREW_SHIMS_PATH = (HOMEBREW_LIBRARY_PATH.parent/"Homebrew/shims").freeze HOMEBREW_SHIMS_PATH = (HOMEBREW_LIBRARY_PATH/"shims").freeze
require "extend/git_repository" require "extend/git_repository"