From a5160e355f4e07055d53272c5776028b446c44c3 Mon Sep 17 00:00:00 2001 From: Michael Cho Date: Sat, 23 Mar 2024 22:30:17 -0400 Subject: [PATCH] formula_cellar_checks: more granular mismatched_binary_allowlist Add support for providing more granular glob patterns via the mismatched_binary_allowlist.json rather than an all-or-nothing option. This allows catching any unwanted binaries in new releases. The glob patterns are assumed to be relative to the formula's prefix. Patterns are matched using fnmatch with flags for: * `File::FNM_DOTMATCH` to allow matching all files with `**/*` * `File::FNM_EXTGLOB` to behave like `Dir.glob` for `{a,b}` * `File::FNM_PATHNAME` to allow restricting `*` across directories The original file format of `[""]` should behave similar to `{"": "**/*"}`. Also some changes to add type signature. Signed-off-by: Michael Cho --- Library/Homebrew/formula_cellar_checks.rb | 27 +++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Library/Homebrew/formula_cellar_checks.rb b/Library/Homebrew/formula_cellar_checks.rb index 79738cfea1ec4..160ee87bebb2f 100644 --- a/Library/Homebrew/formula_cellar_checks.rb +++ b/Library/Homebrew/formula_cellar_checks.rb @@ -334,6 +334,7 @@ def check_cpuid_instruction(formula) "No `cpuid` instruction detected. #{formula} should not use `ENV.runtime_cpu_detection`." end + sig { params(formula: Formula).returns(T.nilable(String)) } def check_binary_arches(formula) return unless formula.prefix.directory? @@ -347,19 +348,31 @@ def check_binary_arches(formula) compatible_universal_binaries, mismatches = mismatches.partition do |file, arch| arch == :universal && file.archs.include?(Hardware::CPU.arch) - end.map(&:to_h) # To prevent transformation into nested arrays + end + # To prevent transformation into nested arrays + compatible_universal_binaries = compatible_universal_binaries.to_h + mismatches = mismatches.to_h - universal_binaries_expected = if formula.tap.present? && formula.tap.core_tap? - formula.tap.audit_exception(:universal_binary_allowlist, formula.name) + universal_binaries_expected = if (formula_tap = formula.tap).present? && formula_tap.core_tap? + formula_tap.audit_exception(:universal_binary_allowlist, formula.name) else true end - return if T.must(mismatches).empty? && universal_binaries_expected - mismatches_expected = formula.tap.blank? || - formula.tap.audit_exception(:mismatched_binary_allowlist, formula.name) - return if T.must(compatible_universal_binaries).empty? && mismatches_expected + mismatches_expected = (formula_tap = formula.tap).blank? || + formula_tap.audit_exception(:mismatched_binary_allowlist, formula.name) + mismatches_expected = [mismatches_expected] if mismatches_expected.is_a?(String) + if mismatches_expected.is_a?(Array) + glob_flags = File::FNM_DOTMATCH | File::FNM_EXTGLOB | File::FNM_PATHNAME + mismatches.delete_if do |file, _arch| + mismatches_expected.any? { |pattern| file.fnmatch?("#{formula.prefix.realpath}/#{pattern}", glob_flags) } + end + mismatches_expected = false + return if mismatches.empty? && compatible_universal_binaries.empty? + end + return if mismatches.empty? && universal_binaries_expected + return if compatible_universal_binaries.empty? && mismatches_expected return if universal_binaries_expected && mismatches_expected s = ""