From 3b4e1cb573d2faff6d887c73e7da9a71527ccc8a Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 25 Jun 2024 22:08:48 +0200 Subject: [PATCH 1/4] Share code between cask token and formula name audits. --- Library/Homebrew/cask/audit.rb | 31 +++++-------- Library/Homebrew/formula_auditor.rb | 9 +++- Library/Homebrew/test/cask/audit_spec.rb | 44 +++++-------------- Library/Homebrew/test/formula_auditor_spec.rb | 6 +-- Library/Homebrew/token_auditor.rb | 40 +++++++++++++++++ 5 files changed, 70 insertions(+), 60 deletions(-) create mode 100644 Library/Homebrew/token_auditor.rb diff --git a/Library/Homebrew/cask/audit.rb b/Library/Homebrew/cask/audit.rb index 1d6fa742e4df8..9e10a195fdee9 100644 --- a/Library/Homebrew/cask/audit.rb +++ b/Library/Homebrew/cask/audit.rb @@ -9,6 +9,7 @@ require "source_location" require "system_command" require "utils/backtrace" +require "token_auditor" require "utils/curl" require "utils/git" require "utils/shared_audits" @@ -392,6 +393,15 @@ def audit_languages end end + sig { void } + def audit_token + token_auditor = Homebrew::TokenAuditor.new(cask.token) + return if (errors = token_auditor.errors).empty? + + add_error "Cask token '#{cask.token}' must not contain #{errors.to_sentence(two_words_connector: " or ", + last_word_connector: " or ")}." + end + sig { void } def audit_token_conflicts return unless token_conflicts? @@ -406,27 +416,6 @@ def audit_token_conflicts end end - sig { void } - def audit_token_valid - add_error "cask token contains non-ascii characters" unless cask.token.ascii_only? - add_error "cask token + should be replaced by -plus-" if cask.token.include? "+" - add_error "cask token whitespace should be replaced by hyphens" if cask.token.include? " " - add_error "cask token underscores should be replaced by hyphens" if cask.token.include? "_" - add_error "cask token should not contain double hyphens" if cask.token.include? "--" - - if cask.token.match?(/[^@a-z0-9-]/) - add_error "cask token should only contain lowercase alphanumeric characters, hyphens and @" - end - - if cask.token.start_with?("-", "@") || cask.token.end_with?("-", "@") - add_error "cask token should not have leading or trailing hyphens and/or @" - end - - add_error "cask token @ unrelated to versioning should be replaced by -at-" if cask.token.count("@") > 1 - add_error "cask token should not contain a hyphen followed by @" if cask.token.include? "-@" - add_error "cask token should not contain @ followed by a hyphen" if cask.token.include? "@-" - end - sig { void } def audit_token_bad_words return unless new_cask? diff --git a/Library/Homebrew/formula_auditor.rb b/Library/Homebrew/formula_auditor.rb index f0c63a2e51426..70350d59c4b9b 100644 --- a/Library/Homebrew/formula_auditor.rb +++ b/Library/Homebrew/formula_auditor.rb @@ -3,6 +3,7 @@ require "deprecate_disable" require "formula_versions" +require "token_auditor" require "resource_auditor" require "utils/shared_audits" @@ -160,10 +161,14 @@ def audit_synced_versions_formulae end end - def audit_formula_name + def audit_name name = formula.name - problem "Formula name '#{name}' must not contain uppercase letters." if name != name.downcase + token_auditor = Homebrew::TokenAuditor.new(name) + unless (errors = token_auditor.errors).empty? + problem "Formula name '#{name}' must not contain #{errors.to_sentence(two_words_connector: " or ", + last_word_connector: " or ")}." + end return unless @strict return unless @core_tap diff --git a/Library/Homebrew/test/cask/audit_spec.rb b/Library/Homebrew/test/cask/audit_spec.rb index 6da7326f7fdf9..c38f0b481e321 100644 --- a/Library/Homebrew/test/cask/audit_spec.rb +++ b/Library/Homebrew/test/cask/audit_spec.rb @@ -182,7 +182,7 @@ def tmp_cask(name, text) describe "token validation" do let(:strict) { true } - let(:only) { ["token_valid"] } + let(:only) { ["token"] } let(:cask) do tmp_cask cask_token.to_s, <<~RUBY cask '#{cask_token}' do @@ -200,7 +200,7 @@ def tmp_cask(name, text) let(:cask_token) { "Upper-Case" } it "fails" do - expect(run).to error_with(/lowercase/) + expect(run).to error_with(/not contain uppercase/) end end @@ -208,15 +208,7 @@ def tmp_cask(name, text) let(:cask_token) { "asciiāŒ˜" } it "fails" do - expect(run).to error_with(/contains non-ascii characters/) - end - end - - context "when cask token has +" do - let(:cask_token) { "app++" } - - it "fails" do - expect(run).to error_with(/\+ should be replaced by -plus-/) + expect(run).to error_with(/not contain non-ASCII characters/) end end @@ -240,7 +232,7 @@ def tmp_cask(name, text) let(:cask_token) { "app@stuff@beta" } it "fails" do - expect(run).to error_with(/@ unrelated to versioning should be replaced by -at-/) + expect(run).to error_with(/not contain multiple @ symbols/) end end @@ -248,7 +240,7 @@ def tmp_cask(name, text) let(:cask_token) { "app-@beta" } it "fails" do - expect(run).to error_with(/should not contain a hyphen followed by @/) + expect(run).to error_with(/not contain a hyphen followed by an @/) end end @@ -256,7 +248,7 @@ def tmp_cask(name, text) let(:cask_token) { "app@-beta" } it "fails" do - expect(run).to error_with(/should not contain @ followed by a hyphen/) + expect(run).to error_with(/not contain an @ followed by a hyphen/) end end @@ -264,23 +256,7 @@ def tmp_cask(name, text) let(:cask_token) { "app stuff" } it "fails" do - expect(run).to error_with(/whitespace should be replaced by hyphens/) - end - end - - context "when cask token has underscores" do - let(:cask_token) { "app_stuff" } - - it "fails" do - expect(run).to error_with(/underscores should be replaced by hyphens/) - end - end - - context "when cask token has non-alphanumeric characters" do - let(:cask_token) { "app(stuff)" } - - it "fails" do - expect(run).to error_with(/alphanumeric characters, hyphens and @/) + expect(run).to error_with(/not contain whitespace/) end end @@ -288,7 +264,7 @@ def tmp_cask(name, text) let(:cask_token) { "app--stuff" } it "fails" do - expect(run).to error_with(/should not contain double hyphens/) + expect(run).to error_with(/not contain double hyphens/) end end @@ -296,7 +272,7 @@ def tmp_cask(name, text) let(:cask_token) { "-app" } it "fails" do - expect(run).to error_with(/should not have leading or trailing hyphens/) + expect(run).to error_with(/not contain a leading hyphen/) end end @@ -304,7 +280,7 @@ def tmp_cask(name, text) let(:cask_token) { "app-" } it "fails" do - expect(run).to error_with(/should not have leading or trailing hyphens/) + expect(run).to error_with(/not contain a trailing hyphen/) end end end diff --git a/Library/Homebrew/test/formula_auditor_spec.rb b/Library/Homebrew/test/formula_auditor_spec.rb index 84178498491d6..b32615cbf4c25 100644 --- a/Library/Homebrew/test/formula_auditor_spec.rb +++ b/Library/Homebrew/test/formula_auditor_spec.rb @@ -476,7 +476,7 @@ class Foo < Formula end end - describe "#audit_formula_name" do + describe "#audit_name" do specify "no issue" do fa = formula_auditor "foo", <<~RUBY, core_tap: true, strict: true class Foo < Formula @@ -485,7 +485,7 @@ class Foo < Formula end RUBY - fa.audit_formula_name + fa.audit_name expect(fa.problems).to be_empty end @@ -497,7 +497,7 @@ class Foo < Formula end RUBY - fa.audit_formula_name + fa.audit_name expect(fa.problems.first[:message]).to match "must not contain uppercase letters" end end diff --git a/Library/Homebrew/token_auditor.rb b/Library/Homebrew/token_auditor.rb new file mode 100644 index 0000000000000..11ad69388b4eb --- /dev/null +++ b/Library/Homebrew/token_auditor.rb @@ -0,0 +1,40 @@ +# typed: true +# frozen_string_literal: true + +module Homebrew + class TokenAuditor + sig { returns(String) } + attr_reader :token + + sig { params(token: String).void } + def initialize(token) + @token = token + end + + sig { returns(T::Array[String]) } + def errors + errors = [] + + errors << "uppercase letters" if token.match?(/[A-Z]/) + errors << "whitespace" if token.match?(/\s/) + errors << "non-ASCII characters" unless token.ascii_only? + errors << "double hyphens" if token.include?("--") + + # A bunch of formulae contain these: + # errors << "underscores" if token.include?("_") + # errors << "plus symbols" if token.include?("+") + + errors << "a leading @" if token.start_with?("@") + errors << "a trailing @" if token.end_with?("@") + errors << "a leading hyphen" if token.start_with?("-") + errors << "a trailing hyphen" if token.end_with?("-") + + errors << "multiple @ symbols" if token.count("@") > 1 + + errors << "a hyphen followed by an @" if token.include? "-@" + errors << "an @ followed by a hyphen" if token.include? "@-" + + errors + end + end +end From 40d55f8035c30c40193a69c75361d28a7ddc568a Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 30 Jul 2024 21:43:30 +0200 Subject: [PATCH 2/4] Change type name. --- Library/Homebrew/cask/audit.rb | 4 ++-- Library/Homebrew/formula_auditor.rb | 6 +++--- ...{token_auditor.rb => formula_name_cask_token_auditor.rb} | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename Library/Homebrew/{token_auditor.rb => formula_name_cask_token_auditor.rb} (96%) diff --git a/Library/Homebrew/cask/audit.rb b/Library/Homebrew/cask/audit.rb index 9e10a195fdee9..cacc2afe4ca1b 100644 --- a/Library/Homebrew/cask/audit.rb +++ b/Library/Homebrew/cask/audit.rb @@ -9,7 +9,7 @@ require "source_location" require "system_command" require "utils/backtrace" -require "token_auditor" +require "formula_name_cask_token_auditor" require "utils/curl" require "utils/git" require "utils/shared_audits" @@ -395,7 +395,7 @@ def audit_languages sig { void } def audit_token - token_auditor = Homebrew::TokenAuditor.new(cask.token) + token_auditor = Homebrew::FormulaNameCaskTokenAuditor.new(cask.token) return if (errors = token_auditor.errors).empty? add_error "Cask token '#{cask.token}' must not contain #{errors.to_sentence(two_words_connector: " or ", diff --git a/Library/Homebrew/formula_auditor.rb b/Library/Homebrew/formula_auditor.rb index 70350d59c4b9b..4c2aa07401208 100644 --- a/Library/Homebrew/formula_auditor.rb +++ b/Library/Homebrew/formula_auditor.rb @@ -3,7 +3,7 @@ require "deprecate_disable" require "formula_versions" -require "token_auditor" +require "formula_name_cask_token_auditor" require "resource_auditor" require "utils/shared_audits" @@ -164,8 +164,8 @@ def audit_synced_versions_formulae def audit_name name = formula.name - token_auditor = Homebrew::TokenAuditor.new(name) - unless (errors = token_auditor.errors).empty? + name_auditor = Homebrew::FormulaNameCaskTokenAuditor.new(name) + unless (errors = name_auditor.errors).empty? problem "Formula name '#{name}' must not contain #{errors.to_sentence(two_words_connector: " or ", last_word_connector: " or ")}." end diff --git a/Library/Homebrew/token_auditor.rb b/Library/Homebrew/formula_name_cask_token_auditor.rb similarity index 96% rename from Library/Homebrew/token_auditor.rb rename to Library/Homebrew/formula_name_cask_token_auditor.rb index 11ad69388b4eb..78b708b56764b 100644 --- a/Library/Homebrew/token_auditor.rb +++ b/Library/Homebrew/formula_name_cask_token_auditor.rb @@ -2,7 +2,7 @@ # frozen_string_literal: true module Homebrew - class TokenAuditor + class FormulaNameCaskTokenAuditor sig { returns(String) } attr_reader :token From 77e3a405f54b32f4a38af3b622b923f58c50d678 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 30 Jul 2024 21:44:10 +0200 Subject: [PATCH 3/4] Remove unneeded rules. --- Library/Homebrew/formula_name_cask_token_auditor.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Library/Homebrew/formula_name_cask_token_auditor.rb b/Library/Homebrew/formula_name_cask_token_auditor.rb index 78b708b56764b..2789db89f6a7d 100644 --- a/Library/Homebrew/formula_name_cask_token_auditor.rb +++ b/Library/Homebrew/formula_name_cask_token_auditor.rb @@ -20,10 +20,6 @@ def errors errors << "non-ASCII characters" unless token.ascii_only? errors << "double hyphens" if token.include?("--") - # A bunch of formulae contain these: - # errors << "underscores" if token.include?("_") - # errors << "plus symbols" if token.include?("+") - errors << "a leading @" if token.start_with?("@") errors << "a trailing @" if token.end_with?("@") errors << "a leading hyphen" if token.start_with?("-") From 4a1643e7ad6cfdf5dca40a9384f289f82af5060f Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 30 Jul 2024 21:48:59 +0200 Subject: [PATCH 4/4] Refactor condition. --- Library/Homebrew/cask/audit.rb | 2 +- Library/Homebrew/formula_auditor.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/cask/audit.rb b/Library/Homebrew/cask/audit.rb index cacc2afe4ca1b..217b7250a4eb3 100644 --- a/Library/Homebrew/cask/audit.rb +++ b/Library/Homebrew/cask/audit.rb @@ -396,7 +396,7 @@ def audit_languages sig { void } def audit_token token_auditor = Homebrew::FormulaNameCaskTokenAuditor.new(cask.token) - return if (errors = token_auditor.errors).empty? + return if (errors = token_auditor.errors).none? add_error "Cask token '#{cask.token}' must not contain #{errors.to_sentence(two_words_connector: " or ", last_word_connector: " or ")}." diff --git a/Library/Homebrew/formula_auditor.rb b/Library/Homebrew/formula_auditor.rb index 4c2aa07401208..1c0319a6307da 100644 --- a/Library/Homebrew/formula_auditor.rb +++ b/Library/Homebrew/formula_auditor.rb @@ -165,7 +165,7 @@ def audit_name name = formula.name name_auditor = Homebrew::FormulaNameCaskTokenAuditor.new(name) - unless (errors = name_auditor.errors).empty? + if (errors = name_auditor.errors).any? problem "Formula name '#{name}' must not contain #{errors.to_sentence(two_words_connector: " or ", last_word_connector: " or ")}." end