Merge pull request #17165 from reitermarkus/docs-private-by-default

This commit is contained in:
Markus Reiter 2024-05-01 11:45:59 +02:00 committed by GitHub
commit e479f4bc35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
172 changed files with 1803 additions and 953 deletions

View File

@ -1 +1 @@
# Please fill out one of the templates on: https://github.com/Homebrew/brew/issues/new/choose or we will close it without comment. Please fill out one of the templates on https://github.com/Homebrew/brew/issues/new/choose or we will close your issue without comment.

View File

@ -25,9 +25,22 @@ jobs:
- name: Install vale - name: Install vale
run: brew install vale run: brew install vale
- name: Run vale for docs linting - name: Lint docs
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}/docs working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
run: vale . run: |
set -euo pipefail
# Avoid failing on broken symlinks.
rm Library/Homebrew/os/mac/pkgconfig/fuse/fuse.pc
rm Library/Homebrew/os/mac/pkgconfig/fuse/osxfuse.pc
# No ignore support (https://github.com/errata-ai/vale/issues/131).
rm -r Library/Homebrew/vendor
vale .
# Restore removed files.
git reset --hard
- name: Install Ruby - name: Install Ruby
uses: ruby/setup-ruby@1198b074305f9356bd56dd4b311757cc0dab2f1c # v1.175.1 uses: ruby/setup-ruby@1198b074305f9356bd56dd4b311757cc0dab2f1c # v1.175.1

1
.gitignore vendored
View File

@ -107,6 +107,7 @@
**/vendor/bundle/ruby/*/gems/rainbow-*/ **/vendor/bundle/ruby/*/gems/rainbow-*/
**/vendor/bundle/ruby/*/gems/rbi-*/ **/vendor/bundle/ruby/*/gems/rbi-*/
**/vendor/bundle/ruby/*/gems/rdoc-*/ **/vendor/bundle/ruby/*/gems/rdoc-*/
**/vendor/bundle/ruby/*/gems/redcarpet-*/
**/vendor/bundle/ruby/*/gems/regexp_parser-*/ **/vendor/bundle/ruby/*/gems/regexp_parser-*/
**/vendor/bundle/ruby/*/gems/rexml-*/ **/vendor/bundle/ruby/*/gems/rexml-*/
**/vendor/bundle/ruby/*/gems/rspec-*/ **/vendor/bundle/ruby/*/gems/rspec-*/

View File

@ -1,4 +1,7 @@
StylesPath = ./docs/vale-styles StylesPath = ./docs/vale-styles
[*.md] [formats]
rb = md
[*.{md,rb}]
BasedOnStyles = Homebrew BasedOnStyles = Homebrew

View File

@ -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"

View File

@ -16,6 +16,7 @@ end
# installed gems (should all be require: false) # installed gems (should all be require: false)
# ALL gems that are not vendored should be in a group # ALL gems that are not vendored should be in a group
group :doc, optional: true do group :doc, optional: true do
gem "redcarpet", require: false
gem "yard", require: false gem "yard", require: false
gem "yard-sorbet", require: false gem "yard-sorbet", require: false
end end

View File

@ -53,6 +53,7 @@ GEM
rbi (0.1.12) rbi (0.1.12)
prism (>= 0.18.0, < 0.28) prism (>= 0.18.0, < 0.28)
sorbet-runtime (>= 0.5.9204) sorbet-runtime (>= 0.5.9204)
redcarpet (3.6.0)
regexp_parser (2.9.0) regexp_parser (2.9.0)
rexml (3.2.6) rexml (3.2.6)
rspec (3.13.0) rspec (3.13.0)
@ -175,6 +176,7 @@ DEPENDENCIES
patchelf patchelf
plist plist
pry pry
redcarpet
rexml rexml
rspec rspec
rspec-github rspec-github

View File

@ -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

View File

@ -6,9 +6,10 @@ require "cli/parser"
module Homebrew module Homebrew
# Subclass this to implement a `brew` command. This is preferred to declaring a named function in the `Homebrew` # Subclass this to implement a `brew` command. This is preferred to declaring a named function in the `Homebrew`
# module, because: # module, because:
#
# - Each Command lives in an isolated namespace. # - Each Command lives in an isolated namespace.
# - Each Command implements a defined interface. # - Each Command implements a defined interface.
# - `args` is available as an ivar, and thus does not need to be passed as an argument to helper methods. # - `args` is available as an instance method and thus does not need to be passed as an argument to helper methods.
# - Subclasses no longer need to reference `CLI::Parser` or parse args explicitly. # - Subclasses no longer need to reference `CLI::Parser` or parse args explicitly.
# #
# To subclass, implement a `run` method and provide a `cmd_args` block to document the command and its allowed args. # To subclass, implement a `run` method and provide a `cmd_args` block to document the command and its allowed args.

View File

@ -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

View File

@ -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'

View File

@ -28,7 +28,7 @@ class BuildEnvironment
# DSL for specifying build environment settings. # DSL for specifying build environment settings.
module DSL module DSL
# Initialise @env for each class which may use this DSL (e.g. each formula subclass). # Initialise @env for each class which may use this DSL (e.g. each formula subclass).
# `env` may never be called, and it needs to be initialised before the class is frozen. # `env` may never be called and it needs to be initialised before the class is frozen.
def inherited(child) def inherited(child)
super super
child.instance_eval do child.instance_eval do

View File

@ -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

View File

@ -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})"

View File

@ -685,7 +685,7 @@ module Cask
sig { void } sig { void }
def audit_github_repository_archived def audit_github_repository_archived
# Deprecated/disabled casks may have an archived repo. # Deprecated/disabled casks may have an archived repository.
return if cask.discontinued? || cask.deprecated? || cask.disabled? return if cask.discontinued? || cask.deprecated? || cask.disabled?
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if online? user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if online?
@ -699,7 +699,7 @@ module Cask
sig { void } sig { void }
def audit_gitlab_repository_archived def audit_gitlab_repository_archived
# Deprecated/disabled casks may have an archived repo. # Deprecated/disabled casks may have an archived repository.
return if cask.discontinued? || cask.deprecated? || cask.disabled? return if cask.discontinued? || cask.deprecated? || cask.disabled?
user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) if online? user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) if online?

View File

@ -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(" ")}>"

View File

@ -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?

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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."

View File

@ -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

View File

@ -68,7 +68,7 @@ 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",
@ -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],

