| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-24 16:14:44 +01:00
										 |  |  | require "formula" | 
					
						
							| 
									
										
										
										
											2016-01-14 13:33:56 +08:00
										 |  |  | require "formula_versions" | 
					
						
							| 
									
										
										
										
											2017-12-03 14:02:55 +01:00
										 |  |  | require "utils/curl" | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  | require "utils/notability" | 
					
						
							| 
									
										
										
										
											2020-08-04 10:07:57 -07:00
										 |  |  | require "utils/spdx" | 
					
						
							| 
									
										
										
										
											2015-05-24 16:14:44 +01:00
										 |  |  | require "extend/ENV" | 
					
						
							|  |  |  | require "formula_cellar_checks" | 
					
						
							| 
									
										
										
										
											2015-05-31 18:40:28 +08:00
										 |  |  | require "cmd/search" | 
					
						
							| 
									
										
										
										
											2018-06-05 23:19:18 -04:00
										 |  |  | require "style" | 
					
						
							| 
									
										
										
										
											2015-07-09 15:28:27 +01:00
										 |  |  | require "date" | 
					
						
							| 
									
										
										
										
											2017-03-18 17:02:08 +02:00
										 |  |  | require "missing_formula" | 
					
						
							| 
									
										
										
										
											2017-02-02 21:25:29 +00:00
										 |  |  | require "digest" | 
					
						
							| 
									
										
										
										
											2019-04-17 18:25:08 +09:00
										 |  |  | require "cli/parser" | 
					
						
							| 
									
										
										
										
											2020-06-16 01:00:36 +08:00
										 |  |  | require "json" | 
					
						
							| 
									
										
										
										
											2012-03-17 19:49:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-18 22:41:47 -05:00
										 |  |  | module Homebrew | 
					
						
							| 
									
										
										
										
											2016-09-26 01:44:51 +02:00
										 |  |  |   module_function | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-30 18:25:38 +05:30
										 |  |  |   def audit_args | 
					
						
							|  |  |  |     Homebrew::CLI::Parser.new do | 
					
						
							| 
									
										
										
										
											2018-09-08 22:21:04 +05:30
										 |  |  |       usage_banner <<~EOS | 
					
						
							| 
									
										
										
										
											2019-08-06 14:17:17 -04:00
										 |  |  |         `audit` [<options>] [<formula>] | 
					
						
							| 
									
										
										
										
											2018-06-28 09:28:19 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-30 21:33:03 +00:00
										 |  |  |         Check <formula> for Homebrew coding style violations. This should be run before | 
					
						
							| 
									
										
										
										
											2019-08-20 00:04:14 -04:00
										 |  |  |         submitting a new formula. If no <formula> are provided, check all locally | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |         available formulae and skip style checks. Will exit with a non-zero status if any | 
					
						
							|  |  |  |         errors are found. | 
					
						
							| 
									
										
										
										
											2018-06-28 09:28:19 +05:30
										 |  |  |       EOS | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       switch "--strict", | 
					
						
							| 
									
										
										
										
											2020-04-16 08:24:38 +01:00
										 |  |  |              description: "Run additional, stricter style checks." | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       switch "--git", | 
					
						
							|  |  |  |              description: "Run additional, slower style checks that navigate the Git repository." | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       switch "--online", | 
					
						
							| 
									
										
										
										
											2020-04-16 08:24:38 +01:00
										 |  |  |              description: "Run additional, slower style checks that require a network connection." | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       switch "--new-formula", | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |              description: "Run various additional style checks to determine if a new formula is eligible "\ | 
					
						
							|  |  |  |                           "for Homebrew. This should be used when creating new formula and implies "\ | 
					
						
							|  |  |  |                           "`--strict` and `--online`." | 
					
						
							| 
									
										
										
										
											2020-08-06 09:43:02 +01:00
										 |  |  |       flag   "--tap=", | 
					
						
							|  |  |  |              description: "Check the formulae within the given tap, specified as <user>`/`<repo>." | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       switch "--fix", | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |              description: "Fix style violations automatically using RuboCop's auto-correct feature." | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       switch "--display-cop-names", | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |              description: "Include the RuboCop cop name for each violation in the output." | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       switch "--display-filename", | 
					
						
							| 
									
										
										
										
											2019-08-06 14:22:24 -04:00
										 |  |  |              description: "Prefix every line of output with the file or formula name being audited, to "\ | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |                           "make output easy to grep." | 
					
						
							| 
									
										
										
										
											2020-04-16 08:24:38 +01:00
										 |  |  |       switch "--skip-style", | 
					
						
							|  |  |  |              description: "Skip running non-RuboCop style checks. Useful if you plan on running "\ | 
					
						
							| 
									
										
										
										
											2020-08-06 09:43:02 +01:00
										 |  |  |                           "`brew style` separately. Default unless a formula is specified by name" | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       switch "-D", "--audit-debug", | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |              description: "Enable debugging and profiling of audit methods." | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       comma_array "--only", | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |                   description: "Specify a comma-separated <method> list to only run the methods named "\ | 
					
						
							|  |  |  |                                "`audit_`<method>." | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       comma_array "--except", | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |                   description: "Specify a comma-separated <method> list to skip running the methods named "\ | 
					
						
							|  |  |  |                                "`audit_`<method>." | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       comma_array "--only-cops", | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |                   description: "Specify a comma-separated <cops> list to check for violations of only the listed "\ | 
					
						
							|  |  |  |                                "RuboCop cops." | 
					
						
							| 
									
										
										
										
											2018-09-22 09:31:30 +05:30
										 |  |  |       comma_array "--except-cops", | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |                   description: "Specify a comma-separated <cops> list to skip checking for violations of the listed "\ | 
					
						
							|  |  |  |                                "RuboCop cops." | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-08 22:49:03 -04:00
										 |  |  |       conflicts "--only", "--except" | 
					
						
							| 
									
										
										
										
											2019-12-11 14:59:47 -05:00
										 |  |  |       conflicts "--only-cops", "--except-cops", "--strict" | 
					
						
							|  |  |  |       conflicts "--only-cops", "--except-cops", "--only" | 
					
						
							| 
									
										
										
										
											2020-04-16 08:24:38 +01:00
										 |  |  |       conflicts "--display-cop-names", "--skip-style" | 
					
						
							|  |  |  |       conflicts "--display-cop-names", "--only-cops" | 
					
						
							|  |  |  |       conflicts "--display-cop-names", "--except-cops" | 
					
						
							| 
									
										
										
										
											2018-03-25 17:48:22 +05:30
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2018-07-30 18:25:38 +05:30
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def audit | 
					
						
							| 
									
										
										
										
											2020-07-23 06:25:35 +02:00
										 |  |  |     args = audit_args.parse | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-02 12:38:18 +05:30
										 |  |  |     Homebrew.auditing = true | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     inject_dump_stats!(FormulaAuditor, /^audit_/) if args.audit_debug? | 
					
						
							| 
									
										
										
										
											2016-04-18 17:39:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     formula_count = 0
 | 
					
						
							|  |  |  |     problem_count = 0
 | 
					
						
							| 
									
										
										
										
											2018-08-26 19:33:19 +05:30
										 |  |  |     corrected_problem_count = 0
 | 
					
						
							| 
									
										
										
										
											2018-05-22 18:16:46 +05:30
										 |  |  |     new_formula_problem_count = 0
 | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     new_formula = args.new_formula? | 
					
						
							|  |  |  |     strict = new_formula || args.strict? | 
					
						
							|  |  |  |     online = new_formula || args.online? | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |     git = args.git? | 
					
						
							| 
									
										
										
										
											2020-08-06 09:43:02 +01:00
										 |  |  |     skip_style = args.skip_style? || args.no_named? || args.tap | 
					
						
							| 
									
										
										
										
											2015-07-09 12:31:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-28 02:04:50 +02:00
										 |  |  |     ENV.activate_extensions! | 
					
						
							|  |  |  |     ENV.setup_build_environment | 
					
						
							| 
									
										
										
										
											2013-05-07 18:39:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 09:43:02 +01:00
										 |  |  |     audit_formulae = if args.tap | 
					
						
							|  |  |  |       Tap.fetch(args.tap).formula_names.map { |name| Formula[name] } | 
					
						
							|  |  |  |     elsif args.no_named? | 
					
						
							|  |  |  |       Formula | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       args.resolved_formulae | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |     style_files = args.formulae_paths unless skip_style | 
					
						
							| 
									
										
										
										
											2016-08-16 17:00:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     only_cops = args.only_cops | 
					
						
							|  |  |  |     except_cops = args.except_cops | 
					
						
							| 
									
										
										
										
											2020-08-02 03:36:09 +02:00
										 |  |  |     options = { fix: args.fix?, debug: args.debug?, verbose: args.verbose? } | 
					
						
							| 
									
										
										
										
											2017-05-03 11:33:00 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     if only_cops | 
					
						
							| 
									
										
										
										
											2017-05-03 11:33:00 +05:30
										 |  |  |       options[:only_cops] = only_cops | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     elsif args.new_formula? | 
					
						
							| 
									
										
										
										
											2017-07-28 05:01:01 +05:30
										 |  |  |       nil | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     elsif except_cops | 
					
						
							| 
									
										
										
										
											2017-05-03 11:33:00 +05:30
										 |  |  |       options[:except_cops] = except_cops | 
					
						
							|  |  |  |     elsif !strict | 
					
						
							| 
									
										
										
										
											2020-04-16 08:24:38 +01:00
										 |  |  |       options[:except_cops] = [:FormulaAuditStrict] | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2014-12-27 12:38:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-23 04:09:13 +05:30
										 |  |  |     # Check style in a single batch run up front for performance | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |     style_results = Style.check_style_json(style_files, options) if style_files | 
					
						
							| 
									
										
										
										
											2020-06-16 00:19:32 +08:00
										 |  |  |     # load licenses | 
					
						
							| 
									
										
										
										
											2020-08-04 10:07:57 -07:00
										 |  |  |     spdx_data = SPDX.spdx_data | 
					
						
							| 
									
										
										
										
											2018-04-30 01:22:04 +05:30
										 |  |  |     new_formula_problem_lines = [] | 
					
						
							| 
									
										
										
										
											2020-04-16 08:24:38 +01:00
										 |  |  |     audit_formulae.sort.each do |f| | 
					
						
							| 
									
										
										
										
											2018-10-30 23:44:14 +05:30
										 |  |  |       only = only_cops ? ["style"] : args.only | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       options = { | 
					
						
							| 
									
										
										
										
											2020-06-24 18:32:53 +08:00
										 |  |  |         new_formula: new_formula, | 
					
						
							|  |  |  |         strict:      strict, | 
					
						
							|  |  |  |         online:      online, | 
					
						
							|  |  |  |         git:         git, | 
					
						
							|  |  |  |         only:        only, | 
					
						
							|  |  |  |         except:      args.except, | 
					
						
							| 
									
										
										
										
											2020-06-24 20:43:33 +08:00
										 |  |  |         spdx_data:   spdx_data, | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       } | 
					
						
							|  |  |  |       options[:style_offenses] = style_results.file_offenses(f.path) if style_results | 
					
						
							| 
									
										
										
										
											2019-09-02 10:48:19 +01:00
										 |  |  |       options[:display_cop_names] = args.display_cop_names? | 
					
						
							| 
									
										
										
										
											2020-07-26 09:44:10 +02:00
										 |  |  |       options[:build_stable] = args.build_stable? | 
					
						
							| 
									
										
										
										
											2019-09-02 10:48:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-18 17:39:21 -04:00
										 |  |  |       fa = FormulaAuditor.new(f, options) | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       fa.audit | 
					
						
							| 
									
										
										
										
											2018-05-22 17:02:20 +05:30
										 |  |  |       next if fa.problems.empty? && fa.new_formula_problems.empty? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 07:00:39 -07:00
										 |  |  |       fa.problems | 
					
						
							| 
									
										
										
										
											2016-04-18 17:39:21 -04:00
										 |  |  |       formula_count += 1
 | 
					
						
							|  |  |  |       problem_count += fa.problems.size | 
					
						
							| 
									
										
										
										
											2018-04-30 01:22:04 +05:30
										 |  |  |       problem_lines = format_problem_lines(fa.problems) | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       corrected_problem_count = options[:style_offenses].count(&:corrected?) if options[:style_offenses] | 
					
						
							| 
									
										
										
										
											2018-04-30 01:22:04 +05:30
										 |  |  |       new_formula_problem_lines = format_problem_lines(fa.new_formula_problems) | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |       if args.display_filename? | 
					
						
							| 
									
										
										
										
											2016-05-16 18:46:47 +01:00
										 |  |  |         puts problem_lines.map { |s| "#{f.path}: #{s}" } | 
					
						
							| 
									
										
										
										
											2016-05-11 09:19:45 -07:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2016-05-16 18:46:47 +01:00
										 |  |  |         puts "#{f.full_name}:", problem_lines.map { |s| "  #{s}" } | 
					
						
							| 
									
										
										
										
											2016-05-11 09:19:45 -07:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-18 13:50:43 +01:00
										 |  |  |     new_formula_problem_count += new_formula_problem_lines.size | 
					
						
							|  |  |  |     puts new_formula_problem_lines.map { |s| "  #{s}" } | 
					
						
							| 
									
										
										
										
											2018-04-30 01:22:04 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-22 18:16:46 +05:30
										 |  |  |     total_problems_count = problem_count + new_formula_problem_count | 
					
						
							| 
									
										
										
										
											2018-09-17 20:11:11 +02:00
										 |  |  |     problem_plural = "#{total_problems_count} #{"problem".pluralize(total_problems_count)}" | 
					
						
							|  |  |  |     formula_plural = "#{formula_count} #{"formula".pluralize(formula_count)}" | 
					
						
							|  |  |  |     corrected_problem_plural = "#{corrected_problem_count} #{"problem".pluralize(corrected_problem_count)}" | 
					
						
							| 
									
										
										
										
											2018-08-26 19:33:19 +05:30
										 |  |  |     errors_summary = "#{problem_plural} in #{formula_plural} detected" | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |     errors_summary += ", #{corrected_problem_plural} corrected" if corrected_problem_count.positive? | 
					
						
							| 
									
										
										
										
											2018-05-22 18:16:46 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-25 12:52:42 +01:00
										 |  |  |     ofail errors_summary if problem_count.positive? || new_formula_problem_count.positive? | 
					
						
							| 
									
										
										
										
											2018-04-30 01:22:04 +05:30
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-09-22 20:12:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-30 01:22:04 +05:30
										 |  |  |   def format_problem_lines(problems) | 
					
						
							| 
									
										
										
										
											2019-01-22 13:30:24 +00:00
										 |  |  |     problems.uniq.map { |p| "* #{p.chomp.gsub("\n", "\n    ")}" } | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-03-17 19:49:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |   class FormulaText | 
					
						
							|  |  |  |     def initialize(path) | 
					
						
							|  |  |  |       @text = path.open("rb", &:read) | 
					
						
							|  |  |  |       @lines = @text.lines.to_a | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-07-23 21:31:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def without_patch | 
					
						
							|  |  |  |       @text.split("\n__END__").first | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-11-29 19:37:39 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def trailing_newline? | 
					
						
							|  |  |  |       /\Z\n/ =~ @text | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-02-24 15:54:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def =~(other) | 
					
						
							|  |  |  |       other =~ @text | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-06-08 18:57:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def include?(s) | 
					
						
							|  |  |  |       @text.include? s | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-07-13 18:28:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def line_number(regex, skip = 0) | 
					
						
							|  |  |  |       index = @lines.drop(skip).index { |line| line =~ regex } | 
					
						
							|  |  |  |       index ? index + 1 : nil | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-08-25 07:00:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def reverse_line_number(regex) | 
					
						
							|  |  |  |       index = @lines.reverse.index { |line| line =~ regex } | 
					
						
							|  |  |  |       index ? @lines.count - index : nil | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-08-25 07:00:39 -07:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-09-07 14:34:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |   class FormulaAuditor | 
					
						
							|  |  |  |     include FormulaCellarChecks | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 04:14:57 +08:00
										 |  |  |     attr_reader :formula, :text, :problems, :new_formula_problems | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def initialize(formula, options = {}) | 
					
						
							|  |  |  |       @formula = formula | 
					
						
							| 
									
										
										
										
											2018-10-19 11:16:04 +10:00
										 |  |  |       @versioned_formula = formula.versioned_formula? | 
					
						
							| 
									
										
										
										
											2018-10-24 13:54:05 +10:00
										 |  |  |       @new_formula_inclusive = options[:new_formula] | 
					
						
							| 
									
										
										
										
											2018-10-19 11:16:04 +10:00
										 |  |  |       @new_formula = options[:new_formula] && !@versioned_formula | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       @strict = options[:strict] | 
					
						
							|  |  |  |       @online = options[:online] | 
					
						
							| 
									
										
										
										
											2020-07-26 09:44:10 +02:00
										 |  |  |       @build_stable = options[:build_stable] | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       @git = options[:git] | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       @display_cop_names = options[:display_cop_names] | 
					
						
							|  |  |  |       @only = options[:only] | 
					
						
							|  |  |  |       @except = options[:except] | 
					
						
							|  |  |  |       # Accept precomputed style offense results, for efficiency | 
					
						
							|  |  |  |       @style_offenses = options[:style_offenses] | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |       # Allow the formula tap to be set as homebrew/core, for testing purposes | 
					
						
							| 
									
										
										
										
											2018-10-11 17:37:43 +10:00
										 |  |  |       @core_tap = formula.tap&.core_tap? || options[:core_tap] | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       @problems = [] | 
					
						
							| 
									
										
										
										
											2018-04-30 01:22:04 +05:30
										 |  |  |       @new_formula_problems = [] | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       @text = FormulaText.new(formula.path) | 
					
						
							|  |  |  |       @specs = %w[stable devel head].map { |s| formula.send(s) }.compact | 
					
						
							| 
									
										
										
										
											2020-06-23 01:42:24 +08:00
										 |  |  |       @spdx_data = options[:spdx_data] | 
					
						
							| 
									
										
										
										
											2016-04-18 17:39:21 -04:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_style | 
					
						
							|  |  |  |       return unless @style_offenses | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       @style_offenses.each do |offense| | 
					
						
							|  |  |  |         problem offense.to_s(display_cop_name: @display_cop_names) | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-08-25 07:00:39 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_file | 
					
						
							| 
									
										
										
										
											2018-07-17 06:48:31 -04:00
										 |  |  |       if formula.core_formula? && @versioned_formula | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         unversioned_formula = begin | 
					
						
							|  |  |  |           # build this ourselves as we want e.g. homebrew/core to be present | 
					
						
							|  |  |  |           full_name = if formula.tap | 
					
						
							|  |  |  |             "#{formula.tap}/#{formula.name}" | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             formula.name | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |           Formulary.factory(full_name.gsub(/@.*$/, "")).path | 
					
						
							|  |  |  |         rescue FormulaUnavailableError, TapFormulaAmbiguityError, | 
					
						
							|  |  |  |                TapFormulaWithOldnameAmbiguityError | 
					
						
							|  |  |  |           Pathname.new formula.path.to_s.gsub(/@.*\.rb$/, ".rb") | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         unless unversioned_formula.exist? | 
					
						
							|  |  |  |           unversioned_name = unversioned_formula.basename(".rb") | 
					
						
							|  |  |  |           problem "#{formula} is versioned but no #{unversioned_name} formula exists" | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2020-07-26 09:44:10 +02:00
										 |  |  |       elsif @build_stable && formula.stable? && | 
					
						
							| 
									
										
										
										
											2018-05-12 14:35:50 -04:00
										 |  |  |             !(versioned_formulae = formula.versioned_formulae).empty? | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         versioned_aliases = formula.aliases.grep(/.@\d/) | 
					
						
							| 
									
										
										
										
											2018-05-12 14:35:50 -04:00
										 |  |  |         _, last_alias_version = versioned_formulae.map(&:name).last.split("@") | 
					
						
							| 
									
										
										
										
											2020-08-11 12:40:35 -07:00
										 |  |  |         alias_name_major = "#{formula.name}@#{formula.version.major}" | 
					
						
							|  |  |  |         alias_name_major_minor = "#{alias_name_major}.#{formula.version.minor}" | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         alias_name = if last_alias_version.split(".").length == 1
 | 
					
						
							|  |  |  |           alias_name_major | 
					
						
							| 
									
										
										
										
											2017-04-22 13:00:36 +01:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |           alias_name_major_minor | 
					
						
							| 
									
										
										
										
											2017-04-22 13:00:36 +01:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         valid_alias_names = [alias_name_major, alias_name_major_minor] | 
					
						
							| 
									
										
										
										
											2017-05-09 15:10:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-11 17:37:43 +10:00
										 |  |  |         unless @core_tap | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |           versioned_aliases.map! { |a| "#{formula.tap}/#{a}" } | 
					
						
							|  |  |  |           valid_alias_names.map! { |a| "#{formula.tap}/#{a}" } | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2017-05-17 15:18:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 16:37:39 +01:00
										 |  |  |         # Fix naming based on what people expect. | 
					
						
							|  |  |  |         if alias_name_major_minor == "adoptopenjdk@1.8" | 
					
						
							|  |  |  |           valid_alias_names << "adoptopenjdk@8" | 
					
						
							|  |  |  |           valid_alias_names.delete "adoptopenjdk@1" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         valid_versioned_aliases = versioned_aliases & valid_alias_names | 
					
						
							|  |  |  |         invalid_versioned_aliases = versioned_aliases - valid_alias_names | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if valid_versioned_aliases.empty? | 
					
						
							|  |  |  |           if formula.tap | 
					
						
							|  |  |  |             problem <<~EOS | 
					
						
							|  |  |  |               Formula has other versions so create a versioned alias: | 
					
						
							|  |  |  |                 cd #{formula.tap.alias_dir} | 
					
						
							|  |  |  |                 ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name} | 
					
						
							|  |  |  |             EOS | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             problem "Formula has other versions so create an alias named #{alias_name}." | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2017-05-09 15:10:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 16:37:39 +01:00
										 |  |  |         if invalid_versioned_aliases.present? | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |           problem <<~EOS | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |             Formula has invalid versioned aliases: | 
					
						
							|  |  |  |               #{invalid_versioned_aliases.join("\n  ")} | 
					
						
							| 
									
										
										
										
											2017-05-09 15:10:29 +01:00
										 |  |  |           EOS | 
					
						
							| 
									
										
										
										
											2017-03-26 20:36:37 +01:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2017-05-09 15:10:29 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-02-23 09:14:54 +00:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-05-31 18:40:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def self.aliases | 
					
						
							|  |  |  |       # core aliases + tap alias names + tap alias full name | 
					
						
							|  |  |  |       @aliases ||= Formula.aliases + Formula.tap_aliases | 
					
						
							| 
									
										
										
										
											2016-11-20 00:40:54 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_formula_name | 
					
						
							|  |  |  |       return unless @strict | 
					
						
							| 
									
										
										
										
											2018-10-11 17:37:43 +10:00
										 |  |  |       return unless @core_tap | 
					
						
							| 
									
										
										
										
											2015-05-31 18:40:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       name = formula.name | 
					
						
							| 
									
										
										
										
											2015-08-09 14:48:12 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 21:10:16 +01:00
										 |  |  |       problem "'#{name}' is not allowed in homebrew/core." if MissingFormula.disallowed_reason(name) | 
					
						
							| 
									
										
										
										
											2015-09-07 18:54:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       if Formula.aliases.include? name | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |         problem "Formula name conflicts with existing aliases in homebrew/core." | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         return | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2015-05-31 18:40:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       if oldname = CoreTap.instance.formula_renames[name] | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |         problem "'#{name}' is reserved as the old name of #{oldname} in homebrew/core." | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         return | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2014-10-17 00:11:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       return if formula.core_formula? | 
					
						
							|  |  |  |       return unless Formula.core_names.include?(name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       problem "Formula name conflicts with existing core formula." | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 08:19:41 -07:00
										 |  |  |     PROVIDED_BY_MACOS_DEPENDS_ON_ALLOWLIST = %w[
 | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  |       apr | 
					
						
							|  |  |  |       apr-util | 
					
						
							| 
									
										
										
										
											2020-07-18 15:23:27 -07:00
										 |  |  |       libressl | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  |       openblas | 
					
						
							|  |  |  |       openssl@1.1
 | 
					
						
							|  |  |  |     ].freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 20:42:54 +10:00
										 |  |  |     PERMITTED_LICENSE_MISMATCHES = { | 
					
						
							|  |  |  |       "AGPL-3.0" => ["AGPL-3.0-only", "AGPL-3.0-or-later"], | 
					
						
							|  |  |  |       "GPL-2.0"  => ["GPL-2.0-only",  "GPL-2.0-or-later"], | 
					
						
							|  |  |  |       "GPL-3.0"  => ["GPL-3.0-only",  "GPL-3.0-or-later"], | 
					
						
							|  |  |  |       "LGPL-2.1" => ["LGPL-2.1-only", "LGPL-2.1-or-later"], | 
					
						
							|  |  |  |       "LGPL-3.0" => ["LGPL-3.0-only", "LGPL-3.0-or-later"], | 
					
						
							|  |  |  |     }.freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 03:38:06 +08:00
										 |  |  |     def audit_license | 
					
						
							| 
									
										
										
										
											2020-07-02 09:04:58 +01:00
										 |  |  |       if formula.license.present? | 
					
						
							| 
									
										
										
										
											2020-08-04 10:47:41 +01:00
										 |  |  |         non_standard_licenses = formula.license.map do |license| | 
					
						
							|  |  |  |           next if license == :public_domain | 
					
						
							| 
									
										
										
										
											2020-07-25 21:39:29 +08:00
										 |  |  |           next if @spdx_data["licenses"].any? { |spdx| spdx["licenseId"] == license } | 
					
						
							| 
									
										
										
										
											2020-07-12 13:21:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 10:47:41 +01:00
										 |  |  |           license | 
					
						
							|  |  |  |         end.compact | 
					
						
							| 
									
										
										
										
											2020-07-12 12:35:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if non_standard_licenses.present? | 
					
						
							| 
									
										
										
										
											2020-07-25 21:39:29 +08:00
										 |  |  |           problem "Formula #{formula.name} contains non-standard SPDX licenses: #{non_standard_licenses}." | 
					
						
							| 
									
										
										
										
											2020-07-12 12:35:27 +08:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 13:39:27 -04:00
										 |  |  |         if @strict | 
					
						
							|  |  |  |           deprecated_licenses = formula.license.map do |license| | 
					
						
							|  |  |  |             next if license == :public_domain | 
					
						
							|  |  |  |             next if @spdx_data["licenses"].any? do |spdx| | 
					
						
							|  |  |  |               spdx["licenseId"] == license && !spdx["isDeprecatedLicenseId"] | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             license | 
					
						
							|  |  |  |           end.compact | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if deprecated_licenses.present? | 
					
						
							|  |  |  |             problem "Formula #{formula.name} contains deprecated SPDX licenses: #{deprecated_licenses}." | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-12 13:21:42 +08:00
										 |  |  |         return unless @online | 
					
						
							| 
									
										
										
										
											2020-06-16 01:00:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-12 13:21:42 +08:00
										 |  |  |         user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @new_formula | 
					
						
							|  |  |  |         return if user.blank? | 
					
						
							| 
									
										
										
										
											2020-06-16 01:00:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-12 13:21:42 +08:00
										 |  |  |         github_license = GitHub.get_repo_license(user, repo) | 
					
						
							|  |  |  |         return if github_license && (formula.license + ["NOASSERTION"]).include?(github_license) | 
					
						
							| 
									
										
										
										
											2020-08-04 20:42:54 +10:00
										 |  |  |         return if PERMITTED_LICENSE_MISMATCHES[github_license]&.any? { |license| formula.license.include? license } | 
					
						
							| 
									
										
										
										
											2020-07-12 12:35:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 20:42:54 +10:00
										 |  |  |         problem "Formula license #{formula.license} does not match GitHub license #{Array(github_license)}." | 
					
						
							| 
									
										
										
										
											2020-07-12 12:35:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 20:42:54 +10:00
										 |  |  |       elsif @new_formula && @core_tap | 
					
						
							|  |  |  |         problem "Formulae in homebrew/core must specify a license." | 
					
						
							| 
									
										
										
										
											2020-06-13 02:43:02 +08:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-06-16 01:00:36 +08:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-06-13 03:43:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_deps | 
					
						
							|  |  |  |       @specs.each do |spec| | 
					
						
							|  |  |  |         # Check for things we don't like to depend on. | 
					
						
							|  |  |  |         # We allow non-Homebrew installs whenever possible. | 
					
						
							|  |  |  |         spec.deps.each do |dep| | 
					
						
							|  |  |  |           begin | 
					
						
							|  |  |  |             dep_f = dep.to_formula | 
					
						
							|  |  |  |           rescue TapFormulaUnavailableError | 
					
						
							|  |  |  |             # Don't complain about missing cross-tap dependencies | 
					
						
							|  |  |  |             next | 
					
						
							|  |  |  |           rescue FormulaUnavailableError | 
					
						
							|  |  |  |             problem "Can't find dependency #{dep.name.inspect}." | 
					
						
							|  |  |  |             next | 
					
						
							|  |  |  |           rescue TapFormulaAmbiguityError | 
					
						
							|  |  |  |             problem "Ambiguous dependency #{dep.name.inspect}." | 
					
						
							|  |  |  |             next | 
					
						
							|  |  |  |           rescue TapFormulaWithOldnameAmbiguityError | 
					
						
							|  |  |  |             problem "Ambiguous oldname dependency #{dep.name.inspect}." | 
					
						
							|  |  |  |             next | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2015-08-09 14:48:12 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |           if dep_f.oldname && dep.name.split("/").last == dep_f.oldname | 
					
						
							|  |  |  |             problem "Dependency '#{dep.name}' was renamed; use new name '#{dep_f.name}'." | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2014-10-17 00:07:35 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |           if self.class.aliases.include?(dep.name) && | 
					
						
							| 
									
										
										
										
											2020-07-31 16:37:39 +01:00
										 |  |  |              dep_f.core_formula? && !dep_f.versioned_formula? | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |             problem "Dependency '#{dep.name}' from homebrew/core is an alias; " \ | 
					
						
							|  |  |  |             "use the canonical name '#{dep.to_formula.full_name}'." | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |           end | 
					
						
							| 
									
										
										
										
											2017-03-19 20:45:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-27 19:25:26 -07:00
										 |  |  |           if @core_tap && | 
					
						
							|  |  |  |              @new_formula && | 
					
						
							| 
									
										
										
										
											2020-04-13 14:19:58 +10:00
										 |  |  |              dep_f.keg_only? && | 
					
						
							| 
									
										
										
										
											2020-04-11 14:15:42 +01:00
										 |  |  |              dep_f.keg_only_reason.provided_by_macos? && | 
					
						
							|  |  |  |              dep_f.keg_only_reason.applicable? && | 
					
						
							| 
									
										
										
										
											2020-07-21 08:19:41 -07:00
										 |  |  |              !PROVIDED_BY_MACOS_DEPENDS_ON_ALLOWLIST.include?(dep.name) | 
					
						
							| 
									
										
										
										
											2018-09-02 16:15:09 +01:00
										 |  |  |             new_formula_problem( | 
					
						
							| 
									
										
										
										
											2019-10-10 17:29:57 +02:00
										 |  |  |               "Dependency '#{dep.name}' is provided by macOS; " \ | 
					
						
							|  |  |  |               "please replace 'depends_on' with 'uses_from_macos'.", | 
					
						
							| 
									
										
										
										
											2018-09-02 16:15:09 +01:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           dep.options.each do |opt| | 
					
						
							| 
									
										
										
										
											2019-01-22 13:30:24 +00:00
										 |  |  |             next if @core_tap | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |             next if dep_f.option_defined?(opt) | 
					
						
							| 
									
										
										
										
											2018-09-02 20:14:54 +01:00
										 |  |  |             next if dep_f.requirements.find do |r| | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |               if r.recommended? | 
					
						
							|  |  |  |                 opt.name == "with-#{r.name}" | 
					
						
							|  |  |  |               elsif r.optional? | 
					
						
							|  |  |  |                 opt.name == "without-#{r.name}" | 
					
						
							|  |  |  |               end | 
					
						
							| 
									
										
										
										
											2014-10-17 00:07:35 -05:00
										 |  |  |             end | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             problem "Dependency #{dep} does not define option #{opt.name.inspect}" | 
					
						
							| 
									
										
										
										
											2014-02-16 22:35:14 +00:00
										 |  |  |           end | 
					
						
							| 
									
										
										
										
											2017-10-07 00:31:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 12:12:26 +00:00
										 |  |  |           problem "Don't use git as a dependency (it's always available)" if @new_formula && dep.name == "git" | 
					
						
							| 
									
										
										
										
											2013-01-23 00:26:31 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |           problem "Dependency '#{dep.name}' is marked as :run. Remove :run; it is a no-op." if dep.tags.include?(:run) | 
					
						
							| 
									
										
										
										
											2018-05-22 19:39:10 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-11 17:37:43 +10:00
										 |  |  |           next unless @core_tap | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-22 19:39:10 +10:00
										 |  |  |           if dep.tags.include?(:recommended) || dep.tags.include?(:optional) | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |             problem "Formulae in homebrew/core should not have optional or recommended dependencies" | 
					
						
							| 
									
										
										
										
											2018-05-22 19:39:10 +10:00
										 |  |  |           end | 
					
						
							| 
									
										
										
										
											2018-03-19 10:11:08 +00:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2018-07-11 23:21:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-11 17:37:43 +10:00
										 |  |  |         next unless @core_tap | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-11 23:21:41 +10:00
										 |  |  |         if spec.requirements.map(&:recommended?).any? || spec.requirements.map(&:optional?).any? | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |           problem "Formulae in homebrew/core should not have optional or recommended requirements" | 
					
						
							| 
									
										
										
										
											2018-07-11 23:21:41 +10:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2018-03-19 10:11:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_conflicts | 
					
						
							|  |  |  |       formula.conflicts.each do |c| | 
					
						
							| 
									
										
										
										
											2019-10-13 10:03:26 +01:00
										 |  |  |         Formulary.factory(c.name) | 
					
						
							|  |  |  |       rescue TapFormulaUnavailableError | 
					
						
							|  |  |  |         # Don't complain about missing cross-tap conflicts. | 
					
						
							|  |  |  |         next | 
					
						
							|  |  |  |       rescue FormulaUnavailableError | 
					
						
							|  |  |  |         problem "Can't find conflicting formula #{c.name.inspect}." | 
					
						
							|  |  |  |       rescue TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError | 
					
						
							|  |  |  |         problem "Ambiguous conflicting formula #{c.name.inspect}." | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-09-13 15:16:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-09 19:31:19 +00:00
										 |  |  |     def audit_postgresql | 
					
						
							|  |  |  |       return unless formula.name == "postgresql" | 
					
						
							| 
									
										
										
										
											2019-01-22 13:30:24 +00:00
										 |  |  |       return unless @core_tap | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-11 12:40:35 -07:00
										 |  |  |       major_version = formula.version.major.to_i | 
					
						
							| 
									
										
										
										
											2018-12-09 19:31:19 +00:00
										 |  |  |       previous_major_version = major_version - 1
 | 
					
						
							|  |  |  |       previous_formula_name = "postgresql@#{previous_major_version}" | 
					
						
							|  |  |  |       begin | 
					
						
							|  |  |  |         Formula[previous_formula_name] | 
					
						
							|  |  |  |       rescue FormulaUnavailableError | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |         problem "Versioned #{previous_formula_name} in homebrew/core must be created for " \ | 
					
						
							| 
									
										
										
										
											2018-12-09 19:31:19 +00:00
										 |  |  |                 "`brew-postgresql-upgrade-database` and `pg_upgrade` to work." | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 16:37:39 +01:00
										 |  |  |     # openssl@1.1 only needed for Linux | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |     VERSIONED_KEG_ONLY_ALLOWLIST = %w[
 | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  |       autoconf@2.13
 | 
					
						
							|  |  |  |       bash-completion@2
 | 
					
						
							|  |  |  |       gnupg@1.4
 | 
					
						
							| 
									
										
										
										
											2020-05-31 22:39:29 +01:00
										 |  |  |       libsigc++@2
 | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  |       lua@5.1
 | 
					
						
							|  |  |  |       numpy@1.16
 | 
					
						
							| 
									
										
										
										
											2020-07-31 16:37:39 +01:00
										 |  |  |       openssl@1.1
 | 
					
						
							| 
									
										
										
										
											2020-05-31 22:39:29 +01:00
										 |  |  |       python@3.8
 | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  |     ].freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-26 13:57:21 +10:00
										 |  |  |     def audit_versioned_keg_only | 
					
						
							| 
									
										
										
										
											2018-10-19 11:16:04 +10:00
										 |  |  |       return unless @versioned_formula | 
					
						
							| 
									
										
										
										
											2018-08-26 13:57:21 +10:00
										 |  |  |       return unless @core_tap | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-07 10:27:17 +00:00
										 |  |  |       if formula.keg_only? | 
					
						
							| 
									
										
										
										
											2020-04-11 14:15:42 +01:00
										 |  |  |         return if formula.keg_only_reason.versioned_formula? | 
					
						
							| 
									
										
										
										
											2018-12-07 10:27:17 +00:00
										 |  |  |         if formula.name.start_with?("openssl", "libressl") && | 
					
						
							| 
									
										
										
										
											2020-04-22 01:00:35 +01:00
										 |  |  |            formula.keg_only_reason.by_macos? | 
					
						
							| 
									
										
										
										
											2018-12-07 10:27:17 +00:00
										 |  |  |           return | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2018-08-26 13:57:21 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 16:37:39 +01:00
										 |  |  |       return if VERSIONED_KEG_ONLY_ALLOWLIST.include?(formula.name) | 
					
						
							|  |  |  |       return if formula.name.start_with?("adoptopenjdk@") | 
					
						
							|  |  |  |       return if formula.name.start_with?("gcc@") | 
					
						
							| 
									
										
										
										
											2018-08-26 13:57:21 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |       problem "Versioned formulae in homebrew/core should use `keg_only :versioned_formula`" | 
					
						
							| 
									
										
										
										
											2018-08-26 13:57:21 +10:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_homepage | 
					
						
							|  |  |  |       homepage = formula.homepage | 
					
						
							| 
									
										
										
										
											2017-04-28 04:53:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       return if homepage.nil? || homepage.empty? | 
					
						
							| 
									
										
										
										
											2014-09-14 15:43:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       return unless @online | 
					
						
							| 
									
										
										
										
											2017-02-26 16:49:09 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       return unless DevelopmentTools.curl_handles_most_https_certificates? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       if http_content_problem = curl_check_http_content(homepage, | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |                                                         user_agents:   [:browser, :default], | 
					
						
							|  |  |  |                                                         check_content: true, | 
					
						
							|  |  |  |                                                         strict:        @strict) | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         problem http_content_problem | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-12-23 20:29:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-24 13:54:05 +10:00
										 |  |  |     def audit_bottle_spec | 
					
						
							|  |  |  |       # special case: new versioned formulae should be audited | 
					
						
							|  |  |  |       return unless @new_formula_inclusive | 
					
						
							|  |  |  |       return unless @core_tap | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return if formula.bottle_disabled? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return unless formula.bottle_defined? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |       new_formula_problem "New formulae in homebrew/core should not have a `bottle do` block" | 
					
						
							| 
									
										
										
										
											2018-10-24 13:54:05 +10:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-04 13:19:16 +10:00
										 |  |  |     def audit_bottle_disabled | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       return unless formula.bottle_disabled? | 
					
						
							| 
									
										
										
										
											2018-07-04 13:19:16 +10:00
										 |  |  |       return if formula.bottle_unneeded? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |       problem "Unrecognized bottle modifier" unless formula.bottle_disable_reason.valid? | 
					
						
							| 
									
										
										
										
											2019-01-22 13:30:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       return unless @core_tap | 
					
						
							| 
									
										
										
										
											2019-02-19 13:12:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |       problem "Formulae in homebrew/core should not use `bottle :disabled`" | 
					
						
							| 
									
										
										
										
											2018-07-04 13:19:16 +10:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 21:52:35 +02:00
										 |  |  |     def audit_github_repository_archived | 
					
						
							|  |  |  |       return if formula.deprecated? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @online | 
					
						
							|  |  |  |       return if user.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       metadata = SharedAudits.github_repo_data(user, repo) | 
					
						
							|  |  |  |       return if metadata.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       problem "GitHub repo is archived" if metadata["archived"] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def audit_gitlab_repository_archived | 
					
						
							|  |  |  |       return if formula.deprecated? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) if @online | 
					
						
							|  |  |  |       return if user.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       metadata = SharedAudits.gitlab_repo_data(user, repo) | 
					
						
							|  |  |  |       return if metadata.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       problem "GitLab repo is archived" if metadata["archived"] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_github_repository | 
					
						
							| 
									
										
										
										
											2020-06-25 05:09:56 +08:00
										 |  |  |       user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @new_formula | 
					
						
							| 
									
										
										
										
											2020-06-28 02:07:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-29 16:12:05 +08:00
										 |  |  |       return if user.blank? | 
					
						
							| 
									
										
										
										
											2015-07-08 14:22:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  |       warning = SharedAudits.github(user, repo) | 
					
						
							|  |  |  |       return if warning.nil? | 
					
						
							| 
									
										
										
										
											2016-03-13 01:40:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  |       new_formula_problem warning | 
					
						
							| 
									
										
										
										
											2015-07-08 14:22:44 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 14:50:02 +02:00
										 |  |  |     def audit_gitlab_repository | 
					
						
							| 
									
										
										
										
											2020-06-25 05:09:56 +08:00
										 |  |  |       user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) if @new_formula | 
					
						
							| 
									
										
										
										
											2020-06-29 16:12:05 +08:00
										 |  |  |       return if user.blank? | 
					
						
							| 
									
										
										
										
											2019-07-02 14:50:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  |       warning = SharedAudits.gitlab(user, repo) | 
					
						
							|  |  |  |       return if warning.nil? | 
					
						
							| 
									
										
										
										
											2019-07-02 14:50:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  |       new_formula_problem warning | 
					
						
							| 
									
										
										
										
											2019-07-02 14:50:02 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-05 20:27:00 +02:00
										 |  |  |     def audit_bitbucket_repository | 
					
						
							| 
									
										
										
										
											2020-06-25 05:09:56 +08:00
										 |  |  |       user, repo = get_repo_data(%r{https?://bitbucket\.org/([^/]+)/([^/]+)/?.*}) if @new_formula | 
					
						
							| 
									
										
										
										
											2020-06-29 16:12:05 +08:00
										 |  |  |       return if user.blank? | 
					
						
							| 
									
										
										
										
											2019-09-05 20:27:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  |       warning = SharedAudits.bitbucket(user, repo) | 
					
						
							|  |  |  |       return if warning.nil? | 
					
						
							| 
									
										
										
										
											2019-09-05 20:27:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  |       new_formula_problem warning | 
					
						
							| 
									
										
										
										
											2019-09-05 20:27:00 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-19 04:20:19 +08:00
										 |  |  |     def get_repo_data(regex) | 
					
						
							| 
									
										
										
										
											2019-07-02 14:50:02 +02:00
										 |  |  |       return unless @core_tap | 
					
						
							|  |  |  |       return unless @online | 
					
						
							| 
									
										
										
										
											2020-06-16 01:00:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 14:50:02 +02:00
										 |  |  |       _, user, repo = *regex.match(formula.stable.url) if formula.stable | 
					
						
							|  |  |  |       _, user, repo = *regex.match(formula.homepage) unless user | 
					
						
							| 
									
										
										
										
											2020-07-13 11:04:27 -04:00
										 |  |  |       _, user, repo = *regex.match(formula.head.url) if !user && formula.head | 
					
						
							| 
									
										
										
										
											2019-07-02 14:50:02 +02:00
										 |  |  |       return if !user || !repo | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-25 12:18:41 +01:00
										 |  |  |       repo.delete_suffix!(".git") | 
					
						
							| 
									
										
										
										
											2019-07-02 14:50:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       [user, repo] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |     VERSIONED_HEAD_SPEC_ALLOWLIST = %w[
 | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  |       bash-completion@2
 | 
					
						
							|  |  |  |       imagemagick@6
 | 
					
						
							|  |  |  |     ].freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-11 11:28:37 -04:00
										 |  |  |     THROTTLED_FORMULAE = { | 
					
						
							|  |  |  |       "aws-sdk-cpp" => 10, | 
					
						
							|  |  |  |       "awscli@1"    => 10, | 
					
						
							|  |  |  |       "balena-cli"  => 10, | 
					
						
							|  |  |  |       "gatsby-cli"  => 10, | 
					
						
							|  |  |  |       "quicktype"   => 10, | 
					
						
							|  |  |  |       "vim"         => 50, | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  |     }.freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |     UNSTABLE_ALLOWLIST = { | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  |       "aalib"           => "1.4rc", | 
					
						
							|  |  |  |       "automysqlbackup" => "3.0-rc", | 
					
						
							|  |  |  |       "aview"           => "1.3.0rc", | 
					
						
							|  |  |  |       "elm-format"      => "0.6.0-alpha", | 
					
						
							|  |  |  |       "ftgl"            => "2.1.3-rc", | 
					
						
							|  |  |  |       "hidapi"          => "0.8.0-rc", | 
					
						
							|  |  |  |       "libcaca"         => "0.99b", | 
					
						
							|  |  |  |       "premake"         => "4.4-beta", | 
					
						
							|  |  |  |       "pwnat"           => "0.3-beta", | 
					
						
							|  |  |  |       "recode"          => "3.7-beta", | 
					
						
							|  |  |  |       "speexdsp"        => "1.2rc", | 
					
						
							|  |  |  |       "sqoop"           => "1.4.", | 
					
						
							|  |  |  |       "tcptraceroute"   => "1.5beta", | 
					
						
							|  |  |  |       "tiny-fugue"      => "5.0b", | 
					
						
							|  |  |  |       "vbindiff"        => "3.0_beta", | 
					
						
							|  |  |  |     }.freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |     GNOME_DEVEL_ALLOWLIST = { | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  |       "libart"              => "2.3", | 
					
						
							|  |  |  |       "gtk-mac-integration" => "2.1", | 
					
						
							|  |  |  |       "gtk-doc"             => "1.31", | 
					
						
							|  |  |  |       "gcab"                => "1.3", | 
					
						
							|  |  |  |       "libepoxy"            => "1.5", | 
					
						
							|  |  |  |     }.freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-25 22:06:00 +08:00
										 |  |  |     GITHUB_PRERELEASE_ALLOWLIST = { | 
					
						
							| 
									
										
										
										
											2020-08-12 21:34:07 -04:00
										 |  |  |       "cbmc"         => "5.12.6", | 
					
						
							|  |  |  |       "elm-format"   => "0.8.3", | 
					
						
							| 
									
										
										
										
											2020-07-25 22:06:00 +08:00
										 |  |  |       "gitless"      => "0.8.8", | 
					
						
							| 
									
										
										
										
											2020-08-12 21:34:07 -04:00
										 |  |  |       "infrakit"     => "0.5", | 
					
						
							|  |  |  |       "riff"         => "0.5.0", | 
					
						
							| 
									
										
										
										
											2020-07-25 22:06:00 +08:00
										 |  |  |       "telegram-cli" => "1.3.1", | 
					
						
							| 
									
										
										
										
											2020-08-12 21:34:07 -04:00
										 |  |  |       "volta"        => "0.8.6", | 
					
						
							| 
									
										
										
										
											2020-07-25 22:06:00 +08:00
										 |  |  |     }.freeze | 
					
						
							| 
									
										
										
										
											2020-06-12 15:51:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  |     # version_prefix = stable_version_string.sub(/\d+$/, "") | 
					
						
							| 
									
										
										
										
											2020-08-11 12:40:35 -07:00
										 |  |  |     # version_prefix = stable.version.major_minor | 
					
						
							| 
									
										
										
										
											2020-04-11 14:43:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_specs | 
					
						
							| 
									
										
										
										
											2019-01-22 13:30:24 +00:00
										 |  |  |       problem "Head-only (no stable download)" if head_only?(formula) | 
					
						
							|  |  |  |       problem "Devel-only (no stable download)" if devel_only?(formula) | 
					
						
							| 
									
										
										
										
											2016-01-14 13:33:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       %w[Stable Devel HEAD].each do |name| | 
					
						
							|  |  |  |         spec_name = name.downcase.to_sym | 
					
						
							|  |  |  |         next unless spec = formula.send(spec_name) | 
					
						
							| 
									
										
										
										
											2017-05-10 20:45:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         ra = ResourceAuditor.new(spec, spec_name, online: @online, strict: @strict).audit | 
					
						
							|  |  |  |         problems.concat ra.problems.map { |problem| "#{name}: #{problem}" } | 
					
						
							| 
									
										
										
										
											2017-05-10 20:45:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         spec.resources.each_value do |resource| | 
					
						
							| 
									
										
										
										
											2019-11-26 00:58:35 +00:00
										 |  |  |           problem "Resource name should be different from the formula name" if resource.name == formula.name | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |           ra = ResourceAuditor.new(resource, spec_name, online: @online, strict: @strict).audit | 
					
						
							|  |  |  |           problems.concat ra.problems.map { |problem| | 
					
						
							|  |  |  |             "#{name} resource #{resource.name.inspect}: #{problem}" | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-08-18 12:55:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         next if spec.patches.empty? | 
					
						
							| 
									
										
										
										
											2018-05-23 07:36:59 +10:00
										 |  |  |         next unless @new_formula | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-02 16:15:09 +01:00
										 |  |  |         new_formula_problem( | 
					
						
							|  |  |  |           "Formulae should not require patches to build. " \ | 
					
						
							|  |  |  |           "Patches should be submitted and accepted upstream first.", | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-11-13 13:35:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       %w[Stable Devel].each do |name| | 
					
						
							|  |  |  |         next unless spec = formula.send(name.downcase) | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         version = spec.version | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |         problem "#{name}: version (#{version}) is set to a string without a digit" if version.to_s !~ /\d/ | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         if version.to_s.start_with?("HEAD") | 
					
						
							|  |  |  |           problem "#{name}: non-HEAD version name (#{version}) should not begin with HEAD" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-11-13 13:35:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       if formula.stable && formula.devel | 
					
						
							|  |  |  |         if formula.devel.version < formula.stable.version | 
					
						
							|  |  |  |           problem "devel version #{formula.devel.version} is older than stable version #{formula.stable.version}" | 
					
						
							|  |  |  |         elsif formula.devel.version == formula.stable.version | 
					
						
							|  |  |  |           problem "stable and devel versions are identical" | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2017-04-23 18:56:22 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-11-15 09:02:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:30:24 +00:00
										 |  |  |       return unless @core_tap | 
					
						
							| 
									
										
										
										
											2018-10-11 23:07:51 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 15:38:48 -05:00
										 |  |  |       problem "Formulae in homebrew/core should not have a `devel` spec" if formula.devel | 
					
						
							| 
									
										
										
										
											2019-01-22 13:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-02 10:56:27 +01:00
										 |  |  |       if formula.head && @versioned_formula | 
					
						
							| 
									
										
										
										
											2020-07-11 10:13:48 -04:00
										 |  |  |         head_spec_message = "Versioned formulae should not have a `HEAD` spec" | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         problem head_spec_message unless VERSIONED_HEAD_SPEC_ALLOWLIST.include?(formula.name) | 
					
						
							| 
									
										
										
										
											2016-11-13 13:35:25 +00:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-04-23 18:56:22 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       stable = formula.stable | 
					
						
							| 
									
										
										
										
											2019-06-10 09:01:58 +01:00
										 |  |  |       return unless stable | 
					
						
							|  |  |  |       return unless stable.url | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       stable_version_string = stable.version.to_s | 
					
						
							|  |  |  |       stable_url_version = Version.parse(stable.url) | 
					
						
							| 
									
										
										
										
											2020-08-11 12:40:35 -07:00
										 |  |  |       stable_url_minor_version = stable_url_version.minor.to_i | 
					
						
							| 
									
										
										
										
											2019-06-10 09:01:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-11 12:40:35 -07:00
										 |  |  |       formula_suffix = stable.version.patch.to_i | 
					
						
							| 
									
										
										
										
											2020-07-11 11:28:37 -04:00
										 |  |  |       throttled_rate = THROTTLED_FORMULAE[formula.name] | 
					
						
							|  |  |  |       if throttled_rate && formula_suffix.modulo(throttled_rate).nonzero? | 
					
						
							|  |  |  |         problem "should only be updated every #{throttled_rate} releases on multiples of #{throttled_rate}" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-12 14:51:49 +01:00
										 |  |  |       case (url = stable.url) | 
					
						
							| 
									
										
										
										
											2020-06-02 09:49:23 +01:00
										 |  |  |       when /[\d._-](alpha|beta|rc\d)/ | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         matched = Regexp.last_match(1) | 
					
						
							| 
									
										
										
										
											2019-06-10 09:01:58 +01:00
										 |  |  |         version_prefix = stable_version_string.sub(/\d+$/, "") | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         return if UNSTABLE_ALLOWLIST[formula.name] == version_prefix | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         problem "Stable version URLs should not contain #{matched}" | 
					
						
							|  |  |  |       when %r{download\.gnome\.org/sources}, %r{ftp\.gnome\.org/pub/GNOME/sources}i | 
					
						
							| 
									
										
										
										
											2020-08-11 12:40:35 -07:00
										 |  |  |         version_prefix = stable.version.major_minor | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         return if GNOME_DEVEL_ALLOWLIST[formula.name] == version_prefix | 
					
						
							| 
									
										
										
										
											2019-06-10 09:01:58 +01:00
										 |  |  |         return if stable_url_version < Version.create("1.0") | 
					
						
							|  |  |  |         return if stable_url_minor_version.even? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-10 09:01:58 +01:00
										 |  |  |         problem "#{stable.version} is a development release" | 
					
						
							|  |  |  |       when %r{isc.org/isc/bind\d*/}i | 
					
						
							|  |  |  |         return if stable_url_minor_version.even? | 
					
						
							| 
									
										
										
										
											2019-05-30 09:34:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-10 09:01:58 +01:00
										 |  |  |         problem "#{stable.version} is a development release" | 
					
						
							| 
									
										
										
										
											2020-08-12 10:31:59 -04:00
										 |  |  |       when %r{^https://github.com/([\w-]+)/([\w-]+)} | 
					
						
							| 
									
										
										
										
											2020-04-12 14:51:49 +01:00
										 |  |  |         owner = Regexp.last_match(1) | 
					
						
							|  |  |  |         repo = Regexp.last_match(2) | 
					
						
							|  |  |  |         tag = url.match(%r{^https://github\.com/[\w-]+/[\w-]+/archive/([^/]+)\.(tar\.gz|zip)$}) | 
					
						
							|  |  |  |                  .to_a | 
					
						
							|  |  |  |                  .second | 
					
						
							|  |  |  |         tag ||= url.match(%r{^https://github\.com/[\w-]+/[\w-]+/releases/download/([^/]+)/}) | 
					
						
							|  |  |  |                    .to_a | 
					
						
							|  |  |  |                    .second | 
					
						
							| 
									
										
										
										
											2020-08-12 10:31:59 -04:00
										 |  |  |         tag ||= formula.stable.specs[:tag] | 
					
						
							| 
									
										
										
										
											2020-04-12 14:51:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 00:13:58 +09:00
										 |  |  |         begin | 
					
						
							| 
									
										
										
										
											2020-06-04 08:55:54 -04:00
										 |  |  |           if @online && (release = GitHub.open_api("#{GitHub::API_URL}/repos/#{owner}/#{repo}/releases/tags/#{tag}")) | 
					
						
							| 
									
										
										
										
											2020-08-12 21:33:37 -04:00
										 |  |  |             if release["prerelease"] && (GITHUB_PRERELEASE_ALLOWLIST[formula.name] != formula.version) | 
					
						
							| 
									
										
										
										
											2020-06-12 15:51:43 +01:00
										 |  |  |               problem "#{tag} is a GitHub prerelease" | 
					
						
							|  |  |  |             elsif release["draft"] | 
					
						
							|  |  |  |               problem "#{tag} is a GitHub draft" | 
					
						
							|  |  |  |             end | 
					
						
							| 
									
										
										
										
											2020-04-02 00:13:58 +09:00
										 |  |  |           end | 
					
						
							| 
									
										
										
										
											2020-04-12 14:51:49 +01:00
										 |  |  |         rescue GitHub::HTTPNotFoundError | 
					
						
							|  |  |  |           # No-op if we can't find the release. | 
					
						
							|  |  |  |           nil | 
					
						
							| 
									
										
										
										
											2020-03-28 16:57:47 +09:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2019-05-30 09:34:27 +02:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-10-30 13:49:55 -04:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-09-22 20:12:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_revision_and_version_scheme | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       return unless @git | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       return unless formula.tap # skip formula not from core or any taps | 
					
						
							|  |  |  |       return unless formula.tap.git? # git log is required | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       return if formula.stable.blank? | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       fv = FormulaVersions.new(formula) | 
					
						
							| 
									
										
										
										
											2017-04-26 11:33:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       current_version = formula.stable.version | 
					
						
							|  |  |  |       current_checksum = formula.stable.checksum | 
					
						
							|  |  |  |       current_version_scheme = formula.version_scheme | 
					
						
							|  |  |  |       current_revision = formula.revision | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       previous_version = nil | 
					
						
							|  |  |  |       previous_version_scheme = nil | 
					
						
							|  |  |  |       previous_revision = nil | 
					
						
							| 
									
										
										
										
											2017-04-23 18:56:22 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       newest_committed_version = nil | 
					
						
							| 
									
										
										
										
											2020-07-03 09:21:49 +01:00
										 |  |  |       newest_committed_checksum = nil | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       newest_committed_revision = nil | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       fv.rev_list("origin/master") do |rev| | 
					
						
							|  |  |  |         fv.formula_at_revision(rev) do |f| | 
					
						
							|  |  |  |           stable = f.stable | 
					
						
							|  |  |  |           next if stable.blank? | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |           previous_version = stable.version | 
					
						
							|  |  |  |           previous_checksum = stable.checksum | 
					
						
							|  |  |  |           previous_version_scheme = f.version_scheme | 
					
						
							|  |  |  |           previous_revision = f.revision | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |           newest_committed_version ||= previous_version | 
					
						
							| 
									
										
										
										
											2020-07-03 09:21:49 +01:00
										 |  |  |           newest_committed_checksum ||= previous_checksum | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |           newest_committed_revision ||= previous_revision | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |         break if previous_version && current_version != previous_version | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       if current_version == previous_version && | 
					
						
							| 
									
										
										
										
											2020-07-03 09:21:49 +01:00
										 |  |  |          current_checksum != newest_committed_checksum | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |         problem( | 
					
						
							|  |  |  |           "stable sha256 changed without the version also changing; " \ | 
					
						
							|  |  |  |           "please create an issue upstream to rule out malicious " \ | 
					
						
							|  |  |  |           "circumstances and to find out why the file changed.", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       if !newest_committed_version.nil? && | 
					
						
							|  |  |  |          current_version < newest_committed_version && | 
					
						
							|  |  |  |          current_version_scheme == previous_version_scheme | 
					
						
							|  |  |  |         problem "stable version should not decrease (from #{newest_committed_version} to #{current_version})" | 
					
						
							| 
									
										
										
										
											2016-01-15 16:17:14 +08:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-01-14 13:33:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       unless previous_version_scheme.nil? | 
					
						
							|  |  |  |         if current_version_scheme < previous_version_scheme | 
					
						
							|  |  |  |           problem "version_scheme should not decrease (from #{previous_version_scheme} " \ | 
					
						
							|  |  |  |                   "to #{current_version_scheme})" | 
					
						
							|  |  |  |         elsif current_version_scheme > (previous_version_scheme + 1) | 
					
						
							|  |  |  |           problem "version_schemes should only increment by 1" | 
					
						
							| 
									
										
										
										
											2016-11-02 13:23:38 -04:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       if previous_version != newest_committed_version && | 
					
						
							|  |  |  |          !current_revision.zero? && | 
					
						
							|  |  |  |          current_revision == newest_committed_revision && | 
					
						
							|  |  |  |          current_revision == previous_revision | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         problem "'revision #{current_revision}' should be removed" | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |       elsif current_version == previous_version && | 
					
						
							|  |  |  |             !previous_revision.nil? && | 
					
						
							|  |  |  |             current_revision < previous_revision | 
					
						
							|  |  |  |         problem "revision should not decrease (from #{previous_revision} to #{current_revision})" | 
					
						
							| 
									
										
										
										
											2020-06-10 08:39:41 +01:00
										 |  |  |       elsif newest_committed_revision && | 
					
						
							|  |  |  |             current_revision > (newest_committed_revision + 1) | 
					
						
							| 
									
										
										
										
											2020-06-08 15:00:09 +01:00
										 |  |  |         problem "revisions should only increment by 1" | 
					
						
							| 
									
										
										
										
											2016-10-24 15:07:49 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-07-16 23:15:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_text | 
					
						
							|  |  |  |       bin_names = Set.new | 
					
						
							|  |  |  |       bin_names << formula.name | 
					
						
							|  |  |  |       bin_names += formula.aliases | 
					
						
							|  |  |  |       [formula.bin, formula.sbin].each do |dir| | 
					
						
							|  |  |  |         next unless dir.exist? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         bin_names += dir.children.map(&:basename).map(&:to_s) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       bin_names.each do |name| | 
					
						
							|  |  |  |         ["system", "shell_output", "pipe_output"].each do |cmd| | 
					
						
							| 
									
										
										
										
											2020-06-02 09:49:23 +01:00
										 |  |  |           if text.to_s.match?(/test do.*#{cmd}[(\s]+['"]#{Regexp.escape(name)}[\s'"]/m) | 
					
						
							| 
									
										
										
										
											2019-04-08 12:47:15 -04:00
										 |  |  |             problem %Q(fully scope test #{cmd} calls, e.g. #{cmd} "\#{bin}/#{name}") | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-04-18 08:17:24 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_reverse_migration | 
					
						
							| 
									
										
										
										
											2018-10-11 17:37:43 +10:00
										 |  |  |       # Only enforce for new formula being re-added to core | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       return unless @strict | 
					
						
							| 
									
										
										
										
											2018-10-11 17:37:43 +10:00
										 |  |  |       return unless @core_tap | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       return unless formula.tap.tap_migrations.key?(formula.name) | 
					
						
							| 
									
										
										
										
											2013-07-16 20:38:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       problem <<~EOS | 
					
						
							|  |  |  |         #{formula.name} seems to be listed in tap_migrations.json! | 
					
						
							|  |  |  |         Please remove #{formula.name} from present tap & tap_migrations.json | 
					
						
							|  |  |  |         before submitting it to Homebrew/homebrew-#{formula.tap.repo}. | 
					
						
							|  |  |  |       EOS | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-06-17 04:58:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_prefix_has_contents | 
					
						
							|  |  |  |       return unless formula.prefix.directory? | 
					
						
							|  |  |  |       return unless Keg.new(formula.prefix).empty_installation? | 
					
						
							| 
									
										
										
										
											2015-02-02 22:53:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       problem <<~EOS | 
					
						
							|  |  |  |         The installation seems to be empty. Please ensure the prefix | 
					
						
							|  |  |  |         is set correctly and expected files are installed. | 
					
						
							|  |  |  |         The prefix configure/make argument may be case-sensitive. | 
					
						
							|  |  |  |       EOS | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-02-02 22:53:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def quote_dep(dep) | 
					
						
							|  |  |  |       dep.is_a?(Symbol) ? dep.inspect : "'#{dep}'" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-07-15 19:29:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def problem_if_output(output) | 
					
						
							|  |  |  |       problem(output) if output | 
					
						
							| 
									
										
										
										
											2017-04-18 08:17:24 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit | 
					
						
							|  |  |  |       only_audits = @only | 
					
						
							|  |  |  |       except_audits = @except | 
					
						
							| 
									
										
										
										
											2010-11-09 13:00:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       methods.map(&:to_s).grep(/^audit_/).each do |audit_method_name| | 
					
						
							| 
									
										
										
										
											2020-05-22 08:52:26 +01:00
										 |  |  |         name = audit_method_name.delete_prefix("audit_") | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         if only_audits | 
					
						
							|  |  |  |           next unless only_audits.include?(name) | 
					
						
							|  |  |  |         elsif except_audits | 
					
						
							|  |  |  |           next if except_audits.include?(name) | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         send(audit_method_name) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-05-31 13:23:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     private | 
					
						
							| 
									
										
										
										
											2014-11-12 21:30:09 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def problem(p) | 
					
						
							|  |  |  |       @problems << p | 
					
						
							| 
									
										
										
										
											2018-04-30 01:22:04 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def new_formula_problem(p) | 
					
						
							|  |  |  |       @new_formula_problems << p | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-01-24 23:36:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def head_only?(formula) | 
					
						
							|  |  |  |       formula.head && formula.devel.nil? && formula.stable.nil? | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-09-18 18:08:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def devel_only?(formula) | 
					
						
							|  |  |  |       formula.devel && formula.stable.nil? | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-09-18 18:08:50 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |   class ResourceAuditor | 
					
						
							| 
									
										
										
										
											2020-07-07 11:29:33 +01:00
										 |  |  |     attr_reader :name, :version, :checksum, :url, :mirrors, :using, :specs, :owner, :spec_name, :problems | 
					
						
							| 
									
										
										
										
											2013-09-18 18:08:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def initialize(resource, spec_name, options = {}) | 
					
						
							|  |  |  |       @name     = resource.name | 
					
						
							|  |  |  |       @version  = resource.version | 
					
						
							|  |  |  |       @checksum = resource.checksum | 
					
						
							|  |  |  |       @url      = resource.url | 
					
						
							|  |  |  |       @mirrors  = resource.mirrors | 
					
						
							|  |  |  |       @using    = resource.using | 
					
						
							|  |  |  |       @specs    = resource.specs | 
					
						
							|  |  |  |       @owner    = resource.owner | 
					
						
							|  |  |  |       @spec_name = spec_name | 
					
						
							|  |  |  |       @online    = options[:online] | 
					
						
							|  |  |  |       @strict    = options[:strict] | 
					
						
							|  |  |  |       @problems  = [] | 
					
						
							| 
									
										
										
										
											2013-09-18 18:08:50 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit | 
					
						
							|  |  |  |       audit_version | 
					
						
							|  |  |  |       audit_download_strategy | 
					
						
							|  |  |  |       audit_urls | 
					
						
							|  |  |  |       self | 
					
						
							| 
									
										
										
										
											2013-09-18 18:08:50 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-04-19 14:31:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_version | 
					
						
							|  |  |  |       if version.nil? | 
					
						
							|  |  |  |         problem "missing version" | 
					
						
							|  |  |  |       elsif !version.detected_from_url? | 
					
						
							|  |  |  |         version_text = version | 
					
						
							|  |  |  |         version_url = Version.detect(url, specs) | 
					
						
							|  |  |  |         if version_url.to_s == version_text.to_s && version.instance_of?(Version) | 
					
						
							|  |  |  |           problem "version #{version_text} is redundant with version scanned from URL" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2014-12-18 18:04:22 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_download_strategy | 
					
						
							|  |  |  |       url_strategy = DownloadStrategyDetector.detect(url) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if using == :git || url_strategy == GitDownloadStrategy | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |         problem "Git should specify :revision when a :tag is specified." if specs[:tag] && !specs[:revision] | 
					
						
							| 
									
										
										
										
											2015-03-07 15:02:25 +00:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       return unless using | 
					
						
							| 
									
										
										
										
											2013-09-18 18:08:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       if using == :cvs | 
					
						
							|  |  |  |         mod = specs[:module] | 
					
						
							| 
									
										
										
										
											2014-12-22 00:43:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         problem "Redundant :module value in URL" if mod == name | 
					
						
							| 
									
										
										
										
											2014-12-22 00:43:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-13 19:26:39 +01:00
										 |  |  |         if url.match?(%r{:[^/]+$}) | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |           mod = url.split(":").last | 
					
						
							| 
									
										
										
										
											2014-12-22 00:43:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |           if mod == name | 
					
						
							|  |  |  |             problem "Redundant CVS module appended to URL" | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             problem "Specify CVS module as `:module => \"#{mod}\"` instead of appending it to the URL" | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2014-12-22 00:43:02 -05:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       return unless url_strategy == DownloadStrategyDetector.detect("", using) | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       problem "Redundant :using value in URL" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-09-18 18:08:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def self.curl_openssl_and_deps | 
					
						
							|  |  |  |       @curl_openssl_and_deps ||= begin | 
					
						
							|  |  |  |         formulae_names = ["curl", "openssl"] | 
					
						
							|  |  |  |         formulae_names += formulae_names.flat_map do |f| | 
					
						
							|  |  |  |           Formula[f].recursive_dependencies.map(&:name) | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         formulae_names.uniq | 
					
						
							|  |  |  |       rescue FormulaUnavailableError | 
					
						
							|  |  |  |         [] | 
					
						
							| 
									
										
										
										
											2017-09-14 19:58:37 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def audit_urls | 
					
						
							|  |  |  |       return unless @online | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-27 16:25:40 +00:00
										 |  |  |       urls = [url] + mirrors | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |       urls.each do |url| | 
					
						
							|  |  |  |         next if !@strict && mirrors.include?(url) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         strategy = DownloadStrategyDetector.detect(url, using) | 
					
						
							|  |  |  |         if strategy <= CurlDownloadStrategy && !url.start_with?("file") | 
					
						
							|  |  |  |           # A `brew mirror`'ed URL is usually not yet reachable at the time of | 
					
						
							|  |  |  |           # pull request. | 
					
						
							| 
									
										
										
										
											2019-10-13 19:26:39 +01:00
										 |  |  |           next if url.match?(%r{^https://dl.bintray.com/homebrew/mirror/}) | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-28 08:10:37 +01:00
										 |  |  |           if http_content_problem = curl_check_http_content(url) | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |             problem http_content_problem | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         elsif strategy <= GitDownloadStrategy | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |           problem "The URL #{url} is not a valid git URL" unless Utils.git_remote_exists? url | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |         elsif strategy <= SubversionDownloadStrategy | 
					
						
							|  |  |  |           next unless DevelopmentTools.subversion_handles_most_https_certificates? | 
					
						
							|  |  |  |           next unless Utils.svn_available? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |           problem "The URL #{url} is not a valid svn URL" unless Utils.svn_remote_exists? url | 
					
						
							| 
									
										
										
										
											2016-12-10 14:20:47 +00:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-12-08 21:41:24 +00:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-02-02 21:25:29 +00:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 17:27:44 +02:00
										 |  |  |     def problem(text) | 
					
						
							|  |  |  |       @problems << text | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-09-18 18:08:50 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | end |