audit: Port audit_checksum method to rubocop and add tests
This commit is contained in:
parent
134da5b8c2
commit
d09d5ecc55
@ -12,6 +12,9 @@ FormulaAudit/Text:
|
|||||||
FormulaAudit/Caveats:
|
FormulaAudit/Caveats:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
FormulaAudit/Checksum:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
FormulaAuditStrict/BottleBlock:
|
FormulaAuditStrict/BottleBlock:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
|||||||
@ -1246,7 +1246,6 @@ class ResourceAuditor
|
|||||||
|
|
||||||
def audit
|
def audit
|
||||||
audit_version
|
audit_version
|
||||||
audit_checksum
|
|
||||||
audit_download_strategy
|
audit_download_strategy
|
||||||
audit_urls
|
audit_urls
|
||||||
self
|
self
|
||||||
@ -1273,28 +1272,6 @@ class ResourceAuditor
|
|||||||
problem "version #{version} should not end with an underline and a number"
|
problem "version #{version} should not end with an underline and a number"
|
||||||
end
|
end
|
||||||
|
|
||||||
def audit_checksum
|
|
||||||
return unless checksum
|
|
||||||
|
|
||||||
case checksum.hash_type
|
|
||||||
when :md5
|
|
||||||
problem "MD5 checksums are deprecated, please use SHA256"
|
|
||||||
return
|
|
||||||
when :sha1
|
|
||||||
problem "SHA1 checksums are deprecated, please use SHA256"
|
|
||||||
return
|
|
||||||
when :sha256 then len = 64
|
|
||||||
end
|
|
||||||
|
|
||||||
if checksum.empty?
|
|
||||||
problem "#{checksum.hash_type} is empty"
|
|
||||||
else
|
|
||||||
problem "#{checksum.hash_type} should be #{len} characters" unless checksum.hexdigest.length == len
|
|
||||||
problem "#{checksum.hash_type} contains invalid characters" unless checksum.hexdigest =~ /^[a-fA-F0-9]+$/
|
|
||||||
problem "#{checksum.hash_type} should be lowercase" unless checksum.hexdigest == checksum.hexdigest.downcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def audit_download_strategy
|
def audit_download_strategy
|
||||||
if url =~ %r{^(cvs|bzr|hg|fossil)://} || url =~ %r{^(svn)\+http://}
|
if url =~ %r{^(cvs|bzr|hg|fossil)://} || url =~ %r{^(svn)\+http://}
|
||||||
problem "Use of the #{$&} scheme is deprecated, pass `:using => :#{$1}` instead"
|
problem "Use of the #{$&} scheme is deprecated, pass `:using => :#{$1}` instead"
|
||||||
|
|||||||
@ -5,3 +5,4 @@ require_relative "./rubocops/components_redundancy_cop"
|
|||||||
require_relative "./rubocops/homepage_cop"
|
require_relative "./rubocops/homepage_cop"
|
||||||
require_relative "./rubocops/text_cop"
|
require_relative "./rubocops/text_cop"
|
||||||
require_relative "./rubocops/caveats_cop"
|
require_relative "./rubocops/caveats_cop"
|
||||||
|
require_relative "./rubocops/checksum_cop"
|
||||||
|
|||||||
55
Library/Homebrew/rubocops/checksum_cop.rb
Normal file
55
Library/Homebrew/rubocops/checksum_cop.rb
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
require_relative "./extend/formula_cop"
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module FormulaAudit
|
||||||
|
class Checksum < FormulaCop
|
||||||
|
def audit_formula(_node, _class_node, _parent_class_node, body_node)
|
||||||
|
%w[Stable Devel HEAD].each do |name|
|
||||||
|
next unless spec_node = find_block(body_node, name.downcase.to_sym)
|
||||||
|
_, _, spec_body = *spec_node
|
||||||
|
audit_checksums(spec_body, name)
|
||||||
|
resource_blocks = find_all_blocks(spec_body, :resource)
|
||||||
|
resource_blocks.each do |rb|
|
||||||
|
_, _, resource_body = *rb
|
||||||
|
audit_checksums(resource_body, name, string_content(parameters(rb).first))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def audit_checksums(node, spec, resource_name = nil)
|
||||||
|
msg_prefix = if resource_name
|
||||||
|
"#{spec} resource \"#{resource_name}\": "
|
||||||
|
else
|
||||||
|
"#{spec}: "
|
||||||
|
end
|
||||||
|
if find_node_method_by_name(node, :md5)
|
||||||
|
problem "#{msg_prefix}MD5 checksums are deprecated, please use SHA256"
|
||||||
|
end
|
||||||
|
|
||||||
|
if find_node_method_by_name(node, :sha1)
|
||||||
|
problem "#{msg_prefix}SHA1 checksums are deprecated, please use SHA256"
|
||||||
|
end
|
||||||
|
|
||||||
|
checksum_node = find_node_method_by_name(node, :sha256)
|
||||||
|
checksum = parameters(checksum_node).first
|
||||||
|
if string_content(checksum).size.zero?
|
||||||
|
problem "#{msg_prefix}sha256 is empty"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if string_content(checksum).size != 64 && regex_match_group(checksum, /^\w*$/)
|
||||||
|
problem "#{msg_prefix}sha256 should be 64 characters"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless regex_match_group(checksum, /^[a-f0-9]+$/i)
|
||||||
|
problem "#{msg_prefix}sha256 contains invalid characters"
|
||||||
|
end
|
||||||
|
|
||||||
|
return unless regex_match_group(checksum, /^[a-f0-9]+$/)
|
||||||
|
problem "#{msg_prefix}sha256 should be lowercase"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -176,7 +176,7 @@ module RuboCop
|
|||||||
# Returns an array of block nodes of any depth below node in AST
|
# Returns an array of block nodes of any depth below node in AST
|
||||||
def find_all_blocks(node, block_name)
|
def find_all_blocks(node, block_name)
|
||||||
return if node.nil?
|
return if node.nil?
|
||||||
node.each_descendant(:block).select { |block_node| block_name == block_node.method_name}
|
node.each_descendant(:block).select { |block_node| block_name == block_node.method_name }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns a method definition node with method_name
|
# Returns a method definition node with method_name
|
||||||
@ -256,8 +256,7 @@ module RuboCop
|
|||||||
|
|
||||||
# Returns the array of arguments of the method_node
|
# Returns the array of arguments of the method_node
|
||||||
def parameters(method_node)
|
def parameters(method_node)
|
||||||
return unless method_node.send_type? || method_node.block_type?
|
method_node.method_args if method_node.send_type? || method_node.block_type?
|
||||||
method_node.method_args
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns true if the given parameters are present in method call
|
# Returns true if the given parameters are present in method call
|
||||||
|
|||||||
78
Library/Homebrew/test/rubocops/checksum_cop_spec.rb
Normal file
78
Library/Homebrew/test/rubocops/checksum_cop_spec.rb
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
require "rubocop"
|
||||||
|
require "rubocop/rspec/support"
|
||||||
|
require_relative "../../extend/string"
|
||||||
|
require_relative "../../rubocops/checksum_cop"
|
||||||
|
|
||||||
|
describe RuboCop::Cop::FormulaAudit::Checksum do
|
||||||
|
subject(:cop) { described_class.new }
|
||||||
|
|
||||||
|
context "When auditing spec checksums" do
|
||||||
|
it "When the checksum is empty" do
|
||||||
|
source = <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
url 'http://example.com/foo-1.0.tgz'
|
||||||
|
stable do
|
||||||
|
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz"
|
||||||
|
sha256 ""
|
||||||
|
|
||||||
|
resource "foo-package" do
|
||||||
|
url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz"
|
||||||
|
sha256 ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
expected_offenses = [{ message: "Stable: sha256 is empty",
|
||||||
|
severity: :convention,
|
||||||
|
line: 5,
|
||||||
|
column: 4,
|
||||||
|
source: source },
|
||||||
|
{ message: "Stable resource \"foo-package\": sha256 is empty",
|
||||||
|
severity: :convention,
|
||||||
|
line: 9,
|
||||||
|
column: 6,
|
||||||
|
source: source }]
|
||||||
|
|
||||||
|
inspect_source(cop, source)
|
||||||
|
|
||||||
|
expected_offenses.zip(cop.offenses).each do |expected, actual|
|
||||||
|
expect_offense(expected, actual)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "When the checksum is not 64 characters" do
|
||||||
|
source = <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
url 'http://example.com/foo-1.0.tgz'
|
||||||
|
stable do
|
||||||
|
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz"
|
||||||
|
sha256 "5cf6e1ae0a645b426c0474cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9ad"
|
||||||
|
|
||||||
|
resource "foo-package" do
|
||||||
|
url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz"
|
||||||
|
sha256 "5cf6e1ae0a645b426c047aaa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
expected_offenses = [{ message: "Stable: sha256 should be 64 characters",
|
||||||
|
severity: :convention,
|
||||||
|
line: 5,
|
||||||
|
column: 12,
|
||||||
|
source: source },
|
||||||
|
{ message: "Stable resource \"foo-package\": sha256 should be 64 characters",
|
||||||
|
severity: :convention,
|
||||||
|
line: 9,
|
||||||
|
column: 14,
|
||||||
|
source: source }]
|
||||||
|
|
||||||
|
inspect_source(cop, source)
|
||||||
|
|
||||||
|
expected_offenses.zip(cop.offenses).each do |expected, actual|
|
||||||
|
expect_offense(expected, actual)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
x
Reference in New Issue
Block a user