mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Warn about undocumented non-private APIs.
This commit is contained in:
parent
7c0b989740
commit
caf87c0336
@ -70,6 +70,11 @@ Style/Documentation:
|
|||||||
- version.rb
|
- version.rb
|
||||||
- tap.rb
|
- tap.rb
|
||||||
|
|
||||||
|
Homebrew/NegateInclude:
|
||||||
|
Exclude:
|
||||||
|
# YARD runs stand-alone.
|
||||||
|
- yard/docstring_parser.rb
|
||||||
|
|
||||||
Style/DocumentationMethod:
|
Style/DocumentationMethod:
|
||||||
Include:
|
Include:
|
||||||
- "formula.rb"
|
- "formula.rb"
|
||||||
|
@ -18,6 +18,7 @@ end
|
|||||||
group :doc, optional: true do
|
group :doc, optional: true do
|
||||||
gem "yard", require: false
|
gem "yard", require: false
|
||||||
gem "yard-sorbet", require: false
|
gem "yard-sorbet", require: false
|
||||||
|
gem "redcarpet", require: false
|
||||||
end
|
end
|
||||||
group :ast, optional: true do
|
group :ast, optional: true do
|
||||||
gem "rubocop-ast", require: false
|
gem "rubocop-ast", require: false
|
||||||
|
@ -60,7 +60,6 @@ class PATH
|
|||||||
@paths.join(File::PATH_SEPARATOR)
|
@paths.join(File::PATH_SEPARATOR)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s = to_str
|
def to_s = to_str
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ module Homebrew
|
|||||||
sig { returns(Pathname) }
|
sig { returns(Pathname) }
|
||||||
def self.gh_executable
|
def self.gh_executable
|
||||||
# NOTE: We disable HOMEBREW_VERIFY_ATTESTATIONS when installing `gh` itself,
|
# NOTE: We disable HOMEBREW_VERIFY_ATTESTATIONS when installing `gh` itself,
|
||||||
# to prevent a cycle during bootstrapping. This can eventually be resolved
|
# to prevent a cycle during bootstrapping. This can eventually be resolved
|
||||||
# by vendoring a pure-Ruby Sigstore verifier client.
|
# by vendoring a pure-Ruby Sigstore verifier client.
|
||||||
@gh_executable ||= T.let(with_env("HOMEBREW_VERIFY_ATTESTATIONS" => nil) do
|
@gh_executable ||= T.let(with_env("HOMEBREW_VERIFY_ATTESTATIONS" => nil) do
|
||||||
ensure_executable!("gh")
|
ensure_executable!("gh")
|
||||||
end, T.nilable(Pathname))
|
end, T.nilable(Pathname))
|
||||||
|
@ -265,7 +265,7 @@ EOS
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# NOTE: the members of the array in the second arg must not have spaces!
|
# NOTE: The members of the array in the second arg must not have spaces!
|
||||||
check-array-membership() {
|
check-array-membership() {
|
||||||
local item=$1
|
local item=$1
|
||||||
shift
|
shift
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Note: that we use a non-standard config file name to reduce
|
# NOTE: We use a non-standard config file name to reduce name clashes with
|
||||||
# name clashes with other IRB config files like `.irbrc`.
|
# other IRB config files like `.irbrc`.
|
||||||
# Note #2: This doesn't work with system Ruby for some reason.
|
# NOTE: This doesn't work with system Ruby for some reason.
|
||||||
|
|
||||||
require 'irb/completion'
|
require 'irb/completion'
|
||||||
|
|
||||||
|
@ -9,16 +9,26 @@ class BuildOptions
|
|||||||
end
|
end
|
||||||
|
|
||||||
# True if a {Formula} is being built with a specific option.
|
# True if a {Formula} is being built with a specific option.
|
||||||
# <pre>args << "--i-want-spam" if build.with? "spam"
|
|
||||||
#
|
#
|
||||||
|
# ### Examples
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# args << "--i-want-spam" if build.with? "spam"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
# args << "--qt-gui" if build.with? "qt" # "--with-qt" ==> build.with? "qt"
|
# args << "--qt-gui" if build.with? "qt" # "--with-qt" ==> build.with? "qt"
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# # If a formula presents a user with a choice, but the choice must be fulfilled:
|
# If a formula presents a user with a choice, but the choice must be fulfilled:
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
# if build.with? "example2"
|
# if build.with? "example2"
|
||||||
# args << "--with-example2"
|
# args << "--with-example2"
|
||||||
# else
|
# else
|
||||||
# args << "--with-example1"
|
# args << "--with-example1"
|
||||||
# end</pre>
|
# end
|
||||||
|
# ```
|
||||||
def with?(val)
|
def with?(val)
|
||||||
option_names = val.respond_to?(:option_names) ? val.option_names : [val]
|
option_names = val.respond_to?(:option_names) ? val.option_names : [val]
|
||||||
|
|
||||||
@ -34,7 +44,12 @@ class BuildOptions
|
|||||||
end
|
end
|
||||||
|
|
||||||
# True if a {Formula} is being built without a specific option.
|
# True if a {Formula} is being built without a specific option.
|
||||||
# <pre>args << "--no-spam-plz" if build.without? "spam"</pre>
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# args << "--no-spam-plz" if build.without? "spam"
|
||||||
|
# ```
|
||||||
def without?(val)
|
def without?(val)
|
||||||
!with?(val)
|
!with?(val)
|
||||||
end
|
end
|
||||||
@ -45,19 +60,33 @@ class BuildOptions
|
|||||||
end
|
end
|
||||||
|
|
||||||
# True if a {Formula} is being built with {Formula.head} instead of {Formula.stable}.
|
# True if a {Formula} is being built with {Formula.head} instead of {Formula.stable}.
|
||||||
# <pre>args << "--some-new-stuff" if build.head?</pre>
|
#
|
||||||
# <pre># If there are multiple conditional arguments use a block instead of lines.
|
# ### Examples
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# args << "--some-new-stuff" if build.head?
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# If there are multiple conditional arguments use a block instead of lines.
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
# if build.head?
|
# if build.head?
|
||||||
# args << "--i-want-pizza"
|
# args << "--i-want-pizza"
|
||||||
# args << "--and-a-cold-beer" if build.with? "cold-beer"
|
# args << "--and-a-cold-beer" if build.with? "cold-beer"
|
||||||
# end</pre>
|
# end
|
||||||
|
# ```
|
||||||
def head?
|
def head?
|
||||||
include? "HEAD"
|
include? "HEAD"
|
||||||
end
|
end
|
||||||
|
|
||||||
# True if a {Formula} is being built with {Formula.stable} instead of {Formula.head}.
|
# True if a {Formula} is being built with {Formula.stable} instead of {Formula.head}.
|
||||||
# This is the default.
|
# This is the default.
|
||||||
# <pre>args << "--some-beta" if build.head?</pre>
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# args << "--some-beta" if build.head?
|
||||||
|
# ```
|
||||||
def stable?
|
def stable?
|
||||||
!head?
|
!head?
|
||||||
end
|
end
|
||||||
|
@ -147,7 +147,6 @@ module Cask
|
|||||||
cask.config
|
cask.config
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"#{summarize} (#{self.class.english_name})"
|
"#{summarize} (#{self.class.english_name})"
|
||||||
|
@ -78,7 +78,8 @@ module Cask
|
|||||||
@allow_reassignment = allow_reassignment
|
@allow_reassignment = allow_reassignment
|
||||||
@loaded_from_api = loaded_from_api
|
@loaded_from_api = loaded_from_api
|
||||||
@loader = loader
|
@loader = loader
|
||||||
# Sorbet has trouble with bound procs assigned to ivars: https://github.com/sorbet/sorbet/issues/6843
|
# Sorbet has trouble with bound procs assigned to instance variables:
|
||||||
|
# https://github.com/sorbet/sorbet/issues/6843
|
||||||
instance_variable_set(:@block, block)
|
instance_variable_set(:@block, block)
|
||||||
|
|
||||||
@default_config = config || Config.new
|
@default_config = config || Config.new
|
||||||
@ -323,11 +324,9 @@ module Cask
|
|||||||
end
|
end
|
||||||
|
|
||||||
# @api public
|
# @api public
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s = token
|
def to_s = token
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<Cask #{token}#{sourcefile_path&.to_s&.prepend(" ")}>"
|
"#<Cask #{token}#{sourcefile_path&.to_s&.prepend(" ")}>"
|
||||||
|
@ -112,6 +112,16 @@ module Cask
|
|||||||
@token = cask.token
|
@token = cask.token
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Specifies the cask's name.
|
||||||
|
#
|
||||||
|
# NOTE: Multiple names can be specified.
|
||||||
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# name "Visual Studio Code"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def name(*args)
|
def name(*args)
|
||||||
@name ||= []
|
@name ||= []
|
||||||
@ -120,6 +130,14 @@ module Cask
|
|||||||
@name.concat(args.flatten)
|
@name.concat(args.flatten)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Describes the cask.
|
||||||
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# desc "Open-source code editor"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def desc(description = nil)
|
def desc(description = nil)
|
||||||
set_unique_stanza(:desc, description.nil?) { description }
|
set_unique_stanza(:desc, description.nil?) { description }
|
||||||
@ -146,6 +164,14 @@ module Cask
|
|||||||
raise CaskInvalidError.new(cask, "'#{stanza}' stanza failed with: #{e}")
|
raise CaskInvalidError.new(cask, "'#{stanza}' stanza failed with: #{e}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sets the cask's homepage.
|
||||||
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# homepage "https://code.visualstudio.com/"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def homepage(homepage = nil)
|
def homepage(homepage = nil)
|
||||||
set_unique_stanza(:homepage, homepage.nil?) { homepage }
|
set_unique_stanza(:homepage, homepage.nil?) { homepage }
|
||||||
@ -201,6 +227,14 @@ module Cask
|
|||||||
@language_blocks.keys.flatten
|
@language_blocks.keys.flatten
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sets the cask's download URL.
|
||||||
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# url "https://update.code.visualstudio.com/#{version}/#{arch}/stable"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def url(*args, **options, &block)
|
def url(*args, **options, &block)
|
||||||
caller_location = T.must(caller_locations).fetch(0)
|
caller_location = T.must(caller_locations).fetch(0)
|
||||||
@ -214,6 +248,8 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sets the cask's appcast URL.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def appcast(*args, **kwargs)
|
def appcast(*args, **kwargs)
|
||||||
set_unique_stanza(:appcast, args.empty? && kwargs.empty?) do
|
set_unique_stanza(:appcast, args.empty? && kwargs.empty?) do
|
||||||
@ -222,6 +258,22 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sets the cask's container type or nested container path.
|
||||||
|
#
|
||||||
|
# ### Examples
|
||||||
|
#
|
||||||
|
# The container is a nested disk image:
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# container nested: "orca-#{version}.dmg"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# The container should not be unarchived:
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# container type: :naked
|
||||||
|
# ```
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def container(**kwargs)
|
def container(**kwargs)
|
||||||
set_unique_stanza(:container, kwargs.empty?) do
|
set_unique_stanza(:container, kwargs.empty?) do
|
||||||
@ -229,6 +281,15 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sets the cask's version.
|
||||||
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# version "1.88.1"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# @see DSL::Version
|
||||||
# @api public
|
# @api public
|
||||||
def version(arg = nil)
|
def version(arg = nil)
|
||||||
set_unique_stanza(:version, arg.nil?) do
|
set_unique_stanza(:version, arg.nil?) do
|
||||||
@ -240,6 +301,23 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sets the cask's download checksum.
|
||||||
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# For universal or single-architecture downloads:
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# sha256 "7bdb497080ffafdfd8cc94d8c62b004af1be9599e865e5555e456e2681e150ca"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# For architecture-dependent downloads:
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# sha256 arm: "7bdb497080ffafdfd8cc94d8c62b004af1be9599e865e5555e456e2681e150ca",
|
||||||
|
# intel: "b3c1c2442480a0219b9e05cf91d03385858c20f04b764ec08a3fa83d1b27e7b2"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def sha256(arg = nil, arm: nil, intel: nil)
|
def sha256(arg = nil, arm: nil, intel: nil)
|
||||||
should_return = arg.nil? && arm.nil? && intel.nil?
|
should_return = arg.nil? && arm.nil? && intel.nil?
|
||||||
@ -259,6 +337,14 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sets the cask's architecture strings.
|
||||||
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# arch arm: "darwin-arm64", intel: "darwin"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def arch(arm: nil, intel: nil)
|
def arch(arm: nil, intel: nil)
|
||||||
should_return = arm.nil? && intel.nil?
|
should_return = arm.nil? && intel.nil?
|
||||||
@ -270,7 +356,10 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# `depends_on` uses a load method so that multiple stanzas can be merged.
|
# Declare dependencies and requirements for a cask.
|
||||||
|
#
|
||||||
|
# NOTE: Multiple dependencies can be specified.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def depends_on(**kwargs)
|
def depends_on(**kwargs)
|
||||||
@depends_on ||= DSL::DependsOn.new
|
@depends_on ||= DSL::DependsOn.new
|
||||||
@ -284,9 +373,11 @@ module Cask
|
|||||||
@depends_on
|
@depends_on
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Declare conflicts that keep a cask from installing or working correctly.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def conflicts_with(**kwargs)
|
def conflicts_with(**kwargs)
|
||||||
# TODO: remove this constraint, and instead merge multiple conflicts_with stanzas
|
# TODO: Remove this constraint and instead merge multiple `conflicts_with` stanzas
|
||||||
set_unique_stanza(:conflicts_with, kwargs.empty?) { DSL::ConflictsWith.new(**kwargs) }
|
set_unique_stanza(:conflicts_with, kwargs.empty?) { DSL::ConflictsWith.new(**kwargs) }
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -298,6 +389,8 @@ module Cask
|
|||||||
cask.caskroom_path
|
cask.caskroom_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The staged location for this cask, including version number.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def staged_path
|
def staged_path
|
||||||
return @staged_path if @staged_path
|
return @staged_path if @staged_path
|
||||||
@ -306,6 +399,8 @@ module Cask
|
|||||||
@staged_path = caskroom_path.join(cask_version.to_s)
|
@staged_path = caskroom_path.join(cask_version.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Provide the user with cask-specific information at install time.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def caveats(*strings, &block)
|
def caveats(*strings, &block)
|
||||||
@caveats ||= DSL::Caveats.new(cask)
|
@caveats ||= DSL::Caveats.new(cask)
|
||||||
@ -326,11 +421,15 @@ module Cask
|
|||||||
@caveats&.discontinued? == true
|
@caveats&.discontinued? == true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Asserts that the cask artifacts auto-update.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def auto_updates(auto_updates = nil)
|
def auto_updates(auto_updates = nil)
|
||||||
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
|
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Automatically fetch the latest version of a cask from changelogs.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def livecheck(&block)
|
def livecheck(&block)
|
||||||
@livecheck ||= Livecheck.new(cask)
|
@livecheck ||= Livecheck.new(cask)
|
||||||
@ -344,6 +443,10 @@ module Cask
|
|||||||
@livecheck.instance_eval(&block)
|
@livecheck.instance_eval(&block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Declare that a cask is no longer functional or supported.
|
||||||
|
#
|
||||||
|
# NOTE: A warning will be shown when trying to install this cask.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def deprecate!(date:, because:)
|
def deprecate!(date:, because:)
|
||||||
@deprecation_date = Date.parse(date)
|
@deprecation_date = Date.parse(date)
|
||||||
@ -353,6 +456,10 @@ module Cask
|
|||||||
@deprecated = true
|
@deprecated = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Declare that a cask is no longer functional or supported.
|
||||||
|
#
|
||||||
|
# NOTE: An error will be thrown when trying to install this cask.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def disable!(date:, because:)
|
def disable!(date:, because:)
|
||||||
@disable_date = Date.parse(date)
|
@disable_date = Date.parse(date)
|
||||||
@ -405,6 +512,8 @@ module Cask
|
|||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The directory `app`s are installed into.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def appdir
|
def appdir
|
||||||
return HOMEBREW_CASK_APPDIR_PLACEHOLDER if Cask.generating_hash?
|
return HOMEBREW_CASK_APPDIR_PLACEHOLDER if Cask.generating_hash?
|
||||||
|
@ -37,7 +37,6 @@ module Cask
|
|||||||
|
|
||||||
private_class_method :caveat
|
private_class_method :caveat
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
(@custom_caveats + @built_in_caveats.values).join("\n")
|
(@custom_caveats + @built_in_caveats.values).join("\n")
|
||||||
|
@ -27,7 +27,6 @@ module Cask
|
|||||||
pairs.to_yaml
|
pairs.to_yaml
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s = pairs.inspect
|
def to_s = pairs.inspect
|
||||||
end
|
end
|
||||||
|
@ -9,8 +9,8 @@ module Cask
|
|||||||
class Postflight < Base
|
class Postflight < Base
|
||||||
include Staged
|
include Staged
|
||||||
|
|
||||||
def suppress_move_to_applications(_options = {})
|
def suppress_move_to_applications(**_options)
|
||||||
odisabled "Cask::DSL#suppress_move_to_applications"
|
odisabled "`Cask::DSL::Postflight#suppress_move_to_applications`"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -94,70 +94,94 @@ module Cask
|
|||||||
to_s == "latest"
|
to_s == "latest"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The major version.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(T.self_type) }
|
sig { returns(T.self_type) }
|
||||||
def major
|
def major
|
||||||
version { slice(MAJOR_MINOR_PATCH_REGEX, 1) }
|
version { slice(MAJOR_MINOR_PATCH_REGEX, 1) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The minor version.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(T.self_type) }
|
sig { returns(T.self_type) }
|
||||||
def minor
|
def minor
|
||||||
version { slice(MAJOR_MINOR_PATCH_REGEX, 2) }
|
version { slice(MAJOR_MINOR_PATCH_REGEX, 2) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The patch version.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(T.self_type) }
|
sig { returns(T.self_type) }
|
||||||
def patch
|
def patch
|
||||||
version { slice(MAJOR_MINOR_PATCH_REGEX, 3) }
|
version { slice(MAJOR_MINOR_PATCH_REGEX, 3) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The major and minor version.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(T.self_type) }
|
sig { returns(T.self_type) }
|
||||||
def major_minor
|
def major_minor
|
||||||
version { [major, minor].reject(&:empty?).join(".") }
|
version { [major, minor].reject(&:empty?).join(".") }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The major, minor and patch version.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(T.self_type) }
|
sig { returns(T.self_type) }
|
||||||
def major_minor_patch
|
def major_minor_patch
|
||||||
version { [major, minor, patch].reject(&:empty?).join(".") }
|
version { [major, minor, patch].reject(&:empty?).join(".") }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The minor and patch version.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(T.self_type) }
|
sig { returns(T.self_type) }
|
||||||
def minor_patch
|
def minor_patch
|
||||||
version { [minor, patch].reject(&:empty?).join(".") }
|
version { [minor, patch].reject(&:empty?).join(".") }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The comma separated values of the version as array.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(T::Array[Version]) } # Only top-level T.self_type is supported https://sorbet.org/docs/self-type
|
sig { returns(T::Array[Version]) } # Only top-level T.self_type is supported https://sorbet.org/docs/self-type
|
||||||
def csv
|
def csv
|
||||||
split(",").map { self.class.new(_1) }
|
split(",").map { self.class.new(_1) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The version part before the first comma.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(T.self_type) }
|
sig { returns(T.self_type) }
|
||||||
def before_comma
|
def before_comma
|
||||||
version { split(",", 2).first }
|
version { split(",", 2).first }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The version part after the first comma.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(T.self_type) }
|
sig { returns(T.self_type) }
|
||||||
def after_comma
|
def after_comma
|
||||||
version { split(",", 2).second }
|
version { split(",", 2).second }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The version without any dividers.
|
||||||
|
#
|
||||||
|
# @see DIVIDER_REGEX
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(T.self_type) }
|
sig { returns(T.self_type) }
|
||||||
def no_dividers
|
def no_dividers
|
||||||
version { gsub(DIVIDER_REGEX, "") }
|
version { gsub(DIVIDER_REGEX, "") }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The version with the given record separator removed from the end.
|
||||||
|
#
|
||||||
|
# @see String#chomp
|
||||||
# @api public
|
# @api public
|
||||||
sig { params(separator: T.nilable(String)).returns(T.self_type) }
|
sig { params(separator: String).returns(T.self_type) }
|
||||||
def chomp(separator = nil)
|
def chomp(separator = T.unsafe(nil))
|
||||||
version { to_s.chomp(T.unsafe(separator)) }
|
version { to_s.chomp(separator) }
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -13,7 +13,6 @@ module Cask
|
|||||||
@errors = errors
|
@errors = errors
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
<<~EOS
|
<<~EOS
|
||||||
@ -41,7 +40,6 @@ module Cask
|
|||||||
|
|
||||||
# Error when a cask is not installed.
|
# Error when a cask is not installed.
|
||||||
class CaskNotInstalledError < AbstractCaskErrorWithToken
|
class CaskNotInstalledError < AbstractCaskErrorWithToken
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' is not installed."
|
"Cask '#{token}' is not installed."
|
||||||
@ -57,7 +55,6 @@ module Cask
|
|||||||
@message = message
|
@message = message
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' has been #{message}"
|
"Cask '#{token}' has been #{message}"
|
||||||
@ -73,7 +70,6 @@ module Cask
|
|||||||
@conflicting_cask = conflicting_cask
|
@conflicting_cask = conflicting_cask
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' conflicts with '#{conflicting_cask}'."
|
"Cask '#{token}' conflicts with '#{conflicting_cask}'."
|
||||||
@ -82,7 +78,6 @@ module Cask
|
|||||||
|
|
||||||
# Error when a cask is not available.
|
# Error when a cask is not available.
|
||||||
class CaskUnavailableError < AbstractCaskErrorWithToken
|
class CaskUnavailableError < AbstractCaskErrorWithToken
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' is unavailable#{reason.empty? ? "." : ": #{reason}"}"
|
"Cask '#{token}' is unavailable#{reason.empty? ? "." : ": #{reason}"}"
|
||||||
@ -91,7 +86,6 @@ module Cask
|
|||||||
|
|
||||||
# Error when a cask is unreadable.
|
# Error when a cask is unreadable.
|
||||||
class CaskUnreadableError < CaskUnavailableError
|
class CaskUnreadableError < CaskUnavailableError
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' is unreadable#{reason.empty? ? "." : ": #{reason}"}"
|
"Cask '#{token}' is unreadable#{reason.empty? ? "." : ": #{reason}"}"
|
||||||
@ -107,7 +101,6 @@ module Cask
|
|||||||
@tap = tap
|
@tap = tap
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = super
|
s = super
|
||||||
@ -142,7 +135,6 @@ module Cask
|
|||||||
|
|
||||||
# Error when a cask already exists.
|
# Error when a cask already exists.
|
||||||
class CaskAlreadyCreatedError < AbstractCaskErrorWithToken
|
class CaskAlreadyCreatedError < AbstractCaskErrorWithToken
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
%Q(Cask '#{token}' already exists. Run #{Formatter.identifier("brew edit --cask #{token}")} to edit it.)
|
%Q(Cask '#{token}' already exists. Run #{Formatter.identifier("brew edit --cask #{token}")} to edit it.)
|
||||||
@ -151,7 +143,6 @@ module Cask
|
|||||||
|
|
||||||
# Error when there is a cyclic cask dependency.
|
# Error when there is a cyclic cask dependency.
|
||||||
class CaskCyclicDependencyError < AbstractCaskErrorWithToken
|
class CaskCyclicDependencyError < AbstractCaskErrorWithToken
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' includes cyclic dependencies on other Casks#{reason.empty? ? "." : ": #{reason}"}"
|
"Cask '#{token}' includes cyclic dependencies on other Casks#{reason.empty? ? "." : ": #{reason}"}"
|
||||||
@ -160,7 +151,6 @@ module Cask
|
|||||||
|
|
||||||
# Error when a cask depends on itself.
|
# Error when a cask depends on itself.
|
||||||
class CaskSelfReferencingDependencyError < CaskCyclicDependencyError
|
class CaskSelfReferencingDependencyError < CaskCyclicDependencyError
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' depends on itself."
|
"Cask '#{token}' depends on itself."
|
||||||
@ -169,7 +159,6 @@ module Cask
|
|||||||
|
|
||||||
# Error when no cask is specified.
|
# Error when no cask is specified.
|
||||||
class CaskUnspecifiedError < CaskError
|
class CaskUnspecifiedError < CaskError
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"This command requires a Cask token."
|
"This command requires a Cask token."
|
||||||
@ -178,7 +167,6 @@ module Cask
|
|||||||
|
|
||||||
# Error when a cask is invalid.
|
# Error when a cask is invalid.
|
||||||
class CaskInvalidError < AbstractCaskErrorWithToken
|
class CaskInvalidError < AbstractCaskErrorWithToken
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' definition is invalid#{reason.empty? ? "." : ": #{reason}"}"
|
"Cask '#{token}' definition is invalid#{reason.empty? ? "." : ": #{reason}"}"
|
||||||
@ -203,7 +191,6 @@ module Cask
|
|||||||
@reason = reason
|
@reason = reason
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = +"Failed to quarantine #{path}."
|
s = +"Failed to quarantine #{path}."
|
||||||
@ -220,7 +207,6 @@ module Cask
|
|||||||
|
|
||||||
# Error while propagating quarantine information to subdirectories.
|
# Error while propagating quarantine information to subdirectories.
|
||||||
class CaskQuarantinePropagationError < CaskQuarantineError
|
class CaskQuarantinePropagationError < CaskQuarantineError
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = +"Failed to quarantine one or more files within #{path}."
|
s = +"Failed to quarantine one or more files within #{path}."
|
||||||
@ -237,7 +223,6 @@ module Cask
|
|||||||
|
|
||||||
# Error while removing quarantine information.
|
# Error while removing quarantine information.
|
||||||
class CaskQuarantineReleaseError < CaskQuarantineError
|
class CaskQuarantineReleaseError < CaskQuarantineError
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = +"Failed to release #{path} from quarantine."
|
s = +"Failed to release #{path} from quarantine."
|
||||||
|
@ -17,22 +17,32 @@ module Cask
|
|||||||
extend Forwardable
|
extend Forwardable
|
||||||
def_delegators :uri, :path, :scheme, :to_s
|
def_delegators :uri, :path, :scheme, :to_s
|
||||||
|
|
||||||
# @api public
|
|
||||||
sig {
|
sig {
|
||||||
params(
|
params(
|
||||||
uri: T.any(URI::Generic, String),
|
uri: T.any(URI::Generic, String),
|
||||||
|
# @api public
|
||||||
verified: T.nilable(String),
|
verified: T.nilable(String),
|
||||||
|
# @api public
|
||||||
using: T.any(Class, Symbol, NilClass),
|
using: T.any(Class, Symbol, NilClass),
|
||||||
|
# @api public
|
||||||
tag: T.nilable(String),
|
tag: T.nilable(String),
|
||||||
|
# @api public
|
||||||
branch: T.nilable(String),
|
branch: T.nilable(String),
|
||||||
|
# @api public
|
||||||
revisions: T.nilable(T::Array[String]),
|
revisions: T.nilable(T::Array[String]),
|
||||||
|
# @api public
|
||||||
revision: T.nilable(String),
|
revision: T.nilable(String),
|
||||||
|
# @api public
|
||||||
trust_cert: T.nilable(T::Boolean),
|
trust_cert: T.nilable(T::Boolean),
|
||||||
|
# @api public
|
||||||
cookies: T.nilable(T::Hash[String, String]),
|
cookies: T.nilable(T::Hash[String, String]),
|
||||||
referer: T.nilable(T.any(URI::Generic, String)),
|
referer: T.nilable(T.any(URI::Generic, String)),
|
||||||
|
# @api public
|
||||||
header: T.nilable(T.any(String, T::Array[String])),
|
header: T.nilable(T.any(String, T::Array[String])),
|
||||||
user_agent: T.nilable(T.any(Symbol, String)),
|
user_agent: T.nilable(T.any(Symbol, String)),
|
||||||
|
# @api public
|
||||||
data: T.nilable(T::Hash[String, String]),
|
data: T.nilable(T::Hash[String, String]),
|
||||||
|
# @api public
|
||||||
only_path: T.nilable(String),
|
only_path: T.nilable(String),
|
||||||
).void
|
).void
|
||||||
}
|
}
|
||||||
@ -77,8 +87,19 @@ module Cask
|
|||||||
end
|
end
|
||||||
|
|
||||||
class BlockDSL
|
class BlockDSL
|
||||||
# To access URL associated with page contents.
|
# Allow accessing the URL associated with page contents.
|
||||||
module PageWithURL
|
module PageWithURL
|
||||||
|
# Get the URL of the fetched page.
|
||||||
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# url "https://example.org/download" do |page|
|
||||||
|
# file = page[/href="([^"]+.dmg)"/, 1]
|
||||||
|
# URL.join(page.url, file)
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(URI::Generic) }
|
sig { returns(URI::Generic) }
|
||||||
attr_accessor :url
|
attr_accessor :url
|
||||||
@ -87,12 +108,12 @@ module Cask
|
|||||||
sig {
|
sig {
|
||||||
params(
|
params(
|
||||||
uri: T.nilable(T.any(URI::Generic, String)),
|
uri: T.nilable(T.any(URI::Generic, String)),
|
||||||
dsl: T.nilable(::Cask::DSL),
|
dsl: ::Cask::DSL,
|
||||||
block: T.proc.params(arg0: T.all(String, PageWithURL))
|
block: T.proc.params(arg0: T.all(String, PageWithURL))
|
||||||
.returns(T.any(T.any(URI::Generic, String), [T.any(URI::Generic, String), Hash])),
|
.returns(T.any(T.any(URI::Generic, String), [T.any(URI::Generic, String), Hash])),
|
||||||
).void
|
).void
|
||||||
}
|
}
|
||||||
def initialize(uri, dsl: nil, &block)
|
def initialize(uri, dsl:, &block)
|
||||||
@uri = uri
|
@uri = uri
|
||||||
@dsl = dsl
|
@dsl = dsl
|
||||||
@block = block
|
@block = block
|
||||||
@ -114,6 +135,8 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Allows calling a nested `url` stanza in a `url do` block.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig {
|
sig {
|
||||||
params(
|
params(
|
||||||
@ -123,10 +146,12 @@ module Cask
|
|||||||
).returns(T.any(T.any(URI::Generic, String), [T.any(URI::Generic, String), Hash]))
|
).returns(T.any(T.any(URI::Generic, String), [T.any(URI::Generic, String), Hash]))
|
||||||
}
|
}
|
||||||
def url(uri, &block)
|
def url(uri, &block)
|
||||||
self.class.new(uri, &block).call
|
self.class.new(uri, dsl: @dsl, &block).call
|
||||||
end
|
end
|
||||||
private :url
|
private :url
|
||||||
|
|
||||||
|
# This allows calling DSL methods from inside a `url` block.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
def method_missing(method, *args, &block)
|
def method_missing(method, *args, &block)
|
||||||
if @dsl.respond_to?(method)
|
if @dsl.respond_to?(method)
|
||||||
@ -135,10 +160,12 @@ module Cask
|
|||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
private :method_missing
|
||||||
|
|
||||||
def respond_to_missing?(method, include_all)
|
def respond_to_missing?(method, include_all)
|
||||||
@dsl.respond_to?(method, include_all) || super
|
@dsl.respond_to?(method, include_all) || super
|
||||||
end
|
end
|
||||||
|
private :respond_to_missing?
|
||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
@ -187,7 +214,7 @@ module Cask
|
|||||||
super(
|
super(
|
||||||
if block
|
if block
|
||||||
LazyObject.new do
|
LazyObject.new do
|
||||||
uri2, options = *BlockDSL.new(uri, dsl:, &block).call
|
uri2, options = *BlockDSL.new(uri, dsl: T.must(dsl), &block).call
|
||||||
options ||= {}
|
options ||= {}
|
||||||
DSL.new(uri2, **options)
|
DSL.new(uri2, **options)
|
||||||
end
|
end
|
||||||
|
@ -68,9 +68,9 @@ module Cask
|
|||||||
unless tried_permissions
|
unless tried_permissions
|
||||||
print_stderr = Context.current.debug? || Context.current.verbose?
|
print_stderr = Context.current.debug? || Context.current.verbose?
|
||||||
# TODO: Better handling for the case where path is a symlink.
|
# TODO: Better handling for the case where path is a symlink.
|
||||||
# The -h and -R flags cannot be combined, and behavior is
|
# The `-h` and `-R` flags cannot be combined and behavior is
|
||||||
# dependent on whether the file argument has a trailing
|
# dependent on whether the file argument has a trailing
|
||||||
# slash. This should do the right thing, but is fragile.
|
# slash. This should do the right thing, but is fragile.
|
||||||
command.run("/usr/bin/chflags",
|
command.run("/usr/bin/chflags",
|
||||||
print_stderr:,
|
print_stderr:,
|
||||||
args: command_args + ["--", "000", path])
|
args: command_args + ["--", "000", path])
|
||||||
@ -87,7 +87,7 @@ module Cask
|
|||||||
unless tried_ownership
|
unless tried_ownership
|
||||||
# in case of ownership problems
|
# in case of ownership problems
|
||||||
# TODO: Further examine files to see if ownership is the problem
|
# TODO: Further examine files to see if ownership is the problem
|
||||||
# before using sudo+chown
|
# before using `sudo` and `chown`.
|
||||||
ohai "Using sudo to gain ownership of path '#{path}'"
|
ohai "Using sudo to gain ownership of path '#{path}'"
|
||||||
command.run("/usr/sbin/chown",
|
command.run("/usr/sbin/chown",
|
||||||
args: command_args + ["--", User.current, path],
|
args: command_args + ["--", User.current, path],
|
||||||
|
@ -756,7 +756,7 @@ class ReporterHub
|
|||||||
def dump(auto_update: false)
|
def dump(auto_update: false)
|
||||||
report_all = ENV["HOMEBREW_UPDATE_REPORT_ALL_FORMULAE"].present?
|
report_all = ENV["HOMEBREW_UPDATE_REPORT_ALL_FORMULAE"].present?
|
||||||
if report_all && !Homebrew::EnvConfig.no_install_from_api?
|
if report_all && !Homebrew::EnvConfig.no_install_from_api?
|
||||||
odisabled "HOMEBREW_UPDATE_REPORT_ALL_FORMULAE"
|
odisabled "`HOMEBREW_UPDATE_REPORT_ALL_FORMULAE`"
|
||||||
opoo "This will not report all formulae because Homebrew cannot get this data from the API."
|
opoo "This will not report all formulae because Homebrew cannot get this data from the API."
|
||||||
report_all = false
|
report_all = false
|
||||||
end
|
end
|
||||||
|
@ -65,7 +65,6 @@ class CompilerFailure
|
|||||||
type == compiler.type && version_matched
|
type == compiler.type && version_matched
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{type} #{version}>"
|
"#<#{self.class.name}: #{type} #{version}>"
|
||||||
|
@ -22,7 +22,6 @@ class CxxStdlib
|
|||||||
type.to_s.gsub(/cxx$/, "c++")
|
type.to_s.gsub(/cxx$/, "c++")
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{compiler} #{type}>"
|
"#<#{self.class.name}: #{compiler} #{type}>"
|
||||||
|
@ -35,7 +35,6 @@ class Dependencies < SimpleDelegator
|
|||||||
self.class.new(*__getobj__.reject { |dep| dep.uses_from_macos? && dep.use_macos_install? })
|
self.class.new(*__getobj__.reject { |dep| dep.uses_from_macos? && dep.use_macos_install? })
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{__getobj__}>"
|
"#<#{self.class.name}: #{__getobj__}>"
|
||||||
@ -62,7 +61,6 @@ class Requirements < SimpleDelegator
|
|||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: {#{__getobj__.to_a.join(", ")}}>"
|
"#<#{self.class.name}: {#{__getobj__.to_a.join(", ")}}>"
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
require "dependable"
|
require "dependable"
|
||||||
|
|
||||||
# A dependency on another Homebrew formula.
|
# A dependency on another Homebrew formula.
|
||||||
|
#
|
||||||
|
# @api internal
|
||||||
class Dependency
|
class Dependency
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
include Dependable
|
include Dependable
|
||||||
@ -94,11 +96,9 @@ class Dependency
|
|||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s = name
|
def to_s = name
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{name.inspect} #{tags.inspect}>"
|
"#<#{self.class.name}: #{name.inspect} #{tags.inspect}>"
|
||||||
@ -115,6 +115,8 @@ class Dependency
|
|||||||
# the list.
|
# the list.
|
||||||
# The default filter, which is applied when a block is not given, omits
|
# The default filter, which is applied when a block is not given, omits
|
||||||
# optionals and recommends based on what the dependent has asked for
|
# optionals and recommends based on what the dependent has asked for
|
||||||
|
#
|
||||||
|
# @api internal
|
||||||
def expand(dependent, deps = dependent.deps, cache_key: nil, &block)
|
def expand(dependent, deps = dependent.deps, cache_key: nil, &block)
|
||||||
# Keep track dependencies to avoid infinite cyclic dependency recursion.
|
# Keep track dependencies to avoid infinite cyclic dependency recursion.
|
||||||
@expand_stack ||= []
|
@expand_stack ||= []
|
||||||
@ -181,6 +183,8 @@ class Dependency
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Keep a dependency, but prune its dependencies.
|
# Keep a dependency, but prune its dependencies.
|
||||||
|
#
|
||||||
|
# @api internal
|
||||||
sig { void }
|
sig { void }
|
||||||
def keep_but_prune_recursive_deps
|
def keep_but_prune_recursive_deps
|
||||||
throw(:action, :keep_but_prune_recursive_deps)
|
throw(:action, :keep_but_prune_recursive_deps)
|
||||||
@ -282,7 +286,6 @@ class UsesFromMacOSDependency < Dependency
|
|||||||
self.class.new(formula.full_name.to_s, tags, bounds:)
|
self.class.new(formula.full_name.to_s, tags, bounds:)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{name.inspect} #{tags.inspect} #{bounds.inspect}>"
|
"#<#{self.class.name}: #{name.inspect} #{tags.inspect} #{bounds.inspect}>"
|
||||||
|
@ -98,7 +98,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
odie "Could not find #{name}! The formula or version may not have existed." if test_formula.nil?
|
odie "Could not find #{name}! The formula or version may not have existed." if test_formula.nil?
|
||||||
else
|
else
|
||||||
# Search in the root directory of <repo> as well as recursively in all of its subdirectories
|
# Search in the root directory of `repo` as well as recursively in all of its subdirectories.
|
||||||
files = Dir[repo/"{,**/}"].filter_map do |dir|
|
files = Dir[repo/"{,**/}"].filter_map do |dir|
|
||||||
Pathname.glob("#{dir}/#{name}.rb").find(&:file?)
|
Pathname.glob("#{dir}/#{name}.rb").find(&:file?)
|
||||||
end
|
end
|
||||||
|
@ -20,16 +20,18 @@ module Homebrew
|
|||||||
def run
|
def run
|
||||||
Homebrew.install_bundler_gems!(groups: ["doc"])
|
Homebrew.install_bundler_gems!(groups: ["doc"])
|
||||||
|
|
||||||
HOMEBREW_LIBRARY_PATH.cd do
|
HOMEBREW_LIBRARY_PATH.cd do |dir|
|
||||||
no_api_args = if args.only_public?
|
no_api_args = if args.only_public?
|
||||||
["--hide-api", "private", "--hide-api", "internal"]
|
["--hide-api", "private", "--hide-api", "internal"]
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
system "bundle", "exec", "yard", "doc", "--output", "doc", *no_api_args
|
output_dir = dir/"doc"
|
||||||
|
|
||||||
exec_browser "file://#{HOMEBREW_LIBRARY_PATH}/doc/index.html" if args.open?
|
safe_system "bundle", "exec", "yard", "doc", "--fail-on-warning", *no_api_args, "--output", output_dir
|
||||||
|
|
||||||
|
exec_browser "file://#{output_dir}/index.html" if args.open?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -77,11 +77,9 @@ class AbstractDownloadStrategy
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Disable any output during downloading.
|
# Disable any output during downloading.
|
||||||
#
|
|
||||||
# @deprecated
|
|
||||||
sig { void }
|
sig { void }
|
||||||
def shutup!
|
def shutup!
|
||||||
odeprecated "AbstractDownloadStrategy#shutup!", "AbstractDownloadStrategy#quiet!"
|
odeprecated "`AbstractDownloadStrategy#shutup!`", "`AbstractDownloadStrategy#quiet!`"
|
||||||
quiet!
|
quiet!
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -125,7 +123,6 @@ class AbstractDownloadStrategy
|
|||||||
end
|
end
|
||||||
private :chdir
|
private :chdir
|
||||||
|
|
||||||
# @!attribute [r] source_modified_time
|
|
||||||
# Returns the most recent modified time for all files in the current working directory after stage.
|
# Returns the most recent modified time for all files in the current working directory after stage.
|
||||||
#
|
#
|
||||||
# @api public
|
# @api public
|
||||||
@ -236,9 +233,7 @@ class VCSDownloadStrategy < AbstractDownloadStrategy
|
|||||||
version.respond_to?(:head?) && version.head?
|
version.respond_to?(:head?) && version.head?
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!attribute [r] last_commit
|
# Return the most recent modified timestamp.
|
||||||
# Return last commit's unique identifier for the repository.
|
|
||||||
# Return most recent modified timestamp unless overridden.
|
|
||||||
#
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
@ -733,7 +728,8 @@ class SubversionDownloadStrategy < VCSDownloadStrategy
|
|||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see AbstractDownloadStrategy#source_modified_time
|
# Returns the most recent modified time for all files in the current working directory after stage.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(Time) }
|
sig { returns(Time) }
|
||||||
def source_modified_time
|
def source_modified_time
|
||||||
@ -747,7 +743,8 @@ class SubversionDownloadStrategy < VCSDownloadStrategy
|
|||||||
Time.parse time
|
Time.parse time
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see VCSDownloadStrategy#last_commit
|
# Return last commit's unique identifier for the repository.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def last_commit
|
def last_commit
|
||||||
@ -847,7 +844,8 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
|||||||
@ref ||= "master"
|
@ref ||= "master"
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see AbstractDownloadStrategy#source_modified_time
|
# Returns the most recent modified time for all files in the current working directory after stage.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(Time) }
|
sig { returns(Time) }
|
||||||
def source_modified_time
|
def source_modified_time
|
||||||
@ -855,7 +853,8 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
|||||||
Time.parse(out)
|
Time.parse(out)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see VCSDownloadStrategy#last_commit
|
# Return last commit's unique identifier for the repository.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def last_commit
|
def last_commit
|
||||||
@ -1165,7 +1164,8 @@ class CVSDownloadStrategy < VCSDownloadStrategy
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see AbstractDownloadStrategy#source_modified_time
|
# Returns the most recent modified time for all files in the current working directory after stage.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(Time) }
|
sig { returns(Time) }
|
||||||
def source_modified_time
|
def source_modified_time
|
||||||
@ -1240,7 +1240,8 @@ class MercurialDownloadStrategy < VCSDownloadStrategy
|
|||||||
@url = @url.sub(%r{^hg://}, "")
|
@url = @url.sub(%r{^hg://}, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see AbstractDownloadStrategy#source_modified_time
|
# Returns the most recent modified time for all files in the current working directory after stage.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(Time) }
|
sig { returns(Time) }
|
||||||
def source_modified_time
|
def source_modified_time
|
||||||
@ -1250,7 +1251,8 @@ class MercurialDownloadStrategy < VCSDownloadStrategy
|
|||||||
Time.parse(out)
|
Time.parse(out)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see VCSDownloadStrategy#last_commit
|
# Return last commit's unique identifier for the repository.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def last_commit
|
def last_commit
|
||||||
@ -1327,7 +1329,8 @@ class BazaarDownloadStrategy < VCSDownloadStrategy
|
|||||||
@url = @url.sub(%r{^bzr://}, "")
|
@url = @url.sub(%r{^bzr://}, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see AbstractDownloadStrategy#source_modified_time
|
# Returns the most recent modified time for all files in the current working directory after stage.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(Time) }
|
sig { returns(Time) }
|
||||||
def source_modified_time
|
def source_modified_time
|
||||||
@ -1338,7 +1341,8 @@ class BazaarDownloadStrategy < VCSDownloadStrategy
|
|||||||
Time.parse(timestamp)
|
Time.parse(timestamp)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see VCSDownloadStrategy#last_commit
|
# Return last commit's unique identifier for the repository.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def last_commit
|
def last_commit
|
||||||
@ -1390,7 +1394,8 @@ class FossilDownloadStrategy < VCSDownloadStrategy
|
|||||||
@url = @url.sub(%r{^fossil://}, "")
|
@url = @url.sub(%r{^fossil://}, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see AbstractDownloadStrategy#source_modified_time
|
# Returns the most recent modified time for all files in the current working directory after stage.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(Time) }
|
sig { returns(Time) }
|
||||||
def source_modified_time
|
def source_modified_time
|
||||||
@ -1398,7 +1403,8 @@ class FossilDownloadStrategy < VCSDownloadStrategy
|
|||||||
Time.parse(out[/^uuid: +\h+ (.+)$/, 1])
|
Time.parse(out[/^uuid: +\h+ (.+)$/, 1])
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see VCSDownloadStrategy#last_commit
|
# Return last commit's unique identifier for the repository.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def last_commit
|
def last_commit
|
||||||
|
@ -16,7 +16,6 @@ class UsageError < RuntimeError
|
|||||||
@reason = reason
|
@reason = reason
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = "Invalid usage"
|
s = "Invalid usage"
|
||||||
@ -109,7 +108,6 @@ class FormulaOrCaskUnavailableError < RuntimeError
|
|||||||
"Did you mean #{similar_formula_names.to_sentence two_words_connector: " or ", last_word_connector: " or "}?"
|
"Did you mean #{similar_formula_names.to_sentence two_words_connector: " or ", last_word_connector: " or "}?"
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = "No available formula or cask with the name \"#{name}\". #{did_you_mean}".strip
|
s = "No available formula or cask with the name \"#{name}\". #{did_you_mean}".strip
|
||||||
@ -129,7 +127,6 @@ class TapFormulaOrCaskUnavailableError < FormulaOrCaskUnavailableError
|
|||||||
@tap = tap
|
@tap = tap
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = super
|
s = super
|
||||||
@ -149,7 +146,6 @@ class FormulaUnavailableError < FormulaOrCaskUnavailableError
|
|||||||
" (dependency of #{dependent})" if dependent && dependent != name
|
" (dependency of #{dependent})" if dependent && dependent != name
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"No available formula with the name \"#{name}\"#{dependent_s}. #{did_you_mean}".strip
|
"No available formula with the name \"#{name}\"#{dependent_s}. #{did_you_mean}".strip
|
||||||
@ -160,7 +156,6 @@ end
|
|||||||
module FormulaClassUnavailableErrorModule
|
module FormulaClassUnavailableErrorModule
|
||||||
attr_reader :path, :class_name, :class_list
|
attr_reader :path, :class_name, :class_list
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = super
|
s = super
|
||||||
@ -204,7 +199,6 @@ end
|
|||||||
module FormulaUnreadableErrorModule
|
module FormulaUnreadableErrorModule
|
||||||
attr_reader :formula_error
|
attr_reader :formula_error
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"#{name}: " + formula_error.to_s
|
"#{name}: " + formula_error.to_s
|
||||||
@ -233,7 +227,6 @@ class TapFormulaUnavailableError < FormulaUnavailableError
|
|||||||
super "#{tap}/#{name}"
|
super "#{tap}/#{name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = super
|
s = super
|
||||||
@ -572,7 +565,7 @@ class UnbottledError < RuntimeError
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Raised by Homebrew.install, Homebrew.reinstall, and Homebrew.upgrade
|
# Raised by `Homebrew.install`, `Homebrew.reinstall` and `Homebrew.upgrade`
|
||||||
# if the user passes any flags/environment that would case a bottle-only
|
# if the user passes any flags/environment that would case a bottle-only
|
||||||
# installation on a system without build tools to fail.
|
# installation on a system without build tools to fail.
|
||||||
class BuildFlagsError < RuntimeError
|
class BuildFlagsError < RuntimeError
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# typed: strict
|
# typed: strict
|
||||||
|
|
||||||
|
# @!visibility private
|
||||||
module EnvMethods
|
module EnvMethods
|
||||||
include Kernel
|
include Kernel
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ module EnvActivation
|
|||||||
include Superenv
|
include Superenv
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @!visibility private
|
||||||
class Sorbet
|
class Sorbet
|
||||||
module Private
|
module Private
|
||||||
module Static
|
module Static
|
||||||
|
@ -4,6 +4,7 @@ module SharedEnvExtension
|
|||||||
include EnvMethods
|
include EnvMethods
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @!visibility private
|
||||||
class Sorbet
|
class Sorbet
|
||||||
module Private
|
module Private
|
||||||
module Static
|
module Static
|
||||||
|
@ -2,59 +2,72 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Array
|
class Array
|
||||||
# Equal to <tt>self[1]</tt>.
|
# Equal to `self[1]`.
|
||||||
#
|
#
|
||||||
# %w( a b c d e ).second # => "b"
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# %w( a b c d e ).second # => "b"
|
||||||
|
# ```
|
||||||
def second = self[1]
|
def second = self[1]
|
||||||
|
|
||||||
# Equal to <tt>self[2]</tt>.
|
# Equal to `self[2]`.
|
||||||
#
|
#
|
||||||
# %w( a b c d e ).third # => "c"
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# %w( a b c d e ).third # => "c"
|
||||||
|
# ```
|
||||||
def third = self[2]
|
def third = self[2]
|
||||||
|
|
||||||
# Equal to <tt>self[3]</tt>.
|
# Equal to `self[3]`.
|
||||||
#
|
#
|
||||||
# %w( a b c d e ).fourth # => "d"
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# %w( a b c d e ).fourth # => "d"
|
||||||
|
# ```
|
||||||
def fourth = self[3]
|
def fourth = self[3]
|
||||||
|
|
||||||
# Equal to <tt>self[4]</tt>.
|
# Equal to `self[4]`.
|
||||||
#
|
#
|
||||||
# %w( a b c d e ).fifth # => "e"
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# %w( a b c d e ).fifth # => "e"
|
||||||
|
# ```
|
||||||
def fifth = self[4]
|
def fifth = self[4]
|
||||||
|
|
||||||
# Converts the array to a comma-separated sentence where the last element is
|
# Converts the array to a comma-separated sentence where the last element is
|
||||||
# joined by the connector word.
|
# joined by the connector word.
|
||||||
#
|
#
|
||||||
# You can pass the following kwargs to change the default behavior:
|
# ### Examples
|
||||||
#
|
#
|
||||||
# * <tt>:words_connector</tt> - The sign or word used to join all but the last
|
# ```ruby
|
||||||
# element in arrays with three or more elements (default: ", ").
|
# [].to_sentence # => ""
|
||||||
# * <tt>:last_word_connector</tt> - The sign or word used to join the last element
|
# ['one'].to_sentence # => "one"
|
||||||
# in arrays with three or more elements (default: ", and ").
|
# ['one', 'two'].to_sentence # => "one and two"
|
||||||
# * <tt>:two_words_connector</tt> - The sign or word used to join the elements
|
# ['one', 'two', 'three'].to_sentence # => "one, two and three"
|
||||||
# in arrays with two elements (default: " and ").
|
# ['one', 'two'].to_sentence(two_words_connector: '-')
|
||||||
|
# # => "one-two"
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ```
|
||||||
|
# ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
|
||||||
|
# # => "one or two or at least three"
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# [].to_sentence # => ""
|
|
||||||
# ['one'].to_sentence # => "one"
|
|
||||||
# ['one', 'two'].to_sentence # => "one and two"
|
|
||||||
# ['one', 'two', 'three'].to_sentence # => "one, two, and three"
|
|
||||||
# ['one', 'two'].to_sentence(two_words_connector: '-')
|
|
||||||
# # => "one-two"
|
|
||||||
#
|
|
||||||
# ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
|
|
||||||
# # => "one or two or at least three"
|
|
||||||
# @see https://github.com/rails/rails/blob/v7.0.4.2/activesupport/lib/active_support/core_ext/array/conversions.rb#L8-L84
|
# @see https://github.com/rails/rails/blob/v7.0.4.2/activesupport/lib/active_support/core_ext/array/conversions.rb#L8-L84
|
||||||
# ActiveSupport Array#to_sentence monkey-patch
|
# ActiveSupport Array#to_sentence monkey-patch
|
||||||
#
|
#
|
||||||
|
#
|
||||||
# Copyright (c) David Heinemeier Hansson
|
# Copyright (c) David Heinemeier Hansson
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
# a copy of this software and associated documentation files (the
|
# a copy of this software and associated documentation files (the
|
||||||
# "Software"), to deal in the Software without restriction, including
|
# "Software"), to deal in the Software without restriction, including
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
# without limitation the rights to use, copy, modify, merge, publish,
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
# distribute, sublicense and/or sell copies of the Software and to
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
# permit persons to whom the Software is furnished to do so, subject to
|
||||||
# the following conditions:
|
# the following conditions:
|
||||||
#
|
#
|
||||||
@ -68,6 +81,14 @@ class Array
|
|||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# @param [String] words_connector The sign or word used to join all but the last
|
||||||
|
# element in arrays with three or more elements (default: `", "`).
|
||||||
|
# @param [String] last_word_connector The sign or word used to join the last element
|
||||||
|
# in arrays with three or more elements (default: `" and "`).
|
||||||
|
# @param [String] two_words_connector The sign or word used to join the elements
|
||||||
|
# in arrays with two elements (default: `" and "`).
|
||||||
sig { params(words_connector: String, two_words_connector: String, last_word_connector: String).returns(String) }
|
sig { params(words_connector: String, two_words_connector: String, last_word_connector: String).returns(String) }
|
||||||
def to_sentence(words_connector: ", ", two_words_connector: " and ", last_word_connector: " and ")
|
def to_sentence(words_connector: ", ", two_words_connector: " and ", last_word_connector: " and ")
|
||||||
case length
|
case length
|
||||||
|
@ -3,15 +3,20 @@
|
|||||||
|
|
||||||
class Object
|
class Object
|
||||||
# An object is blank if it's false, empty, or a whitespace string.
|
# An object is blank if it's false, empty, or a whitespace string.
|
||||||
# For example, +nil+, '', ' ', [], {}, and +false+ are all blank.
|
|
||||||
#
|
#
|
||||||
# This simplifies
|
# For example, `nil`, `''`, `' '`, `[]`, `{}` and `false` are all blank.
|
||||||
#
|
#
|
||||||
# !address || address.empty?
|
# ### Example
|
||||||
#
|
#
|
||||||
# to
|
# ```ruby
|
||||||
|
# !address || address.empty?
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# address.blank?
|
# can be simplified to
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# address.blank?
|
||||||
|
# ```
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def blank?
|
def blank?
|
||||||
respond_to?(:empty?) ? !!T.unsafe(self).empty? : false
|
respond_to?(:empty?) ? !!T.unsafe(self).empty? : false
|
||||||
@ -21,20 +26,23 @@ class Object
|
|||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def present? = !blank?
|
def present? = !blank?
|
||||||
|
|
||||||
# Returns the receiver if it's present otherwise returns +nil+.
|
# Returns the receiver if it's present, otherwise returns `nil`.
|
||||||
# <tt>object.presence</tt> is equivalent to
|
|
||||||
#
|
#
|
||||||
# object.present? ? object : nil
|
# `object.presence` is equivalent to `object.present? ? object : nil`.
|
||||||
#
|
#
|
||||||
# For example, something like
|
# ### Example
|
||||||
#
|
#
|
||||||
# state = params[:state] if params[:state].present?
|
# ```ruby
|
||||||
# country = params[:country] if params[:country].present?
|
# state = params[:state] if params[:state].present?
|
||||||
# region = state || country || 'US'
|
# country = params[:country] if params[:country].present?
|
||||||
|
# region = state || country || 'US'
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# becomes
|
# can be simplified to
|
||||||
#
|
#
|
||||||
# region = params[:state].presence || params[:country].presence || 'US'
|
# ```ruby
|
||||||
|
# region = params[:state].presence || params[:country].presence || 'US'
|
||||||
|
# ```
|
||||||
sig { returns(T.nilable(T.self_type)) }
|
sig { returns(T.nilable(T.self_type)) }
|
||||||
def presence
|
def presence
|
||||||
self if present?
|
self if present?
|
||||||
@ -42,9 +50,11 @@ class Object
|
|||||||
end
|
end
|
||||||
|
|
||||||
class NilClass
|
class NilClass
|
||||||
# +nil+ is blank:
|
# `nil` is blank:
|
||||||
#
|
#
|
||||||
# nil.blank? # => true
|
# ```ruby
|
||||||
|
# nil.blank? # => true
|
||||||
|
# ```
|
||||||
sig { returns(TrueClass) }
|
sig { returns(TrueClass) }
|
||||||
def blank? = true
|
def blank? = true
|
||||||
|
|
||||||
@ -53,9 +63,11 @@ class NilClass
|
|||||||
end
|
end
|
||||||
|
|
||||||
class FalseClass
|
class FalseClass
|
||||||
# +false+ is blank:
|
# `false` is blank:
|
||||||
#
|
#
|
||||||
# false.blank? # => true
|
# ```ruby
|
||||||
|
# false.blank? # => true
|
||||||
|
# ```
|
||||||
sig { returns(TrueClass) }
|
sig { returns(TrueClass) }
|
||||||
def blank? = true
|
def blank? = true
|
||||||
|
|
||||||
@ -64,9 +76,11 @@ class FalseClass
|
|||||||
end
|
end
|
||||||
|
|
||||||
class TrueClass
|
class TrueClass
|
||||||
# +true+ is not blank:
|
# `true` is not blank:
|
||||||
#
|
#
|
||||||
# true.blank? # => false
|
# ```ruby
|
||||||
|
# true.blank? # => false
|
||||||
|
# ```
|
||||||
sig { returns(FalseClass) }
|
sig { returns(FalseClass) }
|
||||||
def blank? = false
|
def blank? = false
|
||||||
|
|
||||||
@ -77,11 +91,12 @@ end
|
|||||||
class Array
|
class Array
|
||||||
# An array is blank if it's empty:
|
# An array is blank if it's empty:
|
||||||
#
|
#
|
||||||
# [].blank? # => true
|
# ```ruby
|
||||||
# [1,2,3].blank? # => false
|
# [].blank? # => true
|
||||||
#
|
# [1,2,3].blank? # => false
|
||||||
# @return [true, false]
|
# ```
|
||||||
alias blank? empty?
|
sig { returns(T::Boolean) }
|
||||||
|
def blank? = empty?
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def present? = !empty? # :nodoc:
|
def present? = !empty? # :nodoc:
|
||||||
@ -90,11 +105,13 @@ end
|
|||||||
class Hash
|
class Hash
|
||||||
# A hash is blank if it's empty:
|
# A hash is blank if it's empty:
|
||||||
#
|
#
|
||||||
# {}.blank? # => true
|
|
||||||
# { key: 'value' }.blank? # => false
|
|
||||||
#
|
#
|
||||||
# @return [true, false]
|
# ```ruby
|
||||||
alias blank? empty?
|
# {}.blank? # => true
|
||||||
|
# { key: 'value' }.blank? # => false
|
||||||
|
# ```
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def blank? = empty?
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def present? = !empty? # :nodoc:
|
def present? = !empty? # :nodoc:
|
||||||
@ -103,9 +120,12 @@ end
|
|||||||
class Symbol
|
class Symbol
|
||||||
# A Symbol is blank if it's empty:
|
# A Symbol is blank if it's empty:
|
||||||
#
|
#
|
||||||
# :''.blank? # => true
|
# ```ruby
|
||||||
# :symbol.blank? # => false
|
# :''.blank? # => true
|
||||||
alias blank? empty?
|
# :symbol.blank? # => false
|
||||||
|
# ```
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def blank? = empty?
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def present? = !empty? # :nodoc:
|
def present? = !empty? # :nodoc:
|
||||||
@ -122,14 +142,18 @@ class String
|
|||||||
|
|
||||||
# A string is blank if it's empty or contains whitespaces only:
|
# A string is blank if it's empty or contains whitespaces only:
|
||||||
#
|
#
|
||||||
# ''.blank? # => true
|
# ```ruby
|
||||||
# ' '.blank? # => true
|
# ''.blank? # => true
|
||||||
# "\t\n\r".blank? # => true
|
# ' '.blank? # => true
|
||||||
# ' blah '.blank? # => false
|
# "\t\n\r".blank? # => true
|
||||||
|
# ' blah '.blank? # => false
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# Unicode whitespace is supported:
|
# Unicode whitespace is supported:
|
||||||
#
|
#
|
||||||
# "\u00a0".blank? # => true
|
# ```ruby
|
||||||
|
# "\u00a0".blank? # => true
|
||||||
|
# ```
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def blank?
|
def blank?
|
||||||
# The regexp that matches blank strings is expensive. For the case of empty
|
# The regexp that matches blank strings is expensive. For the case of empty
|
||||||
@ -150,8 +174,10 @@ end
|
|||||||
class Numeric # :nodoc:
|
class Numeric # :nodoc:
|
||||||
# No number is blank:
|
# No number is blank:
|
||||||
#
|
#
|
||||||
# 1.blank? # => false
|
# ```ruby
|
||||||
# 0.blank? # => false
|
# 1.blank? # => false
|
||||||
|
# 0.blank? # => false
|
||||||
|
# ```
|
||||||
sig { returns(FalseClass) }
|
sig { returns(FalseClass) }
|
||||||
def blank? = false
|
def blank? = false
|
||||||
|
|
||||||
@ -162,7 +188,9 @@ end
|
|||||||
class Time # :nodoc:
|
class Time # :nodoc:
|
||||||
# No Time is blank:
|
# No Time is blank:
|
||||||
#
|
#
|
||||||
# Time.now.blank? # => false
|
# ```ruby
|
||||||
|
# Time.now.blank? # => false
|
||||||
|
# ```
|
||||||
sig { returns(FalseClass) }
|
sig { returns(FalseClass) }
|
||||||
def blank? = false
|
def blank? = false
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Enumerable
|
module Enumerable
|
||||||
# The negative of the <tt>Enumerable#include?</tt>. Returns +true+ if the
|
# The negative of the {Enumerable#include?}. Returns `true` if the
|
||||||
# collection does not include the object.
|
# collection does not include the object.
|
||||||
sig { params(object: T.untyped).returns(T::Boolean) }
|
sig { params(object: T.untyped).returns(T::Boolean) }
|
||||||
def exclude?(object) = !include?(object)
|
def exclude?(object) = !include?(object)
|
||||||
@ -10,21 +10,29 @@ module Enumerable
|
|||||||
# Returns a new +Array+ without the blank items.
|
# Returns a new +Array+ without the blank items.
|
||||||
# Uses Object#blank? for determining if an item is blank.
|
# Uses Object#blank? for determining if an item is blank.
|
||||||
#
|
#
|
||||||
# [1, "", nil, 2, " ", [], {}, false, true].compact_blank
|
# ### Examples
|
||||||
# # => [1, 2, true]
|
|
||||||
#
|
#
|
||||||
# Set.new([nil, "", 1, false]).compact_blank
|
# ```
|
||||||
# # => [1]
|
# [1, "", nil, 2, " ", [], {}, false, true].compact_blank
|
||||||
|
# # => [1, 2, true]
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# When called on a +Hash+, returns a new +Hash+ without the blank values.
|
# ```ruby
|
||||||
|
# Set.new([nil, "", 1, false]).compact_blank
|
||||||
|
# # => [1]
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
|
# When called on a {Hash}, returns a new {Hash} without the blank values.
|
||||||
# # => { b: 1, f: true }
|
#
|
||||||
|
# ```ruby
|
||||||
|
# { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
|
||||||
|
# # => { b: 1, f: true }
|
||||||
|
# ```
|
||||||
sig { returns(T.self_type) }
|
sig { returns(T.self_type) }
|
||||||
def compact_blank = T.unsafe(self).reject(&:blank?)
|
def compact_blank = T.unsafe(self).reject(&:blank?)
|
||||||
end
|
end
|
||||||
|
|
||||||
class Hash
|
class Hash
|
||||||
# Hash#reject has its own definition, so this needs one too.
|
# {Hash#reject} has its own definition, so this needs one too.
|
||||||
def compact_blank = reject { |_k, v| T.unsafe(v).blank? }
|
def compact_blank = reject { |_k, v| T.unsafe(v).blank? }
|
||||||
end
|
end
|
||||||
|
@ -2,25 +2,31 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Hash
|
class Hash
|
||||||
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
# Returns a new hash with `self` and `other_hash` merged recursively.
|
||||||
#
|
#
|
||||||
# h1 = { a: true, b: { c: [1, 2, 3] } }
|
# ### Examples
|
||||||
# h2 = { a: false, b: { x: [3, 4, 5] } }
|
|
||||||
#
|
#
|
||||||
# h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
|
# ```ruby
|
||||||
|
# h1 = { a: true, b: { c: [1, 2, 3] } }
|
||||||
|
# h2 = { a: false, b: { x: [3, 4, 5] } }
|
||||||
|
#
|
||||||
|
# h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# Like with Hash#merge in the standard library, a block can be provided
|
# Like with Hash#merge in the standard library, a block can be provided
|
||||||
# to merge values:
|
# to merge values:
|
||||||
#
|
#
|
||||||
# h1 = { a: 100, b: 200, c: { c1: 100 } }
|
# ```ruby
|
||||||
# h2 = { b: 250, c: { c1: 200 } }
|
# h1 = { a: 100, b: 200, c: { c1: 100 } }
|
||||||
# h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
|
# h2 = { b: 250, c: { c1: 200 } }
|
||||||
# # => { a: 100, b: 450, c: { c1: 300 } }
|
# h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
|
||||||
|
# # => { a: 100, b: 450, c: { c1: 300 } }
|
||||||
|
# ```
|
||||||
def deep_merge(other_hash, &block)
|
def deep_merge(other_hash, &block)
|
||||||
dup.deep_merge!(other_hash, &block)
|
dup.deep_merge!(other_hash, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Same as +deep_merge+, but modifies +self+.
|
# Same as {#deep_merge}, but modifies `self`.
|
||||||
def deep_merge!(other_hash, &block)
|
def deep_merge!(other_hash, &block)
|
||||||
merge!(other_hash) do |key, this_val, other_val|
|
merge!(other_hash) do |key, this_val, other_val|
|
||||||
if T.unsafe(this_val).is_a?(Hash) && other_val.is_a?(Hash)
|
if T.unsafe(this_val).is_a?(Hash) && other_val.is_a?(Hash)
|
||||||
|
@ -6,11 +6,14 @@ class Hash
|
|||||||
# This includes the values from the root hash and from all
|
# This includes the values from the root hash and from all
|
||||||
# nested hashes and arrays.
|
# nested hashes and arrays.
|
||||||
#
|
#
|
||||||
# @example
|
# ### Example
|
||||||
# hash = { person: { name: 'Rob', age: '28' } }
|
|
||||||
#
|
#
|
||||||
# hash.deep_transform_values{ |value| value.to_s.upcase }
|
# ```ruby
|
||||||
# # => {person: {name: "ROB", age: "28"}}
|
# hash = { person: { name: 'Rob', age: '28' } }
|
||||||
|
#
|
||||||
|
# hash.deep_transform_values{ |value| value.to_s.upcase }
|
||||||
|
# # => {person: {name: "ROB", age: "28"}}
|
||||||
|
# ```
|
||||||
def deep_transform_values(&block) = _deep_transform_values_in_object(self, &block)
|
def deep_transform_values(&block) = _deep_transform_values_in_object(self, &block)
|
||||||
|
|
||||||
# Destructively converts all values by using the block operation.
|
# Destructively converts all values by using the block operation.
|
||||||
|
@ -5,14 +5,18 @@ class Hash
|
|||||||
# Validates all keys in a hash match `*valid_keys`, raising
|
# Validates all keys in a hash match `*valid_keys`, raising
|
||||||
# `ArgumentError` on a mismatch.
|
# `ArgumentError` on a mismatch.
|
||||||
#
|
#
|
||||||
# Note that keys are treated differently than HashWithIndifferentAccess,
|
# Note that keys are treated differently than `HashWithIndifferentAccess`,
|
||||||
# meaning that string and symbol keys will not match.
|
# meaning that string and symbol keys will not match.
|
||||||
#
|
#
|
||||||
# { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age)
|
# ### Example#
|
||||||
# # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
|
#
|
||||||
# { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age')
|
# ```ruby
|
||||||
# # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
|
# { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age)
|
||||||
# { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
|
# # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
|
||||||
|
# { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age')
|
||||||
|
# # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
|
||||||
|
# { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
|
||||||
|
# ```
|
||||||
sig { params(valid_keys: T.untyped).void }
|
sig { params(valid_keys: T.untyped).void }
|
||||||
def assert_valid_keys(*valid_keys)
|
def assert_valid_keys(*valid_keys)
|
||||||
valid_keys.flatten!
|
valid_keys.flatten!
|
||||||
@ -28,10 +32,14 @@ class Hash
|
|||||||
# This includes the keys from the root hash and from all
|
# This includes the keys from the root hash and from all
|
||||||
# nested hashes and arrays.
|
# nested hashes and arrays.
|
||||||
#
|
#
|
||||||
# hash = { person: { name: 'Rob', age: '28' } }
|
# ### Example
|
||||||
#
|
#
|
||||||
# hash.deep_transform_keys{ |key| key.to_s.upcase }
|
# ```ruby
|
||||||
# # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
|
# hash = { person: { name: 'Rob', age: '28' } }
|
||||||
|
#
|
||||||
|
# hash.deep_transform_keys{ |key| key.to_s.upcase }
|
||||||
|
# # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
|
||||||
|
# ```
|
||||||
def deep_transform_keys(&block) = _deep_transform_keys_in_object(self, &block)
|
def deep_transform_keys(&block) = _deep_transform_keys_in_object(self, &block)
|
||||||
|
|
||||||
# Destructively converts all keys by using the block operation.
|
# Destructively converts all keys by using the block operation.
|
||||||
@ -43,10 +51,14 @@ class Hash
|
|||||||
# This includes the keys from the root hash and from all
|
# This includes the keys from the root hash and from all
|
||||||
# nested hashes and arrays.
|
# nested hashes and arrays.
|
||||||
#
|
#
|
||||||
# hash = { person: { name: 'Rob', age: '28' } }
|
# ### Example
|
||||||
#
|
#
|
||||||
# hash.deep_stringify_keys
|
# ```ruby
|
||||||
# # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
|
# hash = { person: { name: 'Rob', age: '28' } }
|
||||||
|
#
|
||||||
|
# hash.deep_stringify_keys
|
||||||
|
# # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
|
||||||
|
# ```
|
||||||
def deep_stringify_keys = T.unsafe(self).deep_transform_keys(&:to_s)
|
def deep_stringify_keys = T.unsafe(self).deep_transform_keys(&:to_s)
|
||||||
|
|
||||||
# Destructively converts all keys to strings.
|
# Destructively converts all keys to strings.
|
||||||
@ -55,13 +67,17 @@ class Hash
|
|||||||
def deep_stringify_keys! = T.unsafe(self).deep_transform_keys!(&:to_s)
|
def deep_stringify_keys! = T.unsafe(self).deep_transform_keys!(&:to_s)
|
||||||
|
|
||||||
# Returns a new hash with all keys converted to symbols, as long as
|
# Returns a new hash with all keys converted to symbols, as long as
|
||||||
# they respond to +to_sym+. This includes the keys from the root hash
|
# they respond to `to_sym`. This includes the keys from the root hash
|
||||||
# and from all nested hashes and arrays.
|
# and from all nested hashes and arrays.
|
||||||
#
|
#
|
||||||
# hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
|
# ### Example
|
||||||
#
|
#
|
||||||
# hash.deep_symbolize_keys
|
# ```ruby
|
||||||
# # => {:person=>{:name=>"Rob", :age=>"28"}}
|
# hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
|
||||||
|
#
|
||||||
|
# hash.deep_symbolize_keys
|
||||||
|
# # => {:person=>{:name=>"Rob", :age=>"28"}}
|
||||||
|
# ```
|
||||||
def deep_symbolize_keys
|
def deep_symbolize_keys
|
||||||
deep_transform_keys do |key|
|
deep_transform_keys do |key|
|
||||||
T.unsafe(key).to_sym
|
T.unsafe(key).to_sym
|
||||||
@ -71,7 +87,7 @@ class Hash
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Destructively converts all keys to symbols, as long as they respond
|
# Destructively converts all keys to symbols, as long as they respond
|
||||||
# to +to_sym+. This includes the keys from the root hash and from all
|
# to `to_sym`. This includes the keys from the root hash and from all
|
||||||
# nested hashes and arrays.
|
# nested hashes and arrays.
|
||||||
def deep_symbolize_keys!
|
def deep_symbolize_keys!
|
||||||
deep_transform_keys! do |key|
|
deep_transform_keys! do |key|
|
||||||
@ -102,7 +118,7 @@ class Hash
|
|||||||
def _deep_transform_keys_in_object!(object, &block)
|
def _deep_transform_keys_in_object!(object, &block)
|
||||||
case object
|
case object
|
||||||
when Hash
|
when Hash
|
||||||
# We can't use `each_key` here because we're updating the hash in-place
|
# We can't use `each_key` here because we're updating the hash in-place.
|
||||||
object.keys.each do |key| # rubocop:disable Style/HashEachMethods
|
object.keys.each do |key| # rubocop:disable Style/HashEachMethods
|
||||||
value = object.delete(key)
|
value = object.delete(key)
|
||||||
object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
|
object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
|
||||||
|
@ -493,14 +493,20 @@ module Kernel
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Calls the given block with the passed environment variables
|
# Calls the given block with the passed environment variables
|
||||||
# added to ENV, then restores ENV afterwards.
|
# added to `ENV`, then restores `ENV` afterwards.
|
||||||
# <pre>with_env(PATH: "/bin") do
|
#
|
||||||
# system "echo $PATH"
|
# NOTE: This method is **not** thread-safe – other threads
|
||||||
# end</pre>
|
# which happen to be scheduled during the block will also
|
||||||
|
# see these environment variables.
|
||||||
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# with_env(PATH: "/bin") do
|
||||||
|
# system "echo $PATH"
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# @note This method is *not* thread-safe - other threads
|
|
||||||
# which happen to be scheduled during the block will also
|
|
||||||
# see these environment variables.
|
|
||||||
# @api public
|
# @api public
|
||||||
def with_env(hash)
|
def with_env(hash)
|
||||||
old_values = {}
|
old_values = {}
|
||||||
|
@ -1,24 +1,30 @@
|
|||||||
# typed: strict
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
#--
|
|
||||||
# Most objects are cloneable, but not all. For example you can't dup methods:
|
# Most objects are cloneable, but not all. For example you can't dup methods:
|
||||||
#
|
#
|
||||||
# method(:puts).dup # => TypeError: allocator undefined for Method
|
# ```ruby
|
||||||
|
# method(:puts).dup # => TypeError: allocator undefined for Method
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# Classes may signal their instances are not duplicable removing +dup+/+clone+
|
# Classes may signal their instances are not duplicable removing +dup+/+clone+
|
||||||
# or raising exceptions from them. So, to dup an arbitrary object you normally
|
# or raising exceptions from them. So, to dup an arbitrary object you normally
|
||||||
# use an optimistic approach and are ready to catch an exception, say:
|
# use an optimistic approach and are ready to catch an exception, say:
|
||||||
#
|
#
|
||||||
# arbitrary_object.dup rescue object
|
# ```ruby
|
||||||
|
# arbitrary_object.dup rescue object
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# Rails dups objects in a few critical spots where they are not that arbitrary.
|
# Rails dups objects in a few critical spots where they are not that arbitrary.
|
||||||
# That rescue is very expensive (like 40 times slower than a predicate), and it
|
# That `rescue` is very expensive (like 40 times slower than a predicate) and it
|
||||||
# is often triggered.
|
# is often triggered.
|
||||||
#
|
#
|
||||||
# That's why we hardcode the following cases and check duplicable? instead of
|
# That's why we hardcode the following cases and check duplicable? instead of
|
||||||
# using that rescue idiom.
|
# using that rescue idiom.
|
||||||
#++
|
# rubocop:disable Layout/EmptyLines
|
||||||
|
|
||||||
|
|
||||||
|
# rubocop:enable Layout/EmptyLines
|
||||||
class Object
|
class Object
|
||||||
# Can you safely dup this object?
|
# Can you safely dup this object?
|
||||||
#
|
#
|
||||||
@ -31,8 +37,10 @@ end
|
|||||||
class Method
|
class Method
|
||||||
# Methods are not duplicable:
|
# Methods are not duplicable:
|
||||||
#
|
#
|
||||||
# method(:puts).duplicable? # => false
|
# ```ruby
|
||||||
# method(:puts).dup # => TypeError: allocator undefined for Method
|
# method(:puts).duplicable? # => false
|
||||||
|
# method(:puts).dup # => TypeError: allocator undefined for Method
|
||||||
|
# ```
|
||||||
sig { returns(FalseClass) }
|
sig { returns(FalseClass) }
|
||||||
def duplicable? = false
|
def duplicable? = false
|
||||||
end
|
end
|
||||||
@ -40,8 +48,10 @@ end
|
|||||||
class UnboundMethod
|
class UnboundMethod
|
||||||
# Unbound methods are not duplicable:
|
# Unbound methods are not duplicable:
|
||||||
#
|
#
|
||||||
# method(:puts).unbind.duplicable? # => false
|
# ```ruby
|
||||||
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
|
# method(:puts).unbind.duplicable? # => false
|
||||||
|
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
|
||||||
|
# ```
|
||||||
sig { returns(FalseClass) }
|
sig { returns(FalseClass) }
|
||||||
def duplicable? = false
|
def duplicable? = false
|
||||||
end
|
end
|
||||||
@ -51,7 +61,9 @@ require "singleton"
|
|||||||
module Singleton
|
module Singleton
|
||||||
# Singleton instances are not duplicable:
|
# Singleton instances are not duplicable:
|
||||||
#
|
#
|
||||||
# Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
|
# ```ruby
|
||||||
|
# Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
|
||||||
|
# ```
|
||||||
sig { returns(FalseClass) }
|
sig { returns(FalseClass) }
|
||||||
def duplicable? = false
|
def duplicable? = false
|
||||||
end
|
end
|
||||||
|
@ -16,7 +16,7 @@ module Homebrew
|
|||||||
return unless @args.cask?
|
return unless @args.cask?
|
||||||
|
|
||||||
# NOTE: We don't raise an error here because we don't want
|
# NOTE: We don't raise an error here because we don't want
|
||||||
# to print the help page or a stack trace.
|
# to print the help page or a stack trace.
|
||||||
odie "Invalid `--cask` usage: Casks do not work on Linux"
|
odie "Invalid `--cask` usage: Casks do not work on Linux"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -27,12 +27,11 @@ module Stdenv
|
|||||||
|
|
||||||
append "LDFLAGS", "-Wl,-headerpad_max_install_names"
|
append "LDFLAGS", "-Wl,-headerpad_max_install_names"
|
||||||
|
|
||||||
# sed is strict, and errors out when it encounters files with
|
# `sed` is strict and errors out when it encounters files with mixed character sets.
|
||||||
# mixed character sets
|
|
||||||
delete("LC_ALL")
|
delete("LC_ALL")
|
||||||
self["LC_CTYPE"] = "C"
|
self["LC_CTYPE"] = "C"
|
||||||
|
|
||||||
# Add lib and include etc. from the current macosxsdk to compiler flags:
|
# Add `lib` and `include` etc. from the current `macosxsdk` to compiler flags:
|
||||||
macosxsdk(formula: @formula, testing_formula:)
|
macosxsdk(formula: @formula, testing_formula:)
|
||||||
|
|
||||||
return unless MacOS::Xcode.without_clt?
|
return unless MacOS::Xcode.without_clt?
|
||||||
@ -42,8 +41,8 @@ module Stdenv
|
|||||||
end
|
end
|
||||||
|
|
||||||
def remove_macosxsdk(version = nil)
|
def remove_macosxsdk(version = nil)
|
||||||
# Clear all lib and include dirs from CFLAGS, CPPFLAGS, LDFLAGS that were
|
# Clear all `lib` and `include` dirs from `CFLAGS`, `CPPFLAGS`, `LDFLAGS` that were
|
||||||
# previously added by macosxsdk
|
# previously added by `macosxsdk`.
|
||||||
remove_from_cflags(/ ?-mmacosx-version-min=\d+\.\d+/)
|
remove_from_cflags(/ ?-mmacosx-version-min=\d+\.\d+/)
|
||||||
delete("CPATH")
|
delete("CPATH")
|
||||||
remove "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib"
|
remove "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib"
|
||||||
@ -58,14 +57,14 @@ module Stdenv
|
|||||||
if HOMEBREW_PREFIX.to_s == "/usr/local"
|
if HOMEBREW_PREFIX.to_s == "/usr/local"
|
||||||
delete("CMAKE_PREFIX_PATH")
|
delete("CMAKE_PREFIX_PATH")
|
||||||
else
|
else
|
||||||
# It was set in setup_build_environment, so we have to restore it here.
|
# It was set in `setup_build_environment`, so we have to restore it here.
|
||||||
self["CMAKE_PREFIX_PATH"] = HOMEBREW_PREFIX.to_s
|
self["CMAKE_PREFIX_PATH"] = HOMEBREW_PREFIX.to_s
|
||||||
end
|
end
|
||||||
remove "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks"
|
remove "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks"
|
||||||
end
|
end
|
||||||
|
|
||||||
def macosxsdk(version = nil, formula: nil, testing_formula: false)
|
def macosxsdk(version = nil, formula: nil, testing_formula: false)
|
||||||
# Sets all needed lib and include dirs to CFLAGS, CPPFLAGS, LDFLAGS.
|
# Sets all needed `lib` and `include` dirs to `CFLAGS`, `CPPFLAGS`, `LDFLAGS`.
|
||||||
remove_macosxsdk
|
remove_macosxsdk
|
||||||
min_version = version || MacOS.version
|
min_version = version || MacOS.version
|
||||||
append_to_cflags("-mmacosx-version-min=#{min_version}")
|
append_to_cflags("-mmacosx-version-min=#{min_version}")
|
||||||
|
@ -83,8 +83,8 @@ module Hardware
|
|||||||
sysctl_bool("hw.optional.sse4_2")
|
sysctl_bool("hw.optional.sse4_2")
|
||||||
end
|
end
|
||||||
|
|
||||||
# NOTE: this is more reliable than checking uname.
|
# NOTE: This is more reliable than checking `uname`. `sysctl` returns
|
||||||
# `sysctl` returns the right answer even when running in Rosetta 2.
|
# the right answer even when running in Rosetta 2.
|
||||||
def physical_cpu_arm64?
|
def physical_cpu_arm64?
|
||||||
sysctl_bool("hw.optional.arm64")
|
sysctl_bool("hw.optional.arm64")
|
||||||
end
|
end
|
||||||
|
@ -126,10 +126,11 @@ class Pathname
|
|||||||
|
|
||||||
mkpath
|
mkpath
|
||||||
|
|
||||||
# Use FileUtils.mv over File.rename to handle filesystem boundaries. If src
|
# Use `FileUtils.mv` over `File.rename` to handle filesystem boundaries. If `src`
|
||||||
# is a symlink, and its target is moved first, FileUtils.mv will fail:
|
# is a symlink and its target is moved first, `FileUtils.mv` will fail
|
||||||
# https://bugs.ruby-lang.org/issues/7707
|
# (https://bugs.ruby-lang.org/issues/7707).
|
||||||
# In that case, use the system "mv" command.
|
#
|
||||||
|
# In that case, use the system `mv` command.
|
||||||
if src.symlink?
|
if src.symlink?
|
||||||
raise unless Kernel.system "mv", src.to_s, dst
|
raise unless Kernel.system "mv", src.to_s, dst
|
||||||
else
|
else
|
||||||
@ -178,7 +179,9 @@ class Pathname
|
|||||||
T.unsafe(self).open("a", **open_args) { |f| f.puts(content) }
|
T.unsafe(self).open("a", **open_args) { |f| f.puts(content) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# @note This always overwrites.
|
# Write to a file atomically.
|
||||||
|
#
|
||||||
|
# NOTE: This always overwrites.
|
||||||
#
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { params(content: String).void }
|
sig { params(content: String).void }
|
||||||
@ -201,6 +204,7 @@ class Pathname
|
|||||||
# Changing file ownership failed, moving on.
|
# Changing file ownership failed, moving on.
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# This operation will affect filesystem ACL's
|
# This operation will affect filesystem ACL's
|
||||||
chmod(old_stat.mode)
|
chmod(old_stat.mode)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -37,7 +37,6 @@ class KegOnlyReason
|
|||||||
!by_macos?
|
!by_macos?
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
return @explanation unless @explanation.empty?
|
return @explanation unless @explanation.empty?
|
||||||
|
@ -25,7 +25,6 @@ module Homebrew
|
|||||||
@text.include? string
|
@text.include? string
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
@text
|
@text
|
||||||
|
@ -106,7 +106,6 @@ class GitRepository
|
|||||||
popen_git("log", "-1", "--pretty=%B", commit, "--", safe:, err: :out)&.strip
|
popen_git("log", "-1", "--pretty=%B", commit, "--", safe:, err: :out)&.strip
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s = pathname.to_s
|
def to_s = pathname.to_s
|
||||||
|
|
||||||
|
@ -48,7 +48,6 @@ class Keg
|
|||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = []
|
s = []
|
||||||
@ -67,7 +66,6 @@ class Keg
|
|||||||
|
|
||||||
# Error for when a directory is not writable.
|
# Error for when a directory is not writable.
|
||||||
class DirectoryNotWritableError < LinkError
|
class DirectoryNotWritableError < LinkError
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
<<~EOS
|
<<~EOS
|
||||||
@ -176,11 +174,9 @@ class Keg
|
|||||||
path.parent
|
path.parent
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s = path.to_s
|
def to_s = path.to_s
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}:#{path}>"
|
"#<#{self.class.name}:#{path}>"
|
||||||
|
@ -14,7 +14,7 @@ module Language
|
|||||||
# e.g. `resource "github.com/foo/bar"`.
|
# e.g. `resource "github.com/foo/bar"`.
|
||||||
sig { params(resources: T::Array[Resource], target: T.any(String, Pathname)).void }
|
sig { params(resources: T::Array[Resource], target: T.any(String, Pathname)).void }
|
||||||
def self.stage_deps(resources, target)
|
def self.stage_deps(resources, target)
|
||||||
# odeprecated "Language::Go::stage_deps", "Go modules"
|
# odeprecated "`Language::Go.stage_deps`", "Go modules"
|
||||||
if resources.empty?
|
if resources.empty?
|
||||||
if Homebrew::EnvConfig.developer?
|
if Homebrew::EnvConfig.developer?
|
||||||
odie "Tried to stage empty Language::Go resources array"
|
odie "Tried to stage empty Language::Go resources array"
|
||||||
|
@ -150,8 +150,8 @@ module Language
|
|||||||
#
|
#
|
||||||
# @param venv_root [Pathname, String] the path to the root of the virtualenv
|
# @param venv_root [Pathname, String] the path to the root of the virtualenv
|
||||||
# (often `libexec/"venv"`)
|
# (often `libexec/"venv"`)
|
||||||
# @param python [String, Pathname] which interpreter to use (e.g. "python3"
|
# @param python [String, Pathname] which interpreter to use (e.g. `"python3"`
|
||||||
# or "python3.x")
|
# or `"python3.x"`)
|
||||||
# @param formula [Formula] the active {Formula}
|
# @param formula [Formula] the active {Formula}
|
||||||
# @return [Virtualenv] a {Virtualenv} instance
|
# @return [Virtualenv] a {Virtualenv} instance
|
||||||
sig {
|
sig {
|
||||||
@ -166,7 +166,7 @@ module Language
|
|||||||
def virtualenv_create(venv_root, python = "python", formula = T.cast(self, Formula),
|
def virtualenv_create(venv_root, python = "python", formula = T.cast(self, Formula),
|
||||||
system_site_packages: true, without_pip: true)
|
system_site_packages: true, without_pip: true)
|
||||||
# Limit deprecation to 3.12+ for now (or if we can't determine the version).
|
# Limit deprecation to 3.12+ for now (or if we can't determine the version).
|
||||||
# Some used this argument for setuptools, which we no longer bundle since 3.12.
|
# Some used this argument for `setuptools`, which we no longer bundle since 3.12.
|
||||||
unless without_pip
|
unless without_pip
|
||||||
python_version = Language::Python.major_minor_version(python)
|
python_version = Language::Python.major_minor_version(python)
|
||||||
if python_version.nil? || python_version.null? || python_version >= "3.12"
|
if python_version.nil? || python_version.null? || python_version >= "3.12"
|
||||||
@ -198,8 +198,8 @@ module Language
|
|||||||
|
|
||||||
# Returns true if a formula option for the specified python is currently
|
# Returns true if a formula option for the specified python is currently
|
||||||
# active or if the specified python is required by the formula. Valid
|
# active or if the specified python is required by the formula. Valid
|
||||||
# inputs are "python", "python2", and :python3. Note that
|
# inputs are `"python"`, `"python2"` and `:python3`. Note that
|
||||||
# "with-python", "without-python", "with-python@2", and "without-python@2"
|
# `"with-python"`, `"without-python"`, `"with-python@2"` and `"without-python@2"`
|
||||||
# formula options are handled correctly even if not associated with any
|
# formula options are handled correctly even if not associated with any
|
||||||
# corresponding depends_on statement.
|
# corresponding depends_on statement.
|
||||||
sig { params(python: String).returns(T::Boolean) }
|
sig { params(python: String).returns(T::Boolean) }
|
||||||
|
@ -16,15 +16,20 @@ class LazyObject < Delegator
|
|||||||
@__delegate__ = @__callable__.call
|
@__delegate__ = @__callable__.call
|
||||||
# rubocop:enable Naming/MemoizedInstanceVariableName
|
# rubocop:enable Naming/MemoizedInstanceVariableName
|
||||||
end
|
end
|
||||||
|
private :__getobj__
|
||||||
|
|
||||||
def __setobj__(callable)
|
def __setobj__(callable)
|
||||||
@__callable__ = callable
|
@__callable__ = callable
|
||||||
end
|
end
|
||||||
|
private :__setobj__
|
||||||
|
|
||||||
# Forward to the inner object to make lazy objects type-checkable.
|
# Forward to the inner object to make lazy objects type-checkable.
|
||||||
|
#
|
||||||
|
# @!visibility private
|
||||||
def is_a?(klass)
|
def is_a?(klass)
|
||||||
# see https://sorbet.org/docs/faq#how-can-i-fix-type-errors-that-arise-from-super
|
# see https://sorbet.org/docs/faq#how-can-i-fix-type-errors-that-arise-from-super
|
||||||
T.bind(self, T.untyped)
|
T.bind(self, T.untyped)
|
||||||
|
|
||||||
__getobj__.is_a?(klass) || super
|
__getobj__.is_a?(klass) || super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -39,9 +39,11 @@ module Homebrew
|
|||||||
) do
|
) do
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
|
|
||||||
|
# @!attribute [r] version
|
||||||
# @api public
|
# @api public
|
||||||
delegate version: :bundle_version
|
delegate version: :bundle_version
|
||||||
|
|
||||||
|
# @!attribute [r] short_version
|
||||||
# @api public
|
# @api public
|
||||||
delegate short_version: :bundle_version
|
delegate short_version: :bundle_version
|
||||||
end
|
end
|
||||||
|
@ -54,12 +54,15 @@ module Homebrew
|
|||||||
) do
|
) do
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
|
|
||||||
|
# @!attribute [r] version
|
||||||
# @api public
|
# @api public
|
||||||
delegate version: :bundle_version
|
delegate version: :bundle_version
|
||||||
|
|
||||||
|
# @!attribute [r] short_version
|
||||||
# @api public
|
# @api public
|
||||||
delegate short_version: :bundle_version
|
delegate short_version: :bundle_version
|
||||||
|
|
||||||
|
# @!attribute [r] nice_version
|
||||||
# @api public
|
# @api public
|
||||||
delegate nice_version: :bundle_version
|
delegate nice_version: :bundle_version
|
||||||
end
|
end
|
||||||
|
@ -106,7 +106,6 @@ class Locale
|
|||||||
locale_groups.find { |locales| locales.any? { |locale| include?(locale) } }
|
locale_groups.find { |locales| locales.any? { |locale| include?(locale) } }
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
[@language, @script, @region].compact.join("-")
|
[@language, @script, @region].compact.join("-")
|
||||||
|
@ -132,6 +132,7 @@ class MacOSVersion < Version
|
|||||||
alias requires_popcnt? requires_nehalem_cpu?
|
alias requires_popcnt? requires_nehalem_cpu?
|
||||||
|
|
||||||
# Represents the absence of a version.
|
# Represents the absence of a version.
|
||||||
|
#
|
||||||
# NOTE: Constructor needs to called with an arbitrary macOS-like version which is then set to `nil`.
|
# NOTE: Constructor needs to called with an arbitrary macOS-like version which is then set to `nil`.
|
||||||
NULL = MacOSVersion.new("10.0").tap { |v| v.instance_variable_set(:@version, nil) }.freeze
|
NULL = MacOSVersion.new("10.0").tap { |v| v.instance_variable_set(:@version, nil) }.freeze
|
||||||
end
|
end
|
||||||
@ -141,7 +142,7 @@ require "lazy_object"
|
|||||||
module MacOSVersionErrorCompat
|
module MacOSVersionErrorCompat
|
||||||
def const_missing(name)
|
def const_missing(name)
|
||||||
if name == :MacOSVersionError
|
if name == :MacOSVersionError
|
||||||
odisabled "MacOSVersionError", "MacOSVersion::Error"
|
odisabled "`MacOSVersionError`", "`MacOSVersion::Error`"
|
||||||
return MacOSVersion::Error
|
return MacOSVersion::Error
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -158,7 +159,7 @@ end
|
|||||||
|
|
||||||
module MacOSVersions
|
module MacOSVersions
|
||||||
SYMBOLS = LazyObject.new do # rubocop:disable Style/MutableConstant
|
SYMBOLS = LazyObject.new do # rubocop:disable Style/MutableConstant
|
||||||
odisabled "MacOSVersions::SYMBOLS", "MacOSVersion::SYMBOLS"
|
odisabled "`MacOSVersions::SYMBOLS`", "`MacOSVersion::SYMBOLS`"
|
||||||
MacOSVersion::SYMBOLS
|
MacOSVersion::SYMBOLS
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -167,7 +168,7 @@ module OS
|
|||||||
module Mac
|
module Mac
|
||||||
# TODO: Replace `::Version` with `Version` when this is removed.
|
# TODO: Replace `::Version` with `Version` when this is removed.
|
||||||
Version = LazyObject.new do # rubocop:disable Style/MutableConstant
|
Version = LazyObject.new do # rubocop:disable Style/MutableConstant
|
||||||
odisabled "OS::Mac::Version", "MacOSVersion"
|
odisabled "`OS::Mac::Version`", "`MacOSVersion`"
|
||||||
MacOSVersion
|
MacOSVersion
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -287,17 +287,18 @@ class Migrator
|
|||||||
def repin
|
def repin
|
||||||
return unless pinned?
|
return unless pinned?
|
||||||
|
|
||||||
# old_pin_record is a relative symlink and when we try to to read it
|
# `old_pin_record` is a relative symlink and when we try to to read it
|
||||||
# from <dir> we actually try to find file
|
# from <dir> we actually try to find file
|
||||||
# <dir>/../<...>/../Cellar/name/version.
|
# <dir>/../<...>/../Cellar/name/version.
|
||||||
# To repin formula we need to update the link thus that it points to
|
# To repin formula we need to update the link thus that it points to
|
||||||
# the right directory.
|
# the right directory.
|
||||||
# NOTE: old_pin_record.realpath.sub(oldname, newname) is unacceptable
|
#
|
||||||
# here, because it resolves every symlink for old_pin_record and then
|
# NOTE: `old_pin_record.realpath.sub(oldname, newname)` is unacceptable
|
||||||
|
# here, because it resolves every symlink for `old_pin_record` and then
|
||||||
# substitutes oldname with newname. It breaks things like
|
# substitutes oldname with newname. It breaks things like
|
||||||
# Pathname#make_relative_symlink, where Pathname#relative_path_from
|
# `Pathname#make_relative_symlink`, where `Pathname#relative_path_from`
|
||||||
# is used to find relative path from source to destination parent and
|
# is used to find the relative path from source to destination parent
|
||||||
# it assumes no symlinks.
|
# and it assumes no symlinks.
|
||||||
src_oldname = (old_pin_record.dirname/old_pin_link_record).expand_path
|
src_oldname = (old_pin_record.dirname/old_pin_link_record).expand_path
|
||||||
new_pin_record.make_relative_symlink(src_oldname.sub(oldname, newname))
|
new_pin_record.make_relative_symlink(src_oldname.sub(oldname, newname))
|
||||||
old_pin_record.delete
|
old_pin_record.delete
|
||||||
|
@ -38,7 +38,6 @@ class Mktemp
|
|||||||
@quiet = true
|
@quiet = true
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"[Mktemp: #{tmpdir} retain=#{@retain} quiet=#{@quiet}]"
|
"[Mktemp: #{tmpdir} retain=#{@retain} quiet=#{@quiet}]"
|
||||||
|
@ -11,7 +11,6 @@ class Option
|
|||||||
@description = description
|
@description = description
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s = flag
|
def to_s = flag
|
||||||
|
|
||||||
@ -30,7 +29,6 @@ class Option
|
|||||||
name.hash
|
name.hash
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{flag.inspect}>"
|
"#<#{self.class.name}: #{flag.inspect}>"
|
||||||
@ -134,13 +132,11 @@ class Options
|
|||||||
|
|
||||||
alias to_ary to_a
|
alias to_ary to_a
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
@options.map(&:to_s).join(" ")
|
@options.map(&:to_s).join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{to_a.inspect}>"
|
"#<#{self.class.name}: #{to_a.inspect}>"
|
||||||
|
@ -51,7 +51,6 @@ class EmbeddedPatch
|
|||||||
Utils.safe_popen_write("patch", *args) { |p| p.write(data) }
|
Utils.safe_popen_write("patch", *args) { |p| p.write(data) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{strip.inspect}>"
|
"#<#{self.class.name}: #{strip.inspect}>"
|
||||||
@ -151,7 +150,6 @@ class ExternalPatch
|
|||||||
raise BuildError.new(f, cmd, args, ENV.to_hash)
|
raise BuildError.new(f, cmd, args, ENV.to_hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{strip.inspect} #{url.inspect}>"
|
"#<#{self.class.name}: #{strip.inspect} #{url.inspect}>"
|
||||||
|
@ -39,7 +39,6 @@ class PkgVersion
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s = to_str
|
def to_s = to_str
|
||||||
|
|
||||||
|
@ -140,7 +140,6 @@ class Requirement
|
|||||||
[self.class, name, tags].hash
|
[self.class, name, tags].hash
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{tags.inspect}>"
|
"#<#{self.class.name}: #{tags.inspect}>"
|
||||||
|
@ -27,7 +27,6 @@ class ArchRequirement < Requirement
|
|||||||
"The #{@arch} architecture is required for this software."
|
"The #{@arch} architecture is required for this software."
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: arch=#{@arch.to_s.inspect} #{tags.inspect}>"
|
"#<#{self.class.name}: arch=#{@arch.to_s.inspect} #{tags.inspect}>"
|
||||||
|
@ -96,7 +96,6 @@ class MacOSRequirement < Requirement
|
|||||||
[super, comparator, version].hash
|
[super, comparator, version].hash
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: version#{@comparator}#{@version.to_s.inspect} #{tags.inspect}>"
|
"#<#{self.class.name}: version#{@comparator}#{@version.to_s.inspect} #{tags.inspect}>"
|
||||||
|
@ -48,7 +48,6 @@ class XcodeRequirement < Requirement
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: version>=#{@version.inspect} #{tags.inspect}>"
|
"#<#{self.class.name}: version>=#{@version.inspect} #{tags.inspect}>"
|
||||||
|
@ -146,17 +146,22 @@ class Resource < Downloadable
|
|||||||
super(verify_download_integrity:)
|
super(verify_download_integrity:)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!attribute [w] livecheck
|
|
||||||
# {Livecheck} can be used to check for newer versions of the software.
|
# {Livecheck} can be used to check for newer versions of the software.
|
||||||
# This method evaluates the DSL specified in the livecheck block of the
|
# This method evaluates the DSL specified in the livecheck block of the
|
||||||
# {Resource} (if it exists) and sets the instance variables of a {Livecheck}
|
# {Resource} (if it exists) and sets the instance variables of a {Livecheck}
|
||||||
# object accordingly. This is used by `brew livecheck` to check for newer
|
# object accordingly. This is used by `brew livecheck` to check for newer
|
||||||
# versions of the software.
|
# versions of the software.
|
||||||
#
|
#
|
||||||
# <pre>livecheck do
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# livecheck do
|
||||||
# url "https://example.com/foo/releases"
|
# url "https://example.com/foo/releases"
|
||||||
# regex /foo-(\d+(?:\.\d+)+)\.tar/
|
# regex /foo-(\d+(?:\.\d+)+)\.tar/
|
||||||
# end</pre>
|
# end
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# @!attribute [w] livecheck
|
||||||
def livecheck(&block)
|
def livecheck(&block)
|
||||||
return @livecheck unless block
|
return @livecheck unless block
|
||||||
|
|
||||||
@ -302,7 +307,6 @@ class ResourceStageContext
|
|||||||
@staging = staging
|
@staging = staging
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"<#{self.class}: resource=#{resource} staging=#{staging}>"
|
"<#{self.class}: resource=#{resource} staging=#{staging}>"
|
||||||
|
@ -4,27 +4,26 @@
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Homebrew
|
module Homebrew
|
||||||
# Checks for code that can be written with simpler conditionals
|
# Checks for code that can be simplified using `Object#blank?`.
|
||||||
# using `Object#blank?`.
|
|
||||||
#
|
#
|
||||||
# @note
|
# NOTE: Auto-correction for this cop is unsafe because `' '.empty?` returns `false`,
|
||||||
# This cop is unsafe autocorrection, because `' '.empty?` returns false,
|
# but `' '.blank?` returns `true`. Therefore, auto-correction is not compatible
|
||||||
# but `' '.blank?` returns true. Therefore, autocorrection is not compatible
|
# if the receiver is a non-empty blank string.
|
||||||
# if the receiver is a non-empty blank string, tab, or newline meta characters.
|
|
||||||
#
|
#
|
||||||
# @example
|
# ### Example
|
||||||
# # Converts usages of `nil? || empty?` to `blank?`
|
|
||||||
#
|
#
|
||||||
# # bad
|
# ```ruby
|
||||||
# foo.nil? || foo.empty?
|
# # bad
|
||||||
# foo == nil || foo.empty?
|
# foo.nil? || foo.empty?
|
||||||
|
# foo == nil || foo.empty?
|
||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# foo.blank?
|
# foo.blank?
|
||||||
|
# ```
|
||||||
class Blank < Base
|
class Blank < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG_NIL_OR_EMPTY = "Use `%<prefer>s` instead of `%<current>s`."
|
MSG = "Use `%<prefer>s` instead of `%<current>s`."
|
||||||
|
|
||||||
# `(send nil $_)` is not actually a valid match for an offense. Nodes
|
# `(send nil $_)` is not actually a valid match for an offense. Nodes
|
||||||
# that have a single method call on the left hand side
|
# that have a single method call on the left hand side
|
||||||
@ -49,7 +48,7 @@ module RuboCop
|
|||||||
nil_or_empty?(node) do |var1, var2|
|
nil_or_empty?(node) do |var1, var2|
|
||||||
return if var1 != var2
|
return if var1 != var2
|
||||||
|
|
||||||
message = format(MSG_NIL_OR_EMPTY, prefer: replacement(var1), current: node.source)
|
message = format(MSG, prefer: replacement(var1), current: node.source)
|
||||||
add_offense(node, message:) do |corrector|
|
add_offense(node, message:) do |corrector|
|
||||||
autocorrect(corrector, node)
|
autocorrect(corrector, node)
|
||||||
end
|
end
|
||||||
|
@ -9,20 +9,23 @@ module RuboCop
|
|||||||
module Cask
|
module Cask
|
||||||
# This cop makes sure that OS conditionals are consistent.
|
# This cop makes sure that OS conditionals are consistent.
|
||||||
#
|
#
|
||||||
# @example
|
# ### Example
|
||||||
# # bad
|
|
||||||
# cask 'foo' do
|
|
||||||
# if MacOS.version == :high_sierra
|
|
||||||
# sha256 "..."
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
#
|
||||||
# # good
|
# ```ruby
|
||||||
# cask 'foo' do
|
# # bad
|
||||||
# on_high_sierra do
|
# cask 'foo' do
|
||||||
# sha256 "..."
|
# if MacOS.version == :high_sierra
|
||||||
# end
|
# sha256 "..."
|
||||||
# end
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# cask 'foo' do
|
||||||
|
# on_high_sierra do
|
||||||
|
# sha256 "..."
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
class OnSystemConditionals < Base
|
class OnSystemConditionals < Base
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
@ -6,16 +6,17 @@ module RuboCop
|
|||||||
module Cask
|
module Cask
|
||||||
# This cop checks that a cask's `url` stanza is formatted correctly.
|
# This cop checks that a cask's `url` stanza is formatted correctly.
|
||||||
#
|
#
|
||||||
# @example
|
# ### Example
|
||||||
# # bad
|
|
||||||
# url "https://example.com/download/foo.dmg",
|
|
||||||
# verified: "https://example.com/download"
|
|
||||||
#
|
#
|
||||||
|
# ```ruby
|
||||||
|
# # bad
|
||||||
|
# url "https://example.com/download/foo.dmg",
|
||||||
|
# verified: "https://example.com/download"
|
||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# url "https://example.com/download/foo.dmg",
|
# url "https://example.com/download/foo.dmg",
|
||||||
# verified: "example.com/download/"
|
# verified: "example.com/download/"
|
||||||
#
|
# ```
|
||||||
class Url < Base
|
class Url < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
|
@ -8,16 +8,19 @@ module RuboCop
|
|||||||
module Cask
|
module Cask
|
||||||
# This cop audits variables in casks.
|
# This cop audits variables in casks.
|
||||||
#
|
#
|
||||||
# @example
|
# ### Example
|
||||||
# # bad
|
|
||||||
# cask do
|
|
||||||
# arch = Hardware::CPU.intel? ? "darwin" : "darwin-arm64"
|
|
||||||
# end
|
|
||||||
#
|
#
|
||||||
# # good
|
# ```ruby
|
||||||
# cask 'foo' do
|
# # bad
|
||||||
# arch arm: "darwin-arm64", intel: "darwin"
|
# cask do
|
||||||
# end
|
# arch = Hardware::CPU.intel? ? "darwin" : "darwin-arm64"
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# cask 'foo' do
|
||||||
|
# arch arm: "darwin-arm64", intel: "darwin"
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
class Variables < Base
|
class Variables < Base
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
@ -6,27 +6,30 @@ require "rubocops/extend/formula_cop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module FormulaAudit
|
module FormulaAudit
|
||||||
# This cop makes sure that caveats don't recommend unsupported or unsafe operations.
|
# This cop ensures that caveats don't recommend unsupported or unsafe operations.
|
||||||
#
|
#
|
||||||
# @example
|
# ### Example
|
||||||
# # bad
|
|
||||||
# def caveats
|
|
||||||
# <<~EOS
|
|
||||||
# Use `setuid` to allow running the exeutable by non-root users.
|
|
||||||
# EOS
|
|
||||||
# end
|
|
||||||
#
|
#
|
||||||
# # good
|
# ```ruby
|
||||||
# def caveats
|
# # bad
|
||||||
# <<~EOS
|
# def caveats
|
||||||
# Use `sudo` to run the executable.
|
# <<~EOS
|
||||||
# EOS
|
# Use `setuid` to allow running the exeutable by non-root users.
|
||||||
# end
|
# EOS
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# def caveats
|
||||||
|
# <<~EOS
|
||||||
|
# Use `sudo` to run the executable.
|
||||||
|
# EOS
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
class Caveats < FormulaCop
|
class Caveats < FormulaCop
|
||||||
def audit_formula(_node, _class_node, _parent_class_node, _body_node)
|
def audit_formula(_node, _class_node, _parent_class_node, _body_node)
|
||||||
caveats_strings.each do |n|
|
caveats_strings.each do |n|
|
||||||
if regex_match_group(n, /\bsetuid\b/i)
|
if regex_match_group(n, /\bsetuid\b/i)
|
||||||
problem "Don't recommend setuid in the caveats, suggest sudo instead."
|
problem "Don't recommend `setuid` in the caveats, suggest `sudo` instead."
|
||||||
end
|
end
|
||||||
|
|
||||||
problem "Don't use ANSI escape codes in the caveats." if regex_match_group(n, /\e/)
|
problem "Don't use ANSI escape codes in the caveats." if regex_match_group(n, /\e/)
|
||||||
|
@ -6,43 +6,46 @@ module RuboCop
|
|||||||
module Homebrew
|
module Homebrew
|
||||||
# Checks if collection can be blank-compacted with `compact_blank`.
|
# Checks if collection can be blank-compacted with `compact_blank`.
|
||||||
#
|
#
|
||||||
# @note
|
# NOTE: It is unsafe by default because false positives may occur in the
|
||||||
# It is unsafe by default because false positives may occur in the
|
# blank check of block arguments to the receiver object.
|
||||||
# blank check of block arguments to the receiver object.
|
|
||||||
#
|
#
|
||||||
# For example, `[[1, 2], [3, nil]].reject { |first, second| second.blank? }` and
|
# For example, `[[1, 2], [3, nil]].reject { |first, second| second.blank? }` and
|
||||||
# `[[1, 2], [3, nil]].compact_blank` are not compatible. The same is true for `blank?`.
|
# `[[1, 2], [3, nil]].compact_blank` are not compatible. The same is true for `blank?`.
|
||||||
# This will work fine when the receiver is a hash object.
|
# This will work fine when the receiver is a hash object.
|
||||||
#
|
#
|
||||||
# And `compact_blank!` has different implementations for `Array`, `Hash`, and
|
# And `compact_blank!` has different implementations for `Array`, `Hash`, and
|
||||||
# `ActionController::Parameters`.
|
# `ActionController::Parameters`.
|
||||||
# `Array#compact_blank!`, `Hash#compact_blank!` are equivalent to `delete_if(&:blank?)`.
|
# `Array#compact_blank!`, `Hash#compact_blank!` are equivalent to `delete_if(&:blank?)`.
|
||||||
# `ActionController::Parameters#compact_blank!` is equivalent to `reject!(&:blank?)`.
|
# `ActionController::Parameters#compact_blank!` is equivalent to `reject!(&:blank?)`.
|
||||||
# If the cop makes a mistake, autocorrected code may get unexpected behavior.
|
# If the cop makes a mistake, autocorrected code may get unexpected behavior.
|
||||||
#
|
#
|
||||||
# @example
|
# ### Examples
|
||||||
#
|
#
|
||||||
# # bad
|
# ```ruby
|
||||||
# collection.reject(&:blank?)
|
# # bad
|
||||||
# collection.reject { |_k, v| v.blank? }
|
# collection.reject(&:blank?)
|
||||||
|
# collection.reject { |_k, v| v.blank? }
|
||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# collection.compact_blank
|
# collection.compact_blank
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# # bad
|
# ```ruby
|
||||||
# collection.delete_if(&:blank?) # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
|
# # bad
|
||||||
# collection.delete_if { |_, v| v.blank? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
|
# collection.delete_if(&:blank?) # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
|
||||||
# collection.reject!(&:blank?) # Same behavior as `ActionController::Parameters#compact_blank!`
|
# collection.delete_if { |_, v| v.blank? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
|
||||||
# collection.reject! { |_k, v| v.blank? } # Same behavior as `ActionController::Parameters#compact_blank!`
|
# collection.reject!(&:blank?) # Same behavior as `ActionController::Parameters#compact_blank!`
|
||||||
#
|
# collection.reject! { |_k, v| v.blank? } # Same behavior as `ActionController::Parameters#compact_blank!`
|
||||||
# # good
|
|
||||||
# collection.compact_blank!
|
|
||||||
#
|
#
|
||||||
|
# # good
|
||||||
|
# collection.compact_blank!
|
||||||
|
# ```
|
||||||
class CompactBlank < Base
|
class CompactBlank < Base
|
||||||
include RangeHelp
|
include RangeHelp
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = "Use `%<preferred_method>s` instead."
|
MSG = "Use `%<preferred_method>s` instead."
|
||||||
|
|
||||||
RESTRICT_ON_SEND = [:reject, :delete_if, :reject!].freeze
|
RESTRICT_ON_SEND = [:reject, :delete_if, :reject!].freeze
|
||||||
|
|
||||||
def_node_matcher :reject_with_block?, <<~PATTERN
|
def_node_matcher :reject_with_block?, <<~PATTERN
|
||||||
|
@ -70,7 +70,7 @@ module RuboCop
|
|||||||
# Compact the above into this list as we're able to remove detailed notations, etc over time.
|
# Compact the above into this list as we're able to remove detailed notations, etc over time.
|
||||||
when
|
when
|
||||||
# Check for http:// GitHub homepage URLs, https:// is preferred.
|
# Check for http:// GitHub homepage URLs, https:// is preferred.
|
||||||
# Note: only check homepages that are repo pages, not *.github.com hosts
|
# NOTE: Only check homepages that are repo pages, not *.github.com hosts.
|
||||||
%r{^http://github\.com/},
|
%r{^http://github\.com/},
|
||||||
%r{^http://[^/]*\.github\.io/},
|
%r{^http://[^/]*\.github\.io/},
|
||||||
|
|
||||||
|
@ -4,9 +4,10 @@
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Homebrew
|
module Homebrew
|
||||||
# This cop restricts usage of IO.read functions for security reasons.
|
# This cop restricts usage of `IO.read` functions for security reasons.
|
||||||
class IORead < Base
|
class IORead < Base
|
||||||
MSG = "The use of `IO.%<method>s` is a security risk."
|
MSG = "The use of `IO.%<method>s` is a security risk."
|
||||||
|
|
||||||
RESTRICT_ON_SEND = [:read, :readlines].freeze
|
RESTRICT_ON_SEND = [:read, :readlines].freeze
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
|
@ -7,23 +7,25 @@ module RuboCop
|
|||||||
# Enforces the use of `collection.exclude?(obj)`
|
# Enforces the use of `collection.exclude?(obj)`
|
||||||
# over `!collection.include?(obj)`.
|
# over `!collection.include?(obj)`.
|
||||||
#
|
#
|
||||||
# @note
|
# NOTE: This cop is unsafe because false positives will occur for
|
||||||
# This cop is unsafe because false positive will occur for
|
# receiver objects that do not have an `#exclude?` method (e.g. `IPAddr`).
|
||||||
# receiver objects that do not have an `exclude?` method. (e.g. `IPAddr`)
|
|
||||||
#
|
#
|
||||||
# @example
|
# ### Example
|
||||||
# # bad
|
|
||||||
# !array.include?(2)
|
|
||||||
# !hash.include?(:key)
|
|
||||||
#
|
#
|
||||||
# # good
|
# ```ruby
|
||||||
# array.exclude?(2)
|
# # bad
|
||||||
# hash.exclude?(:key)
|
# !array.include?(2)
|
||||||
|
# !hash.include?(:key)
|
||||||
#
|
#
|
||||||
|
# # good
|
||||||
|
# array.exclude?(2)
|
||||||
|
# hash.exclude?(:key)
|
||||||
|
# ```
|
||||||
class NegateInclude < Base
|
class NegateInclude < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = "Use `.exclude?` and remove the negation part."
|
MSG = "Use `.exclude?` and remove the negation part."
|
||||||
|
|
||||||
RESTRICT_ON_SEND = [:!].freeze
|
RESTRICT_ON_SEND = [:!].freeze
|
||||||
|
|
||||||
def_node_matcher :negate_include_call?, <<~PATTERN
|
def_node_matcher :negate_include_call?, <<~PATTERN
|
||||||
|
@ -7,37 +7,41 @@ module RuboCop
|
|||||||
# Checks code that can be written more easily using
|
# Checks code that can be written more easily using
|
||||||
# `Object#presence` defined by Active Support.
|
# `Object#presence` defined by Active Support.
|
||||||
#
|
#
|
||||||
# @example
|
# ### Examples
|
||||||
# # bad
|
|
||||||
# a.present? ? a : nil
|
|
||||||
#
|
#
|
||||||
# # bad
|
# ```ruby
|
||||||
# !a.present? ? nil : a
|
# # bad
|
||||||
|
# a.present? ? a : nil
|
||||||
#
|
#
|
||||||
# # bad
|
# # bad
|
||||||
# a.blank? ? nil : a
|
# !a.present? ? nil : a
|
||||||
#
|
#
|
||||||
# # bad
|
# # bad
|
||||||
# !a.blank? ? a : nil
|
# a.blank? ? nil : a
|
||||||
#
|
#
|
||||||
# # good
|
# # bad
|
||||||
# a.presence
|
# !a.blank? ? a : nil
|
||||||
#
|
#
|
||||||
# @example
|
# # good
|
||||||
# # bad
|
# a.presence
|
||||||
# a.present? ? a : b
|
# ```
|
||||||
#
|
#
|
||||||
# # bad
|
# ```ruby
|
||||||
# !a.present? ? b : a
|
# # bad
|
||||||
|
# a.present? ? a : b
|
||||||
#
|
#
|
||||||
# # bad
|
# # bad
|
||||||
# a.blank? ? b : a
|
# !a.present? ? b : a
|
||||||
#
|
#
|
||||||
# # bad
|
# # bad
|
||||||
# !a.blank? ? a : b
|
# a.blank? ? b : a
|
||||||
#
|
#
|
||||||
# # good
|
# # bad
|
||||||
# a.presence || b
|
# !a.blank? ? a : b
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# a.presence || b
|
||||||
|
# ```
|
||||||
class Presence < Base
|
class Presence < Base
|
||||||
include RangeHelp
|
include RangeHelp
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
@ -4,24 +4,24 @@
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Homebrew
|
module Homebrew
|
||||||
# Checks for code that can be written with simpler conditionals
|
# Checks for code that can be simplified using `Object#present?`.
|
||||||
# using `Object#present?`.
|
|
||||||
#
|
#
|
||||||
# @example
|
# ### Example
|
||||||
# # Converts usages of `!nil? && !empty?` to `present?`
|
|
||||||
#
|
#
|
||||||
# # bad
|
# ```ruby
|
||||||
# !foo.nil? && !foo.empty?
|
# # bad
|
||||||
|
# !foo.nil? && !foo.empty?
|
||||||
#
|
#
|
||||||
# # bad
|
# # bad
|
||||||
# foo != nil && !foo.empty?
|
# foo != nil && !foo.empty?
|
||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# foo.present?
|
# foo.present?
|
||||||
|
# ```
|
||||||
class Present < Base
|
class Present < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG_EXISTS_AND_NOT_EMPTY = "Use `%<prefer>s` instead of `%<current>s`."
|
MSG = "Use `%<prefer>s` instead of `%<current>s`."
|
||||||
|
|
||||||
def_node_matcher :exists_and_not_empty?, <<~PATTERN
|
def_node_matcher :exists_and_not_empty?, <<~PATTERN
|
||||||
(and
|
(and
|
||||||
@ -41,7 +41,7 @@ module RuboCop
|
|||||||
exists_and_not_empty?(node) do |var1, var2|
|
exists_and_not_empty?(node) do |var1, var2|
|
||||||
return if var1 != var2
|
return if var1 != var2
|
||||||
|
|
||||||
message = format(MSG_EXISTS_AND_NOT_EMPTY, prefer: replacement(var1), current: node.source)
|
message = format(MSG, prefer: replacement(var1), current: node.source)
|
||||||
|
|
||||||
add_offense(node, message:) do |corrector|
|
add_offense(node, message:) do |corrector|
|
||||||
autocorrect(corrector, node)
|
autocorrect(corrector, node)
|
||||||
@ -53,7 +53,7 @@ module RuboCop
|
|||||||
exists_and_not_empty?(node) do |var1, var2|
|
exists_and_not_empty?(node) do |var1, var2|
|
||||||
return if var1 != var2
|
return if var1 != var2
|
||||||
|
|
||||||
add_offense(node, message: MSG_EXISTS_AND_NOT_EMPTY) do |corrector|
|
add_offense(node, message: MSG) do |corrector|
|
||||||
autocorrect(corrector, node)
|
autocorrect(corrector, node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -7,28 +7,26 @@ module RuboCop
|
|||||||
# Checks to make sure safe navigation isn't used with `blank?` in
|
# Checks to make sure safe navigation isn't used with `blank?` in
|
||||||
# a conditional.
|
# a conditional.
|
||||||
#
|
#
|
||||||
# @note
|
# NOTE: While the safe navigation operator is generally a good idea, when
|
||||||
# While the safe navigation operator is generally a good idea, when
|
# checking `foo&.blank?` in a conditional, `foo` being `nil` will actually
|
||||||
# checking `foo&.blank?` in a conditional, `foo` being `nil` will actually
|
# do the opposite of what the author intends:
|
||||||
# do the opposite of what the author intends.
|
|
||||||
#
|
#
|
||||||
# For example:
|
# ```ruby
|
||||||
|
# foo&.blank? #=> nil
|
||||||
|
# foo.blank? #=> true
|
||||||
|
# ```
|
||||||
#
|
#
|
||||||
# [source,ruby]
|
# ### Example
|
||||||
# ----
|
|
||||||
# foo&.blank? #=> nil
|
|
||||||
# foo.blank? #=> true
|
|
||||||
# ----
|
|
||||||
#
|
#
|
||||||
# @example
|
# ```ruby
|
||||||
# # bad
|
# # bad
|
||||||
# do_something if foo&.blank?
|
# do_something if foo&.blank?
|
||||||
# do_something unless foo&.blank?
|
# do_something unless foo&.blank?
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# do_something if foo.blank?
|
|
||||||
# do_something unless foo.blank?
|
|
||||||
#
|
#
|
||||||
|
# # good
|
||||||
|
# do_something if foo.blank?
|
||||||
|
# do_something unless foo.blank?
|
||||||
|
# ```
|
||||||
class SafeNavigationWithBlank < Base
|
class SafeNavigationWithBlank < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ module RuboCop
|
|||||||
method_calls.delete(:service)
|
method_calls.delete(:service)
|
||||||
|
|
||||||
# NOTE: Solving the first problem here might solve the second one too
|
# NOTE: Solving the first problem here might solve the second one too
|
||||||
# so we don't show both of them at the same time.
|
# so we don't show both of them at the same time.
|
||||||
if !method_calls.keys.intersect?(REQUIRED_METHOD_CALLS)
|
if !method_calls.keys.intersect?(REQUIRED_METHOD_CALLS)
|
||||||
offending_node(service_node)
|
offending_node(service_node)
|
||||||
problem "Service blocks require `run` or `name` to be defined."
|
problem "Service blocks require `run` or `name` to be defined."
|
||||||
|
@ -174,10 +174,19 @@ module RuboCop
|
|||||||
|
|
||||||
# Matches a method with a receiver. Yields to a block with matching method node.
|
# Matches a method with a receiver. Yields to a block with matching method node.
|
||||||
#
|
#
|
||||||
# @example to match `Formula.factory(name)`
|
# ### Examples
|
||||||
# find_instance_method_call(node, "Formula", :factory)
|
#
|
||||||
# @example to match `build.head?`
|
# Match `Formula.factory(name)`.
|
||||||
# find_instance_method_call(node, :build, :head?)
|
#
|
||||||
|
# ```ruby
|
||||||
|
# find_instance_method_call(node, "Formula", :factory)
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# Match `build.head?`.
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# find_instance_method_call(node, :build, :head?)
|
||||||
|
# ```
|
||||||
def find_instance_method_call(node, instance, method_name)
|
def find_instance_method_call(node, instance, method_name)
|
||||||
methods = find_every_method_call_by_name(node, method_name)
|
methods = find_every_method_call_by_name(node, method_name)
|
||||||
methods.each do |method|
|
methods.each do |method|
|
||||||
@ -194,8 +203,13 @@ module RuboCop
|
|||||||
|
|
||||||
# Matches receiver part of method. Yields to a block with parent node of receiver.
|
# Matches receiver part of method. Yields to a block with parent node of receiver.
|
||||||
#
|
#
|
||||||
# @example to match `ARGV.<whatever>()`
|
# ### Example
|
||||||
# find_instance_call(node, "ARGV")
|
#
|
||||||
|
# Match `ARGV.<whatever>()`.
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# find_instance_call(node, "ARGV")
|
||||||
|
# ```
|
||||||
def find_instance_call(node, name)
|
def find_instance_call(node, name)
|
||||||
node.each_descendant(:send) do |method_node|
|
node.each_descendant(:send) do |method_node|
|
||||||
next if method_node.receiver.nil?
|
next if method_node.receiver.nil?
|
||||||
|
@ -40,9 +40,11 @@ module RuboCop
|
|||||||
until
|
until
|
||||||
while
|
while
|
||||||
].freeze
|
].freeze
|
||||||
|
private_constant :SHELL_BUILTINS
|
||||||
|
|
||||||
# https://github.com/ruby/ruby/blob/v2_6_3/process.c#L2495
|
# https://github.com/ruby/ruby/blob/v2_6_3/process.c#L2495
|
||||||
SHELL_METACHARACTERS = %W[* ? { } [ ] < > ( ) ~ & | \\ $ ; ' ` " \n #].freeze
|
SHELL_METACHARACTERS = %W[* ? { } [ ] < > ( ) ~ & | \\ $ ; ' ` " \n #].freeze
|
||||||
|
private_constant :SHELL_METACHARACTERS
|
||||||
|
|
||||||
# This cop makes sure that shell command arguments are separated.
|
# This cop makes sure that shell command arguments are separated.
|
||||||
class ShellCommands < Base
|
class ShellCommands < Base
|
||||||
@ -60,6 +62,8 @@ module RuboCop
|
|||||||
[:Utils, :popen_write],
|
[:Utils, :popen_write],
|
||||||
[:Utils, :safe_popen_write],
|
[:Utils, :safe_popen_write],
|
||||||
].freeze
|
].freeze
|
||||||
|
private_constant :TARGET_METHODS
|
||||||
|
|
||||||
RESTRICT_ON_SEND = TARGET_METHODS.map(&:second).uniq.freeze
|
RESTRICT_ON_SEND = TARGET_METHODS.map(&:second).uniq.freeze
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
|
@ -207,7 +207,7 @@ module RuboCop
|
|||||||
problem "Use versioned rather than branch tarballs for stable checksums."
|
problem "Use versioned rather than branch tarballs for stable checksums."
|
||||||
end
|
end
|
||||||
|
|
||||||
# Use new-style archive downloads
|
# Use new-style archive downloads.
|
||||||
archive_gh_pattern = %r{https://.*github.*/(?:tar|zip)ball/}
|
archive_gh_pattern = %r{https://.*github.*/(?:tar|zip)ball/}
|
||||||
audit_urls(urls, archive_gh_pattern) do |_, url|
|
audit_urls(urls, archive_gh_pattern) do |_, url|
|
||||||
next if url.end_with?(".git")
|
next if url.end_with?(".git")
|
||||||
|
@ -138,7 +138,7 @@ class SoftwareSpec
|
|||||||
end
|
end
|
||||||
|
|
||||||
def go_resource(name, &block)
|
def go_resource(name, &block)
|
||||||
# odeprecated "SoftwareSpec#go_resource", "Go modules"
|
# odeprecated "`SoftwareSpec#go_resource`", "Go modules"
|
||||||
resource name, Resource::Go, &block
|
resource name, Resource::Go, &block
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -207,18 +207,6 @@ class SoftwareSpec
|
|||||||
depends_on UsesFromMacOSDependency.new(dep, tags, bounds:)
|
depends_on UsesFromMacOSDependency.new(dep, tags, bounds:)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @deprecated
|
|
||||||
def uses_from_macos_elements
|
|
||||||
# TODO: Remember to remove the delegate from `Formula`.
|
|
||||||
odisabled "#uses_from_macos_elements", "#declared_deps"
|
|
||||||
end
|
|
||||||
|
|
||||||
# @deprecated
|
|
||||||
def uses_from_macos_names
|
|
||||||
# TODO: Remember to remove the delegate from `Formula`.
|
|
||||||
odisabled "#uses_from_macos_names", "#declared_deps"
|
|
||||||
end
|
|
||||||
|
|
||||||
def deps
|
def deps
|
||||||
dependency_collector.deps.dup_without_system_deps
|
dependency_collector.deps.dup_without_system_deps
|
||||||
end
|
end
|
||||||
@ -318,7 +306,6 @@ class Bottle
|
|||||||
"#{name}--#{version}#{extname}"
|
"#{name}--#{version}#{extname}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s = to_str
|
def to_s = to_str
|
||||||
|
|
||||||
|
@ -80,21 +80,12 @@ class Formula
|
|||||||
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T::Boolean) }
|
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T::Boolean) }
|
||||||
def loaded_from_api?(*args, **options, &block); end
|
def loaded_from_api?(*args, **options, &block); end
|
||||||
|
|
||||||
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
|
||||||
def resource(*args, **options, &block); end
|
|
||||||
|
|
||||||
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||||
def deps(*args, **options, &block); end
|
def deps(*args, **options, &block); end
|
||||||
|
|
||||||
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||||
def declared_deps(*args, **options, &block); end
|
def declared_deps(*args, **options, &block); end
|
||||||
|
|
||||||
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
|
||||||
def uses_from_macos_elements(*args, **options, &block); end
|
|
||||||
|
|
||||||
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
|
||||||
def uses_from_macos_names(*args, **options, &block); end
|
|
||||||
|
|
||||||
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||||
def requirements(*args, **options, &block); end
|
def requirements(*args, **options, &block); end
|
||||||
|
|
||||||
@ -161,9 +152,6 @@ class Formula
|
|||||||
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||||
def env(*args, **options, &block); end
|
def env(*args, **options, &block); end
|
||||||
|
|
||||||
sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) }
|
|
||||||
def conflicts(*args, **options, &block); end
|
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def self.loaded_from_api?; end
|
def self.loaded_from_api?; end
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ module Homebrew
|
|||||||
@column = column
|
@column = column
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
"#{line}#{column&.to_s&.prepend(":")}"
|
"#{line}#{column&.to_s&.prepend(":")}"
|
||||||
|
@ -179,7 +179,7 @@ module Homebrew
|
|||||||
# -f (--force) : we know what we are doing, force apply patches
|
# -f (--force) : we know what we are doing, force apply patches
|
||||||
# -d / (--directory=/) : change to root directory, since we use absolute file paths
|
# -d / (--directory=/) : change to root directory, since we use absolute file paths
|
||||||
# -p0 (--strip=0) : do not strip path prefixes, since we are at root directory
|
# -p0 (--strip=0) : do not strip path prefixes, since we are at root directory
|
||||||
# NOTE: we use short flags where for compatibility
|
# NOTE: We use short flags for compatibility.
|
||||||
patch_command = %w[patch -g 0 -f -d / -p0]
|
patch_command = %w[patch -g 0 -f -d / -p0]
|
||||||
patches = system_command(shellcheck, args: ["--format=diff", *args]).stdout
|
patches = system_command(shellcheck, args: ["--format=diff", *args]).stdout
|
||||||
Utils.safe_popen_write(*patch_command) { |p| p.write(patches) } if patches.present?
|
Utils.safe_popen_write(*patch_command) { |p| p.write(patches) } if patches.present?
|
||||||
|
@ -13,12 +13,18 @@ class Tab
|
|||||||
|
|
||||||
FILENAME = "INSTALL_RECEIPT.json"
|
FILENAME = "INSTALL_RECEIPT.json"
|
||||||
|
|
||||||
|
# Check whether the formula was installed as a dependency.
|
||||||
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
attr_accessor :installed_as_dependency
|
attr_accessor :installed_as_dependency
|
||||||
|
|
||||||
|
# Check whether the formula was installed on request.
|
||||||
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
attr_accessor :installed_on_request
|
attr_accessor :installed_on_request
|
||||||
|
|
||||||
|
# Check whether the formula was poured from a bottle.
|
||||||
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
attr_accessor :poured_from_bottle
|
attr_accessor :poured_from_bottle
|
||||||
|
|
||||||
@ -27,6 +33,8 @@ class Tab
|
|||||||
:built_on
|
:built_on
|
||||||
attr_writer :used_options, :unused_options, :compiler, :source_modified_time
|
attr_writer :used_options, :unused_options, :compiler, :source_modified_time
|
||||||
|
|
||||||
|
# Returns the formula's runtime dependencies.
|
||||||
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
attr_writer :runtime_dependencies
|
attr_writer :runtime_dependencies
|
||||||
|
|
||||||
@ -72,7 +80,8 @@ class Tab
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Returns the {Tab} for an install receipt at `path`.
|
# Returns the {Tab} for an install receipt at `path`.
|
||||||
# Results are cached.
|
#
|
||||||
|
# NOTE: Results are cached.
|
||||||
def self.from_file(path)
|
def self.from_file(path)
|
||||||
cache.fetch(path) do |p|
|
cache.fetch(path) do |p|
|
||||||
content = File.read(p)
|
content = File.read(p)
|
||||||
@ -282,7 +291,10 @@ class Tab
|
|||||||
spec == :stable
|
spec == :stable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The options used to install the formula.
|
||||||
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
|
sig { returns(Options) }
|
||||||
def used_options
|
def used_options
|
||||||
Options.create(@used_options)
|
Options.create(@used_options)
|
||||||
end
|
end
|
||||||
@ -321,6 +333,7 @@ class Tab
|
|||||||
built_as_bottle
|
built_as_bottle
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(Tap)) }
|
||||||
def tap
|
def tap
|
||||||
tap_name = source["tap"]
|
tap_name = source["tap"]
|
||||||
Tap.fetch(tap_name) if tap_name
|
Tap.fetch(tap_name) if tap_name
|
||||||
@ -407,7 +420,6 @@ class Tab
|
|||||||
tabfile.atomic_write(to_json)
|
tabfile.atomic_write(to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = []
|
s = []
|
||||||
|
@ -154,7 +154,6 @@ class Tap
|
|||||||
attr_reader :name
|
attr_reader :name
|
||||||
|
|
||||||
# @api public
|
# @api public
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s = name
|
def to_s = name
|
||||||
|
|
||||||
|
@ -73,8 +73,8 @@ RSpec.describe "ENV" do
|
|||||||
expect(subject["foo"]).to eq("1")
|
expect(subject["foo"]).to eq("1")
|
||||||
end
|
end
|
||||||
|
|
||||||
# NOTE: this may be a wrong behavior; we should probably reject objects that
|
# NOTE: This may be a wrong behavior; we should probably reject objects that
|
||||||
# do not respond to #to_str. For now this documents existing behavior.
|
# do not respond to `#to_str`. For now this documents existing behavior.
|
||||||
it "coerces a value to a string" do
|
it "coerces a value to a string" do
|
||||||
subject.append "foo", 42
|
subject.append "foo", 42
|
||||||
expect(subject["foo"]).to eq("42")
|
expect(subject["foo"]).to eq("42")
|
||||||
|
@ -332,8 +332,8 @@ RSpec.describe Cask::Cask, :cask do
|
|||||||
expect(JSON.pretty_generate(h["variations"])).to eq expected_sha256_variations.strip
|
expect(JSON.pretty_generate(h["variations"])).to eq expected_sha256_variations.strip
|
||||||
end
|
end
|
||||||
|
|
||||||
# @note The calls to `Cask.generating_hash!` and `Cask.generated_hash!`
|
# NOTE: The calls to `Cask.generating_hash!` and `Cask.generated_hash!`
|
||||||
# are not idempotent so they can only be used in one test.
|
# are not idempotent so they can only be used in one test.
|
||||||
it "returns the correct hash placeholders" do
|
it "returns the correct hash placeholders" do
|
||||||
described_class.generating_hash!
|
described_class.generating_hash!
|
||||||
expect(described_class).to be_generating_hash
|
expect(described_class).to be_generating_hash
|
||||||
|
@ -87,7 +87,7 @@ RSpec.describe Caveats do
|
|||||||
expect(caveats).to include("tmux")
|
expect(caveats).to include("tmux")
|
||||||
end
|
end
|
||||||
|
|
||||||
# @todo This should get deprecated and the service block `plist_name` method should get used instead.
|
# TODO: This should get deprecated and the service block `plist_name` method should get used instead.
|
||||||
it "prints info when there are custom service files" do
|
it "prints info when there are custom service files" do
|
||||||
f = formula do
|
f = formula do
|
||||||
url "foo-1.0"
|
url "foo-1.0"
|
||||||
|
@ -79,9 +79,9 @@ RSpec.describe Homebrew::Livecheck::Strategy::ElectronBuilder do
|
|||||||
end).to eq(find_versions_cached_return_hash.merge({ regex: }))
|
end).to eq(find_versions_cached_return_hash.merge({ regex: }))
|
||||||
|
|
||||||
# NOTE: A regex should be provided using the `#regex` method in a
|
# NOTE: A regex should be provided using the `#regex` method in a
|
||||||
# `livecheck` block but we're using a regex literal in the `strategy`
|
# `livecheck` block but we're using a regex literal in the `strategy`
|
||||||
# block here simply to ensure this method works as expected when a
|
# block here simply to ensure this method works as expected when a
|
||||||
# regex isn't provided.
|
# regex isn't provided.
|
||||||
expect(electron_builder.find_versions(url: http_url, provided_content: content) do |yaml|
|
expect(electron_builder.find_versions(url: http_url, provided_content: content) do |yaml|
|
||||||
regex = /^v?(\d+(?:\.\d+)+)$/i
|
regex = /^v?(\d+(?:\.\d+)+)$/i
|
||||||
yaml["version"][regex, 1]
|
yaml["version"][regex, 1]
|
||||||
|
@ -75,7 +75,7 @@ RSpec.describe Homebrew::Livecheck::Strategy::HeaderMatch do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "returns an array of version strings when given headers and a block" do
|
it "returns an array of version strings when given headers and a block" do
|
||||||
# Returning a string from block, no regex
|
# Returning a string from block, no regex.
|
||||||
expect(
|
expect(
|
||||||
header_match.versions_from_headers(headers[:location]) do |headers|
|
header_match.versions_from_headers(headers[:location]) do |headers|
|
||||||
v = Version.parse(headers["location"], detected_from_url: true)
|
v = Version.parse(headers["location"], detected_from_url: true)
|
||||||
@ -83,16 +83,17 @@ RSpec.describe Homebrew::Livecheck::Strategy::HeaderMatch do
|
|||||||
end,
|
end,
|
||||||
).to eq(versions[:location])
|
).to eq(versions[:location])
|
||||||
|
|
||||||
# Returning a string from block, explicit regex
|
# Returning a string from block, explicit regex.
|
||||||
expect(
|
expect(
|
||||||
header_match.versions_from_headers(headers[:location], regexes[:latest]) do |headers, regex|
|
header_match.versions_from_headers(headers[:location], regexes[:latest]) do |headers, regex|
|
||||||
headers["location"] ? headers["location"][regex, 1] : nil
|
headers["location"] ? headers["location"][regex, 1] : nil
|
||||||
end,
|
end,
|
||||||
).to eq(versions[:location])
|
).to eq(versions[:location])
|
||||||
|
|
||||||
# Returning an array of strings from block
|
# Returning an array of strings from block.
|
||||||
# NOTE: Strategies runs `#compact` on an array from a block, so nil
|
#
|
||||||
# values are filtered out without needing to use `#compact` in the block.
|
# NOTE: Strategies runs `#compact` on an array from a block, so nil values
|
||||||
|
# are filtered out without needing to use `#compact` in the block.
|
||||||
expect(
|
expect(
|
||||||
header_match.versions_from_headers(
|
header_match.versions_from_headers(
|
||||||
headers[:content_disposition_and_location],
|
headers[:content_disposition_and_location],
|
||||||
|
@ -126,9 +126,9 @@ RSpec.describe Homebrew::Livecheck::Strategy::Json do
|
|||||||
end).to eq(find_versions_cached_return_hash)
|
end).to eq(find_versions_cached_return_hash)
|
||||||
|
|
||||||
# NOTE: A regex should be provided using the `#regex` method in a
|
# NOTE: A regex should be provided using the `#regex` method in a
|
||||||
# `livecheck` block but we're using a regex literal in the `strategy`
|
# `livecheck` block but we're using a regex literal in the `strategy`
|
||||||
# block here simply to ensure this method works as expected when a
|
# block here simply to ensure this method works as expected when a
|
||||||
# regex isn't provided.
|
# regex isn't provided.
|
||||||
expect(json.find_versions(url: http_url, provided_content: content) do |json|
|
expect(json.find_versions(url: http_url, provided_content: content) do |json|
|
||||||
regex = /^v?(\d+(?:\.\d+)+)$/i
|
regex = /^v?(\d+(?:\.\d+)+)$/i
|
||||||
json["versions"].select { |item| item["version"]&.match?(regex) }
|
json["versions"].select { |item| item["version"]&.match?(regex) }
|
||||||
|
@ -109,11 +109,11 @@ RSpec.describe Homebrew::Livecheck::Strategy::PageMatch do
|
|||||||
.to eq(find_versions_cached_return_hash)
|
.to eq(find_versions_cached_return_hash)
|
||||||
|
|
||||||
# NOTE: Ideally, a regex should always be provided to `#find_versions`
|
# NOTE: Ideally, a regex should always be provided to `#find_versions`
|
||||||
# for `PageMatch` but there are currently some `livecheck` blocks in
|
# for `PageMatch` but there are currently some `livecheck` blocks in
|
||||||
# casks where `#regex` isn't used and the regex only exists within a
|
# casks where `#regex` isn't used and the regex only exists within a
|
||||||
# `strategy` block. This isn't ideal but, for the moment, we allow a
|
# `strategy` block. This isn't ideal but, for the moment, we allow a
|
||||||
# `strategy` block to act as a substitution for a regex and we need to
|
# `strategy` block to act as a substitution for a regex and we need to
|
||||||
# test this scenario to ensure it works.
|
# test this scenario to ensure it works.
|
||||||
#
|
#
|
||||||
# Under normal circumstances, a regex should be established in a
|
# Under normal circumstances, a regex should be established in a
|
||||||
# `livecheck` block using `#regex` and passed into the `strategy` block
|
# `livecheck` block using `#regex` and passed into the `strategy` block
|
||||||
|
@ -218,9 +218,9 @@ RSpec.describe Homebrew::Livecheck::Strategy::Xml do
|
|||||||
end).to eq(find_versions_cached_return_hash)
|
end).to eq(find_versions_cached_return_hash)
|
||||||
|
|
||||||
# NOTE: A regex should be provided using the `#regex` method in a
|
# NOTE: A regex should be provided using the `#regex` method in a
|
||||||
# `livecheck` block but we're using a regex literal in the `strategy`
|
# `livecheck` block but we're using a regex literal in the `strategy`
|
||||||
# block here simply to ensure this method works as expected when a
|
# block here simply to ensure this method works as expected when a
|
||||||
# regex isn't provided.
|
# regex isn't provided.
|
||||||
expect(xml.find_versions(url: http_url, provided_content: content_version_text) do |xml|
|
expect(xml.find_versions(url: http_url, provided_content: content_version_text) do |xml|
|
||||||
regex = /^v?(\d+(?:\.\d+)+)$/i
|
regex = /^v?(\d+(?:\.\d+)+)$/i
|
||||||
xml.get_elements("/versions/version").map { |item| item.text[regex, 1] }
|
xml.get_elements("/versions/version").map { |item| item.text[regex, 1] }
|
||||||
|
@ -127,9 +127,9 @@ RSpec.describe Homebrew::Livecheck::Strategy::Yaml do
|
|||||||
end).to eq(find_versions_cached_return_hash)
|
end).to eq(find_versions_cached_return_hash)
|
||||||
|
|
||||||
# NOTE: A regex should be provided using the `#regex` method in a
|
# NOTE: A regex should be provided using the `#regex` method in a
|
||||||
# `livecheck` block but we're using a regex literal in the `strategy`
|
# `livecheck` block but we're using a regex literal in the `strategy`
|
||||||
# block here simply to ensure this method works as expected when a
|
# block here simply to ensure this method works as expected when a
|
||||||
# regex isn't provided.
|
# regex isn't provided.
|
||||||
expect(yaml.find_versions(url: http_url, provided_content: content) do |yaml|
|
expect(yaml.find_versions(url: http_url, provided_content: content) do |yaml|
|
||||||
regex = /^v?(\d+(?:\.\d+)+)$/i
|
regex = /^v?(\d+(?:\.\d+)+)$/i
|
||||||
yaml["versions"].select { |item| item["version"]&.match?(regex) }
|
yaml["versions"].select { |item| item["version"]&.match?(regex) }
|
||||||
|
@ -1058,8 +1058,8 @@ RSpec.describe Homebrew::Service do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# @note The calls to `Formula.generating_hash!` and `Formula.generated_hash!`
|
# NOTE: The calls to `Formula.generating_hash!` and `Formula.generated_hash!`
|
||||||
# are not idempotent so they can only be used in one test.
|
# are not idempotent so they can only be used in one test.
|
||||||
it "replaces local paths with placeholders" do
|
it "replaces local paths with placeholders" do
|
||||||
f = stub_formula do
|
f = stub_formula do
|
||||||
service do
|
service do
|
||||||
|
@ -10,7 +10,7 @@ RSpec.describe Tapioca::Compilers::Args do
|
|||||||
Homebrew::Cmd::List.parser
|
Homebrew::Cmd::List.parser
|
||||||
end
|
end
|
||||||
|
|
||||||
# good testing candidate, bc it has multiple for each of switch, flag, and comma_array args:
|
# Good testing candidate because it has multiple for each of `switch`, `flag` and `comma_array` args:
|
||||||
let(:update_python_resources_parser) do
|
let(:update_python_resources_parser) do
|
||||||
require "dev-cmd/update-python-resources"
|
require "dev-cmd/update-python-resources"
|
||||||
Homebrew::DevCmd::UpdatePythonResources.parser
|
Homebrew::DevCmd::UpdatePythonResources.parser
|
||||||
|
@ -35,8 +35,8 @@ module Cachable
|
|||||||
# A list of all classes that have been loaded into memory that mixin or
|
# A list of all classes that have been loaded into memory that mixin or
|
||||||
# inherit `Cachable` at the class or module level.
|
# inherit `Cachable` at the class or module level.
|
||||||
#
|
#
|
||||||
# Note: Classes that inherit from `Formula` are excluded since it's not
|
# NOTE: Classes that inherit from `Formula` are excluded since it's not
|
||||||
# necessary to track and clear individual formula caches.
|
# necessary to track and clear individual formula caches.
|
||||||
def self.class_list
|
def self.class_list
|
||||||
@class_list ||= []
|
@class_list ||= []
|
||||||
end
|
end
|
||||||
@ -44,8 +44,8 @@ module Cachable
|
|||||||
# Clear the cache of every class or module that mixes in or inherits
|
# Clear the cache of every class or module that mixes in or inherits
|
||||||
# `Cachable` at the class or module level.
|
# `Cachable` at the class or module level.
|
||||||
#
|
#
|
||||||
# Note: Classes that inherit from `Formula` are excluded since it's not
|
# NOTE: Classes that inherit from `Formula` are excluded since it's not
|
||||||
# necessary to track and clear individual formula caches.
|
# necessary to track and clear individual formula caches.
|
||||||
def self.clear_all_caches
|
def self.clear_all_caches
|
||||||
class_list.each(&:clear_cache)
|
class_list.each(&:clear_cache)
|
||||||
end
|
end
|
||||||
|
@ -6,11 +6,11 @@ RSpec.describe UnpackStrategy::Zstd do
|
|||||||
let(:path) { TEST_FIXTURE_DIR/"cask/container.tar.zst" }
|
let(:path) { TEST_FIXTURE_DIR/"cask/container.tar.zst" }
|
||||||
|
|
||||||
it "is correctly detected" do
|
it "is correctly detected" do
|
||||||
# UnpackStrategy.detect(path) for a .tar.XXX file returns either UnpackStrategy::Tar if
|
# `UnpackStrategy.detect(path)` for a `.tar.XXX` file returns either `UnpackStrategy::Tar` if
|
||||||
# the host's tar is able to extract that compressed file or UnpackStrategy::XXX otherwise,
|
# the host's `tar` is able to extract that compressed file or `UnpackStrategy::XXX` otherwise,
|
||||||
# such as UnpackStrategy::Zstd. On macOS UnpackStrategy.detect("container.tar.zst")
|
# such as `UnpackStrategy::Zstd`. On macOS `UnpackStrategy.detect("container.tar.zst")`
|
||||||
# returns UnpackStrategy::Zstd, and on ubuntu-22.04 it returns UnpackStrategy::Tar,
|
# returns `UnpackStrategy::Zstd` and on Ubuntu 22.04 it returns `UnpackStrategy::Tar`,
|
||||||
# because the host's version of tar is recent enough and zstd is installed.
|
# because the host's version of `tar` is recent enough and `zstd` is installed.
|
||||||
expect(UnpackStrategy.detect(path)).to(be_a(described_class).or(be_a(UnpackStrategy::Tar)))
|
expect(UnpackStrategy.detect(path)).to(be_a(described_class).or(be_a(UnpackStrategy::Tar)))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -72,7 +72,7 @@ RSpec.describe Utils::Shell do
|
|||||||
specify "::csh_quote" do
|
specify "::csh_quote" do
|
||||||
expect(described_class.send(:csh_quote, "")).to eq("''")
|
expect(described_class.send(:csh_quote, "")).to eq("''")
|
||||||
expect(described_class.send(:csh_quote, "\\")).to eq("\\\\")
|
expect(described_class.send(:csh_quote, "\\")).to eq("\\\\")
|
||||||
# NOTE: this test is different than for sh
|
# NOTE: This test is different than for `sh`.
|
||||||
expect(described_class.send(:csh_quote, "\n")).to eq("'\\\n'")
|
expect(described_class.send(:csh_quote, "\n")).to eq("'\\\n'")
|
||||||
expect(described_class.send(:csh_quote, "$")).to eq("\\$")
|
expect(described_class.send(:csh_quote, "$")).to eq("\\$")
|
||||||
expect(described_class.send(:csh_quote, "word")).to eq("word")
|
expect(described_class.send(:csh_quote, "word")).to eq("word")
|
||||||
|
@ -15,7 +15,6 @@ class URL
|
|||||||
@specs.freeze
|
@specs.freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
@url
|
@url
|
||||||
|
@ -202,7 +202,6 @@ module Utils
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
to_sym.to_s
|
to_sym.to_s
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user