Merge pull request #7348 from MikeMcQuaid/brew-style-fixes

`brew style` fixes
This commit is contained in:
Mike McQuaid 2020-04-13 16:23:54 +01:00 committed by GitHub
commit 5f3347486b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 140 additions and 188 deletions

View File

@ -8,10 +8,6 @@ FormulaAudit:
FormulaAuditStrict: FormulaAuditStrict:
Enabled: true Enabled: true
# disable all formulae strict audits by default
NewFormulaAudit:
Enabled: false
# make our hashes consistent # make our hashes consistent
Layout/HashAlignment: Layout/HashAlignment:
EnforcedHashRocketStyle: table EnforcedHashRocketStyle: table

View File

@ -1,4 +0,0 @@
inherit_from: ./.rubocop.yml
NewFormulaAudit:
Enabled: true

View File

@ -8,9 +8,6 @@ AllCops:
Exclude: Exclude:
- '**/vendor/**/*' - '**/vendor/**/*'
NewFormulaAudit:
Enabled: true
# Intentionally disabled as it doesn't fit with our code style. # Intentionally disabled as it doesn't fit with our code style.
RSpec/AnyInstance: RSpec/AnyInstance:
Enabled: false Enabled: false

View File

@ -57,9 +57,7 @@ module Homebrew
elsif except_cops elsif except_cops
options[:except_cops] = except_cops options[:except_cops] = except_cops
elsif only_cops.nil? && except_cops.nil? elsif only_cops.nil? && except_cops.nil?
options[:except_cops] = %w[FormulaAudit options[:except_cops] = %w[FormulaAuditStrict]
FormulaAuditStrict
NewFormulaAudit]
end end
Homebrew.failed = !Style.check_style_and_print(target, options) Homebrew.failed = !Style.check_style_and_print(target, options)

View File

@ -95,8 +95,6 @@ module Homebrew
options[:only_cops] = only_cops options[:only_cops] = only_cops
elsif args.new_formula? elsif args.new_formula?
nil nil
elsif strict
options[:except_cops] = [:NewFormulaAudit]
elsif except_cops elsif except_cops
options[:except_cops] = except_cops options[:except_cops] = except_cops
elsif !strict elsif !strict
@ -231,12 +229,6 @@ module Homebrew
return unless @style_offenses return unless @style_offenses
@style_offenses.each do |offense| @style_offenses.each do |offense|
if offense.cop_name.start_with?("NewFormulaAudit")
next if @versioned_formula
new_formula_problem offense.to_s(display_cop_name: @display_cop_names)
next
end
problem offense.to_s(display_cop_name: @display_cop_names) problem offense.to_s(display_cop_name: @display_cop_names)
end end
end end

View File

@ -26,11 +26,18 @@ module RuboCop
end end
end end
class TestCalls < 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)
test = find_block(body_node, :test) test = find_block(body_node, :test)
return unless test return unless test
if test.body.nil?
problem "`test do` should not be empty"
return
end
problem "`test do` should contain a real test" if test.body.single_line? && test.body.source.to_s == "true"
test_calls(test) do |node, params| test_calls(test) do |node, params|
p1, p2 = params p1, p2 = params
if match = string_content(p1).match(%r{(/usr/local/(s?bin))}) if match = string_content(p1).match(%r{(/usr/local/(s?bin))})
@ -70,26 +77,13 @@ module RuboCop
end end
end end
module FormulaAudit module FormulaAuditStrict
# - `test do ..end` should be meaningfully defined in the formula. # - `test do ..end` should defined in the formula.
class Test < FormulaCop class TestPresent < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
test = find_block(body_node, :test) return if find_block(body_node, :test)
unless test
problem "A `test do` test block should be added" problem "A `test do` test block should be added"
return
end
if test.body.nil?
problem "`test do` should not be empty"
return
end
return unless test.body.single_line?
return if test.body.source.to_s != "true"
problem "`test do` should contain a real test"
end end
end end
end end

View File

