| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 19:42:27 +09:00
										 |  |  | module Homebrew | 
					
						
							|  |  |  |   module CLI | 
					
						
							| 
									
										
										
										
											2024-11-30 13:52:46 -08:00
										 |  |  |     class Args | 
					
						
							| 
									
										
										
										
											2024-08-19 09:47:16 -07:00
										 |  |  |       # Represents a processed option. The array elements are: | 
					
						
							|  |  |  |       #   0: short option name (e.g. "-d") | 
					
						
							|  |  |  |       #   1: long option name (e.g. "--debug") | 
					
						
							| 
									
										
										
										
											2024-08-19 13:15:34 -07:00
										 |  |  |       #   2: option description (e.g. "Print debugging information") | 
					
						
							|  |  |  |       #   3: whether the option is hidden | 
					
						
							|  |  |  |       OptionsType = T.type_alias { T::Array[[String, T.nilable(String), String, T::Boolean]] } | 
					
						
							| 
									
										
										
										
											2024-11-30 13:52:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2024-11-30 13:52:46 -08:00
										 |  |  |       attr_reader :options_only, :flags_only, :remaining | 
					
						
							| 
									
										
										
										
											2020-05-10 15:12:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 12:03:48 +02:00
										 |  |  |       sig { void } | 
					
						
							| 
									
										
										
										
											2020-07-31 17:37:36 +02:00
										 |  |  |       def initialize | 
					
						
							| 
									
										
										
										
											2020-11-29 21:23:44 +01:00
										 |  |  |         require "cli/named_args" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |         @cli_args = T.let(nil, T.nilable(T::Array[String])) | 
					
						
							|  |  |  |         @processed_options = T.let([], OptionsType) | 
					
						
							|  |  |  |         @options_only = T.let([], T::Array[String]) | 
					
						
							|  |  |  |         @flags_only = T.let([], T::Array[String]) | 
					
						
							|  |  |  |         @cask_options = T.let(false, T::Boolean) | 
					
						
							| 
									
										
										
										
											2024-12-06 20:15:48 -08:00
										 |  |  |         @table = T.let({}, T::Hash[Symbol, T.untyped]) | 
					
						
							| 
									
										
										
										
											2019-09-22 20:13:11 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 10:33:02 +01:00
										 |  |  |         # Can set these because they will be overwritten by freeze_named_args! | 
					
						
							|  |  |  |         # (whereas other values below will only be overwritten if passed). | 
					
						
							| 
									
										
										
										
											2024-11-30 13:52:46 -08:00
										 |  |  |         @named = T.let(NamedArgs.new(parent: self), T.nilable(NamedArgs)) | 
					
						
							|  |  |  |         @remaining = T.let([], T::Array[String]) | 
					
						
							| 
									
										
										
										
											2019-09-22 20:13:11 +05:30
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { params(remaining_args: T::Array[T.any(T::Array[String], String)]).void } | 
					
						
							| 
									
										
										
										
											2024-11-30 13:52:46 -08:00
										 |  |  |       def freeze_remaining_args!(remaining_args) = @remaining.replace(remaining_args).freeze | 
					
						
							| 
									
										
										
										
											2020-07-31 15:07:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { params(named_args: T::Array[String], cask_options: T::Boolean, without_api: T::Boolean).void } | 
					
						
							| 
									
										
										
										
											2023-06-19 03:57:52 +01:00
										 |  |  |       def freeze_named_args!(named_args, cask_options:, without_api:) | 
					
						
							| 
									
										
										
										
											2024-11-30 13:52:46 -08:00
										 |  |  |         @named = T.let( | 
					
						
							| 
									
										
										
										
											2024-12-06 20:08:02 -08:00
										 |  |  |           NamedArgs.new( | 
					
						
							|  |  |  |             *named_args.freeze, | 
					
						
							|  |  |  |             cask_options:, | 
					
						
							|  |  |  |             flags:         flags_only, | 
					
						
							| 
									
										
										
										
											2024-12-06 20:15:48 -08:00
										 |  |  |             force_bottle:  @table[:force_bottle?] || false, | 
					
						
							|  |  |  |             override_spec: @table[:HEAD?] ? :head : nil, | 
					
						
							| 
									
										
										
										
											2024-12-06 20:08:02 -08:00
										 |  |  |             parent:        self, | 
					
						
							|  |  |  |             without_api:, | 
					
						
							|  |  |  |           ), | 
					
						
							| 
									
										
										
										
											2024-11-30 13:52:46 -08:00
										 |  |  |           T.nilable(NamedArgs), | 
					
						
							| 
									
										
										
										
											2020-08-13 08:55:55 -04:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2019-09-22 20:13:11 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-06 20:08:02 -08:00
										 |  |  |       sig { params(name: Symbol, value: T.untyped).void } | 
					
						
							|  |  |  |       def set_arg(name, value) | 
					
						
							|  |  |  |         @table[name] = value | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2024-11-30 13:52:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-06 20:28:41 -08:00
										 |  |  |       sig { override.params(_blk: T.nilable(T.proc.params(x: T.untyped).void)).returns(T.untyped) } | 
					
						
							| 
									
										
										
										
											2024-12-06 14:26:18 -08:00
										 |  |  |       def tap(&_blk) | 
					
						
							|  |  |  |         return super if block_given? # Object#tap | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @table[:tap] | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { params(processed_options: OptionsType).void } | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |       def freeze_processed_options!(processed_options) | 
					
						
							| 
									
										
										
										
											2020-05-07 10:33:02 +01:00
										 |  |  |         # Reset cache values reliant on processed_options | 
					
						
							|  |  |  |         @cli_args = nil | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |         @processed_options += processed_options | 
					
						
							|  |  |  |         @processed_options.freeze | 
					
						
							| 
									
										
										
										
											2019-09-22 20:13:11 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |         @options_only = cli_args.select { _1.start_with?("-") }.freeze | 
					
						
							|  |  |  |         @flags_only = cli_args.select { _1.start_with?("--") }.freeze | 
					
						
							| 
									
										
										
										
											2019-04-17 19:42:27 +09:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2019-09-25 14:21:06 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-16 01:52:57 +01:00
										 |  |  |       sig { returns(NamedArgs) } | 
					
						
							| 
									
										
										
										
											2019-09-08 19:56:24 +05:30
										 |  |  |       def named | 
					
						
							| 
									
										
										
										
											2020-11-30 04:18:23 +01:00
										 |  |  |         require "formula" | 
					
						
							| 
									
										
										
										
											2024-11-30 13:52:46 -08:00
										 |  |  |         T.must(@named) | 
					
						
							| 
									
										
										
										
											2019-09-08 19:56:24 +05:30
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2024-12-06 11:06:27 -08:00
										 |  |  |       def no_named? = named.empty? | 
					
						
							| 
									
										
										
										
											2020-03-04 17:23:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2020-07-28 14:08:40 +02:00
										 |  |  |       def build_from_source_formulae | 
					
						
							| 
									
										
										
										
											2024-12-06 20:15:48 -08:00
										 |  |  |         if @table[:build_from_source?] || @table[:HEAD?] || @table[:build_bottle?] | 
					
						
							| 
									
										
										
										
											2021-07-27 05:12:15 +01:00
										 |  |  |           named.to_formulae.map(&:full_name) | 
					
						
							| 
									
										
										
										
											2020-07-28 14:08:40 +02:00
										 |  |  |         else | 
					
						
							|  |  |  |           [] | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2020-04-11 18:50:24 +05:30
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2020-07-28 14:08:40 +02:00
										 |  |  |       def include_test_formulae | 
					
						
							| 
									
										
										
										
											2024-12-06 20:15:48 -08:00
										 |  |  |         if @table[:include_test?] | 
					
						
							| 
									
										
										
										
											2020-09-03 10:34:22 +01:00
										 |  |  |           named.to_formulae.map(&:full_name) | 
					
						
							| 
									
										
										
										
											2020-07-28 14:08:40 +02:00
										 |  |  |         else | 
					
						
							|  |  |  |           [] | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2020-05-19 19:12:47 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { params(name: String).returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-05-23 19:39:11 +01:00
										 |  |  |       def value(name) | 
					
						
							|  |  |  |         arg_prefix = "--#{name}=" | 
					
						
							|  |  |  |         flag_with_value = flags_only.find { |arg| arg.start_with?(arg_prefix) } | 
					
						
							|  |  |  |         return unless flag_with_value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         flag_with_value.delete_prefix(arg_prefix) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 12:03:48 +02:00
										 |  |  |       sig { returns(Context::ContextStruct) } | 
					
						
							| 
									
										
										
										
											2020-08-02 14:32:31 +02:00
										 |  |  |       def context | 
					
						
							|  |  |  |         Context::ContextStruct.new(debug: debug?, quiet: quiet?, verbose: verbose?) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { returns(T.nilable(Symbol)) } | 
					
						
							| 
									
										
										
										
											2020-12-16 20:46:47 +09:00
										 |  |  |       def only_formula_or_cask | 
					
						
							| 
									
										
										
										
											2024-12-06 20:08:02 -08:00
										 |  |  |         if @table[:formula?] && !@table[:cask?] | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |           :formula | 
					
						
							| 
									
										
										
										
											2024-12-06 20:08:02 -08:00
										 |  |  |         elsif @table[:cask?] && !@table[:formula?] | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |           :cask | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2020-12-15 23:43:46 +09:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-14 15:33:40 +02:00
										 |  |  |       sig { returns(T::Array[[Symbol, Symbol]]) } | 
					
						
							|  |  |  |       def os_arch_combinations | 
					
						
							|  |  |  |         skip_invalid_combinations = false | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-06 20:15:48 -08:00
										 |  |  |         oses = case (os_sym = @table[:os]&.to_sym) | 
					
						
							| 
									
										
										
										
											2023-04-14 15:33:40 +02:00
										 |  |  |         when nil | 
					
						
							|  |  |  |           [SimulateSystem.current_os] | 
					
						
							|  |  |  |         when :all | 
					
						
							|  |  |  |           skip_invalid_combinations = true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-19 21:33:13 -07:00
										 |  |  |           OnSystem::ALL_OS_OPTIONS | 
					
						
							| 
									
										
										
										
											2023-04-14 15:33:40 +02:00
										 |  |  |         else | 
					
						
							|  |  |  |           [os_sym] | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-06 20:15:48 -08:00
										 |  |  |         arches = case (arch_sym = @table[:arch]&.to_sym) | 
					
						
							| 
									
										
										
										
											2023-04-14 15:33:40 +02:00
										 |  |  |         when nil | 
					
						
							|  |  |  |           [SimulateSystem.current_arch] | 
					
						
							|  |  |  |         when :all | 
					
						
							|  |  |  |           skip_invalid_combinations = true | 
					
						
							|  |  |  |           OnSystem::ARCH_OPTIONS | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           [arch_sym] | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         oses.product(arches).select do |os, arch| | 
					
						
							|  |  |  |           if skip_invalid_combinations | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |             bottle_tag = Utils::Bottles::Tag.new(system: os, arch:) | 
					
						
							| 
									
										
										
										
											2023-04-14 15:33:40 +02:00
										 |  |  |             bottle_tag.valid_combination? | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             true | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |       private | 
					
						
							| 
									
										
										
										
											2020-04-25 21:57:21 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { params(option: String).returns(String) } | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |       def option_to_name(option) | 
					
						
							|  |  |  |         option.sub(/\A--?/, "") | 
					
						
							|  |  |  |               .tr("-", "_") | 
					
						
							| 
									
										
										
										
											2020-04-25 21:57:21 +05:30
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 20:30:58 -07:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |       def cli_args | 
					
						
							| 
									
										
										
										
											2024-12-07 08:09:15 -08:00
										 |  |  |         @cli_args ||= @processed_options.filter_map do |short, long| | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |           option = long || short | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |           switch = :"#{option_to_name(option)}?" | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |           flag = option_to_name(option).to_sym | 
					
						
							|  |  |  |           if @table[switch] == true || @table[flag] == true | 
					
						
							| 
									
										
										
										
											2024-12-07 08:09:15 -08:00
										 |  |  |             option | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |           elsif @table[flag].instance_of? String | 
					
						
							| 
									
										
										
										
											2024-12-07 08:09:15 -08:00
										 |  |  |             "#{option}=#{@table[flag]}" | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |           elsif @table[flag].instance_of? Array | 
					
						
							| 
									
										
										
										
											2024-12-07 08:09:15 -08:00
										 |  |  |             "#{option}=#{@table[flag].join(",")}" | 
					
						
							| 
									
										
										
										
											2020-05-05 12:50:41 +01:00
										 |  |  |           end | 
					
						
							| 
									
										
										
										
											2024-12-06 20:19:04 -08:00
										 |  |  |         end.freeze | 
					
						
							| 
									
										
										
										
											2020-04-05 17:39:30 +05:30
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2019-04-17 19:42:27 +09:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |