Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check binary URL resources with RuboCop #6414

Merged
merged 2 commits into from Sep 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 2 additions & 13 deletions Library/Homebrew/dev-cmd/audit.rb
Expand Up @@ -109,7 +109,6 @@ def audit
options[:only_cops] = [:FormulaAudit]
end

options[:display_cop_names] = args.display_cop_names?
# Check style in a single batch run up front for performance
style_results = Style.check_style_json(files, options)

Expand All @@ -118,6 +117,8 @@ def audit
only = only_cops ? ["style"] : args.only
options = { new_formula: new_formula, strict: strict, online: online, only: only, except: args.except }
options[:style_offenses] = style_results.file_offenses(f.path)
options[:display_cop_names] = args.display_cop_names?

fa = FormulaAuditor.new(f, options)
fa.audit
next if fa.problems.empty? && fa.new_formula_problems.empty?
Expand Down Expand Up @@ -919,18 +920,6 @@ def audit_prefix_has_contents
EOS
end

def audit_url_is_not_binary
return unless @core_tap

urls = @specs.map(&:url)

urls.each do |url|
if url =~ /darwin/i && (url =~ /x86_64/i || url =~ /amd64/i)
problem "#{url} looks like a binary package, not a source archive. The `core` tap is source-only."
end
end
end

def quote_dep(dep)
dep.is_a?(Symbol) ? dep.inspect : "'#{dep}'"
end
Expand Down
34 changes: 34 additions & 0 deletions Library/Homebrew/rubocops/urls.rb
Expand Up @@ -7,6 +7,28 @@ module Cop
module FormulaAudit
# This cop audits URLs and mirrors in Formulae.
class Urls < FormulaCop
# These are formulae that, sadly, require an upstream binary to bootstrap.
BINARY_FORMULA_URLS_WHITELIST = %w[
crystal
fpc
ghc
ghc@8.2
go
go@1.9
go@1.10
go@1.11
haskell-stack
ldc
mlton
rust
].freeze

# specific rust-nightly temporarily acceptable until a newer version is released.
# DO NOT RE-ADD A NEWER RUST-NIGHTLY IN FUTURE.
BINARY_URLS_WHITELIST = %w[
https://static.rust-lang.org/dist/2019-08-24/rust-nightly-x86_64-apple-darwin.tar.xz
].freeze

def audit_formula(_node, _class_node, _parent_class_node, body_node)
urls = find_every_func_call_by_name(body_node, :url)
mirrors = find_every_func_call_by_name(body_node, :mirror)
Expand Down Expand Up @@ -202,6 +224,18 @@ def audit_formula(_node, _class_node, _parent_class_node, body_node)
audit_urls(urls, maven_pattern) do |match, url|
problem "#{url} should be `https://search.maven.org/remotecontent?filepath=#{match[1]}`"
end

return if formula_tap != "homebrew-core"

# Check for binary URLs
audit_urls(urls, /(darwin|macos|osx)/i) do |_, url|
next if url !~ /x86_64/i && url !~ /amd64/i
next if BINARY_FORMULA_URLS_WHITELIST.include?(@formula_name)
next if BINARY_URLS_WHITELIST.include?(url)

problem "#{url} looks like a binary package, not a source archive. " \
"Homebrew/homebrew-core is source-only."
end
end
end

Expand Down
78 changes: 0 additions & 78 deletions Library/Homebrew/test/dev-cmd/audit_spec.rb
Expand Up @@ -530,84 +530,6 @@ def formula_gsub_commit(before, after = "")
end
end

describe "#audit_url_is_not_binary" do
specify "it detects a url containing darwin and x86_64" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/example-darwin.x86_64.tar.gz"
end
RUBY

fa.audit_url_is_not_binary

expect(fa.problems.first)
.to match("looks like a binary package, not a source archive. The `core` tap is source-only.")
end

specify "it detects a url containing darwin and amd64" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/example-darwin.amd64.tar.gz"
end
RUBY

fa.audit_url_is_not_binary

expect(fa.problems.first)
.to match("looks like a binary package, not a source archive. The `core` tap is source-only.")
end

specify "it works on the devel spec" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/valid-1.0.tar.gz"

devel do
url "https://brew.sh/example-darwin.x86_64.tar.gz"
end
end
RUBY

fa.audit_url_is_not_binary

expect(fa.problems.first)
.to match("looks like a binary package, not a source archive. The `core` tap is source-only.")
end

specify "it works on the head spec" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/valid-1.0.tar.gz"

head do
url "https://brew.sh/example-darwin.x86_64.tar.gz"
end
end
RUBY

fa.audit_url_is_not_binary

expect(fa.problems.first)
.to match("looks like a binary package, not a source archive. The `core` tap is source-only.")
end

specify "it ignores resource urls" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/valid-1.0.tar.gz"

resource "binary_res" do
url "https://brew.sh/example-darwin.x86_64.tar.gz"
end
end
RUBY

fa.audit_url_is_not_binary

expect(fa.problems).to eq([])
end
end

describe "#audit_versioned_keg_only" do
specify "it warns when a versioned formula is not `keg_only`" do
fa = formula_auditor "foo@1.1", <<~RUBY, core_tap: true
Expand Down
14 changes: 14 additions & 0 deletions Library/Homebrew/test/rubocops/urls_spec.rb
Expand Up @@ -142,12 +142,26 @@
"msg" => "https://central.maven.org/maven2/com/bar/foo/1.1/foo-1.1.jar should be " \
"`https://search.maven.org/remotecontent?filepath=com/bar/foo/1.1/foo-1.1.jar`",
"col" => 2,
}, {
"url" => "https://brew.sh/example-darwin.x86_64.tar.gz",
"msg" => "https://brew.sh/example-darwin.x86_64.tar.gz looks like a binary package, " \
"not a source archive. Homebrew/homebrew-core is source-only.",
"col" => 2,
"formula_tap" => "homebrew-core",
}, {
"url" => "https://brew.sh/example-darwin.amd64.tar.gz",
"msg" => "https://brew.sh/example-darwin.amd64.tar.gz looks like a binary package, " \
"not a source archive. Homebrew/homebrew-core is source-only.",
"col" => 2,
"formula_tap" => "homebrew-core",
}]
}

context "When auditing urls" do
it "with offenses" do
formulae.each do |formula|
allow_any_instance_of(RuboCop::Cop::FormulaCop).to receive(:formula_tap)
.and_return(formula["formula_tap"])
source = <<~RUBY
class Foo < Formula
desc "foo"
Expand Down