| 
									
										
										
										
											2010-06-23 11:20:47 -07:00
										 |  |  | require 'formula' | 
					
						
							|  |  |  | require 'utils' | 
					
						
							| 
									
										
										
											
												superenv: build-environments that just work
1. A minimal build environment, we don't set CFLAGS, CPPFLAGS, LDFLAGS, etc. the rationale being, the less that is set, the less variables we are introducing that can break builds.
2. A set of scripts that replace cc, ld, etc. and inject the -I, -L, etc. flags we need into the args passed to the build-tools.
Because we now have complete control over compiler instantiations we do a variety of clean-up tasks, like removing bad flags, enforcing universal builds and ensuring makefiles don't try to change the order of library and include paths from ones that work to ones that don't.
The previous ENV-system is still available when --env=std is specified.
superenv applies to Xcode >= 4.3 only currently.
											
										 
											2012-08-11 12:30:51 -04:00
										 |  |  | require 'superenv' | 
					
						
							| 
									
										
										
										
											2012-03-17 19:49:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  | module Homebrew extend self | 
					
						
							|  |  |  |   def audit | 
					
						
							|  |  |  |     formula_count = 0
 | 
					
						
							|  |  |  |     problem_count = 0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ff = if ARGV.named.empty? | 
					
						
							| 
									
										
										
										
											2012-08-21 11:39:45 -04:00
										 |  |  |       Formula | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     else | 
					
						
							|  |  |  |       ARGV.formulae | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ff.each do |f| | 
					
						
							|  |  |  |       fa = FormulaAuditor.new f | 
					
						
							|  |  |  |       fa.audit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       unless fa.problems.empty? | 
					
						
							|  |  |  |         puts "#{f.name}:" | 
					
						
							|  |  |  |         fa.problems.each { |p| puts " * #{p}" } | 
					
						
							|  |  |  |         puts | 
					
						
							|  |  |  |         formula_count += 1
 | 
					
						
							|  |  |  |         problem_count += fa.problems.size | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     unless problem_count.zero? | 
					
						
							|  |  |  |       ofail "#{problem_count} problems in #{formula_count} formulae" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							| 
									
										
										
										
											2012-03-17 19:49:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Module | 
					
						
							|  |  |  |   def redefine_const(name, value) | 
					
						
							|  |  |  |     __send__(:remove_const, name) if const_defined?(name) | 
					
						
							|  |  |  |     const_set(name, value) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							| 
									
										
										
										
											2010-06-23 11:20:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  | # Formula extensions for auditing | 
					
						
							|  |  |  | class Formula | 
					
						
							|  |  |  |   def head_only? | 
					
						
							|  |  |  |     @head and @stable.nil? | 
					
						
							| 
									
										
										
										
											2011-06-06 07:25:00 -07:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-03-21 12:57:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def text | 
					
						
							|  |  |  |     @text ||= FormulaText.new(@path) | 
					
						
							| 
									
										
										
										
											2010-07-12 10:34:12 -07:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2010-07-12 10:34:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  | class FormulaText | 
					
						
							|  |  |  |   def initialize path | 
					
						
							|  |  |  |     @text = path.open('r') { |f| f.read } | 
					
						
							| 
									
										
										
										
											2010-07-23 21:31:32 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def without_patch | 
					
						
							|  |  |  |     @text.split("__END__")[0].strip() | 
					
						
							| 
									
										
										
										
											2011-11-29 19:37:39 -06:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def has_DATA? | 
					
						
							|  |  |  |     /\bDATA\b/ =~ @text | 
					
						
							| 
									
										
										
										
											2010-08-15 15:19:19 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def has_END? | 
					
						
							|  |  |  |     /^__END__$/ =~ @text | 
					
						
							| 
									
										
										
										
											2010-09-08 09:07:59 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def has_trailing_newline? | 
					
						
							|  |  |  |     /.+\z/ =~ @text | 
					
						
							| 
									
										
										
										
											2010-09-07 14:34:39 -07:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2010-09-07 14:34:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  | class FormulaAuditor | 
					
						
							|  |  |  |   attr :f | 
					
						
							|  |  |  |   attr :text | 
					
						
							|  |  |  |   attr :problems, true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BUILD_TIME_DEPS = %W[
 | 
					
						
							|  |  |  |     autoconf | 
					
						
							|  |  |  |     automake | 
					
						
							|  |  |  |     boost-build | 
					
						
							|  |  |  |     bsdmake | 
					
						
							|  |  |  |     cmake | 
					
						
							|  |  |  |     imake | 
					
						
							|  |  |  |     libtool | 
					
						
							|  |  |  |     pkg-config | 
					
						
							|  |  |  |     scons | 
					
						
							|  |  |  |     smake | 
					
						
							| 
									
										
										
										
											2012-09-05 21:12:08 -07:00
										 |  |  |     swig | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def initialize f | 
					
						
							|  |  |  |     @f = f | 
					
						
							|  |  |  |     @problems = [] | 
					
						
							|  |  |  |     @text = f.text.without_patch | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # We need to do this in case the formula defines a patch that uses DATA. | 
					
						
							|  |  |  |     f.class.redefine_const :DATA, "" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def audit_file | 
					
						
							|  |  |  |     unless f.path.stat.mode.to_s(8) == "100644" | 
					
						
							|  |  |  |       problem "Incorrect file permissions: chmod 644 #{f.path}" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-06-23 11:20:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if f.text.has_DATA? and not f.text.has_END? | 
					
						
							|  |  |  |       problem "'DATA' was found, but no '__END__'" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-08-08 10:17:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if f.text.has_END? and not f.text.has_DATA? | 
					
						
							|  |  |  |       problem "'__END__' was found, but 'DATA' is not used" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-08-15 11:32:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if f.text.has_trailing_newline? | 
					
						
							|  |  |  |       problem "File should end with a newline" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-08-08 10:17:53 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def audit_deps | 
					
						
							|  |  |  |     problems = [] | 
					
						
							| 
									
										
										
										
											2010-08-08 10:17:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Don't depend_on aliases; use full name | 
					
						
							|  |  |  |     aliases = Formula.aliases | 
					
						
							| 
									
										
										
										
											2012-08-27 21:17:39 -05:00
										 |  |  |     f.deps.select { |d| aliases.include? d.name }.each do |d| | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       problem "Dependency #{d} is an alias; use the canonical name." | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-09-08 09:22:48 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Check for things we don't like to depend on. | 
					
						
							|  |  |  |     # We allow non-Homebrew installs whenever possible. | 
					
						
							|  |  |  |     f.deps.each do |d| | 
					
						
							|  |  |  |       begin | 
					
						
							|  |  |  |         dep_f = Formula.factory d | 
					
						
							|  |  |  |       rescue | 
					
						
							|  |  |  |         problem "Can't find dependency \"#{d}\"." | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2010-08-08 10:17:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       case d.name | 
					
						
							|  |  |  |       when "git", "python", "ruby", "emacs", "mysql", "postgresql", "mercurial" | 
					
						
							|  |  |  |         problem <<-EOS.undent
 | 
					
						
							|  |  |  |           Don't use #{d} as a dependency. We allow non-Homebrew | 
					
						
							|  |  |  |           #{d} installations. | 
					
						
							|  |  |  |           EOS | 
					
						
							|  |  |  |       when 'gfortran' | 
					
						
							|  |  |  |         problem "Use ENV.fortran during install instead of depends_on 'gfortran'" | 
					
						
							|  |  |  |       when 'open-mpi', 'mpich2' | 
					
						
							|  |  |  |         problem <<-EOS.undent
 | 
					
						
							|  |  |  |           There are multiple conflicting ways to install MPI. Use an MPIDependency: | 
					
						
							|  |  |  |             depends_on MPIDependency.new(<lang list>) | 
					
						
							|  |  |  |           Where <lang list> is a comma delimited list that can include: | 
					
						
							|  |  |  |             :cc, :cxx, :f90, :f77 | 
					
						
							|  |  |  |           EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-09-13 15:16:09 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-07 15:23:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def audit_urls | 
					
						
							|  |  |  |     unless f.homepage =~ %r[^https?://] | 
					
						
							|  |  |  |       problem "The homepage should start with http or https." | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-10-08 20:11:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Google Code homepages should end in a slash | 
					
						
							|  |  |  |     if f.homepage =~ %r[^https?://code\.google\.com/p/[^/]+[^/]$] | 
					
						
							|  |  |  |       problem "Google Code homepage should end with a slash." | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-10-30 08:26:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     urls = [(f.stable.url rescue nil), (f.devel.url rescue nil), (f.head.url rescue nil)].compact | 
					
						
							| 
									
										
										
										
											2010-10-21 07:51:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Check GNU urls; doesn't apply to mirrors | 
					
						
							|  |  |  |     if urls.any? { |p| p =~ %r[^(https?|ftp)://(.+)/gnu/] } | 
					
						
							|  |  |  |       problem "\"ftpmirror.gnu.org\" is preferred for GNU software." | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-03-21 12:54:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # the rest of the checks apply to mirrors as well | 
					
						
							|  |  |  |     urls.concat([(f.stable.mirrors rescue nil), (f.devel.mirrors rescue nil)].flatten.compact) | 
					
						
							| 
									
										
										
										
											2011-11-18 15:22:04 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Check SourceForge urls | 
					
						
							|  |  |  |     urls.each do |p| | 
					
						
							|  |  |  |       # Is it a filedownload (instead of svnroot) | 
					
						
							|  |  |  |       next if p =~ %r[/svnroot/] | 
					
						
							|  |  |  |       next if p =~ %r[svn\.sourceforge] | 
					
						
							| 
									
										
										
										
											2011-12-08 22:16:19 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       # Is it a sourceforge http(s) URL? | 
					
						
							|  |  |  |       next unless p =~ %r[^https?://.*\bsourceforge\.] | 
					
						
							| 
									
										
										
										
											2011-12-08 22:16:19 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       if p =~ /(\?|&)use_mirror=/ | 
					
						
							|  |  |  |         problem "Update this url (don't use #{$1}use_mirror)." | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2012-06-17 17:59:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       if p =~ /\/download$/ | 
					
						
							|  |  |  |         problem "Update this url (don't use /download)." | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2012-06-17 18:01:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       if p =~ %r[^http://prdownloads\.] | 
					
						
							| 
									
										
										
										
											2012-09-18 16:26:02 -04:00
										 |  |  |         problem "Update this url (don't use prdownloads). See:\nhttp://librelist.com/browser/homebrew/2011/1/12/prdownloads-is-bad/" | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2010-08-09 11:59:16 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       if p =~ %r[^http://\w+\.dl\.] | 
					
						
							|  |  |  |         problem "Update this url (don't use specific dl mirrors)." | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2012-03-17 19:49:49 -07:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-09-09 14:16:05 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Check for git:// urls; https:// is preferred. | 
					
						
							|  |  |  |     if urls.any? { |p| p =~ %r[^git://github\.com/] } | 
					
						
							|  |  |  |       problem "Use https:// URLs for accessing GitHub repositories." | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-03-15 21:40:09 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def audit_specs | 
					
						
							|  |  |  |     problem "Head-only (no stable download)" if f.head_only? | 
					
						
							| 
									
										
										
										
											2012-01-25 22:41:53 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     [:stable, :devel].each do |spec| | 
					
						
							|  |  |  |       s = f.send(spec) | 
					
						
							|  |  |  |       next if s.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if s.version.to_s.empty? | 
					
						
							|  |  |  |         problem "Invalid or missing #{spec} version" | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2012-07-10 16:10:16 -05:00
										 |  |  |         version_text = s.version unless s.version.detected_from_url? | 
					
						
							|  |  |  |         version_url = Version.parse(s.url) | 
					
						
							| 
									
										
										
										
											2012-08-27 09:44:54 -05:00
										 |  |  |         if version_url.to_s == version_text.to_s | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |           problem "#{spec} version #{version_text} is redundant with version scanned from URL" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2010-09-29 10:21:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       cksum = s.checksum | 
					
						
							|  |  |  |       next if cksum.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       len = case cksum.hash_type | 
					
						
							|  |  |  |         when :md5 then 32
 | 
					
						
							|  |  |  |         when :sha1 then 40
 | 
					
						
							|  |  |  |         when :sha256 then 64
 | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-02 01:25:36 -07:00
										 |  |  |       problem "md5 is broken, deprecated: use sha1 instead" if cksum.hash_type == :md5 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       if cksum.empty? | 
					
						
							|  |  |  |         problem "#{cksum.hash_type} is empty" | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         problem "#{cksum.hash_type} should be #{len} characters" unless cksum.hexdigest.length == len | 
					
						
							|  |  |  |         problem "#{cksum.hash_type} contains invalid characters" unless cksum.hexdigest =~ /^[a-fA-F0-9]+$/ | 
					
						
							|  |  |  |         problem "#{cksum.hash_type} should be lowercase" unless cksum.hexdigest == cksum.hexdigest.downcase | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2011-11-30 13:14:24 -06:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def audit_patches | 
					
						
							|  |  |  |     # Some formulae use ENV in patches, so set up an environment | 
					
						
							|  |  |  |     ENV.setup_build_environment | 
					
						
							| 
									
										
										
										
											2010-09-09 14:16:05 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     Patches.new(f.patches).select { |p| p.external? }.each do |p| | 
					
						
							|  |  |  |       case p.url | 
					
						
							|  |  |  |       when %r[raw\.github\.com], %r[gist\.github\.com/raw] | 
					
						
							| 
									
										
										
										
											2012-09-06 20:47:05 -05:00
										 |  |  |         unless p.url =~ /[a-fA-F0-9]{40}/ | 
					
						
							|  |  |  |           problem "GitHub/Gist patches should specify a revision:\n#{p.url}" | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       when %r[macports/trunk] | 
					
						
							|  |  |  |         problem "MacPorts patches should specify a revision instead of trunk:\n#{p.url}" | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2010-09-09 14:16:05 -07:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-09-09 14:16:05 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def audit_text | 
					
						
							|  |  |  |     if text =~ /<(Formula|AmazonWebServicesFormula|ScriptFileFormula|GithubGistFormula)/ | 
					
						
							|  |  |  |       problem "Use a space in class inheritance: class Foo < #{$1}" | 
					
						
							| 
									
										
										
										
											2010-09-09 14:16:05 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Commented-out cmake support from default template | 
					
						
							|  |  |  |     if (text =~ /# depends_on 'cmake'/) or (text =~ /# system "cmake/) | 
					
						
							| 
									
										
										
										
											2012-09-13 07:14:45 -07:00
										 |  |  |       problem "Commented cmake support found" | 
					
						
							| 
									
										
										
										
											2010-09-09 14:16:05 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # 2 (or more in an if block) spaces before depends_on, please | 
					
						
							|  |  |  |     if text =~ /^\ ?depends_on/ | 
					
						
							| 
									
										
										
										
											2012-09-13 07:14:45 -07:00
										 |  |  |       problem "Check indentation of 'depends_on'" | 
					
						
							| 
									
										
										
										
											2010-09-09 14:16:05 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # build tools should be flagged properly | 
					
						
							| 
									
										
										
										
											2012-09-04 10:43:44 -07:00
										 |  |  |     # but don't complain about automake; it needs autoconf at runtime | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ /depends_on ['"](#{BUILD_TIME_DEPS*'|'})['"]$/ | 
					
						
							|  |  |  |       problem "#{$1} dependency should be \"depends_on '#{$1}' => :build\"" | 
					
						
							| 
									
										
										
										
											2012-09-04 10:43:44 -07:00
										 |  |  |     end unless f.name == "automake" | 
					
						
							| 
									
										
										
										
											2011-06-13 14:20:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # FileUtils is included in Formula | 
					
						
							|  |  |  |     if text =~ /FileUtils\.(\w+)/ | 
					
						
							|  |  |  |       problem "Don't need 'FileUtils.' before #{$1}." | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-09-09 14:16:05 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Check for long inreplace block vars | 
					
						
							|  |  |  |     if text =~ /inreplace .* do \|(.{2,})\|/ | 
					
						
							|  |  |  |       problem "\"inreplace <filenames> do |s|\" is preferred over \"|#{$1}|\"." | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-01-25 22:41:53 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Check for string interpolation of single values. | 
					
						
							|  |  |  |     if text =~ /(system|inreplace|gsub!|change_make_var!) .* ['"]#\{(\w+(\.\w+)?)\}['"]/ | 
					
						
							|  |  |  |       problem "Don't need to interpolate \"#{$2}\" with #{$1}" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-01-25 22:41:53 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Check for string concatenation; prefer interpolation | 
					
						
							|  |  |  |     if text =~ /(#\{\w+\s*\+\s*['"][^}]+\})/ | 
					
						
							|  |  |  |       problem "Try not to concatenate paths in string interpolation:\n   #{$1}" | 
					
						
							| 
									
										
										
										
											2012-04-05 21:12:02 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-01-25 22:41:53 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Prefer formula path shortcuts in Pathname+ | 
					
						
							|  |  |  |     if text =~ %r{\(\s*(prefix\s*\+\s*(['"])(bin|include|libexec|lib|sbin|share)[/'"])} | 
					
						
							|  |  |  |       problem "\"(#{$1}...#{$2})\" should be \"(#{$3}+...)\"" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-06-18 19:58:35 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ %r[((man)\s*\+\s*(['"])(man[1-8])(['"]))] | 
					
						
							|  |  |  |       problem "\"#{$1}\" should be \"#{$4}\"" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-04-05 21:12:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Prefer formula path shortcuts in strings | 
					
						
							|  |  |  |     if text =~ %r[(\#\{prefix\}/(bin|include|libexec|lib|sbin|share))] | 
					
						
							|  |  |  |       problem "\"#{$1}\" should be \"\#{#{$2}}\"" | 
					
						
							| 
									
										
										
										
											2012-04-05 21:12:02 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-01-25 22:41:53 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ %r[((\#\{prefix\}/share/man/|\#\{man\}/)(man[1-8]))] | 
					
						
							|  |  |  |       problem "\"#{$1}\" should be \"\#{#{$3}}\"" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-01-25 22:41:53 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ %r[((\#\{share\}/(man)))[/'"]] | 
					
						
							|  |  |  |       problem "\"#{$1}\" should be \"\#{#{$3}}\"" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-08-21 11:55:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ %r[(\#\{prefix\}/share/(info|man))] | 
					
						
							|  |  |  |       problem "\"#{$1}\" should be \"\#{#{$2}}\"" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-08-21 11:55:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Commented-out depends_on | 
					
						
							|  |  |  |     if text =~ /#\s*depends_on\s+(.+)\s*$/ | 
					
						
							| 
									
										
										
										
											2012-09-13 07:14:45 -07:00
										 |  |  |       problem "Commented-out dep #{$1}" | 
					
						
							| 
									
										
										
										
											2010-09-07 09:23:29 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # No trailing whitespace, please | 
					
						
							|  |  |  |     if text =~ /(\t|[ ])+$/ | 
					
						
							| 
									
										
										
										
											2012-09-13 07:14:45 -07:00
										 |  |  |       problem "Trailing whitespace was found" | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-08-21 11:55:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ /if\s+ARGV\.include\?\s+'--(HEAD|devel)'/ | 
					
						
							|  |  |  |       problem "Use \"if ARGV.build_#{$1.downcase}?\" instead" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-03-17 19:49:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ /make && make/ | 
					
						
							| 
									
										
										
										
											2012-09-13 07:14:45 -07:00
										 |  |  |       problem "Use separate make calls" | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-03-17 19:49:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ /^[ ]*\t/ | 
					
						
							|  |  |  |       problem "Use spaces instead of tabs for indentation" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-05-31 13:23:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # xcodebuild should specify SYMROOT | 
					
						
							|  |  |  |     if text =~ /system\s+['"]xcodebuild/ and not text =~ /SYMROOT=/ | 
					
						
							|  |  |  |       problem "xcodebuild should be passed an explicit \"SYMROOT\"" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-02-16 20:27:08 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 19:18:58 -07:00
										 |  |  |     if text =~ /ENV\.x11/ | 
					
						
							|  |  |  |       problem "Use \"depends_on :x11\" instead of \"ENV.x11\"" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     # Avoid hard-coding compilers | 
					
						
							|  |  |  |     if text =~ %r[(system|ENV\[.+\]\s?=)\s?['"](/usr/bin/)?(gcc|llvm-gcc|clang)['" ]] | 
					
						
							|  |  |  |       problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{$3}\"" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-08-10 11:52:03 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ %r[(system|ENV\[.+\]\s?=)\s?['"](/usr/bin/)?((g|llvm-g|clang)\+\+)['" ]] | 
					
						
							|  |  |  |       problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{$3}\"" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-02-20 15:03:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ /system\s+['"](env|export)/ | 
					
						
							|  |  |  |       problem "Use ENV instead of invoking '#{$1}' to modify the environment" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-01-22 22:32:15 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     if text =~ /version == ['"]HEAD['"]/ | 
					
						
							| 
									
										
										
										
											2012-08-22 20:59:43 -07:00
										 |  |  |       problem "Use 'build.head?' instead of inspecting 'version'" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-25 09:36:01 -07:00
										 |  |  |     if text =~ /build\.include\?\s+['"]\-\-(.*)['"]/ | 
					
						
							| 
									
										
										
										
											2012-09-13 07:14:45 -07:00
										 |  |  |       problem "Reference '#{$1}' without dashes" | 
					
						
							| 
									
										
										
										
											2012-08-25 09:36:01 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-21 13:23:43 -07:00
										 |  |  |     if text =~ /ARGV\.(?!(debug|verbose|find)\?)/ | 
					
						
							| 
									
										
										
										
											2012-09-13 07:14:45 -07:00
										 |  |  |       problem "Use build instead of ARGV to check options" | 
					
						
							| 
									
										
										
										
											2012-08-22 20:59:43 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if text =~ /def options/ | 
					
						
							| 
									
										
										
										
											2012-09-13 07:14:45 -07:00
										 |  |  |       problem "Use new-style option definitions" | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-09-04 18:18:14 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if text =~ /MACOS_VERSION/ | 
					
						
							|  |  |  |       problem "Use MacOS.version instead of MACOS_VERSION" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-09-10 16:40:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if text =~ /(MacOS.((snow_)?leopard|leopard|(mountain_)?lion)\?)/ | 
					
						
							|  |  |  |       problem "#{$1} is deprecated, use a comparison to MacOS.version instead" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-09-13 07:14:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if text =~ /skip_clean\s+:all/ | 
					
						
							|  |  |  |       problem "`skip_clean :all` is deprecated; brew no longer strips symbols" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-08-09 11:59:16 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def audit | 
					
						
							|  |  |  |     audit_file | 
					
						
							|  |  |  |     audit_specs | 
					
						
							|  |  |  |     audit_urls | 
					
						
							|  |  |  |     audit_deps | 
					
						
							|  |  |  |     audit_patches | 
					
						
							|  |  |  |     audit_text | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-11-09 13:00:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   private | 
					
						
							| 
									
										
										
										
											2011-05-31 13:23:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   def problem p | 
					
						
							|  |  |  |     @problems << p | 
					
						
							| 
									
										
										
										
											2010-06-23 11:20:47 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | end |