Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Library/Homebrew/formula.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3797,12 +3797,12 @@ def stable(&block)
# If called as a method this provides just the {url} for the {SoftwareSpec}.
# If a block is provided you can also add {.depends_on} and {Patch}es just to the {.head} {SoftwareSpec}.
# The download strategies (e.g. `:using =>`) are the same as for {url}.
# `master` is the default branch for Git and doesn't need stating with a `branch:` parameter.
# Git repositories must always specify `branch:`.
#
# ### Example
#
# ```ruby
# head "https://we.prefer.https.over.git.example.com/.git"
# head "https://we.prefer.https.over.git.example.com/.git", branch: "main"
# ```
#
# ```ruby
Expand Down
19 changes: 12 additions & 7 deletions Library/Homebrew/resource_auditor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,18 +178,23 @@ def audit_urls
end

def audit_head_branch
return unless @online
return unless @strict
return if spec_name != :head
return unless Utils::Git.remote_exists?(url)
return if specs[:tag].present?
return if specs[:revision].present?
# Skip `resource` URLs as they use SHAs instead of branch specifiers.
return if name != owner.name
return unless url.end_with?(".git")

problem "Git `head` URL must specify a branch name" if specs[:branch].blank?

return unless @online
return unless Utils::Git.remote_exists?(url)

branch = Utils.popen_read("git", "ls-remote", "--symref", url, "HEAD")
.match(%r{ref: refs/heads/(.*?)\s+HEAD})&.to_a&.second
return if branch.blank? || branch == specs[:branch]
detected_branch = Utils.popen_read("git", "ls-remote", "--symref", url, "HEAD")
.match(%r{ref: refs/heads/(.*?)\s+HEAD})&.to_a&.second
return if detected_branch.blank? || detected_branch == specs[:branch]

problem "Specify the default branch as `branch: \"#{branch}\"`"
problem "Detected a default branch \"#{detected_branch}\", not \"#{specs[:branch]}\""
end

def problem(text)
Expand Down
7 changes: 4 additions & 3 deletions Library/Homebrew/rubocops/components_redundancy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module FormulaAudit
# - `bottle :unneeded`/`:disable` and `bottle do` should not be simultaneously present
# - `stable do` should not be present without a `head` spec
# - `stable do` should not be present with only `url|checksum|mirror|version`
# - `head do` should not be present with only `url`
# - `head do` should not be present with only `url|branch`
class ComponentsRedundancy < FormulaCop
HEAD_MSG = "`head` and `head do` should not be simultaneously present"
BOTTLE_MSG = "`bottle :modifier` and `bottle do` should not be simultaneously present"
Expand Down Expand Up @@ -54,8 +54,9 @@ def audit_formula(formula_nodes)
head_block = find_block(body_node, :head)
if head_block && !head_block.body.nil?
child_nodes = head_block.body.begin_type? ? head_block.body.child_nodes : [head_block.body]
if child_nodes.all? { |n| n.send_type? && n.method_name == :url }
problem "`head do` should not be present with only `url`"
shorthand_head_methods = [:url, :branch]
if child_nodes.all? { |n| n.send_type? && shorthand_head_methods.include?(n.method_name) }
problem "`head do` should not be present with only #{shorthand_head_methods.join("/")}"
end
end

Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/test/dev-cmd/bump_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
content = <<~RUBY
desc "HEAD-only test formula"
homepage "https://brew.sh"
head "https://github.com/Homebrew/brew.git"
head "https://github.com/Homebrew/brew.git", branch: "main"
RUBY
setup_test_formula("headonly", content)

