| 
									
										
										
										
											2020-10-10 14:16:11 +02:00
										 |  |  | # typed: true | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  | require "tab" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module Utils | 
					
						
							| 
									
										
										
										
											2020-08-19 07:50:49 +02:00
										 |  |  |   # Helper functions for bottles. | 
					
						
							|  |  |  |   # | 
					
						
							| 
									
										
										
										
											2024-04-22 21:05:48 +02:00
										 |  |  |   # @api internal | 
					
						
							| 
									
										
										
										
											2020-08-19 07:50:49 +02:00
										 |  |  |   module Bottles | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |     class << self | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |       # Gets the tag for the running OS. | 
					
						
							| 
									
										
										
										
											2024-04-22 21:05:48 +02:00
										 |  |  |       # | 
					
						
							|  |  |  |       # @api internal | 
					
						
							| 
									
										
										
										
											2023-04-14 15:33:40 +02:00
										 |  |  |       sig { params(tag: T.nilable(T.any(Symbol, Tag))).returns(Tag) } | 
					
						
							|  |  |  |       def tag(tag = nil) | 
					
						
							|  |  |  |         case tag | 
					
						
							|  |  |  |         when Symbol | 
					
						
							|  |  |  |           Tag.from_symbol(tag) | 
					
						
							|  |  |  |         when Tag | 
					
						
							|  |  |  |           tag | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           @tag ||= Tag.new( | 
					
						
							|  |  |  |             system: HOMEBREW_SYSTEM.downcase.to_sym, | 
					
						
							|  |  |  |             arch:   HOMEBREW_PROCESSOR.downcase.to_sym, | 
					
						
							|  |  |  |           ) | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |       def built_as?(formula) | 
					
						
							|  |  |  |         return false unless formula.latest_version_installed? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-28 03:23:21 +02:00
										 |  |  |         tab = Keg.new(formula.latest_installed_prefix).tab | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |         tab.built_as_bottle | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |       def file_outdated?(formula, file) | 
					
						
							| 
									
										
										
										
											2024-03-30 03:29:51 +00:00
										 |  |  |         file = file.resolved_path | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |         filename = file.basename.to_s | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |         return false if formula.bottle.blank? | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 03:29:51 +00:00
										 |  |  |         _, bottle_tag, bottle_rebuild = extname_tag_rebuild(filename) | 
					
						
							|  |  |  |         return false if bottle_tag.blank? | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 03:29:51 +00:00
										 |  |  |         bottle_tag != formula.bottle.tag.to_s || bottle_rebuild.to_i != formula.bottle.rebuild | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 17:35:13 +01:00
										 |  |  |       def extname_tag_rebuild(filename) | 
					
						
							|  |  |  |         HOMEBREW_BOTTLES_EXTNAME_REGEX.match(filename).to_a | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |       def receipt_path(bottle_file) | 
					
						
							| 
									
										
										
										
											2021-04-13 14:26:31 +01:00
										 |  |  |         bottle_file_list(bottle_file).find do |line| | 
					
						
							| 
									
										
										
										
											2023-12-27 13:00:48 -08:00
										 |  |  |           %r{.+/.+/INSTALL_RECEIPT.json}.match?(line) | 
					
						
							| 
									
										
										
										
											2016-07-29 15:54:56 -06:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 12:16:26 +01:00
										 |  |  |       def file_from_bottle(bottle_file, file_path) | 
					
						
							| 
									
										
										
										
											2021-04-15 12:17:55 +01:00
										 |  |  |         Utils.popen_read("tar", "--extract", "--to-stdout", "--file", bottle_file, file_path) | 
					
						
							| 
									
										
										
										
											2021-04-15 12:16:26 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |       def resolve_formula_names(bottle_file) | 
					
						
							| 
									
										
										
										
											2021-04-13 14:26:31 +01:00
										 |  |  |         name = bottle_file_list(bottle_file).first.to_s.split("/").first | 
					
						
							|  |  |  |         full_name = if (receipt_file_path = receipt_path(bottle_file)) | 
					
						
							| 
									
										
										
										
											2021-04-15 12:16:26 +01:00
										 |  |  |           receipt_file = file_from_bottle(bottle_file, receipt_file_path) | 
					
						
							| 
									
										
										
										
											2021-04-13 14:26:31 +01:00
										 |  |  |           tap = Tab.from_file_content(receipt_file, "#{bottle_file}/#{receipt_file_path}").tap | 
					
						
							|  |  |  |           "#{tap}/#{name}" if tap.present? && !tap.core_tap? | 
					
						
							| 
									
										
										
										
											2023-11-05 08:55:58 -08:00
										 |  |  |         else | 
					
						
							|  |  |  |           bottle_json_path = Pathname(bottle_file.sub(/\.(\d+\.)?tar\.gz$/, ".json")) | 
					
						
							|  |  |  |           if bottle_json_path.exist? && | 
					
						
							| 
									
										
										
										
											2023-11-05 09:10:28 -08:00
										 |  |  |              (bottle_json_path_contents = bottle_json_path.read.presence) && | 
					
						
							|  |  |  |              (bottle_json = JSON.parse(bottle_json_path_contents).presence) && | 
					
						
							|  |  |  |              bottle_json.is_a?(Hash) | 
					
						
							| 
									
										
										
										
											2023-11-05 08:55:58 -08:00
										 |  |  |             bottle_json.keys.first.presence | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2021-04-13 14:26:31 +01:00
										 |  |  |         full_name ||= name | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         [name, full_name] | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def resolve_version(bottle_file) | 
					
						
							| 
									
										
										
										
											2021-04-13 14:26:31 +01:00
										 |  |  |         version = bottle_file_list(bottle_file).first.to_s.split("/").second | 
					
						
							|  |  |  |         PkgVersion.parse(version) | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-09-25 22:46:51 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       def formula_contents(bottle_file, | 
					
						
							| 
									
										
										
										
											2019-04-30 08:44:35 +01:00
										 |  |  |                            name: resolve_formula_names(bottle_file)[0]) | 
					
						
							| 
									
										
										
										
											2017-09-25 22:46:51 -07:00
										 |  |  |         bottle_version = resolve_version bottle_file | 
					
						
							|  |  |  |         formula_path = "#{name}/#{bottle_version}/.brew/#{name}.rb" | 
					
						
							| 
									
										
										
										
											2021-04-15 12:16:26 +01:00
										 |  |  |         contents = file_from_bottle(bottle_file, formula_path) | 
					
						
							| 
									
										
										
										
											2017-09-25 22:46:51 -07:00
										 |  |  |         raise BottleFormulaUnavailableError.new(bottle_file, formula_path) unless $CHILD_STATUS.success? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-25 22:46:51 -07:00
										 |  |  |         contents | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-04-15 18:06:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       def path_resolved_basename(root_url, name, checksum, filename) | 
					
						
							|  |  |  |         if root_url.match?(GitHubPackages::URL_REGEX) | 
					
						
							|  |  |  |           image_name = GitHubPackages.image_formula_name(name) | 
					
						
							|  |  |  |           ["#{image_name}/blobs/sha256:#{checksum}", filename&.github_packages] | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           filename&.url_encode | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-04-15 12:16:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-11 03:08:59 +01:00
										 |  |  |       def load_tab(formula) | 
					
						
							|  |  |  |         keg = Keg.new(formula.prefix) | 
					
						
							| 
									
										
										
										
											2024-06-22 13:31:50 -04:00
										 |  |  |         tabfile = keg/AbstractTab::FILENAME | 
					
						
							| 
									
										
										
										
											2021-09-27 03:44:33 +01:00
										 |  |  |         bottle_json_path = formula.local_bottle_path&.sub(/\.(\d+\.)?tar\.gz$/, ".json") | 
					
						
							| 
									
										
										
										
											2021-05-11 03:08:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (tab_attributes = formula.bottle_tab_attributes.presence) | 
					
						
							|  |  |  |           Tab.from_file_content(tab_attributes.to_json, tabfile) | 
					
						
							|  |  |  |         elsif !tabfile.exist? && bottle_json_path&.exist? | 
					
						
							|  |  |  |           _, tag, = Utils::Bottles.extname_tag_rebuild(formula.local_bottle_path) | 
					
						
							|  |  |  |           bottle_hash = JSON.parse(File.read(bottle_json_path)) | 
					
						
							|  |  |  |           tab_json = bottle_hash[formula.full_name]["bottle"]["tags"][tag]["tab"].to_json | 
					
						
							|  |  |  |           Tab.from_file_content(tab_json, tabfile) | 
					
						
							|  |  |  |         else | 
					
						
							| 
									
										
										
										
											2024-04-28 03:23:21 +02:00
										 |  |  |           tab = keg.tab | 
					
						
							| 
									
										
										
										
											2024-01-29 15:57:55 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-30 17:15:13 +00:00
										 |  |  |           tab.runtime_dependencies = begin | 
					
						
							| 
									
										
										
										
											2024-01-29 15:57:55 -08:00
										 |  |  |             f_runtime_deps = formula.runtime_dependencies(read_from_tab: false) | 
					
						
							| 
									
										
										
										
											2024-01-30 17:15:13 +00:00
										 |  |  |             Tab.runtime_deps_hash(formula, f_runtime_deps) | 
					
						
							| 
									
										
										
										
											2024-01-29 15:57:55 -08:00
										 |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           tab | 
					
						
							| 
									
										
										
										
											2021-05-11 03:08:59 +01:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 12:16:26 +01:00
										 |  |  |       private | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def bottle_file_list(bottle_file) | 
					
						
							|  |  |  |         @bottle_file_list ||= {} | 
					
						
							|  |  |  |         @bottle_file_list[bottle_file] ||= Utils.popen_read("tar", "--list", "--file", bottle_file) | 
					
						
							|  |  |  |                                                 .lines | 
					
						
							|  |  |  |                                                 .map(&:chomp) | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |     # Denotes the arch and OS of a bottle. | 
					
						
							|  |  |  |     class Tag | 
					
						
							|  |  |  |       attr_reader :system, :arch | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { params(value: Symbol).returns(T.attached_class) } | 
					
						
							|  |  |  |       def self.from_symbol(value) | 
					
						
							| 
									
										
										
										
											2021-04-08 17:39:57 +01:00
										 |  |  |         return new(system: :all, arch: :all) if value == :all | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |         @all_archs_regex ||= begin | 
					
						
							|  |  |  |           all_archs = Hardware::CPU::ALL_ARCHS.map(&:to_s) | 
					
						
							|  |  |  |           /
 | 
					
						
							|  |  |  |             ^((?<arch>#{Regexp.union(all_archs)})_)? | 
					
						
							|  |  |  |             (?<system>[\w.]+)$ | 
					
						
							|  |  |  |           /x
 | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         match = @all_archs_regex.match(value.to_s) | 
					
						
							|  |  |  |         raise ArgumentError, "Invalid bottle tag symbol" unless match | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         system = match[:system].to_sym | 
					
						
							|  |  |  |         arch = match[:arch]&.to_sym || :x86_64 | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |         new(system:, arch:) | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { params(system: Symbol, arch: Symbol).void } | 
					
						
							|  |  |  |       def initialize(system:, arch:) | 
					
						
							|  |  |  |         @system = system | 
					
						
							|  |  |  |         @arch = arch | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def ==(other) | 
					
						
							|  |  |  |         if other.is_a?(Symbol) | 
					
						
							|  |  |  |           to_sym == other | 
					
						
							|  |  |  |         else | 
					
						
							| 
									
										
										
										
											2023-05-05 06:05:58 +02:00
										 |  |  |           self.class == other.class && system == other.system && standardized_arch == other.standardized_arch | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |       def eql?(other) | 
					
						
							|  |  |  |         self.class == other.class && self == other | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def hash | 
					
						
							| 
									
										
										
										
											2023-05-05 06:05:58 +02:00
										 |  |  |         [system, standardized_arch].hash | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-21 16:41:15 +02:00
										 |  |  |       sig { returns(Symbol) } | 
					
						
							| 
									
										
										
										
											2022-07-21 15:32:51 +02:00
										 |  |  |       def standardized_arch | 
					
						
							|  |  |  |         return :x86_64 if [:x86_64, :intel].include? arch | 
					
						
							|  |  |  |         return :arm64 if [:arm64, :arm].include? arch | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         arch | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |       sig { returns(Symbol) } | 
					
						
							|  |  |  |       def to_sym | 
					
						
							| 
									
										
										
										
											2021-04-08 17:39:57 +01:00
										 |  |  |         if system == :all && arch == :all | 
					
						
							|  |  |  |           :all | 
					
						
							| 
									
										
										
										
											2022-07-21 15:32:51 +02:00
										 |  |  |         elsif macos? && [:x86_64, :intel].include?(arch) | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |           system | 
					
						
							|  |  |  |         else | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |           :"#{standardized_arch}_#{system}" | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { returns(String) } | 
					
						
							|  |  |  |       def to_s | 
					
						
							|  |  |  |         to_sym.to_s | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-09 02:15:28 +02:00
										 |  |  |       sig { returns(MacOSVersion) } | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |       def to_macos_version | 
					
						
							| 
									
										
										
										
											2023-05-09 02:15:28 +02:00
										 |  |  |         @to_macos_version ||= MacOSVersion.from_symbol(system) | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { returns(T::Boolean) } | 
					
						
							|  |  |  |       def linux? | 
					
						
							|  |  |  |         system == :linux | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { returns(T::Boolean) } | 
					
						
							|  |  |  |       def macos? | 
					
						
							| 
									
										
										
										
											2023-09-28 14:07:25 +01:00
										 |  |  |         MacOSVersion::SYMBOLS.key?(system) | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-21 15:32:51 +02:00
										 |  |  |       sig { returns(T::Boolean) } | 
					
						
							|  |  |  |       def valid_combination? | 
					
						
							|  |  |  |         return true unless [:arm64, :arm].include? arch | 
					
						
							|  |  |  |         return false if linux? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Big Sur is the first version of macOS that runs on ARM | 
					
						
							|  |  |  |         to_macos_version >= :big_sur | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |       sig { returns(String) } | 
					
						
							|  |  |  |       def default_prefix | 
					
						
							|  |  |  |         if linux? | 
					
						
							|  |  |  |           HOMEBREW_LINUX_DEFAULT_PREFIX | 
					
						
							|  |  |  |         elsif arch == :arm64 | 
					
						
							|  |  |  |           HOMEBREW_MACOS_ARM_DEFAULT_PREFIX | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           HOMEBREW_DEFAULT_PREFIX | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { returns(String) } | 
					
						
							|  |  |  |       def default_cellar | 
					
						
							|  |  |  |         if linux? | 
					
						
							|  |  |  |           Homebrew::DEFAULT_LINUX_CELLAR | 
					
						
							|  |  |  |         elsif arch == :arm64 | 
					
						
							|  |  |  |           Homebrew::DEFAULT_MACOS_ARM_CELLAR | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           Homebrew::DEFAULT_MACOS_CELLAR | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |     # The specification for a specific tag | 
					
						
							|  |  |  |     class TagSpecification | 
					
						
							|  |  |  |       sig { returns(Utils::Bottles::Tag) } | 
					
						
							|  |  |  |       attr_reader :tag | 
					
						
							| 
									
										
										
										
											2020-02-19 11:54:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |       sig { returns(Checksum) } | 
					
						
							|  |  |  |       attr_reader :checksum | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { returns(T.any(Symbol, String)) } | 
					
						
							|  |  |  |       attr_reader :cellar | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def initialize(tag:, checksum:, cellar:) | 
					
						
							|  |  |  |         @tag = tag | 
					
						
							|  |  |  |         @checksum = checksum | 
					
						
							|  |  |  |         @cellar = cellar | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2023-10-23 16:17:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       def ==(other) | 
					
						
							|  |  |  |         self.class == other.class && tag == other.tag && checksum == other.checksum && cellar == other.cellar | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       alias eql? == | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Collector for bottle specifications. | 
					
						
							|  |  |  |     class Collector | 
					
						
							| 
									
										
										
										
											2020-10-20 12:03:48 +02:00
										 |  |  |       sig { void } | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |       def initialize | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |         @tag_specs = T.let({}, T::Hash[Utils::Bottles::Tag, Utils::Bottles::TagSpecification]) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { returns(T::Array[Utils::Bottles::Tag]) } | 
					
						
							|  |  |  |       def tags | 
					
						
							|  |  |  |         @tag_specs.keys | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-23 16:17:31 +01:00
										 |  |  |       def ==(other) | 
					
						
							|  |  |  |         self.class == other.class && @tag_specs == other.instance_variable_get(:@tag_specs) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       alias eql? == | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |       sig { params(tag: Utils::Bottles::Tag, checksum: Checksum, cellar: T.any(Symbol, String)).void } | 
					
						
							|  |  |  |       def add(tag, checksum:, cellar:) | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |         spec = Utils::Bottles::TagSpecification.new(tag:, checksum:, cellar:) | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |         @tag_specs[tag] = spec | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { params(tag: Utils::Bottles::Tag, no_older_versions: T::Boolean).returns(T::Boolean) } | 
					
						
							|  |  |  |       def tag?(tag, no_older_versions: false) | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |         tag = find_matching_tag(tag, no_older_versions:) | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |         tag.present? | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sig { params(block: T.proc.params(tag: Utils::Bottles::Tag).void).void } | 
					
						
							|  |  |  |       def each_tag(&block) | 
					
						
							|  |  |  |         @tag_specs.each_key(&block) | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |       sig { | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |         params(tag: Utils::Bottles::Tag, no_older_versions: T::Boolean) | 
					
						
							|  |  |  |           .returns(T.nilable(Utils::Bottles::TagSpecification)) | 
					
						
							| 
									
										
										
										
											2021-04-08 13:45:15 +01:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |       def specification_for(tag, no_older_versions: false) | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |         tag = find_matching_tag(tag, no_older_versions:) | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |         @tag_specs[tag] if tag | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       private | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 14:58:39 +01:00
										 |  |  |       def find_matching_tag(tag, no_older_versions: false) | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |         if @tag_specs.key?(tag) | 
					
						
							| 
									
										
										
										
											2021-04-08 17:39:57 +01:00
										 |  |  |           tag | 
					
						
							| 
									
										
										
										
											2021-09-16 18:56:47 +01:00
										 |  |  |         else | 
					
						
							|  |  |  |           all = Tag.from_symbol(:all) | 
					
						
							|  |  |  |           all if @tag_specs.key?(all) | 
					
						
							| 
									
										
										
										
											2021-04-08 17:39:57 +01:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | require "extend/os/bottles" |