Merge pull request #807 from ilovezfs/partial_order_compliance
audit: detect partial component order compliance
This commit is contained in:
commit
327f5ca177
@ -72,7 +72,7 @@ module Homebrew
|
|||||||
fa.audit
|
fa.audit
|
||||||
|
|
||||||
next if fa.problems.empty?
|
next if fa.problems.empty?
|
||||||
|
fa.problems
|
||||||
formula_count += 1
|
formula_count += 1
|
||||||
problem_count += fa.problems.size
|
problem_count += fa.problems.size
|
||||||
problem_lines = fa.problems.map { |p| "* #{p.chomp.gsub("\n", "\n ")}" }
|
problem_lines = fa.problems.map { |p| "* #{p.chomp.gsub("\n", "\n ")}" }
|
||||||
@ -121,10 +121,15 @@ class FormulaText
|
|||||||
@text.include? s
|
@text.include? s
|
||||||
end
|
end
|
||||||
|
|
||||||
def line_number(regex)
|
def line_number(regex, skip = 0)
|
||||||
index = @lines.index { |line| line =~ regex }
|
index = @lines.drop(skip).index { |line| line =~ regex }
|
||||||
index ? index + 1 : nil
|
index ? index + 1 : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reverse_line_number(regex)
|
||||||
|
index = @lines.reverse.index { |line| line =~ regex }
|
||||||
|
index ? @lines.count - index : nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class FormulaAuditor
|
class FormulaAuditor
|
||||||
@ -171,6 +176,70 @@ class FormulaAuditor
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def component_problem(before, after, offset = 0)
|
||||||
|
problem "`#{before[1]}` (line #{before[0] + offset}) should be put before `#{after[1]}` (line #{after[0] + offset})"
|
||||||
|
end
|
||||||
|
|
||||||
|
# scan in the reverse direction for remaining problems but report problems
|
||||||
|
# in the forward direction so that contributors don't reverse the order of
|
||||||
|
# lines in the file simply by following instructions
|
||||||
|
def audit_components(reverse = true, previous_pair = nil)
|
||||||
|
component_list = [
|
||||||
|
[/^ include Language::/, "include directive"],
|
||||||
|
[/^ desc ["'][\S\ ]+["']/, "desc"],
|
||||||
|
[/^ homepage ["'][\S\ ]+["']/, "homepage"],
|
||||||
|
[/^ url ["'][\S\ ]+["']/, "url"],
|
||||||
|
[/^ mirror ["'][\S\ ]+["']/, "mirror"],
|
||||||
|
[/^ version ["'][\S\ ]+["']/, "version"],
|
||||||
|
[/^ (sha1|sha256) ["'][\S\ ]+["']/, "checksum"],
|
||||||
|
[/^ revision/, "revision"],
|
||||||
|
[/^ version_scheme/, "version_scheme"],
|
||||||
|
[/^ head ["'][\S\ ]+["']/, "head"],
|
||||||
|
[/^ stable do/, "stable block"],
|
||||||
|
[/^ bottle do/, "bottle block"],
|
||||||
|
[/^ devel do/, "devel block"],
|
||||||
|
[/^ head do/, "head block"],
|
||||||
|
[/^ bottle (:unneeded|:disable)/, "bottle modifier"],
|
||||||
|
[/^ keg_only/, "keg_only"],
|
||||||
|
[/^ option/, "option"],
|
||||||
|
[/^ depends_on/, "depends_on"],
|
||||||
|
[/^ conflicts_with/, "conflicts_with"],
|
||||||
|
[/^ (go_)?resource/, "resource"],
|
||||||
|
[/^ def install/, "install method"],
|
||||||
|
[/^ def caveats/, "caveats method"],
|
||||||
|
[/^ (plist_options|def plist)/, "plist block"],
|
||||||
|
[/^ test do/, "test block"],
|
||||||
|
]
|
||||||
|
if previous_pair
|
||||||
|
previous_before = previous_pair[0]
|
||||||
|
previous_after = previous_pair[1]
|
||||||
|
end
|
||||||
|
offset = (previous_after && previous_after[0] && previous_after[0] >= 1) ? previous_after[0] - 1 : 0
|
||||||
|
present = component_list.map do |regex, name|
|
||||||
|
lineno = if reverse
|
||||||
|
text.reverse_line_number regex
|
||||||
|
else
|
||||||
|
text.line_number regex, offset
|
||||||
|
end
|
||||||
|
next unless lineno
|
||||||
|
[lineno, name]
|
||||||
|
end.compact
|
||||||
|
no_problem = true
|
||||||
|
present.each_cons(2) do |c1, c2|
|
||||||
|
if reverse
|
||||||
|
# scan in the forward direction from the offset
|
||||||
|
audit_components(false, [c1, c2]) if c1[0] > c2[0] # at least one more offense
|
||||||
|
elsif c1[0] > c2[0] && (offset == 0 || previous_pair.nil? || (c1[0] + offset) != previous_before[0] || (c2[0] + offset) != previous_after[0])
|
||||||
|
component_problem c1, c2, offset
|
||||||
|
no_problem = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if no_problem && previous_pair
|
||||||
|
component_problem previous_before, previous_after
|
||||||
|
end
|
||||||
|
present
|
||||||
|
end
|
||||||
|
|
||||||
def audit_file
|
def audit_file
|
||||||
# Under normal circumstances (umask 0022), we expect a file mode of 644. If
|
# Under normal circumstances (umask 0022), we expect a file mode of 644. If
|
||||||
# the user's umask is more restrictive, respect that by masking out the
|
# the user's umask is more restrictive, respect that by masking out the
|
||||||
@ -200,43 +269,8 @@ class FormulaAuditor
|
|||||||
|
|
||||||
return unless @strict
|
return unless @strict
|
||||||
|
|
||||||
component_list = [
|
present = audit_components
|
||||||
[/^ include Language::/, "include directive"],
|
|
||||||
[/^ desc ["'][\S\ ]+["']/, "desc"],
|
|
||||||
[/^ homepage ["'][\S\ ]+["']/, "homepage"],
|
|
||||||
[/^ url ["'][\S\ ]+["']/, "url"],
|
|
||||||
[/^ mirror ["'][\S\ ]+["']/, "mirror"],
|
|
||||||
[/^ version ["'][\S\ ]+["']/, "version"],
|
|
||||||
[/^ (sha1|sha256) ["'][\S\ ]+["']/, "checksum"],
|
|
||||||
[/^ revision/, "revision"],
|
|
||||||
[/^ version_scheme/, "version_scheme"],
|
|
||||||
[/^ head ["'][\S\ ]+["']/, "head"],
|
|
||||||
[/^ stable do/, "stable block"],
|
|
||||||
[/^ bottle do/, "bottle block"],
|
|
||||||
[/^ devel do/, "devel block"],
|
|
||||||
[/^ head do/, "head block"],
|
|
||||||
[/^ bottle (:unneeded|:disable)/, "bottle modifier"],
|
|
||||||
[/^ keg_only/, "keg_only"],
|
|
||||||
[/^ option/, "option"],
|
|
||||||
[/^ depends_on/, "depends_on"],
|
|
||||||
[/^ conflicts_with/, "conflicts_with"],
|
|
||||||
[/^ (go_)?resource/, "resource"],
|
|
||||||
[/^ def install/, "install method"],
|
|
||||||
[/^ def caveats/, "caveats method"],
|
|
||||||
[/^ (plist_options|def plist)/, "plist block"],
|
|
||||||
[/^ test do/, "test block"],
|
|
||||||
]
|
|
||||||
|
|
||||||
present = component_list.map do |regex, name|
|
|
||||||
lineno = text.line_number regex
|
|
||||||
next unless lineno
|
|
||||||
[lineno, name]
|
|
||||||
end.compact
|
|
||||||
present.each_cons(2) do |c1, c2|
|
|
||||||
unless c1[0] < c2[0]
|
|
||||||
problem "`#{c1[1]}` (line #{c1[0]}) should be put before `#{c2[1]}` (line #{c2[0]})"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
present.map!(&:last)
|
present.map!(&:last)
|
||||||
if present.include?("stable block")
|
if present.include?("stable block")
|
||||||
%w[url checksum mirror].each do |component|
|
%w[url checksum mirror].each do |component|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user