View File

@ -25,27 +25,28 @@ class Cleaner
def clean def clean
ObserverPathnameExtension.reset_counts! ObserverPathnameExtension.reset_counts!
# Many formulae include 'lib/charset.alias', but it is not strictly needed # Many formulae include `lib/charset.alias`, but it is not strictly needed
# and will conflict if more than one formula provides it # and will conflict if more than one formula provides it.
observe_file_removal @formula.lib/"charset.alias" observe_file_removal @formula.lib/"charset.alias"
[@formula.bin, @formula.sbin, @formula.lib].each { |dir| clean_dir(dir) if dir.exist? } [@formula.bin, @formula.sbin, @formula.lib].each { |dir| clean_dir(dir) if dir.exist? }
# Get rid of any info 'dir' files, so they don't conflict at the link stage # Get rid of any info `dir` files, so they don't conflict at the link stage.
# #
# The 'dir' files come in at least 3 locations: # The `dir` files come in at least 3 locations:
# #
# 1. 'info/dir' # 1. `info/dir`
# 2. 'info/#{name}/dir' # 2. `info/#{name}/dir`
# 3. 'info/#{arch}/dir' # 3. `info/#{arch}/dir`
# #
# Of these 3 only 'info/#{name}/dir' is safe to keep since the rest will # Of these 3 only `info/#{name}/dir` is safe to keep since the rest will
# conflict with other formulae because they use a shared location. # conflict with other formulae because they use a shared location.
# #
# See [cleaner: recursively delete info `dir`s by gromgit · Pull Request # See
# #11597][1], [emacs 28.1 bottle does not contain `dir` file · Issue # [cleaner: recursively delete info `dir`s][1],
# #100190][2], and [Keep `info/#{f.name}/dir` files in cleaner by # [emacs 28.1 bottle does not contain `dir` file][2] and
# timvisher][3] for more info. # [Keep `info/#{f.name}/dir` files in cleaner][3]
# for more info.
# #
# [1]: https://github.com/Homebrew/brew/pull/11597 # [1]: https://github.com/Homebrew/brew/pull/11597
# [2]: https://github.com/Homebrew/homebrew-core/issues/100190 # [2]: https://github.com/Homebrew/homebrew-core/issues/100190
@ -114,15 +115,15 @@ class Cleaner
# created as part of installing any Perl module. # created as part of installing any Perl module.
PERL_BASENAMES = Set.new(%w[perllocal.pod .packlist]).freeze PERL_BASENAMES = Set.new(%w[perllocal.pod .packlist]).freeze
# Clean a top-level (bin, sbin, lib) directory, recursively, by fixing file # Clean a top-level (`bin`, `sbin`, `lib`) directory, recursively, by fixing file
# permissions and removing .la files, unless the files (or parent # permissions and removing .la files, unless the files (or parent
# directories) are protected by skip_clean. # directories) are protected by skip_clean.
# #
# bin and sbin should not have any subdirectories; if either do that is # `bin` and `sbin` should not have any subdirectories; if either do that is
# caught as an audit warning # caught as an audit warning.
# #
# lib may have a large directory tree (see Erlang for instance), and # `lib` may have a large directory tree (see Erlang for instance) and
# clean_dir applies cleaning rules to the entire tree # clean_dir applies cleaning rules to the entire tree.
sig { params(directory: Pathname).void } sig { params(directory: Pathname).void }
def clean_dir(directory) def clean_dir(directory)
directory.find do |path| directory.find do |path|
@ -137,7 +138,7 @@ class Cleaner
elsif path.symlink? elsif path.symlink?
# Skip it. # Skip it.
else else
# Set permissions for executables and non-executables # Set permissions for executables and non-executables.
perms = if executable_path?(path) perms = if executable_path?(path)
0555 0555
else else

View File

@ -376,7 +376,7 @@ module Homebrew
def cache_files def cache_files
files = cache.directory? ? cache.children : [] files = cache.directory? ? cache.children : []
cask_files = (cache/"Cask").directory? ? (cache/"Cask").children : [] cask_files = (cache/"Cask").directory? ? (cache/"Cask").children : []
api_source_files = (cache/"api-source").glob("*/*/*/*/*") # org/repo/git_head/type/file.rb api_source_files = (cache/"api-source").glob("*/*/*/*/*") # `<org>/<repo>/<git_head>/<type>/<token>.rb`
gh_actions_artifacts = (cache/"gh-actions-artifact").directory? ? (cache/"gh-actions-artifact").children : [] gh_actions_artifacts = (cache/"gh-actions-artifact").directory? ? (cache/"gh-actions-artifact").children : []
files.map { |path| { path:, type: nil } } + files.map { |path| { path:, type: nil } } +
@ -571,8 +571,8 @@ module Homebrew
HOMEBREW_PREFIX.glob("lib/python*/site-packages").each do |site_packages| HOMEBREW_PREFIX.glob("lib/python*/site-packages").each do |site_packages|
site_packages.each_child do |child| site_packages.each_child do |child|
next unless child.directory? next unless child.directory?
# TODO: Work out a sensible way to clean up pip's, setuptools', and wheel's # TODO: Work out a sensible way to clean up `pip`'s, `setuptools`' and `wheel`'s
# {dist,site}-info directories. Alternatively, consider always removing # `{dist,site}-info` directories. Alternatively, consider always removing
# all `-info` directories, because we may not be making use of them. # all `-info` directories, because we may not be making use of them.
next if child.basename.to_s.end_with?("-info") next if child.basename.to_s.end_with?("-info")

View File

@ -95,7 +95,7 @@ module Homebrew
dirs = HOMEBREW_PREFIX.subdirs.map { |dir| dir.basename.to_s } dirs = HOMEBREW_PREFIX.subdirs.map { |dir| dir.basename.to_s }
dirs -= %w[Library Cellar Caskroom .git] dirs -= %w[Library Cellar Caskroom .git]
# Exclude cache, logs, and repository, if they are located under the prefix. # Exclude cache, logs and repository, if they are located under the prefix.
[HOMEBREW_CACHE, HOMEBREW_LOGS, HOMEBREW_REPOSITORY].each do |dir| [HOMEBREW_CACHE, HOMEBREW_LOGS, HOMEBREW_REPOSITORY].each do |dir|
dirs.delete dir.relative_path_from(HOMEBREW_PREFIX).to_s dirs.delete dir.relative_path_from(HOMEBREW_PREFIX).to_s
end end

