Merge pull request #9326 from Rylan12/migrate-style-exceptions

Migrate style exceptions to homebrew/core
This commit is contained in:
Rylan Polster 2020-12-01 12:19:45 -05:00 committed by GitHub
commit 77b4275f81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 256 additions and 180 deletions

View File

@ -129,6 +129,9 @@ module Homebrew
sig { returns(T.nilable(T::Boolean)) } sig { returns(T.nilable(T::Boolean)) }
def markdown?; end def markdown?; end
sig { returns(T.nilable(T::Boolean)) }
def reset_cache?; end
sig { returns(T.nilable(String)) } sig { returns(T.nilable(String)) }
def tag; end def tag; end

View File

@ -27,6 +27,8 @@ module Homebrew
description: "Fix style violations automatically using RuboCop's auto-correct feature." description: "Fix style violations automatically using RuboCop's auto-correct feature."
switch "--display-cop-names", switch "--display-cop-names",
description: "Include the RuboCop cop name for each violation in the output." description: "Include the RuboCop cop name for each violation in the output."
switch "--reset-cache",
description: "Reset the RuboCop cache."
comma_array "--only-cops", comma_array "--only-cops",
description: "Specify a comma-separated <cops> list to check for violations of only the "\ description: "Specify a comma-separated <cops> list to check for violations of only the "\
"listed RuboCop cops." "listed RuboCop cops."
@ -51,7 +53,11 @@ module Homebrew
except_cops = args.except_cops except_cops = args.except_cops
options = { options = {
fix: args.fix?, display_cop_names: args.display_cop_names?, debug: args.debug?, verbose: args.verbose? fix: args.fix?,
display_cop_names: args.display_cop_names?,
reset_cache: args.reset_cache?,
debug: args.debug?,
verbose: args.verbose?,
} }
if only_cops if only_cops
options[:only_cops] = only_cops options[:only_cops] = only_cops

View File

