| 
									
										
										
										
											2024-08-12 10:30:59 +01:00
										 |  |  | # typed: true # rubocop:todo Sorbet/StrictSigil | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-19 17:57:36 -05:00
										 |  |  | require "formula" | 
					
						
							| 
									
										
										
										
											2025-08-20 19:20:19 +01:00
										 |  |  | require "utils/output" | 
					
						
							| 
									
										
										
										
											2014-06-19 17:57:36 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 06:09:57 +02:00
										 |  |  | # Helper class for traversing a formula's previous versions. | 
					
						
							|  |  |  | # | 
					
						
							| 
									
										
										
										
											2024-03-06 01:00:39 +01:00
										 |  |  | # @api internal | 
					
						
							| 
									
										
										
										
											2014-05-28 16:23:33 -05:00
										 |  |  | class FormulaVersions | 
					
						
							| 
									
										
										
										
											2020-08-02 14:32:31 +02:00
										 |  |  |   include Context | 
					
						
							| 
									
										
										
										
											2025-08-20 19:20:19 +01:00
										 |  |  |   include Utils::Output::Mixin | 
					
						
							| 
									
										
										
										
											2020-08-02 14:32:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-28 16:23:33 -05:00
										 |  |  |   IGNORED_EXCEPTIONS = [ | 
					
						
							|  |  |  |     ArgumentError, NameError, SyntaxError, TypeError, | 
					
						
							|  |  |  |     FormulaSpecificationError, FormulaValidationError, | 
					
						
							| 
									
										
										
										
											2016-10-08 12:04:38 +02:00
										 |  |  |     ErrorDuringExecution, LoadError, MethodDeprecatedError | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |   ].freeze | 
					
						
							| 
									
										
										
										
											2014-05-28 16:23:33 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 19:31:15 +01:00
										 |  |  |   sig { params(formula: Formula).void } | 
					
						
							| 
									
										
										
										
											2017-04-23 18:56:22 +01:00
										 |  |  |   def initialize(formula) | 
					
						
							| 
									
										
										
										
											2015-04-01 21:06:03 -04:00
										 |  |  |     @name = formula.name | 
					
						
							| 
									
										
										
										
											2015-09-02 16:42:54 +08:00
										 |  |  |     @path = formula.path | 
					
						
							| 
									
										
										
										
											2023-08-14 19:31:15 +01:00
										 |  |  |     @repository = T.must(formula.tap).path | 
					
						
							|  |  |  |     @relative_path = @path.relative_path_from(repository).to_s | 
					
						
							|  |  |  |     # Also look at e.g. older homebrew-core paths before sharding. | 
					
						
							|  |  |  |     if (match = @relative_path.match(%r{^(HomebrewFormula|Formula)/([a-z]|lib)/(.+)})) | 
					
						
							|  |  |  |       @old_relative_path = "#{match[1]}/#{match[3]}" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2017-06-03 00:23:06 +02:00
										 |  |  |     @formula_at_revision = {} | 
					
						
							| 
									
										
										
										
											2014-05-28 16:23:33 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 00:16:50 -04:00
										 |  |  |   def rev_list(branch) | 
					
						
							| 
									
										
										
										
											2014-05-28 16:23:33 -05:00
										 |  |  |     repository.cd do | 
					
						
							| 
									
										
										
										
											2021-05-04 09:45:31 -04:00
										 |  |  |       rev_list_cmd = ["git", "rev-list", "--abbrev-commit", "--remove-empty"] | 
					
						
							| 
									
										
										
										
											2023-08-14 19:31:15 +01:00
										 |  |  |       [relative_path, old_relative_path].compact.each do |entry| | 
					
						
							|  |  |  |         Utils.popen_read(*rev_list_cmd, branch, "--", entry) do |io| | 
					
						
							|  |  |  |           yield [io.readline.chomp, entry] until io.eof? | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2014-05-28 16:23:33 -05:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-14 15:33:40 +02:00
										 |  |  |   sig { | 
					
						
							|  |  |  |     type_parameters(:U) | 
					
						
							| 
									
										
										
										
											2023-08-14 19:31:15 +01:00
										 |  |  |       .params( | 
					
						
							|  |  |  |         revision:              String, | 
					
						
							|  |  |  |         formula_relative_path: String, | 
					
						
							|  |  |  |         _block:                T.proc.params(arg0: Formula).returns(T.type_parameter(:U)), | 
					
						
							|  |  |  |       ).returns(T.nilable(T.type_parameter(:U))) | 
					
						
							| 
									
										
										
										
											2023-04-14 15:33:40 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-08-14 19:31:15 +01:00
										 |  |  |   def formula_at_revision(revision, formula_relative_path = relative_path, &_block) | 
					
						
							| 
									
										
										
										
											2017-06-03 00:23:06 +02:00
										 |  |  |     Homebrew.raise_deprecation_exceptions = true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 19:31:15 +01:00
										 |  |  |     yield @formula_at_revision[revision] ||= begin | 
					
						
							|  |  |  |       contents = file_contents_at_revision(revision, formula_relative_path) | 
					
						
							| 
									
										
										
										
											2021-04-13 17:41:20 +01:00
										 |  |  |       nostdout { Formulary.from_contents(name, path, contents, ignore_errors: true) } | 
					
						
							| 
									
										
										
										
											2014-05-28 16:23:33 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2017-06-03 00:23:06 +02:00
										 |  |  |   rescue *IGNORED_EXCEPTIONS => e | 
					
						
							| 
									
										
										
										
											2024-07-15 13:44:01 -04:00
										 |  |  |     require "utils/backtrace" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-03 00:23:06 +02:00
										 |  |  |     # We rescue these so that we can skip bad versions and | 
					
						
							|  |  |  |     # continue walking the history | 
					
						
							| 
									
										
										
										
											2023-09-11 21:54:27 -07:00
										 |  |  |     odebug "#{e} in #{name} at revision #{revision}", Utils::Backtrace.clean(e) | 
					
						
							| 
									
										
										
										
											2025-08-16 12:54:42 -07:00
										 |  |  |     nil | 
					
						
							| 
									
										
										
										
											2017-06-03 00:23:06 +02:00
										 |  |  |   rescue FormulaUnavailableError | 
					
						
							| 
									
										
										
										
											2018-03-06 09:36:49 +00:00
										 |  |  |     nil | 
					
						
							| 
									
										
										
										
											2017-06-03 00:23:06 +02:00
										 |  |  |   ensure | 
					
						
							|  |  |  |     Homebrew.raise_deprecation_exceptions = false | 
					
						
							| 
									
										
										
										
											2014-05-28 16:23:33 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2023-03-02 16:56:50 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 19:31:15 +01:00
										 |  |  |   private | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   attr_reader :name, :path, :repository, :relative_path, :old_relative_path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sig { params(revision: String, relative_path: String).returns(String) } | 
					
						
							|  |  |  |   def file_contents_at_revision(revision, relative_path) | 
					
						
							|  |  |  |     repository.cd { Utils.popen_read("git", "cat-file", "blob", "#{revision}:#{relative_path}") } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-02 16:56:50 -08:00
										 |  |  |   def nostdout(&block) | 
					
						
							|  |  |  |     if verbose? | 
					
						
							|  |  |  |       yield | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       redirect_stdout(File::NULL, &block) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2014-05-28 16:23:33 -05:00
										 |  |  | end |