Expand Down
85 changes: 71 additions & 14 deletions Library/Homebrew/test/formula_auditor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ class Foo < Formula
formula_text = <<~RUBY
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license "GPL-3.0-or-later"
end
RUBY
Expand All @@ -301,7 +301,7 @@ class Cask < Formula
formula_text = <<~RUBY
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license all_of: ["GPL-3.0-or-later", "MIT"]
end
RUBY
Expand All @@ -317,7 +317,7 @@ class Cask < Formula
formula_text = <<~RUBY
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license "GPL-3.0-or-later" => { with: "LLVM-exception" }
end
RUBY
Expand All @@ -332,7 +332,7 @@ class Cask < Formula
formula_text = <<~RUBY
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license "GPL-3.0-or-later" => { with: "zzz" }
end
RUBY
Expand All @@ -351,7 +351,7 @@ class Cask < Formula
formula_text = <<~RUBY
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license "GPL-3.0-or-later" => { with: "#{deprecated_spdx_exception}" }
end
RUBY
Expand All @@ -371,7 +371,7 @@ class Cask < Formula
fa = formula_auditor "cask", <<~RUBY, spdx_license_data:, online: true, new_formula: true
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license "GPL-3.0-or-later"
end
RUBY
Expand All @@ -385,7 +385,7 @@ class Cask < Formula
fa = formula_auditor "cask", <<~RUBY, spdx_license_data:, online: true, new_formula: true
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license any_of: ["GPL-3.0-or-later", "MIT"]
end
RUBY
Expand All @@ -399,7 +399,7 @@ class Cask < Formula
formula_text = <<~RUBY
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license "0BSD"
end
RUBY
Expand All @@ -416,7 +416,7 @@ class Cask < Formula
formula_text = <<~RUBY
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license "0BSD"
end
RUBY
Expand All @@ -433,7 +433,7 @@ class Cask < Formula
formula_text = <<~RUBY
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license #{license_any_mismatch}
end
RUBY
Expand All @@ -450,7 +450,7 @@ class Cask < Formula
formula_text = <<~RUBY
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
head "https://github.com/cask/cask.git", branch: "main"
license #{license_any}
end
RUBY
Expand Down Expand Up @@ -714,6 +714,63 @@ class Foo < Formula
expect(fa.problems).to be_empty
end

it "requires `branch:` to be specified for Git head URLs" do
fa = formula_auditor "foo", <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
head "https://github.com/example/foo.git"
end
RUBY

fa.audit_specs
expect(fa.problems.first[:message]).to match("Git `head` URL must specify a branch name")
end

it "suggests a detected default branch for Git head URLs" do
fa = formula_auditor "foo", <<~RUBY, online: true
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
head "https://github.com/Homebrew/homebrew-core.git", branch: "master"
end
RUBY

fa.audit_specs
# This is `.last` because the first problem is the unreachable stable URL.
expect(fa.problems.last[:message]).to match('Detected a default branch "main", not "master"')
end

it "ignores `branch:` for non-Git head URLs" do
fa = formula_auditor "foo", <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
head "https://brew.sh/foo.tgz", branch: "develop"
end
RUBY

fa.audit_specs
expect(fa.problems).not_to match("Git `head` URL must specify a branch name")
end

it "ignores `branch:` for `resource` URLs" do
fa = formula_auditor "foo", <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"

resource "bar" do
url "https://raw.githubusercontent.com/Homebrew/homebrew-core/HEAD/Formula/bar.rb"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
end
end
RUBY

fa.audit_specs
expect(fa.problems).to be_empty
end

it "allows versions with no throttle rate" do
fa = formula_auditor "bar", <<~RUBY, core_tap: true
class Bar < Formula
Expand Down Expand Up @@ -770,7 +827,7 @@ class Foo < Formula
class Bar < Formula
url "https://brew.sh/foo-1.0.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
head "https://brew.sh/foo.git"
head "https://brew.sh/foo.git", branch: "develop"
end
RUBY

Expand All @@ -783,7 +840,7 @@ class Bar < Formula
class BarAT1 < Formula
url "https://brew.sh/foo-1.0.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
head "https://brew.sh/foo.git"
head "https://brew.sh/foo.git", branch: "develop"
end
RUBY