@ -11,11 +11,6 @@ module RuboCop
# - `component_precedence_list` has component hierarchy in a nested list # - `component_precedence_list` has component hierarchy in a nested list
# where each sub array contains components' details which are at same precedence level # where each sub array contains components' details which are at same precedence level
class ComponentsOrder < FormulaCop class ComponentsOrder < FormulaCop
# `aspell`: options and resources should be grouped by language
COMPONENT_ALLOWLIST = %w[
aspell
].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
component_precedence_list = [ component_precedence_list = [
[{ name: :include, type: :method_call }], [{ name: :include, type: :method_call }],
@ -234,7 +229,7 @@ module RuboCop
# Method to format message for reporting component precedence violations. # Method to format message for reporting component precedence violations.
def component_problem(c1, c2) def component_problem(c1, c2)
return if COMPONENT_ALLOWLIST.include?(@formula_name) return if tap_style_exception? :components_order_exceptions
problem "`#{format_component(c1)}` (line #{line_number(c1)}) " \ problem "`#{format_component(c1)}` (line #{line_number(c1)}) " \
"should be put before `#{format_component(c2)}` " \ "should be put before `#{format_component(c2)}` " \

View File

@ -12,10 +12,6 @@ module RuboCop
MSG = "Versioned formulae should not use `conflicts_with`. " \ MSG = "Versioned formulae should not use `conflicts_with`. " \
"Use `keg_only :versioned_formula` instead." "Use `keg_only :versioned_formula` instead."
ALLOWLIST = %w[
bash-completion@2
].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
find_method_calls_by_name(body_node, :conflicts_with).each do |conflicts_with_call| find_method_calls_by_name(body_node, :conflicts_with).each do |conflicts_with_call|
next unless parameters(conflicts_with_call).last.respond_to? :values next unless parameters(conflicts_with_call).last.respond_to? :values
@ -35,7 +31,7 @@ module RuboCop
return unless versioned_formula? return unless versioned_formula?
problem MSG if !ALLOWLIST.include?(@formula_name) && problem MSG if !tap_style_exception?(:versioned_formulae_conflicts_allowlist) &&
method_called_ever?(body_node, :conflicts_with) method_called_ever?(body_node, :conflicts_with)
end end

View File

@ -35,6 +35,7 @@ module RuboCop
class_node, parent_class_node, @body = *node class_node, parent_class_node, @body = *node
@formula_name = Pathname.new(@file_path).basename(".rb").to_s @formula_name = Pathname.new(@file_path).basename(".rb").to_s
@tap_style_exceptions = nil
audit_formula(node, class_node, parent_class_node, @body) audit_formula(node, class_node, parent_class_node, @body)
end end
@ -472,6 +473,32 @@ module RuboCop
match_obj[1] match_obj[1]
end end
# Returns whether the given formula exists in the given style exception list.
# Defaults to the current formula being checked.
def tap_style_exception?(list, formula = nil)
if @tap_style_exceptions.nil? && !formula_tap.nil?
@tap_style_exceptions = {}
style_exceptions_dir = "#{File.dirname(File.dirname(@file_path))}/style_exceptions/*.json"
Pathname.glob(style_exceptions_dir).each do |exception_file|
list_name = exception_file.basename.to_s.chomp(".json").to_sym
list_contents = begin
JSON.parse exception_file.read
rescue JSON::ParserError
nil
end
next if list_contents.nil? || list_contents.count.zero?
@tap_style_exceptions[list_name] = list_contents
end
end
return false if @tap_style_exceptions.nil? || @tap_style_exceptions.count.zero?
return false unless @tap_style_exceptions.key? list
@tap_style_exceptions[list].include?(formula || @formula_name)
end
private private
def formula_class?(node) def formula_class?(node)

View File

@ -623,33 +623,13 @@ module RuboCop
# #
# @api private # @api private
class MakeCheck < FormulaCop class MakeCheck < FormulaCop
MAKE_CHECK_ALLOWLIST = %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)
return if formula_tap != "homebrew-core" return if formula_tap != "homebrew-core"
# 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 MAKE_CHECK_ALLOWLIST.include?(@formula_name) next if tap_style_exception? :make_check_allowlist
params = parameters(method) params = parameters(method)
next unless node_equals?(params[0], "make") next unless node_equals?(params[0], "make")

View File

@ -218,10 +218,8 @@ module RuboCop
# #
# @api private # @api private
class LivecheckRegexCaseInsensitive < FormulaCop class LivecheckRegexCaseInsensitive < FormulaCop
REGEX_CASE_SENSITIVE_ALLOWLIST = %w[].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if REGEX_CASE_SENSITIVE_ALLOWLIST.include?(@formula_name) return if tap_style_exception? :regex_case_sensitive_allowlist
livecheck_node = find_block(body_node, :livecheck) livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank? return if livecheck_node.blank?

View File

@ -10,47 +10,6 @@ module RuboCop
# #
# @api private # @api private
class Urls < FormulaCop class Urls < FormulaCop
# These are parts of URLs that look like binaries but actually aren't.
NOT_A_BINARY_URL_PREFIX_ALLOWLIST = %w[
https://downloads.sourceforge.net/project/astyle/astyle/
https://downloads.sourceforge.net/project/bittwist/
https://downloads.sourceforge.net/project/launch4j/
https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard/archive/
https://github.com/obihann/archey-osx
https://github.com/sindresorhus/macos-wallpaper/archive/
https://raw.githubusercontent.com/liyanage/macosx-shell-scripts/
https://osxbook.com/book/bonus/chapter8/core/download/gcore
https://naif.jpl.nasa.gov/pub/naif/toolkit/C/MacIntel_OSX_AppleC_64bit/packages/
https://artifacts.videolan.org/x264/release-macos/
https://github.com/vifm/vifm/releases/download/v0.11/vifm-osx-0.11.tar.bz2
].freeze
# These are formulae that, sadly, require an upstream binary to bootstrap.
BINARY_BOOTSTRAP_FORMULA_URLS_ALLOWLIST = %w[
clozure-cl
crystal
fpc
ghc
ghc@8.6
ghc@8.8
go
go@1.9
go@1.10
go@1.11
go@1.12
go@1.13
go@1.14
haskell-stack
ldc
mlton
openjdk
openjdk@11
openjdk@8
pypy
sbcl
rust
].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
urls = find_every_func_call_by_name(body_node, :url) urls = find_every_func_call_by_name(body_node, :url)
mirrors = find_every_func_call_by_name(body_node, :mirror) mirrors = find_every_func_call_by_name(body_node, :mirror)
@ -281,8 +240,8 @@ module RuboCop
audit_urls(urls, /(darwin|macos|osx)/i) do |match, url| audit_urls(urls, /(darwin|macos|osx)/i) do |match, url|
next if @formula_name.include?(match.to_s.downcase) next if @formula_name.include?(match.to_s.downcase)
next if url.match?(/.(patch|diff)(\?full_index=1)?$/) next if url.match?(/.(patch|diff)(\?full_index=1)?$/)
next if NOT_A_BINARY_URL_PREFIX_ALLOWLIST.any? { |prefix| url.start_with?(prefix) } next if tap_style_exception? :not_a_binary_url_prefix_allowlist
next if BINARY_BOOTSTRAP_FORMULA_URLS_ALLOWLIST.include?(@formula_name) next if tap_style_exception? :binary_bootstrap_formula_urls_allowlist
problem "#{url} looks like a binary package, not a source archive; " \ problem "#{url} looks like a binary package, not a source archive; " \
"homebrew/core is source-only." "homebrew/core is source-only."

View File

@ -6,82 +6,20 @@ require "rubocops/extend/formula"
module RuboCop module RuboCop
module Cop module Cop
module FormulaAudit module FormulaAudit
# This cop audits formulae that are keg-only because they are provided by macos.
class ProvidedByMacos < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
find_method_with_args(body_node, :keg_only, :provided_by_macos) do
unless tap_style_exception? :provided_by_macos_formulae
problem "Formulae that are `keg_only :provided_by_macos` should be added to "\
"`style_exceptions/provided_by_macos_formulae.json`"
end
end
end
end
# This cop audits `uses_from_macos` dependencies in formulae. # This cop audits `uses_from_macos` dependencies in formulae.
class UsesFromMacos < FormulaCop class UsesFromMacos < FormulaCop
# Generate with:
#
# ```
# brew ruby -e 'puts Formula.select {|f| f.keg_only_reason&.provided_by_macos? }.map(&:name).sort.join("\n")'
# ```
#
# Not done at runtime as it's too slow and RuboCop doesn't have access.
PROVIDED_BY_MACOS_FORMULAE = %w[
apr
bc
bison
bzip2
cups
curl
dyld-headers
ed
expat
file-formula
flex
gcore
gnu-getopt
icu4c
krb5
libarchive
libedit
libffi
libiconv
libpcap
libressl
libxml2
libxslt
llvm
lsof
m4
ncompress
ncurses
net-snmp
openldap
openlibm
pod2man
rpcgen
ruby
sqlite
ssh-copy-id
swift
tcl-tk
texinfo
unifdef
unzip
zip
zlib
].freeze
# These formulae aren't `keg_only :provided_by_macos` but are provided by
# macOS (or very similarly, e.g. OpenSSL where system provides LibreSSL).
# TODO: consider making some of these keg-only.
ALLOWED_USES_FROM_MACOS_DEPS = (PROVIDED_BY_MACOS_FORMULAE + %w[
bash
cpio
expect
groff
gzip
openssl
openssl@1.1
perl
php
python
python@3
rsync
vim
xz
zsh
]).freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
find_method_with_args(body_node, :uses_from_macos, /^"(.+)"/).each do |method| find_method_with_args(body_node, :uses_from_macos, /^"(.+)"/).each do |method|
dep = if parameters(method).first.instance_of?(RuboCop::AST::StrNode) dep = if parameters(method).first.instance_of?(RuboCop::AST::StrNode)
@ -90,7 +28,8 @@ module RuboCop
parameters(method).first.keys.first parameters(method).first.keys.first
end end
next if ALLOWED_USES_FROM_MACOS_DEPS.include?(string_content(dep)) next if tap_style_exception? :provided_by_macos_formulae, string_content(dep)
next if tap_style_exception? :non_keg_only_provided_by_macos_formulae, string_content(dep)
problem "`uses_from_macos` should only be used for macOS dependencies, not #{string_content(dep)}." problem "`uses_from_macos` should only be used for macOS dependencies, not #{string_content(dep)}."
end end

View File

@ -40,6 +40,7 @@ module Homebrew
fix: false, fix: false,
except_cops: nil, only_cops: nil, except_cops: nil, only_cops: nil,
display_cop_names: false, display_cop_names: false,
reset_cache: false,
debug: false, verbose: false) debug: false, verbose: false)
raise ArgumentError, "Invalid output type: #{output_type.inspect}" unless [:print, :json].include?(output_type) raise ArgumentError, "Invalid output type: #{output_type.inspect}" unless [:print, :json].include?(output_type)
@ -54,6 +55,7 @@ module Homebrew
fix: fix, fix: fix,
except_cops: except_cops, only_cops: only_cops, except_cops: except_cops, only_cops: only_cops,
display_cop_names: display_cop_names, display_cop_names: display_cop_names,
reset_cache: reset_cache,
debug: debug, verbose: verbose) debug: debug, verbose: verbose)
end end
@ -71,7 +73,7 @@ module Homebrew
end end
def run_rubocop(files, output_type, def run_rubocop(files, output_type,
fix: false, except_cops: nil, only_cops: nil, display_cop_names: false, fix: false, except_cops: nil, only_cops: nil, display_cop_names: false, reset_cache: false,
debug: false, verbose: false) debug: false, verbose: false)
Homebrew.install_bundler_gems! Homebrew.install_bundler_gems!
require "rubocop" require "rubocop"
@ -130,6 +132,8 @@ module Homebrew
cache_env = { "XDG_CACHE_HOME" => "#{HOMEBREW_CACHE}/style" } cache_env = { "XDG_CACHE_HOME" => "#{HOMEBREW_CACHE}/style" }
FileUtils.rm_rf cache_env["XDG_CACHE_HOME"] if reset_cache
case output_type case output_type
when :print when :print
args << "--debug" if debug args << "--debug" if debug