View File

@ -13,7 +13,7 @@ module Homebrew
cmd_args do cmd_args do
description <<~EOS description <<~EOS
List installed casks and formulae that have an updated version available. By default, version List installed casks and formulae that have an updated version available. By default, version
information is displayed in interactive shells, and suppressed otherwise. information is displayed in interactive shells and suppressed otherwise.
EOS EOS
switch "-q", "--quiet", switch "-q", "--quiet",
description: "List only the names of outdated kegs (takes precedence over `--verbose`)." description: "List only the names of outdated kegs (takes precedence over `--verbose`)."

View File

@ -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

View File

@ -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}>"

View File

@ -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}>"

View File

@ -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(", ")}}>"

View File

@ -33,7 +33,7 @@ module DependenciesHelpers
end end
# If a tap isn't installed, we can't find the dependencies of one of # If a tap isn't installed, we can't find the dependencies of one of
# its formulae, and an exception will be thrown if we try. # its formulae and an exception will be thrown if we try.
Dependency.keep_but_prune_recursive_deps if klass == Dependency && dep.tap && !dep.tap.installed? Dependency.keep_but_prune_recursive_deps if klass == Dependency && dep.tap && !dep.tap.installed?
end end
end end

View File

@ -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}>"

View File

@ -7,13 +7,13 @@ require "requirement"
require "requirements" require "requirements"
require "extend/cachable" require "extend/cachable"
## A dependency is a formula that another formula needs to install. # A dependency is a formula that another formula needs to install.
## A requirement is something other than a formula that another formula # A requirement is something other than a formula that another formula
## needs to be present. This includes external language modules, # needs to be present. This includes external language modules,
## command-line tools in the path, or any arbitrary predicate. # command-line tools in the path, or any arbitrary predicate.
## #
## The `depends_on` method in the formula DSL is used to declare # The `depends_on` method in the formula DSL is used to declare
## dependencies and requirements. # dependencies and requirements.
# This class is used by `depends_on` in the formula DSL to turn dependency # This class is used by `depends_on` in the formula DSL to turn dependency
# specifications into the proper kinds of dependencies and requirements. # specifications into the proper kinds of dependencies and requirements.

View File

@ -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

View File

@ -15,7 +15,7 @@ module Homebrew
cmd_args do cmd_args do
description <<~EOS description <<~EOS
Download and publish bottles, and apply the bottle commit from a Download and publish bottles and apply the bottle commit from a
pull request with artifacts generated by GitHub Actions. pull request with artifacts generated by GitHub Actions.
Requires write access to the repository. Requires write access to the repository.
EOS EOS
@ -187,7 +187,7 @@ module Homebrew
end end
end end
# Separates a commit message into subject, body, and trailers. # Separates a commit message into subject, body and trailers.
def separate_commit_message(message) def separate_commit_message(message)
subject = message.lines.first.strip subject = message.lines.first.strip
@ -337,7 +337,7 @@ module Homebrew
new_package = package_file.read new_package = package_file.read
bump_subject = determine_bump_subject(old_package, new_package, package_file, reason:) bump_subject = determine_bump_subject(old_package, new_package, package_file, reason:)
# Commit with the new subject, body, and trailers. # Commit with the new subject, body and trailers.
safe_system("git", "-C", git_repo.pathname, "commit", "--quiet", safe_system("git", "-C", git_repo.pathname, "commit", "--quiet",
"-m", bump_subject, "-m", messages.join("\n"), "-m", trailers.join("\n"), "-m", bump_subject, "-m", messages.join("\n"), "-m", trailers.join("\n"),
"--author", original_author, "--date", original_date, "--", file) "--author", original_author, "--date", original_date, "--", file)

View File

@ -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

View File

