Merge pull request #9326 from Rylan12/migrate-style-exceptions
Migrate style exceptions to homebrew/core
This commit is contained in:
commit
77b4275f81
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)}` " \
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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")
|
||||||
|
|||||||
@ -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?
|
||||||
|
|||||||
@ -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."
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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!
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
61
Library/Homebrew/test/rubocops/provided_by_macos_spec.rb
Normal file
61
Library/Homebrew/test/rubocops/provided_by_macos_spec.rb
Normal 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
|
||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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}/*/"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -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
|
||||||
|
|||||||
@ -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`:
|
||||||
|
|||||||
@ -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\.
|
||||||
.
|
.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user