View File

@ -21,12 +21,14 @@ class Tap
HOMEBREW_TAP_FORMULA_RENAMES_FILE = "formula_renames.json" HOMEBREW_TAP_FORMULA_RENAMES_FILE = "formula_renames.json"
HOMEBREW_TAP_MIGRATIONS_FILE = "tap_migrations.json" HOMEBREW_TAP_MIGRATIONS_FILE = "tap_migrations.json"
HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR = "audit_exceptions" HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR = "audit_exceptions"
HOMEBREW_TAP_STYLE_EXCEPTIONS_DIR = "style_exceptions"
HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS = "pypi_formula_mappings.json" HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS = "pypi_formula_mappings.json"
HOMEBREW_TAP_JSON_FILES = %W[ HOMEBREW_TAP_JSON_FILES = %W[
#{HOMEBREW_TAP_FORMULA_RENAMES_FILE} #{HOMEBREW_TAP_FORMULA_RENAMES_FILE}
#{HOMEBREW_TAP_MIGRATIONS_FILE} #{HOMEBREW_TAP_MIGRATIONS_FILE}
#{HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR}/*.json #{HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR}/*.json
#{HOMEBREW_TAP_STYLE_EXCEPTIONS_DIR}/*.json
#{HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS} #{HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS}
].freeze ].freeze
@ -114,6 +116,7 @@ class Tap
@formula_renames = nil @formula_renames = nil
@tap_migrations = nil @tap_migrations = nil
@audit_exceptions = nil @audit_exceptions = nil
@style_exceptions = nil
@pypi_formula_mappings = nil @pypi_formula_mappings = nil
@config = nil @config = nil
remove_instance_variable(:@private) if instance_variable_defined?(:@private) remove_instance_variable(:@private) if instance_variable_defined?(:@private)
@ -567,6 +570,12 @@ class Tap
@audit_exceptions = read_formula_list_directory "#{HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR}/*" @audit_exceptions = read_formula_list_directory "#{HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR}/*"
end end
# Hash with style exceptions
sig { returns(Hash) }
def style_exceptions
@style_exceptions = read_formula_list_directory "#{HOMEBREW_TAP_STYLE_EXCEPTIONS_DIR}/*"
end
# Hash with pypi formula mappings # Hash with pypi formula mappings
sig { returns(Hash) } sig { returns(Hash) }
def pypi_formula_mappings def pypi_formula_mappings
@ -760,6 +769,15 @@ class CoreTap < Tap
end end
end end
# @private
def style_exceptions
@style_exceptions ||= begin
self.class.ensure_installed!
super
end
end
# @private
def pypi_formula_mappings def pypi_formula_mappings
@pypi_formula_mappings ||= begin @pypi_formula_mappings ||= begin
self.class.ensure_installed! self.class.ensure_installed!