@ -46,6 +46,8 @@ module Homebrew
(tap.path/"Formula").mkpath (tap.path/"Formula").mkpath
# FIXME: https://github.com/errata-ai/vale/issues/818
# <!-- vale off -->
readme = <<~MARKDOWN readme = <<~MARKDOWN
# #{titleized_user} #{titleized_repo} # #{titleized_user} #{titleized_repo}
@ -59,6 +61,7 @@ module Homebrew
`brew help`, `man brew` or check [Homebrew's documentation](https://docs.brew.sh). `brew help`, `man brew` or check [Homebrew's documentation](https://docs.brew.sh).
MARKDOWN MARKDOWN
# <!-- vale on -->
write_path(tap, "README.md", readme) write_path(tap, "README.md", readme)
actions_main = <<~YAML actions_main = <<~YAML

View File

@ -22,13 +22,13 @@ module Homebrew
description: "Include tests that use the GitHub API and tests that use any of the taps for " \ description: "Include tests that use the GitHub API and tests that use any of the taps for " \
"official external commands." "official external commands."
switch "--debug", switch "--debug",
description: "Enable debugging using ruby/debug, or surface the standard `odebug` output." description: "Enable debugging using `ruby/debug`, or surface the standard `odebug` output."
switch "--changed", switch "--changed",
description: "Only runs tests on files that were changed from the master branch." description: "Only runs tests on files that were changed from the master branch."
switch "--fail-fast", switch "--fail-fast",
description: "Exit early on the first failing test." description: "Exit early on the first failing test."
flag "--only=", flag "--only=",
description: "Run only <test_script>`_spec.rb`. Appending `:`<line_number> will start at a " \ description: "Run only `<test_script>_spec.rb`. Appending `:<line_number>` will start at a " \
"specific line." "specific line."
flag "--profile=", flag "--profile=",
description: "Run the test suite serially to find the <n> slowest tests." description: "Run the test suite serially to find the <n> slowest tests."
@ -145,7 +145,10 @@ module Homebrew
end end
# Workaround for: # Workaround for:
#
# ```
# ruby: no -r allowed while running setuid (SecurityError) # ruby: no -r allowed while running setuid (SecurityError)
# ```
Process::UID.change_privilege(Process.euid) if Process.euid != Process.uid Process::UID.change_privilege(Process.euid) if Process.euid != Process.uid
if parallel if parallel

View File

@ -116,7 +116,7 @@ module Homebrew
# update ENV["PATH"] # update ENV["PATH"]
ENV["PATH"] = PATH.new(ENV.fetch("PATH")).prepend(curdir/"bin").to_s ENV["PATH"] = PATH.new(ENV.fetch("PATH")).prepend(curdir/"bin").to_s
# run brew help to install portable-ruby (if needed) # Run `brew help` to install `portable-ruby` (if needed).
quiet_system "brew", "help" quiet_system "brew", "help"
# run brew update # run brew update

View File

@ -221,7 +221,7 @@ module Homebrew
__check_stray_files "/usr/local/lib", "*.dylib", allow_list, <<~EOS __check_stray_files "/usr/local/lib", "*.dylib", allow_list, <<~EOS
Unbrewed dylibs were found in /usr/local/lib. Unbrewed dylibs were found in /usr/local/lib.
If you didn't put them there on purpose they could cause problems when If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted. building Homebrew formulae and may need to be deleted.
Unexpected dylibs: Unexpected dylibs:
EOS EOS
@ -246,7 +246,7 @@ module Homebrew
__check_stray_files "/usr/local/lib", "*.a", allow_list, <<~EOS __check_stray_files "/usr/local/lib", "*.a", allow_list, <<~EOS
Unbrewed static libraries were found in /usr/local/lib. Unbrewed static libraries were found in /usr/local/lib.
If you didn't put them there on purpose they could cause problems when If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted. building Homebrew formulae and may need to be deleted.
Unexpected static libraries: Unexpected static libraries:
EOS EOS
@ -266,7 +266,7 @@ module Homebrew
__check_stray_files "/usr/local/lib/pkgconfig", "*.pc", allow_list, <<~EOS __check_stray_files "/usr/local/lib/pkgconfig", "*.pc", allow_list, <<~EOS
Unbrewed '.pc' files were found in /usr/local/lib/pkgconfig. Unbrewed '.pc' files were found in /usr/local/lib/pkgconfig.
If you didn't put them there on purpose they could cause problems when If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted. building Homebrew formulae and may need to be deleted.
Unexpected '.pc' files: Unexpected '.pc' files:
EOS EOS
@ -287,7 +287,7 @@ module Homebrew
__check_stray_files "/usr/local/lib", "*.la", allow_list, <<~EOS __check_stray_files "/usr/local/lib", "*.la", allow_list, <<~EOS
Unbrewed '.la' files were found in /usr/local/lib. Unbrewed '.la' files were found in /usr/local/lib.
If you didn't put them there on purpose they could cause problems when If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted. building Homebrew formulae and may need to be deleted.
Unexpected '.la' files: Unexpected '.la' files:
EOS EOS
@ -306,7 +306,7 @@ module Homebrew
__check_stray_files "/usr/local/include", "**/*.h", allow_list, <<~EOS __check_stray_files "/usr/local/include", "**/*.h", allow_list, <<~EOS
Unbrewed header files were found in /usr/local/include. Unbrewed header files were found in /usr/local/include.
If you didn't put them there on purpose they could cause problems when If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted. building Homebrew formulae and may need to be deleted.
Unexpected header files: Unexpected header files:
EOS EOS
@ -491,7 +491,7 @@ module Homebrew
<<~EOS <<~EOS
Git could not be found in your PATH. Git could not be found in your PATH.
Homebrew uses Git for several internal functions, and some formulae use Git Homebrew uses Git for several internal functions and some formulae use Git
checkouts instead of stable tarballs. You may want to install Git: checkouts instead of stable tarballs. You may want to install Git:
brew install git brew install git
EOS EOS

View File

@ -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
@ -932,8 +931,8 @@ class GitDownloadStrategy < VCSDownloadStrategy
args << "--no-checkout" << "--filter=blob:none" if partial_clone_sparse_checkout? args << "--no-checkout" << "--filter=blob:none" if partial_clone_sparse_checkout?
args << "--config" << "advice.detachedHead=false" # silences detached head warning args << "--config" << "advice.detachedHead=false" # Silences “detached head” warning.
args << "--config" << "core.fsmonitor=false" # prevent fsmonitor from watching this repo args << "--config" << "core.fsmonitor=false" # Prevent `fsmonitor` from watching this repository.
args << @url << cached_location.to_s args << @url << cached_location.to_s
end end
@ -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

View File

@ -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

View File

@ -17,10 +17,16 @@ module Kernel
private :superenv? private :superenv?
end end
# <!-- vale off -->
# @!parse # @!parse
# # ENV is not actually a class, but this makes `YARD` happy # # `ENV` is not actually a class, but this makes YARD happy
# # @see https://rubydoc.info/stdlib/core/ENV ENV core documentation # # @see https://rubydoc.info/stdlib/core/ENV
# # <code>ENV</code> core documentation
# # @see Superenv
# # @see Stdenv
# class ENV; end # class ENV; end
# <!-- vale on -->
module EnvActivation module EnvActivation
sig { params(env: T.nilable(String)).void } sig { params(env: T.nilable(String)).void }
def activate_extensions!(env: nil) def activate_extensions!(env: nil)

View File

@ -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

View File

@ -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

View File

@ -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]`.
# #
# ### Example
#
# ```ruby
# %w( a b c d e ).second # => "b" # %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]`.
# #
# ### Example
#
# ```ruby
# %w( a b c d e ).third # => "c" # %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]`.
# #
# ### Example
#
# ```ruby
# %w( a b c d e ).fourth # => "d" # %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]`.
# #
# ### Example
#
# ```ruby
# %w( a b c d e ).fifth # => "e" # %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
# element in arrays with three or more elements (default: ", ").
# * <tt>:last_word_connector</tt> - The sign or word used to join the last element
# in arrays with three or more elements (default: ", and ").
# * <tt>:two_words_connector</tt> - The sign or word used to join the elements
# in arrays with two elements (default: " and ").
#
# ==== Examples
# #
# ```ruby
# [].to_sentence # => "" # [].to_sentence # => ""
# ['one'].to_sentence # => "one" # ['one'].to_sentence # => "one"
# ['one', 'two'].to_sentence # => "one and two" # ['one', 'two'].to_sentence # => "one and two"
# ['one', 'two', 'three'].to_sentence # => "one, two, and three" # ['one', 'two', 'three'].to_sentence # => "one, two and three"
# ['one', 'two'].to_sentence(two_words_connector: '-') # ['one', 'two'].to_sentence(two_words_connector: '-')
# # => "one-two" # # => "one-two"
# ```
# #
# ```
# ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ') # ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
# # => "one or two or at least three" # # => "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

View File

