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)
|
|
|
|
@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:)
|
2023-04-14 15:33:40 +02:00
|
|
|
options = {}
|
2024-11-30 13:52:46 -08:00
|
|
|
options[:force_bottle] = true if force_bottle?
|
|
|
|
options[:override_spec] = :head if self.HEAD?
|
2023-04-14 15:33:40 +02:00
|
|
|
options[:flags] = flags_only unless flags_only.empty?
|
2024-11-30 13:52:46 -08:00
|
|
|
@named = T.let(
|
|
|
|
NamedArgs.new(*named_args.freeze, parent: self, cask_options:, without_api:, **options),
|
|
|
|
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-11-30 13:52:46 -08:00
|
|
|
sig { returns(T.nilable(String)) }
|
|
|
|
def arch = nil
|
|
|
|
|
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def build_bottle? = false
|
|
|
|
|
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def build_from_source? = false
|
|
|
|
|
2024-12-01 10:44:53 -08:00
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def cask? = false
|
|
|
|
|
2024-11-30 13:52:46 -08:00
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def force_bottle? = false
|
|
|
|
|
2024-12-01 10:44:53 -08:00
|
|
|
# Defined in extend/os:
|
|
|
|
# def formula; end
|
|
|
|
|
2024-11-30 13:52:46 -08:00
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def HEAD? = false
|
|
|
|
|
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def include_test? = false
|
|
|
|
|
|
|
|
sig { returns(T.nilable(String)) }
|
|
|
|
def os = nil
|
|
|
|
|
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-11-30 13:52:46 -08:00
|
|
|
if build_from_source? || self.HEAD? || 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
|
|
|
|
if 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-01 10:44:53 -08:00
|
|
|
if formula? && !cask?
|
2023-12-14 02:52:30 +00:00
|
|
|
:formula
|
2024-12-01 10:44:53 -08:00
|
|
|
elsif cask? && !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
|
|
|
|
|
|
|
|
oses = case (os_sym = os&.to_sym)
|
|
|
|
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
|
|
|
|
|
|
|
|
arches = case (arch_sym = arch&.to_sym)
|
|
|
|
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-07 08:09:15 -08:00
|
|
|
end.freeze
|
2020-04-05 17:39:30 +05:30
|
|
|
end
|
2019-04-17 19:42:27 +09:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|