View File

@ -8,13 +8,14 @@ module Homebrew
class TapAuditor class TapAuditor
extend T::Sig extend T::Sig
attr_reader :name, :path, :tap_audit_exceptions, :tap_pypi_formula_mappings, :problems attr_reader :name, :path, :tap_audit_exceptions, :tap_style_exceptions, :tap_pypi_formula_mappings, :problems
sig { params(tap: Tap, strict: T.nilable(T::Boolean)).void } sig { params(tap: Tap, strict: T.nilable(T::Boolean)).void }
def initialize(tap, strict:) def initialize(tap, strict:)
@name = tap.name @name = tap.name
@path = tap.path @path = tap.path
@tap_audit_exceptions = tap.audit_exceptions @tap_audit_exceptions = tap.audit_exceptions
@tap_style_exceptions = tap.style_exceptions
@tap_pypi_formula_mappings = tap.pypi_formula_mappings @tap_pypi_formula_mappings = tap.pypi_formula_mappings
@problems = [] @problems = []
end end
@ -38,6 +39,7 @@ module Homebrew
sig { void } sig { void }
def audit_tap_formula_lists def audit_tap_formula_lists
check_formula_list_directory "audit_exceptions", @tap_audit_exceptions check_formula_list_directory "audit_exceptions", @tap_audit_exceptions
check_formula_list_directory "style_exceptions", @tap_style_exceptions
check_formula_list "pypi_formula_mappings", @tap_pypi_formula_mappings check_formula_list "pypi_formula_mappings", @tap_pypi_formula_mappings
end end