@ -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.
# #
# ### Example
#
# ```ruby
# !address || address.empty? # !address || address.empty?
# ```
# #
# to # can be simplified to
# #
# ```ruby
# address.blank? # 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
# #
# ```ruby
# state = params[:state] if params[:state].present? # state = params[:state] if params[:state].present?
# country = params[:country] if params[:country].present? # country = params[:country] if params[:country].present?
# region = state || country || 'US' # region = state || country || 'US'
# ```
# #
# becomes # can be simplified to
# #
# ```ruby
# region = params[:state].presence || params[:country].presence || 'US' # 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:
# #
# ```ruby
# nil.blank? # => true # 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:
# #
# ```ruby
# false.blank? # => true # 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:
# #
# ```ruby
# true.blank? # => false # 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:
# #
# ```ruby
# [].blank? # => true # [].blank? # => true
# [1,2,3].blank? # => false # [1,2,3].blank? # => false
# # ```
# @return [true, false] sig { returns(T::Boolean) }
alias blank? empty? 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:
# #
#
# ```ruby
# {}.blank? # => true # {}.blank? # => true
# { key: 'value' }.blank? # => false # { key: 'value' }.blank? # => false
# # ```
# @return [true, false] sig { returns(T::Boolean) }
alias blank? empty? 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:
# #
# ```ruby
# :''.blank? # => true # :''.blank? # => true
# :symbol.blank? # => false # :symbol.blank? # => 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:
@ -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:
# #
# ```ruby
# ''.blank? # => true # ''.blank? # => true
# ' '.blank? # => true # ' '.blank? # => true
# "\t\n\r".blank? # => true # "\t\n\r".blank? # => true
# ' blah '.blank? # => false # ' blah '.blank? # => false
# ```
# #
# Unicode whitespace is supported: # Unicode whitespace is supported:
# #
# ```ruby
# "\u00a0".blank? # => true # "\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:
# #
# ```ruby
# 1.blank? # => false # 1.blank? # => false
# 0.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:
# #
# ```ruby
# Time.now.blank? # => false # Time.now.blank? # => false
# ```
sig { returns(FalseClass) } sig { returns(FalseClass) }
def blank? = false def blank? = false

View File

@ -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.
# #
# ### Examples
#
# ```
# [1, "", nil, 2, " ", [], {}, false, true].compact_blank # [1, "", nil, 2, " ", [], {}, false, true].compact_blank
# # => [1, 2, true] # # => [1, 2, true]
# ```
# #
# ```ruby
# Set.new([nil, "", 1, false]).compact_blank # Set.new([nil, "", 1, false]).compact_blank
# # => [1] # # => [1]
# ```
# #
# When called on a +Hash+, returns a new +Hash+ without the blank values. # When called on a {Hash}, returns a new {Hash} without the blank values.
# #
# ```ruby
# { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank # { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
# # => { b: 1, f: true } # # => { 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

View File

@ -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.
# #
# ### Examples
#
# ```ruby
# h1 = { a: true, b: { c: [1, 2, 3] } } # h1 = { a: true, b: { c: [1, 2, 3] } }
# h2 = { a: false, b: { x: [3, 4, 5] } } # h2 = { a: false, b: { x: [3, 4, 5] } }
# #
# h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], 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:
# #
# ```ruby
# h1 = { a: 100, b: 200, c: { c1: 100 } } # h1 = { a: 100, b: 200, c: { c1: 100 } }
# h2 = { b: 250, c: { c1: 200 } } # h2 = { b: 250, c: { c1: 200 } }
# h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val } # h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
# # => { a: 100, b: 450, c: { c1: 300 } } # # => { 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)

View File

@ -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
#
# ```ruby
# hash = { person: { name: 'Rob', age: '28' } } # hash = { person: { name: 'Rob', age: '28' } }
# #
# hash.deep_transform_values{ |value| value.to_s.upcase } # hash.deep_transform_values{ |value| value.to_s.upcase }
# # => {person: {name: "ROB", age: "28"}} # # => {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.

View File

@ -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.
# #
# ### Example#
#
# ```ruby
# { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age)
# # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age" # # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
# { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age')
# # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'" # # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
# { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing # { 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.
# #
# ### Example
#
# ```ruby
# hash = { person: { name: 'Rob', age: '28' } } # hash = { person: { name: 'Rob', age: '28' } }
# #
# hash.deep_transform_keys{ |key| key.to_s.upcase } # hash.deep_transform_keys{ |key| key.to_s.upcase }
# # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}} # # => {"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.
# #
# ### Example
#
# ```ruby
# hash = { person: { name: 'Rob', age: '28' } } # hash = { person: { name: 'Rob', age: '28' } }
# #
# hash.deep_stringify_keys # hash.deep_stringify_keys
# # => {"person"=>{"name"=>"Rob", "age"=>"28"}} # # => {"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.
# #
# ### Example
#
# ```ruby
# hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } } # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
# #
# hash.deep_symbolize_keys # hash.deep_symbolize_keys
# # => {:person=>{:name=>"Rob", :age=>"28"}} # # => {: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)

View File

@ -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"
# end</pre>
# #
# @note This method is *not* thread-safe - other threads # NOTE: This method is **not** thread-safe other threads
# which happen to be scheduled during the block will also # which happen to be scheduled during the block will also
# see these environment variables. # see these environment variables.
#
# ### Example
#
# ```ruby
# with_env(PATH: "/bin") do
# system "echo $PATH"
# end
# ```
#
# @api public # @api public
def with_env(hash) def with_env(hash)
old_values = {} old_values = {}

View File

@ -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:
# #
# ```ruby
# method(:puts).dup # => TypeError: allocator undefined for Method # 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:
# #
# ```ruby
# arbitrary_object.dup rescue object # 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:
# #
# ```ruby
# method(:puts).duplicable? # => false # method(:puts).duplicable? # => false
# method(:puts).dup # => TypeError: allocator undefined for Method # 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:
# #
# ```ruby
# method(:puts).unbind.duplicable? # => false # method(:puts).unbind.duplicable? # => false
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod # 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:
# #
# ```ruby
# Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton # 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

View File