@ -10,7 +10,17 @@ module RuboCop
# #
# - Checks for existence of `desc` # - Checks for existence of `desc`
# - Checks if size of `desc` > 80 # - Checks if size of `desc` > 80
class DescLength < FormulaCop # - Checks for leading/trailing whitespace in `desc`
# - Checks if `desc` begins with an article
# - Checks for correct usage of `command-line` in `desc`
# - Checks description starts with a capital letter
# - Checks if `desc` contains the formula name
# - Checks if `desc` ends with a full stop (apart from in the case of "etc.")
class Desc < FormulaCop
VALID_LOWERCASE_WORDS = %w[
macOS
].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
desc_call = find_node_method_by_name(body_node, :desc) desc_call = find_node_method_by_name(body_node, :desc)
@ -20,52 +30,15 @@ module RuboCop
return return
end end
# Check the formula's desc length. Should be >0 and <80 characters.
desc = parameters(desc_call).first desc = parameters(desc_call).first
# Check the formula's desc length. Should be >0 and <80 characters.
pure_desc_length = string_content(desc).length pure_desc_length = string_content(desc).length
if pure_desc_length.zero? if pure_desc_length.zero?
problem "The desc (description) should not be an empty string." problem "The desc (description) should not be an empty string."
return return
end end
desc_length = "#{@formula_name}: #{string_content(desc)}".length
max_desc_length = 80
return if desc_length <= max_desc_length
problem "Description is too long. \"name: desc\" should be less than #{max_desc_length} characters. " \
"Length is calculated as #{@formula_name} + desc. (currently #{desc_length})"
end
end
end
module FormulaAudit
# This cop audits `desc` in Formulae.
#
# - Checks for leading/trailing whitespace in `desc`
# - Checks if `desc` begins with an article
# - Checks for correct usage of `command-line` in `desc`
# - Checks description starts with a capital letter
# - Checks if `desc` contains the formula name
# - Checks if `desc` ends with a full stop (apart from in the case of "etc.")
class Desc < FormulaCop
VALID_LOWERCASE_WORDS = %w[
ex
eXtensible
iOS
macOS
malloc
ooc
preexec
x86
xUnit
].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node)
desc_call = find_node_method_by_name(body_node, :desc)
return if desc_call.nil?
desc = parameters(desc_call).first
# Check for leading whitespace. # Check for leading whitespace.
problem "Description shouldn't have a leading space" if regex_match_group(desc, /^\s+/) problem "Description shouldn't have a leading space" if regex_match_group(desc, /^\s+/)
@ -96,11 +69,18 @@ module RuboCop
end end
# Check if a full stop is used at the end of a formula's desc (apart from in the case of "etc.") # Check if a full stop is used at the end of a formula's desc (apart from in the case of "etc.")
return unless regex_match_group(desc, /\.$/) && !string_content(desc).end_with?("etc.") if regex_match_group(desc, /\.$/) && !string_content(desc).end_with?("etc.")
problem "Description shouldn't end with a full stop" problem "Description shouldn't end with a full stop"
end end
desc_length = "#{@formula_name}: #{string_content(desc)}".length
max_desc_length = 80
return if desc_length <= max_desc_length
problem "Description is too long. \"name: desc\" should be less than #{max_desc_length} characters. " \
"Length is calculated as #{@formula_name} + desc. (currently #{desc_length})"
end
def autocorrect(node) def autocorrect(node)
lambda do |corrector| lambda do |corrector|
correction = node.source correction = node.source

View File