View File

@ -543,7 +543,5 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
end end
RUBY RUBY
end end
include_examples "formulae exist", described_class::COMPONENT_ALLOWLIST
end end
end end

View File

@ -85,6 +85,4 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do
expect(new_source).to eq(corrected_source) expect(new_source).to eq(corrected_source)
end end
end end
include_examples "formulae exist", described_class::ALLOWLIST
end end

View File

@ -1479,8 +1479,6 @@ describe RuboCop::Cop::FormulaAuditStrict::MakeCheck do
end end
RUBY RUBY
end end
include_examples "formulae exist", described_class::MAKE_CHECK_ALLOWLIST
end end
describe RuboCop::Cop::FormulaAuditStrict::ShellCommands do describe RuboCop::Cop::FormulaAuditStrict::ShellCommands do

View File

@ -0,0 +1,61 @@
# typed: false
# frozen_string_literal: true
require "rubocops/uses_from_macos"
describe RuboCop::Cop::FormulaAudit::ProvidedByMacos do
subject(:cop) { described_class.new }
let(:path) { Tap::TAP_DIRECTORY/"homebrew/homebrew-foo" }
before do
path.mkpath
(path/"style_exceptions").mkpath
end
def setup_style_exceptions
(path/"style_exceptions/provided_by_macos_formulae.json").write <<~JSON
[ "foo", "bar" ]
JSON
end
it "fails for formulae not in provided_by_macos_formulae list" do
setup_style_exceptions
expect_offense(<<~RUBY, "#{path}/Formula/baz.rb")
class Baz < Formula
url "https://brew.sh/baz-1.0.tgz"
homepage "https://brew.sh"
keg_only :provided_by_macos
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae that are `keg_only :provided_by_macos` should be added to `style_exceptions/provided_by_macos_formulae.json`
end
RUBY
end
it "succeeds for formulae in provided_by_macos_formulae list" do
setup_style_exceptions
expect_no_offenses(<<~RUBY, "#{path}/Formula/foo.rb")
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
homepage "https://brew.sh"
keg_only :provided_by_macos
end
RUBY
end
it "succeeds for formulae that are keg_only for a different reason" do
setup_style_exceptions
expect_no_offenses(<<~RUBY, "#{path}/Formula/foo.rb")
class Baz < Formula
url "https://brew.sh/foo-1.0.tgz"
homepage "https://brew.sh"
keg_only :versioned_formula
end
RUBY
end
end