@ -340,7 +340,7 @@ module Homebrew
else else
inject_file_list @found, <<~EOS inject_file_list @found, <<~EOS
libiconv files detected at a system prefix other than /usr. libiconv files detected at a system prefix other than /usr.
Homebrew doesn't provide a libiconv formula, and expects to link against Homebrew doesn't provide a libiconv formula and expects to link against
the system version in /usr. libiconv in other prefixes can cause the system version in /usr. libiconv in other prefixes can cause
compile or link failure, especially if compiled with improper compile or link failure, especially if compiled with improper
architectures. macOS itself never installs anything to /usr/local so architectures. macOS itself never installs anything to /usr/local so

View File

@ -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}")

View File

@ -112,7 +112,7 @@ module FormulaCellarChecks
<<~EOS <<~EOS
Libraries were compiled with a flat namespace. Libraries were compiled with a flat namespace.
This can cause linker errors due to name collisions, and This can cause linker errors due to name collisions and
is often due to a bug in detecting the macOS version. is often due to a bug in detecting the macOS version.
#{flat_namespace_files * "\n "} #{flat_namespace_files * "\n "}
EOS EOS

View File

@ -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

View File

@ -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)

View File

@ -20,7 +20,7 @@ module Homebrew
if os.present? if os.present?
return true return true
elsif ENV["HOMEBREW_TEST_GENERIC_OS"].present? elsif ENV["HOMEBREW_TEST_GENERIC_OS"].present?
# `:generic` bottles don't exist, and `--os` flag is not specified. # `:generic` bottles don't exist and `--os` flag is not specified.
return false return false
end end
return true if arch.present? return true if arch.present?

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,8 @@ module Homebrew
@assertions ||= 0 @assertions ||= 0
end end
# Returns the output of running cmd, and asserts the exit status. # Returns the output of running cmd and asserts the exit status.
#
# @api public # @api public
def shell_output(cmd, result = 0) def shell_output(cmd, result = 0)
ohai cmd ohai cmd
@ -28,8 +29,9 @@ module Homebrew
raise raise
end end
# Returns the output of running the cmd with the optional input, and # Returns the output of running the cmd with the optional input and
# optionally asserts the exit status. # optionally asserts the exit status.
#
# @api public # @api public
def pipe_output(cmd, input = nil, result = nil) def pipe_output(cmd, input = nil, result = nil)
ohai cmd ohai cmd

View File

@ -99,6 +99,8 @@ module Homebrew
sig { returns(String) } sig { returns(String) }
def template def template
# FIXME: https://github.com/errata-ai/vale/issues/818
# <!-- vale off -->
<<~ERB <<~ERB
# Documentation: https://docs.brew.sh/Formula-Cookbook # Documentation: https://docs.brew.sh/Formula-Cookbook
# https://rubydoc.brew.sh/Formula # https://rubydoc.brew.sh/Formula
@ -183,14 +185,14 @@ module Homebrew
ENV.prepend_create_path "PERL5LIB", libexec/"lib/perl5" ENV.prepend_create_path "PERL5LIB", libexec/"lib/perl5"
ENV.prepend_path "PERL5LIB", libexec/"lib" ENV.prepend_path "PERL5LIB", libexec/"lib"
# Stage additional dependency (Makefile.PL style) # Stage additional dependency (`Makefile.PL` style).
# resource("").stage do # resource("").stage do
# system "perl", "Makefile.PL", "INSTALL_BASE=\#{libexec}" # system "perl", "Makefile.PL", "INSTALL_BASE=\#{libexec}"
# system "make" # system "make"
# system "make", "install" # system "make", "install"
# end # end
# Stage additional dependency (Build.PL style) # Stage additional dependency (`Build.PL` style).
# resource("").stage do # resource("").stage do
# system "perl", "Build.PL", "--install_base", libexec # system "perl", "Build.PL", "--install_base", libexec
# system "./Build" # system "./Build"
@ -231,6 +233,7 @@ module Homebrew
end end
end end
ERB ERB
# <!-- vale on -->
end end
end end
end end

View File

@ -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?

View File

@ -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

View File