@ -196,26 +196,6 @@ 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
@ -260,18 +240,18 @@ module RuboCop
# Avoid hard-coding compilers # Avoid hard-coding compilers
find_every_method_call_by_name(body_node, :system).each do |method| find_every_method_call_by_name(body_node, :system).each do |method|
param = parameters(method).first param = parameters(method).first
if match = regex_match_group(param, %r{^(/usr/bin/)?(gcc|llvm-gcc|clang)\s?}) if match = regex_match_group(param, %r{^(/usr/bin/)?(gcc|llvm-gcc|clang)[\s"]?})
problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\"" problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\""
elsif match = regex_match_group(param, %r{^(/usr/bin/)?((g|llvm-g|clang)\+\+)\s?}) elsif match = regex_match_group(param, %r{^(/usr/bin/)?((g|llvm-g|clang)\+\+)[\s"]?})
problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\"" problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\""
end end
end end
find_instance_method_call(body_node, "ENV", :[]=) do |method| find_instance_method_call(body_node, "ENV", :[]=) do |method|
param = parameters(method)[1] param = parameters(method)[1]
if match = regex_match_group(param, %r{^(/usr/bin/)?(gcc|llvm-gcc|clang)\s?}) if match = regex_match_group(param, %r{^(/usr/bin/)?(gcc|llvm-gcc|clang)[\s"]?})
problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\"" problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\""
elsif match = regex_match_group(param, %r{^(/usr/bin/)?((g|llvm-g|clang)\+\+)\s?}) elsif match = regex_match_group(param, %r{^(/usr/bin/)?((g|llvm-g|clang)\+\+)[\s"]?})
problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\"" problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\""
end end
end end
@ -439,25 +419,6 @@ module RuboCop
problem "Use the `#{match}` Ruby method instead of `#{method.source}`" problem "Use the `#{match}` Ruby method instead of `#{method.source}`"
end end
return if formula_tap != "homebrew-core"
# Avoid build-time checks in homebrew/core
find_every_method_call_by_name(body_node, :system).each do |method|
next if @formula_name.start_with?("lib")
next if MAKE_CHECK_WHITELIST.include?(@formula_name)
params = parameters(method)
next unless node_equals?(params[0], "make")
params[1..].each do |arg|
next unless regex_match_group(arg, /^(checks?|tests?)$/)
offending_node(method)
problem "Formulae in homebrew/core (except e.g. cryptography, libraries) " \
"should not run build-time checks"
end
end
end end
def modifier?(node) def modifier?(node)
@ -493,5 +454,50 @@ module RuboCop
EOS EOS
end end
end end
module FormulaAuditStrict
class MakeCheck < 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)
return if formula_tap != "homebrew-core"
# Avoid build-time checks in homebrew/core
find_every_method_call_by_name(body_node, :system).each do |method|
next if @formula_name.start_with?("lib")
next if MAKE_CHECK_WHITELIST.include?(@formula_name)
params = parameters(method)
next unless node_equals?(params[0], "make")
params[1..].each do |arg|
next unless regex_match_group(arg, /^(checks?|tests?)$/)
offending_node(method)
problem "Formulae in homebrew/core (except e.g. cryptography, libraries) " \
"should not run build-time checks"
end
end
end
end
end
end end
end end

View File

@ -46,12 +46,5 @@ module RuboCop
end end
end end
end end
# Keep this (empty) module and class around in case we need it later to
# avoid deleting all the NewFormulaAudit referencing logic.
module NewFormulaAudit
class Options < FormulaCop
end
end
end end
end end

View File

@ -44,7 +44,7 @@ module RuboCop
%r{gist\.github\.com/.+/raw}, %r{gist\.github\.com/.+/raw},
%r{gist\.githubusercontent\.com/.+/raw}]) %r{gist\.githubusercontent\.com/.+/raw}])
if regex_match_group(patch, gh_patch_patterns) if regex_match_group(patch, gh_patch_patterns)
unless patch_url.match?(/[a-fA-F0-9]{40}/) unless patch_url.match?(%r{/[a-fA-F0-9]{6,40}/})
problem <<~EOS.chomp problem <<~EOS.chomp
GitHub/Gist patches should specify a revision: GitHub/Gist patches should specify a revision:
#{patch_url} #{patch_url}

View File

@ -61,19 +61,18 @@ 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

@ -60,7 +60,7 @@ module Homebrew
config = if files.first && File.exist?("#{files.first}/spec") config = if files.first && File.exist?("#{files.first}/spec")
HOMEBREW_LIBRARY/".rubocop_rspec.yml" HOMEBREW_LIBRARY/".rubocop_rspec.yml"
else else
HOMEBREW_LIBRARY/".rubocop_audit.yml" HOMEBREW_LIBRARY/".rubocop.yml"
end end
args << "--config" << config args << "--config" << config
end end

View File

@ -50,6 +50,7 @@ RSpec/FilePath:
- 'rubocops/patches_spec.rb' - 'rubocops/patches_spec.rb'
- 'rubocops/text_spec.rb' - 'rubocops/text_spec.rb'
- 'rubocops/uses_from_macos_spec.rb' - 'rubocops/uses_from_macos_spec.rb'
- 'rubocops/formula_desc_spec.rb'
- 'search_spec.rb' - 'search_spec.rb'
- 'string_spec.rb' - 'string_spec.rb'
- 'system_command_result_spec.rb' - 'system_command_result_spec.rb'

View File

@ -10,13 +10,13 @@ end
describe "brew style" do describe "brew style" do
around do |example| around do |example|
FileUtils.ln_s HOMEBREW_LIBRARY_PATH, HOMEBREW_LIBRARY/"Homebrew" FileUtils.ln_s HOMEBREW_LIBRARY_PATH, HOMEBREW_LIBRARY/"Homebrew"
FileUtils.ln_s HOMEBREW_LIBRARY_PATH.parent/".rubocop.yml", HOMEBREW_LIBRARY/".rubocop_audit.yml" FileUtils.ln_s HOMEBREW_LIBRARY_PATH.parent/".rubocop.yml", HOMEBREW_LIBRARY/".rubocop.yml"
FileUtils.ln_s HOMEBREW_LIBRARY_PATH.parent/".rubocop_shared.yml", HOMEBREW_LIBRARY/".rubocop_shared.yml" FileUtils.ln_s HOMEBREW_LIBRARY_PATH.parent/".rubocop_shared.yml", HOMEBREW_LIBRARY/".rubocop_shared.yml"
example.run example.run
ensure ensure
FileUtils.rm_f HOMEBREW_LIBRARY/"Homebrew" FileUtils.rm_f HOMEBREW_LIBRARY/"Homebrew"
FileUtils.rm_f HOMEBREW_LIBRARY/".rubocop_audit.yml" FileUtils.rm_f HOMEBREW_LIBRARY/".rubocop.yml"
FileUtils.rm_f HOMEBREW_LIBRARY/".rubocop_shared.yml" FileUtils.rm_f HOMEBREW_LIBRARY/".rubocop_shared.yml"
end end
@ -62,7 +62,7 @@ describe "brew style" do
EOS EOS
rubocop_result = Homebrew::Style.check_style_json( rubocop_result = Homebrew::Style.check_style_json(
[formula], [formula],
fix: true, only_cops: ["NewFormulaAudit/DependencyOrder"], fix: true, only_cops: ["FormulaAudit/DependencyOrder"],
) )
offense_string = rubocop_result.file_offenses(formula.realpath).first.to_s offense_string = rubocop_result.file_offenses(formula.realpath).first.to_s
expect(offense_string).to match(/\[Corrected\]/) expect(offense_string).to match(/\[Corrected\]/)

View File

@ -50,7 +50,7 @@ describe RuboCop::Cop::FormulaAudit::ClassName do
end end
end end
describe RuboCop::Cop::FormulaAudit::TestCalls do describe RuboCop::Cop::FormulaAudit::Test do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
it "reports an offense when /usr/local/bin is found in test calls" do it "reports an offense when /usr/local/bin is found in test calls" do
@ -79,6 +79,31 @@ describe RuboCop::Cop::FormulaAudit::TestCalls do
RUBY RUBY
end end
it "reports an offense when there is an empty test block" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
test do
^^^^^^^ `test do` should not be empty
end
end
RUBY
end
it "reports an offense when test is falsely true" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
test do
^^^^^^^ `test do` should contain a real test
true
end
end
RUBY
end
it "supports auto-correcting test calls" do it "supports auto-correcting test calls" do
source = <<~RUBY source = <<~RUBY
class Foo < Formula class Foo < Formula
@ -105,7 +130,7 @@ describe RuboCop::Cop::FormulaAudit::TestCalls do
end end
end end
describe RuboCop::Cop::FormulaAudit::Test do describe RuboCop::Cop::FormulaAuditStrict::TestPresent 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
@ -116,29 +141,4 @@ describe RuboCop::Cop::FormulaAudit::Test do
end end
RUBY RUBY
end end
it "reports an offense when there is an empty test block" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
test do
^^^^^^^ `test do` should not be empty
end
end
RUBY
end
it "reports an offense when test is falsely true" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
test do
^^^^^^^ `test do` should contain a real test
true
end
end
RUBY
end
end end

View File

@ -2,7 +2,7 @@
require "rubocops/formula_desc" require "rubocops/formula_desc"
describe RuboCop::Cop::FormulaAudit::DescLength 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
@ -46,10 +46,6 @@ describe RuboCop::Cop::FormulaAudit::DescLength do
RUBY RUBY
end end
end end
end
describe RuboCop::Cop::FormulaAudit::Desc do
subject(:cop) { described_class.new }
context "When auditing formula desc" do context "When auditing formula desc" do
it "When wrong \"command-line\" usage in desc" do it "When wrong \"command-line\" usage in desc" do

View File

@ -349,17 +349,6 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "When auditing formula" do context "When auditing formula" do
it "build-time checks in homebrew/core" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
system "make", "-j1", "test"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core (except e.g. cryptography, libraries) should not run build-time checks
end
RUBY
end
it "FileUtils usage" do it "FileUtils usage" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
@ -860,6 +849,21 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
RUBY RUBY
end end
end end
end
describe RuboCop::Cop::FormulaAuditStrict::MakeCheck do
subject(:cop) { described_class.new }
it "build-time checks in homebrew/core" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
system "make", "-j1", "test"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core (except e.g. cryptography, libraries) should not run build-time checks
end
RUBY
end
include_examples "formulae exist", described_class::MAKE_CHECK_WHITELIST include_examples "formulae exist", described_class::MAKE_CHECK_WHITELIST
end end