Expand All @@ -796,7 +853,7 @@ class BarAT1 < Formula
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
head "https://brew.sh/foo.git"
head "https://brew.sh/foo.git", branch: "develop"
end
RUBY

Expand Down
4 changes: 2 additions & 2 deletions Library/Homebrew/test/livecheck/livecheck_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
desc "Test formula"
homepage "https://brew.sh"
url "https://brew.sh/test-0.0.1.tgz"
head "https://github.com/Homebrew/brew.git"
head "https://github.com/Homebrew/brew.git", branch: "main"

livecheck do
url "https://formulae.brew.sh/api/formula/ruby.json"
Expand Down Expand Up @@ -252,7 +252,7 @@
desc "Test formula with a duplicate URL"
homepage "https://github.com/Homebrew/brew.git"
url "https://brew.sh/test-0.0.1.tgz"
head "https://github.com/Homebrew/brew.git"
head "https://github.com/Homebrew/brew.git", branch: "main"
end
end

Expand Down
4 changes: 2 additions & 2 deletions Library/Homebrew/test/livecheck/skip_conditions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
desc "Test formula"
homepage "https://brew.sh"
url "https://brew.sh/test-0.0.1.tgz"
head "https://github.com/Homebrew/brew.git"
head "https://github.com/Homebrew/brew.git", branch: "main"

livecheck do
url "https://formulae.brew.sh/api/formula/ruby.json"
Expand All @@ -34,7 +34,7 @@
head_only: formula("test_head_only") do
desc "HEAD-only test formula"
homepage "https://brew.sh"
head "https://github.com/Homebrew/brew.git"
head "https://github.com/Homebrew/brew.git", branch: "main"
end,
gist: formula("test_gist") do
desc "Gist test formula"
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/test/livecheck_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
formula do
homepage "https://brew.sh"
url "https://brew.sh/test-0.0.1.tgz"
head "https://github.com/Homebrew/brew.git"
head "https://github.com/Homebrew/brew.git", branch: "main"
end
end
let(:livecheck_f) { described_class.new(f.class) }
Expand Down
22 changes: 18 additions & 4 deletions Library/Homebrew/test/rubocops/components_redundancy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Foo < Formula
it "reports an offense if both `head` and `head do` are present" do
expect_offense(<<~RUBY)
class Foo < Formula
head "https://brew.sh/foo.git"
head "https://brew.sh/foo.git", branch: "develop"
head do
^^^^^^^ FormulaAudit/ComponentsRedundancy: `head` and `head do` should not be simultaneously present
# stuff
Expand All @@ -50,7 +50,7 @@ class Foo < Formula
it "reports no offenses if `stable do` is present with a `head` method" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
head "https://brew.sh/foo.git"
head "https://brew.sh/foo.git", branch: "develop"

stable do
# stuff
Expand Down Expand Up @@ -82,17 +82,30 @@ class Foo < Formula
end

head do
^^^^^^^ FormulaAudit/ComponentsRedundancy: `head do` should not be present with only `url`
^^^^^^^ FormulaAudit/ComponentsRedundancy: `head do` should not be present with only url/branch
url "https://brew.sh/foo.git"
end
end
RUBY
end

it "reports an offense if `head do` is present with only `url` and `branch`" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"

head do
^^^^^^^ FormulaAudit/ComponentsRedundancy: `head do` should not be present with only url/branch
url "https://brew.sh/foo.git", branch: "develop"
end
end
RUBY
end

it "reports no offenses if `stable do` is present with `url` and `depends_on`" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
head "https://brew.sh/foo.git"
head "https://brew.sh/foo.git", branch: "trunk"

stable do
url "https://brew.sh/foo-1.0.tgz"
Expand All @@ -109,6 +122,7 @@ class Foo < Formula

head do
url "https://brew.sh/foo.git"
branch "develop"
depends_on "bar"
end
end
Expand Down
Loading
Loading