@ -537,19 +537,19 @@ module Formulary
class FormulaLoader class FormulaLoader
include Context include Context
# The formula's name # The formula's name.
sig { returns(String) } sig { returns(String) }
attr_reader :name attr_reader :name
# The formula's ruby file's path or filename # The formula file's path.
sig { returns(Pathname) } sig { returns(Pathname) }
attr_reader :path attr_reader :path
# The name used to install the formula # The name used to install the formula.
sig { returns(T.nilable(Pathname)) } sig { returns(T.nilable(Pathname)) }
attr_reader :alias_path attr_reader :alias_path
# The formula's tap (nil if it should be implicitly determined) # The formula's tap (`nil` if it should be implicitly determined).
sig { returns(T.nilable(Tap)) } sig { returns(T.nilable(Tap)) }
attr_reader :tap attr_reader :tap
@ -1019,8 +1019,8 @@ module Formulary
# Return a {Formula} instance for the given rack. # Return a {Formula} instance for the given rack.
# #
# @param spec when nil, will auto resolve the formula's spec. # @param spec when nil, will auto resolve the formula's spec.
# @param :alias_path will be used if the formula is found not to be # @param alias_path will be used if the formula is found not to be
# installed, and discarded if it is installed because the `alias_path` used # installed and discarded if it is installed because the `alias_path` used
# to install the formula will be set instead. # to install the formula will be set instead.
sig { sig {
params( params(

View File

@ -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

View File

@ -94,12 +94,12 @@ class GitHubPackages
end end
def self.repo_without_prefix(repo) def self.repo_without_prefix(repo)
# remove redundant repo prefix for a shorter name # Remove redundant repository prefix for a shorter name.
repo.delete_prefix("homebrew-") repo.delete_prefix("homebrew-")
end end
def self.root_url(org, repo, prefix = URL_PREFIX) def self.root_url(org, repo, prefix = URL_PREFIX)
# docker/skopeo insist on lowercase org ("repository name") # `docker`/`skopeo` insist on lowercase organisation (“repository name”).
org = org.downcase org = org.downcase
"#{prefix}#{org}/#{repo_without_prefix(repo)}" "#{prefix}#{org}/#{repo_without_prefix(repo)}"
@ -115,9 +115,9 @@ class GitHubPackages
end end
def self.image_formula_name(formula_name) def self.image_formula_name(formula_name)
# invalid docker name characters # Invalid docker name characters:
# / makes sense because we already use it to separate repo/formula # - `/` makes sense because we already use it to separate repository/formula.
# x makes sense because we already use it in Formulary # - `x` makes sense because we already use it in `Formulary`.
formula_name.tr("@", "/") formula_name.tr("@", "/")
.tr("+", "x") .tr("+", "x")
end end
@ -231,9 +231,9 @@ class GitHubPackages
inspect_args << "--creds=#{user}:#{token}" inspect_args << "--creds=#{user}:#{token}"
inspect_result = system_command(skopeo, print_stderr: false, args: inspect_args) inspect_result = system_command(skopeo, print_stderr: false, args: inspect_args)
# Order here is important # Order here is important.
if !inspect_result.status.success? && !inspect_result.stderr.match?(/(name|manifest) unknown/) if !inspect_result.status.success? && !inspect_result.stderr.match?(/(name|manifest) unknown/)
# We got an error, and it was not about the tag or package being unknown. # We got an error and it was not about the tag or package being unknown.
if warn_on_error if warn_on_error
opoo "#{image_uri} inspection returned an error, skipping upload!\n#{inspect_result.stderr}" opoo "#{image_uri} inspection returned an error, skipping upload!\n#{inspect_result.stderr}"
return return
@ -241,11 +241,11 @@ class GitHubPackages
odie "#{image_uri} inspection returned an error!\n#{inspect_result.stderr}" odie "#{image_uri} inspection returned an error!\n#{inspect_result.stderr}"
end end
elsif keep_old elsif keep_old
# If the tag doesn't exist, ignore --keep-old. # If the tag doesn't exist, ignore `--keep-old`.
keep_old = false unless inspect_result.status.success? keep_old = false unless inspect_result.status.success?
# Otherwise, do nothing - the tag already existing is expected behaviour for --keep-old. # Otherwise, do nothing - the tag already existing is expected behaviour for --keep-old.
elsif inspect_result.status.success? elsif inspect_result.status.success?
# The tag already exists, and we are not passing --keep-old. # The tag already exists and we are not passing `--keep-old`.
if warn_on_error if warn_on_error
opoo "#{image_uri} already exists, skipping upload!" opoo "#{image_uri} already exists, skipping upload!"
return return

View File

@ -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}>"
@ -556,8 +552,8 @@ class Keg
src = dst.resolved_path src = dst.resolved_path
# src itself may be a symlink, so check lstat to ensure we are dealing with # `src` itself may be a symlink, so check lstat to ensure we are dealing with
# a directory, and not a symlink pointing at a directory (which needs to be # a directory and not a symlink pointing to a directory (which needs to be
# treated as a file). In other words, we only want to resolve one symlink. # treated as a file). In other words, we only want to resolve one symlink.
begin begin

View File

@ -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"

View File

@ -144,14 +144,14 @@ module Language
# Mixin module for {Formula} adding virtualenv support features. # Mixin module for {Formula} adding virtualenv support features.
module Virtualenv module Virtualenv
# Instantiates, creates, and yields a {Virtualenv} object for use from # Instantiates, creates and yields a {Virtualenv} object for use from
# {Formula#install}, which provides helper methods for instantiating and # {Formula#install}, which provides helper methods for instantiating and
# installing packages into a Python virtualenv. # installing packages into a Python virtualenv.
# #
# @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) }
@ -211,7 +211,7 @@ module Language
# Helper method for the common case of installing a Python application. # Helper method for the common case of installing a Python application.
# Creates a virtualenv in `libexec`, installs all `resource`s defined # Creates a virtualenv in `libexec`, installs all `resource`s defined
# on the formula, and then installs the formula. An options hash may be # on the formula and then installs the formula. An options hash may be
# passed (e.g. `:using => "python"`) to override the default, guessed # passed (e.g. `:using => "python"`) to override the default, guessed
# formula preference for python or python@x.y, or to resolve an ambiguous # formula preference for python or python@x.y, or to resolve an ambiguous
# case where it's not clear whether python or python@x.y should be the # case where it's not clear whether python or python@x.y should be the

View File

@ -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

View File

@ -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

View File

@ -13,7 +13,7 @@ module Homebrew
# Livecheck has historically prioritized the {Git} strategy over others # Livecheck has historically prioritized the {Git} strategy over others
# and this behavior was continued when the priority setup was created. # and this behavior was continued when the priority setup was created.
# This is partly related to Livecheck checking formula URLs in order of # This is partly related to Livecheck checking formula URLs in order of
# `head`, `stable`, and then `homepage`. The higher priority here may # `head`, `stable` and then `homepage`. The higher priority here may
# be removed (or altered) in the future if we reevaluate this particular # be removed (or altered) in the future if we reevaluate this particular
# behavior. # behavior.
# #

View File

@ -4,7 +4,7 @@
module Homebrew module Homebrew
module Livecheck module Livecheck
module Strategy module Strategy
# The {Json} strategy fetches content at a URL, parses it as JSON, and # The {Json} strategy fetches content at a URL, parses it as JSON and
# provides the parsed data to a `strategy` block. If a regex is present # provides the parsed data to a `strategy` block. If a regex is present
# in the `livecheck` block, it should be passed as the second argument to # in the `livecheck` block, it should be passed as the second argument to
# the `strategy` block. # the `strategy` block.

View File

@ -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

View File

@ -5,7 +5,7 @@ module Homebrew
module Livecheck module Livecheck
module Strategy module Strategy
# The {Xml} strategy fetches content at a URL, parses it as XML using # The {Xml} strategy fetches content at a URL, parses it as XML using
# `REXML`, and provides the `REXML::Document` to a `strategy` block. # `REXML` and provides the `REXML::Document` to a `strategy` block.
# If a regex is present in the `livecheck` block, it should be passed # If a regex is present in the `livecheck` block, it should be passed
# as the second argument to the `strategy` block. # as the second argument to the `strategy` block.
# #

View File

@ -4,7 +4,7 @@
module Homebrew module Homebrew
module Livecheck module Livecheck
module Strategy module Strategy
# The {Yaml} strategy fetches content at a URL, parses it as YAML, and # The {Yaml} strategy fetches content at a URL, parses it as YAML and
# provides the parsed data to a `strategy` block. If a regex is present # provides the parsed data to a `strategy` block. If a regex is present
# in the `livecheck` block, it should be passed as the second argument to # in the `livecheck` block, it should be passed as the second argument to
# the `strategy` block. # the `strategy` block.

View File

@ -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("-")

View File

@ -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

View File

@ -142,7 +142,7 @@ module Homebrew
sig { returns(String) } sig { returns(String) }
def self.global_cask_options_manpage def self.global_cask_options_manpage
lines = ["These options are applicable to the `install`, `reinstall`, and `upgrade` " \ lines = ["These options are applicable to the `install`, `reinstall` and `upgrade` " \
"subcommands with the `--cask` switch.\n"] "subcommands with the `--cask` switch.\n"]
lines += Homebrew::CLI::Parser.global_cask_options.map do |_, long, kwargs| lines += Homebrew::CLI::Parser.global_cask_options.map do |_, long, kwargs|
generate_option_doc(nil, long.chomp("="), kwargs.fetch(:description)) generate_option_doc(nil, long.chomp("="), kwargs.fetch(:description))

View File

@ -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

View File

@ -1,7 +1,7 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
# Performs {Formula#mktemp}'s functionality, and tracks the results. # Performs {Formula#mktemp}'s functionality and tracks the results.
# Each instance is only intended to be used once. # Each instance is only intended to be used once.
class Mktemp class Mktemp
include FileUtils include FileUtils
@ -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}]"

View File

@ -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}>"

