args: Move named args parsing to separate class

This commit is contained in:
William Ma 2020-08-13 08:55:55 -04:00
parent 535e7dc836
commit 13bc69385c
2 changed files with 186 additions and 141 deletions

View File

@ -1,5 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cli/named_args"
require "ostruct" require "ostruct"
module Homebrew module Homebrew
@ -19,7 +20,7 @@ module Homebrew
# Can set these because they will be overwritten by freeze_named_args! # Can set these because they will be overwritten by freeze_named_args!
# (whereas other values below will only be overwritten if passed). # (whereas other values below will only be overwritten if passed).
self[:named_args] = [] self[:named_args] = NamedArgs.new
self[:remaining] = [] self[:remaining] = []
end end
@ -28,18 +29,12 @@ module Homebrew
end end
def freeze_named_args!(named_args) def freeze_named_args!(named_args)
# Reset cache values reliant on named_args self[:named_args] = NamedArgs.new(
@formulae = nil *named_args.freeze,
@formulae_and_casks = nil override_spec: spec(nil),
@resolved_formulae = nil force_bottle: force_bottle?,
@resolved_formulae_casks = nil flags: flags_only,
@formulae_paths = nil )
@casks = nil
@loaded_casks = nil
@kegs = nil
@kegs_casks = nil
self[:named_args] = named_args.freeze
end end
def freeze_processed_options!(processed_options) def freeze_processed_options!(processed_options)
@ -54,7 +49,7 @@ module Homebrew
end end
def named def named
named_args || [] named_args || NamedArgs.new
end end
def no_named? def no_named?
@ -62,102 +57,39 @@ module Homebrew
end end
def formulae def formulae
require "formula" named.to_formulae
@formulae ||= (downcased_unique_named - casks).map do |name|
Formulary.factory(name, spec, force_bottle: force_bottle?, flags: flags_only)
end.uniq(&:name).freeze
end end
def formulae_and_casks def formulae_and_casks
@formulae_and_casks ||= begin named.to_formulae_and_casks
formulae_and_casks = []
downcased_unique_named.each do |name|
formulae_and_casks << Formulary.factory(name, spec)
rescue FormulaUnavailableError
begin
formulae_and_casks << Cask::CaskLoader.load(name)
rescue Cask::CaskUnavailableError
raise "No available formula or cask with the name \"#{name}\""
end
end
formulae_and_casks.freeze
end
end end
def resolved_formulae def resolved_formulae
require "formula" named.to_resolved_formulae
@resolved_formulae ||= (downcased_unique_named - casks).map do |name|
Formulary.resolve(name, spec: spec(nil), force_bottle: force_bottle?, flags: flags_only)
end.uniq(&:name).freeze
end end
def resolved_formulae_casks def resolved_formulae_casks
@resolved_formulae_casks ||= begin named.to_resolved_formulae_to_casks
resolved_formulae = []
casks = []
downcased_unique_named.each do |name|
resolved_formulae << Formulary.resolve(name, spec: spec(nil),
force_bottle: force_bottle?, flags: flags_only)
rescue FormulaUnavailableError
begin
casks << Cask::CaskLoader.load(name)
rescue Cask::CaskUnavailableError
raise "No available formula or cask with the name \"#{name}\""
end
end
[resolved_formulae.freeze, casks.freeze].freeze
end
end end
def formulae_paths def formulae_paths
@formulae_paths ||= (downcased_unique_named - casks).map do |name| named.to_formulae_paths
Formulary.path(name)
end.uniq.freeze
end end
def casks def casks
@casks ||= downcased_unique_named.grep(HOMEBREW_CASK_TAP_CASK_REGEX) named.homebrew_tap_cask_names
.freeze
end end
def loaded_casks def loaded_casks
@loaded_casks ||= downcased_unique_named.map(&Cask::CaskLoader.method(:load)).freeze named.to_casks
end end
def kegs def kegs
@kegs ||= downcased_unique_named.map do |name| named.to_kegs
resolve_keg name
rescue NoSuchKegError => e
if (reason = Homebrew::MissingFormula.suggest_command(name, "uninstall"))
$stderr.puts reason
end
raise e
end.freeze
end end
def kegs_casks def kegs_casks
@kegs_casks ||= begin named.to_kegs_to_casks
kegs = []
casks = []
downcased_unique_named.each do |name|
kegs << resolve_keg(name)
rescue NoSuchKegError
begin
casks << Cask::CaskLoader.load(name)
rescue Cask::CaskUnavailableError
raise "No installed keg or cask with the name \"#{name}\""
end
end
[kegs.freeze, casks.freeze].freeze
end
end end
def build_stable? def build_stable?
@ -218,17 +150,6 @@ module Homebrew
@cli_args.freeze @cli_args.freeze
end end
def downcased_unique_named
# Only lowercase names, not paths, bottle filenames or URLs
named.map do |arg|
if arg.include?("/") || arg.end_with?(".tar.gz") || File.exist?(arg)
arg
else
arg.downcase
end
end.uniq
end
def spec(default = :stable) def spec(default = :stable)
if HEAD? if HEAD?
:head :head
@ -238,50 +159,6 @@ module Homebrew
default default
end end
end end
def resolve_keg(name)
require "keg"
require "formula"
require "missing_formula"
raise UsageError if name.blank?
rack = Formulary.to_rack(name.downcase)
dirs = rack.directory? ? rack.subdirs : []
raise NoSuchKegError, rack.basename if dirs.empty?
linked_keg_ref = HOMEBREW_LINKED_KEGS/rack.basename
opt_prefix = HOMEBREW_PREFIX/"opt/#{rack.basename}"
begin
if opt_prefix.symlink? && opt_prefix.directory?
Keg.new(opt_prefix.resolved_path)
elsif linked_keg_ref.symlink? && linked_keg_ref.directory?
Keg.new(linked_keg_ref.resolved_path)
elsif dirs.length == 1
Keg.new(dirs.first)
else
f = if name.include?("/") || File.exist?(name)
Formulary.factory(name)
else
Formulary.from_rack(rack)
end
unless (prefix = f.installed_prefix).directory?
raise MultipleVersionsInstalledError, "#{rack.basename} has multiple installed versions"
end
Keg.new(prefix)
end
rescue FormulaUnavailableError
raise MultipleVersionsInstalledError, <<~EOS
Multiple kegs installed to #{rack}
However we don't know which one you refer to.
Please delete (with rm -rf!) all but one and then try again.
EOS
end
end
end end
end end
end end