View File

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

View File

@ -17,6 +17,4 @@ 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

@ -47,7 +47,6 @@ 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",
@ -242,6 +241,10 @@ RSpec.configure do |config|
CoreTap.instance.path/".git", CoreTap.instance.path/".git",
CoreTap.instance.alias_dir, CoreTap.instance.alias_dir,
CoreTap.instance.path/"formula_renames.json", CoreTap.instance.path/"formula_renames.json",
CoreTap.instance.path/"tap_migrations.json",
CoreTap.instance.path/"audit_exceptions",
CoreTap.instance.path/"style_exceptions",
CoreTap.instance.path/"pypi_formula_mappings.json",
*Pathname.glob("#{HOMEBREW_CELLAR}/*/"), *Pathname.glob("#{HOMEBREW_CELLAR}/*/"),
] ]

View File

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

View File

@ -18,6 +18,8 @@ describe Tap do
before do before do
path.mkpath path.mkpath
(path/"audit_exceptions").mkpath
(path/"style_exceptions").mkpath
end end
def setup_tap_files def setup_tap_files
@ -38,6 +40,27 @@ describe Tap do
{ "removed-formula": "homebrew/foo" } { "removed-formula": "homebrew/foo" }
JSON JSON
%w[audit_exceptions style_exceptions].each do |exceptions_directory|
(path/"#{exceptions_directory}/formula_list.json").write <<~JSON
[ "foo", "bar" ]
JSON
(path/"#{exceptions_directory}/formula_hash.json").write <<~JSON
{ "foo": "foo1", "bar": "bar1" }
JSON
end
(path/"pypi_formula_mappings.json").write <<~JSON
{
"formula1": "foo",
"formula2": {
"package_name": "foo",
"extra_packages": ["bar"],
"exclude_packages": ["baz"]
}
}
JSON
[ [
cmd_file, cmd_file,
manpage_file, manpage_file,
@ -320,6 +343,66 @@ describe Tap do
expect(described_class.each).to be_an_instance_of(Enumerator) expect(described_class.each).to be_an_instance_of(Enumerator)
end end
end end
describe "Formula Lists" do
describe "#formula_renames" do
it "returns the formula_renames hash" do
setup_tap_files
expected_result = { "oldname" => "foo" }
expect(subject.formula_renames).to eq expected_result
end
end
describe "#tap_migrations" do
it "returns the tap_migrations hash" do
setup_tap_files
expected_result = { "removed-formula" => "homebrew/foo" }
expect(subject.tap_migrations).to eq expected_result
end
end
describe "#audit_exceptions" do
it "returns the audit_exceptions hash" do
setup_tap_files
expected_result = {
formula_list: ["foo", "bar"],
formula_hash: { "foo" => "foo1", "bar" => "bar1" },
}
expect(subject.audit_exceptions).to eq expected_result
end
end
describe "#style_exceptions" do
it "returns the style_exceptions hash" do
setup_tap_files
expected_result = {
formula_list: ["foo", "bar"],
formula_hash: { "foo" => "foo1", "bar" => "bar1" },
}
expect(subject.style_exceptions).to eq expected_result
end
end
describe "#pypi_formula_mappings" do
it "returns the pypi_formula_mappings hash" do
setup_tap_files
expected_result = {
"formula1" => "foo",
"formula2" => {
"package_name" => "foo",
"extra_packages" => ["bar"],
"exclude_packages" => ["baz"],
},
}
expect(subject.pypi_formula_mappings).to eq expected_result
end
end
end
end end
describe CoreTap do describe CoreTap do
@ -341,6 +424,7 @@ describe CoreTap do
end end
specify "files" do specify "files" do
path = Tap::TAP_DIRECTORY/"homebrew/homebrew-core"
formula_file = subject.formula_dir/"foo.rb" formula_file = subject.formula_dir/"foo.rb"
formula_file.write <<~RUBY formula_file.write <<~RUBY
class Foo < Formula class Foo < Formula
@ -348,6 +432,18 @@ describe CoreTap do
end end
RUBY RUBY
formula_list_file_json = '{ "foo": "foo1", "bar": "bar1" }'
formula_list_file_contents = { "foo" => "foo1", "bar" => "bar1" }
%w[
formula_renames.json
tap_migrations.json
audit_exceptions/formula_list.json
style_exceptions/formula_hash.json
pypi_formula_mappings.json
].each do |file|
(path/file).write formula_list_file_json
end
alias_file = subject.alias_dir/"bar" alias_file = subject.alias_dir/"bar"
alias_file.parent.mkpath alias_file.parent.mkpath
ln_s formula_file, alias_file ln_s formula_file, alias_file
@ -358,5 +454,11 @@ describe CoreTap do
expect(subject.aliases).to eq(["bar"]) expect(subject.aliases).to eq(["bar"])
expect(subject.alias_table).to eq("bar" => "foo") expect(subject.alias_table).to eq("bar" => "foo")
expect(subject.alias_reverse_table).to eq("foo" => ["bar"]) expect(subject.alias_reverse_table).to eq("foo" => ["bar"])
expect(subject.formula_renames).to eq formula_list_file_contents
expect(subject.tap_migrations).to eq formula_list_file_contents
expect(subject.audit_exceptions).to eq({ formula_list: formula_list_file_contents })
expect(subject.style_exceptions).to eq({ formula_hash: formula_list_file_contents })
expect(subject.pypi_formula_mappings).to eq formula_list_file_contents
end end
end end

View File

@ -1212,6 +1212,8 @@ including core code and all formulae.
Fix style violations automatically using RuboCop's auto-correct feature. Fix style violations automatically using RuboCop's auto-correct feature.
* `--display-cop-names`: * `--display-cop-names`:
Include the RuboCop cop name for each violation in the output. Include the RuboCop cop name for each violation in the output.
* `--reset-cache`:
Reset the RuboCop cache.
* `--only-cops`: * `--only-cops`:
Specify a comma-separated *`cops`* list to check for violations of only the listed RuboCop cops. Specify a comma-separated *`cops`* list to check for violations of only the listed RuboCop cops.
* `--except-cops`: * `--except-cops`:

View File

@ -1673,6 +1673,10 @@ Fix style violations automatically using RuboCop\'s auto\-correct feature\.
Include the RuboCop cop name for each violation in the output\. Include the RuboCop cop name for each violation in the output\.
. .
.TP .TP
\fB\-\-reset\-cache\fR
Reset the RuboCop cache\.
.
.TP
\fB\-\-only\-cops\fR \fB\-\-only\-cops\fR
Specify a comma\-separated \fIcops\fR list to check for violations of only the listed RuboCop cops\. Specify a comma\-separated \fIcops\fR list to check for violations of only the listed RuboCop cops\.
. .