diff --git a/Library/Homebrew/rubocops/urls.rb b/Library/Homebrew/rubocops/urls.rb index ca6a22d1ecd3c42497691401ba67a3fe4cb6aca3..5dbceeb83da1953dd0d252435bda3a1d0c88bf6e 100644 --- a/Library/Homebrew/rubocops/urls.rb +++ b/Library/Homebrew/rubocops/urls.rb @@ -315,6 +315,26 @@ module RuboCop "https://pypi.org/project/#{package_name}/#files" end end + + # This cop makes sure that git urls have both a `tag` and `revision`. + # + # @api private + class GitUrls < FormulaCop + def audit_formula(_node, _class_node, _parent_class_node, body_node) + find_method_calls_by_name(body_node, :url).each do |url| + next unless string_content(parameters(url).first).match?(/\.git$/) + + next if url_has_tag_and_revision?(parameters(url).last) + + offending_node(url) + problem "Specify a `tag` and `revision` for git urls" + end + end + + def_node_matcher :url_has_tag_and_revision?, <<~EOS + (hash <(pair (sym :tag) str) (pair (sym :revision) str) ...>) + EOS + end end end end diff --git a/Library/Homebrew/test/rubocops/urls_spec.rb b/Library/Homebrew/test/rubocops/urls_spec.rb index 2d24b5735c69aaa04fdd92c97c43fa2b508e6823..1d6e7e88e5bccb5fd6584c56a793515c638ebbb0 100644 --- a/Library/Homebrew/test/rubocops/urls_spec.rb +++ b/Library/Homebrew/test/rubocops/urls_spec.rb @@ -276,3 +276,123 @@ describe RuboCop::Cop::FormulaAudit::PyPiUrls do end end end + +describe RuboCop::Cop::FormulaAudit::GitUrls do + subject(:cop) { described_class.new } + + context "when a git URL is used" do + it "reports no offenses with a non-git url" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + desc "foo" + url "https://foo.com" + end + RUBY + end + + it "reports no offenses with both a tag and a revision" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + desc "foo" + url "https://github.com/foo/bar.git", + tag: "v1.0.0", + revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + end + RUBY + end + + it "reports no offenses with both a tag, revision and `shallow` before" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + desc "foo" + url "https://github.com/foo/bar.git", + shallow: false, + tag: "v1.0.0", + revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + end + RUBY + end + + it "reports no offenses with both a tag, revision and `shallow` after" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + desc "foo" + url "https://github.com/foo/bar.git", + tag: "v1.0.0", + revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + shallow: false + end + RUBY + end + + it "reports an offense with no `revision`" do + expect_offense(<<~RUBY) + class Foo < Formula + desc "foo" + url "https://github.com/foo/bar.git", + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Specify a `tag` and `revision` for git urls + tag: "v1.0.0" + end + RUBY + end + + it "reports an offense with no `revision` and `shallow`" do + expect_offense(<<~RUBY) + class Foo < Formula + desc "foo" + url "https://github.com/foo/bar.git", + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Specify a `tag` and `revision` for git urls + shallow: false, + tag: "v1.0.0" + end + RUBY + end + + it "reports an offense with no `tag`" do + expect_offense(<<~RUBY) + class Foo < Formula + desc "foo" + url "https://github.com/foo/bar.git", + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Specify a `tag` and `revision` for git urls + revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + end + RUBY + end + + it "reports an offense with no `tag` and `shallow`" do + expect_offense(<<~RUBY) + class Foo < Formula + desc "foo" + url "https://github.com/foo/bar.git", + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Specify a `tag` and `revision` for git urls + revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + shallow: false + end + RUBY + end + + it "reports no offenses with missing arguments in `head`" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + desc "foo" + url "https://foo.com" + head do + url "https://github.com/foo/bar.git" + end + end + RUBY + end + + it "reports no offenses with missing arguments in `devel`" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + desc "foo" + url "https://foo.com" + devel do + url "https://github.com/foo/bar.git" + end + end + RUBY + end + end +end