View File

@ -0,0 +1,168 @@
# frozen_string_literal: true
require "delegate"
module Homebrew
module CLI
class NamedArgs < SimpleDelegator
def initialize(*args, override_spec: nil, force_bottle: false, flags: [])
@args = args
@override_spec = override_spec
@force_bottle = force_bottle
@flags = flags
__setobj__(@args)
end
def to_formulae
@to_formulae ||= (downcased_unique_named - homebrew_tap_cask_names).map do |name|
Formulary.factory(name, spec, force_bottle: @force_bottle, flags: @flags)
end.uniq(&:name).freeze
end
def to_formulae_and_casks
@to_formulae_and_casks ||= begin
formulae_and_casks = []
downcased_unique_named.each do |name|
formulae_and_casks << Formulary.factory(name, spec)
rescue FormulaUnavailableError
begin
formulae_and_casks << Cask::CaskLoader.load(name)
rescue Cask::CaskUnavailableError
raise "No available formula or cask with the name \"#{name}\""
end
end
formulae_and_casks.freeze
end
end
def to_resolved_formulae
@to_resolved_formulae ||= (downcased_unique_named - homebrew_tap_cask_names).map do |name|
Formulary.resolve(name, spec: spec(nil), force_bottle: @force_bottle, flags: @flags)
end.uniq(&:name).freeze
end
def to_resolved_formulae_to_casks
@to_resolved_formulae_to_casks ||= begin
resolved_formulae = []
casks = []
downcased_unique_named.each do |name|
resolved_formulae << Formulary.resolve(name, spec: spec(nil), force_bottle: @force_bottle, flags: @flags)
rescue FormulaUnavailableError
begin
casks << Cask::CaskLoader.load(name)
rescue Cask::CaskUnavailableError
raise "No available formula or cask with the name \"#{name}\""
end
end
[resolved_formulae.freeze, casks.freeze].freeze
end
end
def to_formulae_paths
@to_formulae_paths ||= (downcased_unique_named - homebrew_tap_cask_names).map do |name|
Formulary.path(name)
end.uniq.freeze
end
def to_casks
@to_casks ||= downcased_unique_named.map(&Cask::CaskLoader.method(:load)).freeze
end
def to_kegs
@to_kegs ||= downcased_unique_named.map do |name|
resolve_keg name
rescue NoSuchKegError => e
if (reason = Homebrew::MissingFormula.suggest_command(name, "uninstall"))
$stderr.puts reason
end
raise e
end.freeze
end
def to_kegs_to_casks
@to_kegs_to_casks ||= begin
kegs = []
casks = []
downcased_unique_named.each do |name|
kegs << resolve_keg(name)
rescue NoSuchKegError, FormulaUnavailableError
begin
casks << Cask::CaskLoader.load(name)
rescue Cask::CaskUnavailableError
raise "No installed keg or cask with the name \"#{name}\""
end
end
[kegs.freeze, casks.freeze].freeze
end
end
def homebrew_tap_cask_names
downcased_unique_named.grep(HOMEBREW_CASK_TAP_CASK_REGEX)
end
private
def downcased_unique_named
# Only lowercase names, not paths, bottle filenames or URLs
map do |arg|
if arg.include?("/") || arg.end_with?(".tar.gz") || File.exist?(arg)
arg
else
arg.downcase
end
end.uniq
end
def spec(default = :stable)
@override_spec || default
end
def resolve_keg(name)
raise UsageError if name.blank?
rack = Formulary.to_rack(name.downcase)
dirs = rack.directory? ? rack.subdirs : []
raise NoSuchKegError, rack.basename if dirs.empty?
linked_keg_ref = HOMEBREW_LINKED_KEGS/rack.basename
opt_prefix = HOMEBREW_PREFIX/"opt/#{rack.basename}"
begin
if opt_prefix.symlink? && opt_prefix.directory?
Keg.new(opt_prefix.resolved_path)
elsif linked_keg_ref.symlink? && linked_keg_ref.directory?
Keg.new(linked_keg_ref.resolved_path)
elsif dirs.length == 1
Keg.new(dirs.first)
else
f = if name.include?("/") || File.exist?(name)
Formulary.factory(name)
else
Formulary.from_rack(rack)
end
unless (prefix = f.installed_prefix).directory?
raise MultipleVersionsInstalledError, "#{rack.basename} has multiple installed versions"
end
Keg.new(prefix)
end
rescue FormulaUnavailableError
raise MultipleVersionsInstalledError, <<~EOS
Multiple kegs installed to #{rack}
However we don't know which one you refer to.
Please delete (with rm -rf!) all but one and then try again.
EOS
end
end
end
end
end