View File

@ -173,8 +173,8 @@ module OS
# using that. # using that.
# As of Xcode 10, the Unix-style headers are installed via a # As of Xcode 10, the Unix-style headers are installed via a
# separate package, so we can't rely on their being present. # separate package, so we can't rely on their being present.
# This will only look up SDKs on Xcode 10 or newer, and still # This will only look up SDKs on Xcode 10 or newer and still
# return nil SDKs for Xcode 9 and older. # return `nil` SDKs for Xcode 9 and older.
sig { override.returns(String) } sig { override.returns(String) }
def sdk_prefix def sdk_prefix
@sdk_prefix ||= if CLT.provides_sdk? @sdk_prefix ||= if CLT.provides_sdk?

View File

@ -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}>"

View File

@ -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

View File

@ -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}>"

View File

@ -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}>"

View File

@ -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}>"

View File

@ -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}>"

View File

@ -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
@ -165,8 +170,8 @@ class Resource < Downloadable
end end
# Whether a livecheck specification is defined or not. # Whether a livecheck specification is defined or not.
# It returns true when a livecheck block is present in the {Resource} and # It returns true when a `livecheck` block is present in the {Resource} and
# false otherwise, and is used by livecheck. # false otherwise and is used by livecheck.
def livecheckable? def livecheckable?
@livecheckable == true @livecheckable == true
end end
@ -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}>"

View File

@ -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?`
# #
# ```ruby
# # bad # # bad
# foo.nil? || foo.empty? # 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

View File

@ -44,7 +44,7 @@ module RuboCop
end end
# Separate the lines into those that should be sorted and those that should not # Separate the lines into those that should be sorted and those that should not
# ie. skip the opening and closing brackets of the array # i.e. skip the opening and closing brackets of the array.
to_sort, to_keep = combined_source.partition { |line| !line.include?("[") && !line.include?("]") } to_sort, to_keep = combined_source.partition { |line| !line.include?("[") && !line.include?("]") }
# Sort the lines that should be sorted # Sort the lines that should be sorted

View File

@ -9,7 +9,9 @@ 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
#
# ```ruby
# # bad # # bad
# cask 'foo' do # cask 'foo' do
# if MacOS.version == :high_sierra # if MacOS.version == :high_sierra
@ -23,6 +25,7 @@ module RuboCop
# sha256 "..." # sha256 "..."
# end # end
# end # end
# ```
class OnSystemConditionals < Base class OnSystemConditionals < Base
extend Forwardable extend Forwardable
extend AutoCorrector extend AutoCorrector

View File

@ -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
#
# ```ruby
# # bad # # bad
# url "https://example.com/download/foo.dmg", # url "https://example.com/download/foo.dmg",
# verified: "https://example.com/download" # 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
@ -43,7 +44,7 @@ module RuboCop
# Skip if the URL and the verified value are the same. # Skip if the URL and the verified value are the same.
next if value_node.source == url_stanza.source.gsub(%r{^"https?://}, "\"") next if value_node.source == url_stanza.source.gsub(%r{^"https?://}, "\"")
# Skip if the URL has two path components, eg: `https://github.com/google/fonts.git`. # Skip if the URL has two path components, e.g. `https://github.com/google/fonts.git`.
next if url_stanza.source.gsub(%r{^"https?://}, "\"").count("/") == 2 next if url_stanza.source.gsub(%r{^"https?://}, "\"").count("/") == 2
# Skip if the verified value ends with a slash. # Skip if the verified value ends with a slash.
next if value_node.str_content.end_with?("/") next if value_node.str_content.end_with?("/")

View File

@ -8,7 +8,9 @@ module RuboCop
module Cask module Cask
# This cop audits variables in casks. # This cop audits variables in casks.
# #
# @example # ### Example
#
# ```ruby
# # bad # # bad
# cask do # cask do
# arch = Hardware::CPU.intel? ? "darwin" : "darwin-arm64" # arch = Hardware::CPU.intel? ? "darwin" : "darwin-arm64"
@ -18,6 +20,7 @@ module RuboCop
# cask 'foo' do # cask 'foo' do
# arch arm: "darwin-arm64", intel: "darwin" # arch arm: "darwin-arm64", intel: "darwin"
# end # end
# ```
class Variables < Base class Variables < Base
extend Forwardable extend Forwardable
extend AutoCorrector extend AutoCorrector

View File

@ -6,9 +6,11 @@ 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
#
# ```ruby
# # bad # # bad
# def caveats # def caveats
# <<~EOS # <<~EOS
@ -22,11 +24,12 @@ module RuboCop
# Use `sudo` to run the executable. # Use `sudo` to run the executable.
# EOS # EOS
# end # 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/)

View File

@ -6,29 +6,31 @@ 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
# #
# ```ruby
# # bad # # bad
# collection.reject(&:blank?) # collection.reject(&:blank?)
# collection.reject { |_k, v| v.blank? } # collection.reject { |_k, v| v.blank? }
# #
# # good # # good
# collection.compact_blank # collection.compact_blank
# ```
# #
# ```ruby
# # bad # # bad
# collection.delete_if(&: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.delete_if { |_, v| v.blank? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!` # collection.delete_if { |_, v| v.blank? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
@ -37,12 +39,13 @@ module RuboCop
# #
# # good # # good
# collection.compact_blank! # 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

Some files were not shown because too many files have changed in this diff Show More