2010-06-23 11:20:47 -07:00
|
|
|
require 'formula'
|
|
|
|
require 'utils'
|
|
|
|
|
|
|
|
def ff
|
2010-07-18 13:57:18 -07:00
|
|
|
return Formula.all if ARGV.named.empty?
|
|
|
|
return ARGV.formulae
|
2010-06-23 11:20:47 -07:00
|
|
|
end
|
|
|
|
|
2010-08-09 11:59:16 -07:00
|
|
|
def audit_formula_text text
|
2010-08-07 15:23:13 -07:00
|
|
|
problems = []
|
|
|
|
|
2010-08-08 10:17:53 -07:00
|
|
|
# Commented-out cmake support from default template
|
2010-08-07 15:23:13 -07:00
|
|
|
if text =~ /# depends_on 'cmake'/
|
2010-07-12 10:34:12 -07:00
|
|
|
problems << " * Commented cmake support found."
|
|
|
|
end
|
|
|
|
|
2010-08-08 10:17:53 -07:00
|
|
|
# SourceForge URL madness
|
2010-08-07 15:23:13 -07:00
|
|
|
if text =~ /\?use_mirror=/
|
2010-07-12 10:34:12 -07:00
|
|
|
problems << " * Remove 'use_mirror' from url."
|
2010-06-23 11:20:47 -07:00
|
|
|
end
|
|
|
|
|
2010-07-23 21:31:32 -07:00
|
|
|
# 2 (or more, if in an if block) spaces before depends_on, please
|
2010-08-07 15:23:13 -07:00
|
|
|
if text =~ /^\ ?depends_on/
|
2010-07-23 21:31:32 -07:00
|
|
|
problems << " * Check indentation of 'depends_on'."
|
|
|
|
end
|
|
|
|
|
2010-08-15 15:19:19 -07:00
|
|
|
# FileUtils is included in Formula
|
|
|
|
if text =~ /FileUtils\.(\w+)/
|
|
|
|
problems << " * Don't need 'FileUtils.' before #{$1}."
|
|
|
|
end
|
|
|
|
|
2010-08-08 10:17:53 -07:00
|
|
|
# Check for string concatenation; prefer interpolation
|
2010-08-07 15:23:13 -07:00
|
|
|
if text =~ /(#\{\w+\s*\+\s*['"][^}]+\})/
|
2010-07-12 10:34:12 -07:00
|
|
|
problems << " * Try not to concatenate paths in string interpolation:\n #{$1}"
|
2010-06-23 11:20:47 -07:00
|
|
|
end
|
|
|
|
|
2010-08-08 10:17:53 -07:00
|
|
|
# Prefer formula path shortcuts in Pathname+
|
|
|
|
if text =~ %r{\(\s*(prefix\s*\+\s*(['"])(bin|include|lib|libexec|sbin|share))}
|
|
|
|
problems << " * \"(#{$1}...#{$2})\" should be \"(#{$3}+...)\""
|
|
|
|
end
|
|
|
|
|
2010-08-15 11:32:45 -07:00
|
|
|
if text =~ %r[((man)\s*\+\s*(['"])(man[1-8])(['"]))]
|
|
|
|
problems << " * \"#{$1}\" should be \"#{$4}\""
|
|
|
|
end
|
|
|
|
|
2010-08-08 10:17:53 -07:00
|
|
|
# Prefer formula path shortcuts in strings
|
|
|
|
if text =~ %r[(\#\{prefix\}/(bin|include|lib|libexec|sbin|share))]
|
|
|
|
problems << " * \"#{$1}\" should be \"\#{#{$2}}\""
|
|
|
|
end
|
|
|
|
|
2010-08-09 11:59:16 -07:00
|
|
|
if text =~ %r[((\#\{prefix\}/share/man/|\#\{man\}/)(man[1-8]))]
|
|
|
|
problems << " * \"#{$1}\" should be \"\#{#{$3}}\""
|
2010-08-08 10:17:53 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
if text =~ %r[(\#\{prefix\}/share/(info|man))]
|
|
|
|
problems << " * \"#{$1}\" should be \"\#{#{$2}}\""
|
|
|
|
end
|
|
|
|
|
2010-08-08 18:25:56 -07:00
|
|
|
# Empty checksums
|
|
|
|
if text =~ /md5\s+\'\'/
|
|
|
|
problems << " * md5 is empty"
|
|
|
|
end
|
|
|
|
|
2010-08-10 11:52:03 -07:00
|
|
|
# No trailing whitespace, please
|
|
|
|
if text =~ /[ ]+$/
|
2010-08-07 15:23:13 -07:00
|
|
|
problems << " * Trailing whitespace was found."
|
|
|
|
end
|
|
|
|
|
2010-08-09 11:59:16 -07:00
|
|
|
return problems
|
|
|
|
end
|
|
|
|
|
2010-08-10 13:04:51 -07:00
|
|
|
def audit_formula_options f, text
|
|
|
|
problems = []
|
|
|
|
|
|
|
|
# Find possible options
|
|
|
|
options = []
|
|
|
|
text.scan(/ARGV\.include\?[ ]*\(?(['"])(.+?)\1/) { |m| options << m[1] }
|
|
|
|
options.reject! {|o| o.include? "#"}
|
|
|
|
options.uniq!
|
|
|
|
|
|
|
|
# Find documented options
|
|
|
|
begin
|
|
|
|
opts = f.options
|
|
|
|
documented_options = []
|
|
|
|
opts.each{ |o| documented_options << o[0] }
|
|
|
|
documented_options.reject! {|o| o.include? "="}
|
|
|
|
rescue
|
|
|
|
documented_options = []
|
|
|
|
end
|
|
|
|
|
|
|
|
if options.length > 0
|
|
|
|
options.each do |o|
|
|
|
|
problems << " * Option #{o} is not documented" unless documented_options.include? o
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if documented_options.length > 0
|
|
|
|
documented_options.each do |o|
|
|
|
|
problems << " * Option #{o} is unused" unless options.include? o
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return problems
|
|
|
|
end
|
|
|
|
|
2010-08-21 11:55:57 -07:00
|
|
|
def audit_formula_instance f
|
|
|
|
problems = []
|
|
|
|
|
|
|
|
# Don't depend_on aliases; use full name
|
|
|
|
aliases = Formula.aliases
|
|
|
|
f.deps.select {|d| aliases.include? d}.each do |d|
|
|
|
|
problems << " * Dep #{d} is an alias; switch to the real name."
|
|
|
|
end
|
|
|
|
|
|
|
|
# Google Code homepages should end in a slash
|
|
|
|
if f.homepage =~ %r[^https?://code\.google\.com/p/[^/]+[^/]$]
|
|
|
|
problems << " * Google Code homepage should end with a slash."
|
|
|
|
end
|
|
|
|
|
|
|
|
return problems
|
|
|
|
end
|
|
|
|
|
2010-08-09 11:59:16 -07:00
|
|
|
def audit_some_formulae
|
|
|
|
ff.each do |f|
|
|
|
|
problems = []
|
2010-07-28 06:25:58 -07:00
|
|
|
|
2010-08-21 11:55:57 -07:00
|
|
|
problems += audit_formula_instance f
|
2010-08-09 11:59:16 -07:00
|
|
|
|
|
|
|
text = ""
|
|
|
|
File.open(f.path, "r") { |afile| text = afile.read }
|
|
|
|
|
2010-08-10 11:52:03 -07:00
|
|
|
# DATA with no __END__
|
|
|
|
if (text =~ /\bDATA\b/) and not (text =~ /^\s*__END__\s*$/)
|
|
|
|
problems << " * 'DATA' was found, but no '__END__'"
|
|
|
|
end
|
|
|
|
|
|
|
|
# Don't try remaining audits on text in __END__
|
|
|
|
text_without_patch = (text.split("__END__")[0]).strip()
|
|
|
|
|
|
|
|
problems += audit_formula_text(text_without_patch)
|
2010-08-10 13:04:51 -07:00
|
|
|
problems += audit_formula_options(f, text_without_patch)
|
2010-08-09 11:59:16 -07:00
|
|
|
|
|
|
|
unless problems.empty?
|
|
|
|
puts "#{f.name}:"
|
|
|
|
puts problems * "\n"
|
|
|
|
puts
|
|
|
|
end
|
2010-06-23 11:20:47 -07:00
|
|
|
end
|
|
|
|
end
|
2010-08-09 11:59:16 -07:00
|
|
|
|
|
|
|
audit_some_formulae
|