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
run: brew install vale
- name: Run vale for docs linting
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}/docs
run: vale .
- name: Lint docs
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
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
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/rbi-*/
**/vendor/bundle/ruby/*/gems/rdoc-*/
**/vendor/bundle/ruby/*/gems/redcarpet-*/
**/vendor/bundle/ruby/*/gems/regexp_parser-*/
**/vendor/bundle/ruby/*/gems/rexml-*/
**/vendor/bundle/ruby/*/gems/rspec-*/

View File

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

View File

@ -70,6 +70,11 @@ Style/Documentation:
- version.rb
- tap.rb
Homebrew/NegateInclude:
Exclude:
# YARD runs stand-alone.
- yard/docstring_parser.rb
Style/DocumentationMethod:
Include:
- "formula.rb"

View File

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

View File

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

View File

@ -60,7 +60,6 @@ class PATH
@paths.join(File::PATH_SEPARATOR)
end
# @!visibility private
sig { returns(String) }
def to_s = to_str

View File

@ -6,9 +6,10 @@ require "cli/parser"
module Homebrew
# Subclass this to implement a `brew` command. This is preferred to declaring a named function in the `Homebrew`
# module, because:
#
# - Each Command lives in an isolated namespace.
# - 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.
#
# To subclass, implement a `run` method and provide a `cmd_args` block to document the command and its allowed args.

View File

@ -39,8 +39,8 @@ module Homebrew
sig { returns(Pathname) }
def self.gh_executable
# NOTE: We disable HOMEBREW_VERIFY_ATTESTATIONS when installing `gh` itself,
# to prevent a cycle during bootstrapping. This can eventually be resolved
# by vendoring a pure-Ruby Sigstore verifier client.
# to prevent a cycle during bootstrapping. This can eventually be resolved
# by vendoring a pure-Ruby Sigstore verifier client.
@gh_executable ||= T.let(with_env("HOMEBREW_VERIFY_ATTESTATIONS" => nil) do
ensure_executable!("gh")
end, T.nilable(Pathname))

View File

@ -265,7 +265,7 @@ EOS
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() {
local item=$1
shift

View File

@ -1,6 +1,6 @@
# Note: that we use a non-standard config file name to reduce
# name clashes with other IRB config files like `.irbrc`.
# Note #2: This doesn't work with system Ruby for some reason.
# NOTE: We use a non-standard config file name to reduce name clashes with
# other IRB config files like `.irbrc`.
# NOTE: This doesn't work with system Ruby for some reason.
require 'irb/completion'

View File

@ -28,7 +28,7 @@ class BuildEnvironment
# DSL for specifying build environment settings.
module DSL
# 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)
super
child.instance_eval do

View File

@ -9,16 +9,26 @@ class BuildOptions
end
# 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"
# ```
#
# # 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"
# args << "--with-example2"
# else
# args << "--with-example1"
# end</pre>
# end
# ```
def with?(val)
option_names = val.respond_to?(:option_names) ? val.option_names : [val]
@ -34,7 +44,12 @@ class BuildOptions
end
# 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)
!with?(val)
end
@ -45,19 +60,33 @@ class BuildOptions
end
# 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?
# args << "--i-want-pizza"
# args << "--and-a-cold-beer" if build.with? "cold-beer"
# end</pre>
# end
# ```
def head?
include? "HEAD"
end
# True if a {Formula} is being built with {Formula.stable} instead of {Formula.head}.
# This is the default.
# <pre>args << "--some-beta" if build.head?</pre>
#
# ### Example
#
# ```ruby
# args << "--some-beta" if build.head?
# ```
def stable?
!head?
end

View File

@ -147,7 +147,6 @@ module Cask
cask.config
end
# @!visibility private
sig { returns(String) }
def to_s
"#{summarize} (#{self.class.english_name})"

View File

@ -685,7 +685,7 @@ module Cask
sig { void }
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?
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if online?
@ -699,7 +699,7 @@ module Cask
sig { void }
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?
user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) if online?

View File

@ -78,7 +78,8 @@ module Cask
@allow_reassignment = allow_reassignment
@loaded_from_api = loaded_from_api
@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)
@default_config = config || Config.new
@ -323,11 +324,9 @@ module Cask
end
# @api public
# @!visibility private
sig { returns(String) }
def to_s = token
# @!visibility private
sig { returns(String) }
def inspect
"#<Cask #{token}#{sourcefile_path&.to_s&.prepend(" ")}>"

View File

@ -112,6 +112,16 @@ module Cask
@token = cask.token
end
# Specifies the cask's name.
#
# NOTE: Multiple names can be specified.
#
# ### Example
#
# ```ruby
# name "Visual Studio Code"
# ```
#
# @api public
def name(*args)
@name ||= []
@ -120,6 +130,14 @@ module Cask
@name.concat(args.flatten)
end
# Describes the cask.
#
# ### Example
#
# ```ruby
# desc "Open-source code editor"
# ```
#
# @api public
def desc(description = nil)
set_unique_stanza(:desc, description.nil?) { description }
@ -146,6 +164,14 @@ module Cask
raise CaskInvalidError.new(cask, "'#{stanza}' stanza failed with: #{e}")
end
# Sets the cask's homepage.
#
# ### Example
#
# ```ruby
# homepage "https://code.visualstudio.com/"
# ```
#
# @api public
def homepage(homepage = nil)
set_unique_stanza(:homepage, homepage.nil?) { homepage }
@ -201,6 +227,14 @@ module Cask
@language_blocks.keys.flatten
end
# Sets the cask's download URL.
#
# ### Example
#
# ```ruby
# url "https://update.code.visualstudio.com/#{version}/#{arch}/stable"
# ```
#
# @api public
def url(*args, **options, &block)
caller_location = T.must(caller_locations).fetch(0)
@ -214,6 +248,8 @@ module Cask
end
end
# Sets the cask's appcast URL.
#
# @api public
def appcast(*args, **kwargs)
set_unique_stanza(:appcast, args.empty? && kwargs.empty?) do
@ -222,6 +258,22 @@ module Cask
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
def container(**kwargs)
set_unique_stanza(:container, kwargs.empty?) do
@ -229,6 +281,15 @@ module Cask
end
end
# Sets the cask's version.
#
# ### Example
#
# ```ruby
# version "1.88.1"
# ```
#
# @see DSL::Version
# @api public
def version(arg = nil)
set_unique_stanza(:version, arg.nil?) do
@ -240,6 +301,23 @@ module Cask
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
def sha256(arg = nil, arm: nil, intel: nil)
should_return = arg.nil? && arm.nil? && intel.nil?
@ -259,6 +337,14 @@ module Cask
end
end
# Sets the cask's architecture strings.
#
# ### Example
#
# ```ruby
# arch arm: "darwin-arm64", intel: "darwin"
# ```
#
# @api public
def arch(arm: nil, intel: nil)
should_return = arm.nil? && intel.nil?
@ -270,7 +356,10 @@ module Cask
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
def depends_on(**kwargs)
@depends_on ||= DSL::DependsOn.new
@ -284,9 +373,11 @@ module Cask
@depends_on
end
# Declare conflicts that keep a cask from installing or working correctly.
#
# @api public
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) }
end
@ -298,6 +389,8 @@ module Cask
cask.caskroom_path
end
# The staged location for this cask, including version number.
#
# @api public
def staged_path
return @staged_path if @staged_path
@ -306,6 +399,8 @@ module Cask
@staged_path = caskroom_path.join(cask_version.to_s)
end
# Provide the user with cask-specific information at install time.
#
# @api public
def caveats(*strings, &block)
@caveats ||= DSL::Caveats.new(cask)
@ -326,11 +421,15 @@ module Cask
@caveats&.discontinued? == true
end
# Asserts that the cask artifacts auto-update.
#
# @api public
def auto_updates(auto_updates = nil)
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
end
# Automatically fetch the latest version of a cask from changelogs.
#
# @api public
def livecheck(&block)
@livecheck ||= Livecheck.new(cask)
@ -344,6 +443,10 @@ module Cask
@livecheck.instance_eval(&block)
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
def deprecate!(date:, because:)
@deprecation_date = Date.parse(date)
@ -353,6 +456,10 @@ module Cask
@deprecated = true
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
def disable!(date:, because:)
@disable_date = Date.parse(date)
@ -405,6 +512,8 @@ module Cask
true
end
# The directory `app`s are installed into.
#
# @api public
def appdir
return HOMEBREW_CASK_APPDIR_PLACEHOLDER if Cask.generating_hash?

View File

@ -37,7 +37,6 @@ module Cask
private_class_method :caveat
# @!visibility private
sig { returns(String) }
def to_s
(@custom_caveats + @built_in_caveats.values).join("\n")

View File

@ -27,7 +27,6 @@ module Cask
pairs.to_yaml
end
# @!visibility private
sig { returns(String) }
def to_s = pairs.inspect
end

View File

@ -9,8 +9,8 @@ module Cask
class Postflight < Base
include Staged
def suppress_move_to_applications(_options = {})
odisabled "Cask::DSL#suppress_move_to_applications"
def suppress_move_to_applications(**_options)
odisabled "`Cask::DSL::Postflight#suppress_move_to_applications`"
end
end
end

View File

@ -94,70 +94,94 @@ module Cask
to_s == "latest"
end
# The major version.
#
# @api public
sig { returns(T.self_type) }
def major
version { slice(MAJOR_MINOR_PATCH_REGEX, 1) }
end
# The minor version.
#
# @api public
sig { returns(T.self_type) }
def minor
version { slice(MAJOR_MINOR_PATCH_REGEX, 2) }
end
# The patch version.
#
# @api public
sig { returns(T.self_type) }
def patch
version { slice(MAJOR_MINOR_PATCH_REGEX, 3) }
end
# The major and minor version.
#
# @api public
sig { returns(T.self_type) }
def major_minor
version { [major, minor].reject(&:empty?).join(".") }
end
# The major, minor and patch version.
#
# @api public
sig { returns(T.self_type) }
def major_minor_patch
version { [major, minor, patch].reject(&:empty?).join(".") }
end
# The minor and patch version.
#
# @api public
sig { returns(T.self_type) }
def minor_patch
version { [minor, patch].reject(&:empty?).join(".") }
end
# The comma separated values of the version as array.
#
# @api public
sig { returns(T::Array[Version]) } # Only top-level T.self_type is supported https://sorbet.org/docs/self-type
def csv
split(",").map { self.class.new(_1) }
end
# The version part before the first comma.
#
# @api public
sig { returns(T.self_type) }
def before_comma
version { split(",", 2).first }
end
# The version part after the first comma.
#
# @api public
sig { returns(T.self_type) }
def after_comma
version { split(",", 2).second }
end
# The version without any dividers.
#
# @see DIVIDER_REGEX
# @api public
sig { returns(T.self_type) }
def no_dividers
version { gsub(DIVIDER_REGEX, "") }
end
# The version with the given record separator removed from the end.
#
# @see String#chomp
# @api public
sig { params(separator: T.nilable(String)).returns(T.self_type) }
def chomp(separator = nil)
version { to_s.chomp(T.unsafe(separator)) }
sig { params(separator: String).returns(T.self_type) }
def chomp(separator = T.unsafe(nil))
version { to_s.chomp(separator) }
end
private

View File

@ -13,7 +13,6 @@ module Cask
@errors = errors
end
# @!visibility private
sig { returns(String) }
def to_s
<<~EOS
@ -41,7 +40,6 @@ module Cask
# Error when a cask is not installed.
class CaskNotInstalledError < AbstractCaskErrorWithToken
# @!visibility private
sig { returns(String) }
def to_s
"Cask '#{token}' is not installed."
@ -57,7 +55,6 @@ module Cask
@message = message
end
# @!visibility private
sig { returns(String) }
def to_s
"Cask '#{token}' has been #{message}"
@ -73,7 +70,6 @@ module Cask
@conflicting_cask = conflicting_cask
end
# @!visibility private
sig { returns(String) }
def to_s
"Cask '#{token}' conflicts with '#{conflicting_cask}'."
@ -82,7 +78,6 @@ module Cask
# Error when a cask is not available.
class CaskUnavailableError < AbstractCaskErrorWithToken
# @!visibility private
sig { returns(String) }
def to_s
"Cask '#{token}' is unavailable#{reason.empty? ? "." : ": #{reason}"}"
@ -91,7 +86,6 @@ module Cask
# Error when a cask is unreadable.
class CaskUnreadableError < CaskUnavailableError
# @!visibility private
sig { returns(String) }
def to_s
"Cask '#{token}' is unreadable#{reason.empty? ? "." : ": #{reason}"}"
@ -107,7 +101,6 @@ module Cask
@tap = tap
end
# @!visibility private
sig { returns(String) }
def to_s
s = super
@ -142,7 +135,6 @@ module Cask
# Error when a cask already exists.
class CaskAlreadyCreatedError < AbstractCaskErrorWithToken
# @!visibility private
sig { returns(String) }
def to_s
%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.
class CaskCyclicDependencyError < AbstractCaskErrorWithToken
# @!visibility private
sig { returns(String) }
def to_s
"Cask '#{token}' includes cyclic dependencies on other Casks#{reason.empty? ? "." : ": #{reason}"}"
@ -160,7 +151,6 @@ module Cask
# Error when a cask depends on itself.
class CaskSelfReferencingDependencyError < CaskCyclicDependencyError
# @!visibility private
sig { returns(String) }
def to_s
"Cask '#{token}' depends on itself."
@ -169,7 +159,6 @@ module Cask
# Error when no cask is specified.
class CaskUnspecifiedError < CaskError
# @!visibility private
sig { returns(String) }
def to_s
"This command requires a Cask token."
@ -178,7 +167,6 @@ module Cask
# Error when a cask is invalid.
class CaskInvalidError < AbstractCaskErrorWithToken
# @!visibility private
sig { returns(String) }
def to_s
"Cask '#{token}' definition is invalid#{reason.empty? ? "." : ": #{reason}"}"
@ -203,7 +191,6 @@ module Cask
@reason = reason
end
# @!visibility private
sig { returns(String) }
def to_s
s = +"Failed to quarantine #{path}."
@ -220,7 +207,6 @@ module Cask
# Error while propagating quarantine information to subdirectories.
class CaskQuarantinePropagationError < CaskQuarantineError
# @!visibility private
sig { returns(String) }
def to_s
s = +"Failed to quarantine one or more files within #{path}."
@ -237,7 +223,6 @@ module Cask
# Error while removing quarantine information.
class CaskQuarantineReleaseError < CaskQuarantineError
# @!visibility private
sig { returns(String) }
def to_s
s = +"Failed to release #{path} from quarantine."

View File

@ -17,22 +17,32 @@ module Cask
extend Forwardable
def_delegators :uri, :path, :scheme, :to_s
# @api public
sig {
params(
uri: T.any(URI::Generic, String),
# @api public
verified: T.nilable(String),
# @api public
using: T.any(Class, Symbol, NilClass),
# @api public
tag: T.nilable(String),
# @api public
branch: T.nilable(String),
# @api public
revisions: T.nilable(T::Array[String]),
# @api public
revision: T.nilable(String),
# @api public
trust_cert: T.nilable(T::Boolean),
# @api public
cookies: T.nilable(T::Hash[String, String]),
referer: T.nilable(T.any(URI::Generic, String)),
# @api public
header: T.nilable(T.any(String, T::Array[String])),
user_agent: T.nilable(T.any(Symbol, String)),
# @api public
data: T.nilable(T::Hash[String, String]),
# @api public
only_path: T.nilable(String),
).void
}
@ -77,8 +87,19 @@ module Cask
end
class BlockDSL
# To access URL associated with page contents.
# Allow accessing the URL associated with page contents.
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
sig { returns(URI::Generic) }
attr_accessor :url
@ -87,12 +108,12 @@ module Cask
sig {
params(
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))
.returns(T.any(T.any(URI::Generic, String), [T.any(URI::Generic, String), Hash])),
).void
}
def initialize(uri, dsl: nil, &block)
def initialize(uri, dsl:, &block)
@uri = uri
@dsl = dsl
@block = block
@ -114,6 +135,8 @@ module Cask
end
end
# Allows calling a nested `url` stanza in a `url do` block.
#
# @api public
sig {
params(
@ -123,10 +146,12 @@ module Cask
).returns(T.any(T.any(URI::Generic, String), [T.any(URI::Generic, String), Hash]))
}
def url(uri, &block)
self.class.new(uri, &block).call
self.class.new(uri, dsl: @dsl, &block).call
end
private :url
# This allows calling DSL methods from inside a `url` block.
#
# @api public
def method_missing(method, *args, &block)
if @dsl.respond_to?(method)
@ -135,10 +160,12 @@ module Cask
super
end
end
private :method_missing
def respond_to_missing?(method, include_all)
@dsl.respond_to?(method, include_all) || super
end
private :respond_to_missing?
end
sig {
@ -187,7 +214,7 @@ module Cask
super(
if block
LazyObject.new do
uri2, options = *BlockDSL.new(uri, dsl:, &block).call
uri2, options = *BlockDSL.new(uri, dsl: T.must(dsl), &block).call
options ||= {}
DSL.new(uri2, **options)
end

View File

@ -68,9 +68,9 @@ module Cask
unless tried_permissions
print_stderr = Context.current.debug? || Context.current.verbose?
# 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
# 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",
print_stderr:,
args: command_args + ["--", "000", path])
@ -87,7 +87,7 @@ module Cask
unless tried_ownership
# in case of ownership problems
# 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}'"
command.run("/usr/sbin/chown",
args: command_args + ["--", User.current, path],

View File

@ -25,27 +25,28 @@ class Cleaner
def clean
ObserverPathnameExtension.reset_counts!
# Many formulae include 'lib/charset.alias', but it is not strictly needed
# and will conflict if more than one formula provides it
# Many formulae include `lib/charset.alias`, but it is not strictly needed
# and will conflict if more than one formula provides it.
observe_file_removal @formula.lib/"charset.alias"
[@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'
# 2. 'info/#{name}/dir'
# 3. 'info/#{arch}/dir'
# 1. `info/dir`
# 2. `info/#{name}/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.
#
# See [cleaner: recursively delete info `dir`s by gromgit · Pull Request
# #11597][1], [emacs 28.1 bottle does not contain `dir` file · Issue
# #100190][2], and [Keep `info/#{f.name}/dir` files in cleaner by
# timvisher][3] for more info.
# See
# [cleaner: recursively delete info `dir`s][1],
# [emacs 28.1 bottle does not contain `dir` file][2] and
# [Keep `info/#{f.name}/dir` files in cleaner][3]
# for more info.
#
# [1]: https://github.com/Homebrew/brew/pull/11597
# [2]: https://github.com/Homebrew/homebrew-core/issues/100190
@ -114,15 +115,15 @@ class Cleaner
# created as part of installing any Perl module.
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
# directories) are protected by skip_clean.
#
# bin and sbin should not have any subdirectories; if either do that is
# caught as an audit warning
# `bin` and `sbin` should not have any subdirectories; if either do that is
# caught as an audit warning.
#
# lib may have a large directory tree (see Erlang for instance), and
# clean_dir applies cleaning rules to the entire tree
# `lib` may have a large directory tree (see Erlang for instance) and
# clean_dir applies cleaning rules to the entire tree.
sig { params(directory: Pathname).void }
def clean_dir(directory)
directory.find do |path|
@ -137,7 +138,7 @@ class Cleaner
elsif path.symlink?
# Skip it.
else
# Set permissions for executables and non-executables
# Set permissions for executables and non-executables.
perms = if executable_path?(path)
0555
else

View File

@ -376,7 +376,7 @@ module Homebrew
def cache_files
files = cache.directory? ? cache.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 : []
files.map { |path| { path:, type: nil } } +
@ -571,8 +571,8 @@ module Homebrew
HOMEBREW_PREFIX.glob("lib/python*/site-packages").each do |site_packages|
site_packages.each_child do |child|
next unless child.directory?
# TODO: Work out a sensible way to clean up pip's, setuptools', and wheel's
# {dist,site}-info directories. Alternatively, consider always removing
# TODO: Work out a sensible way to clean up `pip`'s, `setuptools`' and `wheel`'s
# `{dist,site}-info` directories. Alternatively, consider always removing
# all `-info` directories, because we may not be making use of them.
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 -= %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|
dirs.delete dir.relative_path_from(HOMEBREW_PREFIX).to_s
end

View File

@ -13,7 +13,7 @@ module Homebrew
cmd_args do
description <<~EOS
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
switch "-q", "--quiet",
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)
report_all = ENV["HOMEBREW_UPDATE_REPORT_ALL_FORMULAE"].present?
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."
report_all = false
end

View File

@ -65,7 +65,6 @@ class CompilerFailure
type == compiler.type && version_matched
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: #{type} #{version}>"

View File

@ -22,7 +22,6 @@ class CxxStdlib
type.to_s.gsub(/cxx$/, "c++")
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{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? })
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: #{__getobj__}>"
@ -62,7 +61,6 @@ class Requirements < SimpleDelegator
self
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: {#{__getobj__.to_a.join(", ")}}>"

View File

@ -33,7 +33,7 @@ module DependenciesHelpers
end
# 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?
end
end

View File

@ -4,6 +4,8 @@
require "dependable"
# A dependency on another Homebrew formula.
#
# @api internal
class Dependency
extend Forwardable
include Dependable
@ -94,11 +96,9 @@ class Dependency
false
end
# @!visibility private
sig { returns(String) }
def to_s = name
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: #{name.inspect} #{tags.inspect}>"
@ -115,6 +115,8 @@ class Dependency
# the list.
# The default filter, which is applied when a block is not given, omits
# optionals and recommends based on what the dependent has asked for
#
# @api internal
def expand(dependent, deps = dependent.deps, cache_key: nil, &block)
# Keep track dependencies to avoid infinite cyclic dependency recursion.
@expand_stack ||= []
@ -181,6 +183,8 @@ class Dependency
end
# Keep a dependency, but prune its dependencies.
#
# @api internal
sig { void }
def 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:)
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: #{name.inspect} #{tags.inspect} #{bounds.inspect}>"

View File

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

View File

@ -98,7 +98,7 @@ module Homebrew
end
odie "Could not find #{name}! The formula or version may not have existed." if test_formula.nil?
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|
Pathname.glob("#{dir}/#{name}.rb").find(&:file?)
end

View File

@ -15,7 +15,7 @@ module Homebrew
cmd_args do
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.
Requires write access to the repository.
EOS
@ -187,7 +187,7 @@ module Homebrew
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)
subject = message.lines.first.strip
@ -337,7 +337,7 @@ module Homebrew
new_package = package_file.read
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",
"-m", bump_subject, "-m", messages.join("\n"), "-m", trailers.join("\n"),
"--author", original_author, "--date", original_date, "--", file)

View File

@ -20,16 +20,18 @@ module Homebrew
def run
Homebrew.install_bundler_gems!(groups: ["doc"])
HOMEBREW_LIBRARY_PATH.cd do
HOMEBREW_LIBRARY_PATH.cd do |dir|
no_api_args = if args.only_public?
["--hide-api", "private", "--hide-api", "internal"]
else
[]
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

View File

@ -46,6 +46,8 @@ module Homebrew
(tap.path/"Formula").mkpath
# FIXME: https://github.com/errata-ai/vale/issues/818
# <!-- vale off -->
readme = <<~MARKDOWN
# #{titleized_user} #{titleized_repo}
@ -59,6 +61,7 @@ module Homebrew
`brew help`, `man brew` or check [Homebrew's documentation](https://docs.brew.sh).
MARKDOWN
# <!-- vale on -->
write_path(tap, "README.md", readme)
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 " \
"official external commands."
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",
description: "Only runs tests on files that were changed from the master branch."
switch "--fail-fast",
description: "Exit early on the first failing test."
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."
flag "--profile=",
description: "Run the test suite serially to find the <n> slowest tests."
@ -145,7 +145,10 @@ module Homebrew
end
# Workaround for:
#
# ```
# ruby: no -r allowed while running setuid (SecurityError)
# ```
Process::UID.change_privilege(Process.euid) if Process.euid != Process.uid
if parallel

View File

@ -116,7 +116,7 @@ module Homebrew
# update ENV["PATH"]
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"
# run brew update

View File

@ -221,7 +221,7 @@ module Homebrew
__check_stray_files "/usr/local/lib", "*.dylib", allow_list, <<~EOS
Unbrewed dylibs were found in /usr/local/lib.
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:
EOS
@ -246,7 +246,7 @@ module Homebrew
__check_stray_files "/usr/local/lib", "*.a", allow_list, <<~EOS
Unbrewed static libraries were found in /usr/local/lib.
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:
EOS
@ -266,7 +266,7 @@ module Homebrew
__check_stray_files "/usr/local/lib/pkgconfig", "*.pc", allow_list, <<~EOS
Unbrewed '.pc' files were found in /usr/local/lib/pkgconfig.
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:
EOS
@ -287,7 +287,7 @@ module Homebrew
__check_stray_files "/usr/local/lib", "*.la", allow_list, <<~EOS
Unbrewed '.la' files were found in /usr/local/lib.
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:
EOS
@ -306,7 +306,7 @@ module Homebrew
__check_stray_files "/usr/local/include", "**/*.h", allow_list, <<~EOS
Unbrewed header files were found in /usr/local/include.
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:
EOS
@ -491,7 +491,7 @@ module Homebrew
<<~EOS
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:
brew install git
EOS

View File

@ -77,11 +77,9 @@ class AbstractDownloadStrategy
end
# Disable any output during downloading.
#
# @deprecated
sig { void }
def shutup!
odeprecated "AbstractDownloadStrategy#shutup!", "AbstractDownloadStrategy#quiet!"
odeprecated "`AbstractDownloadStrategy#shutup!`", "`AbstractDownloadStrategy#quiet!`"
quiet!
end
@ -125,7 +123,6 @@ class AbstractDownloadStrategy
end
private :chdir
# @!attribute [r] source_modified_time
# Returns the most recent modified time for all files in the current working directory after stage.
#
# @api public
@ -236,9 +233,7 @@ class VCSDownloadStrategy < AbstractDownloadStrategy
version.respond_to?(:head?) && version.head?
end
# @!attribute [r] last_commit
# Return last commit's unique identifier for the repository.
# Return most recent modified timestamp unless overridden.
# Return the most recent modified timestamp.
#
# @api public
sig { returns(String) }
@ -733,7 +728,8 @@ class SubversionDownloadStrategy < VCSDownloadStrategy
super
end
# @see AbstractDownloadStrategy#source_modified_time
# Returns the most recent modified time for all files in the current working directory after stage.
#
# @api public
sig { returns(Time) }
def source_modified_time
@ -747,7 +743,8 @@ class SubversionDownloadStrategy < VCSDownloadStrategy
Time.parse time
end
# @see VCSDownloadStrategy#last_commit
# Return last commit's unique identifier for the repository.
#
# @api public
sig { returns(String) }
def last_commit
@ -847,7 +844,8 @@ class GitDownloadStrategy < VCSDownloadStrategy
@ref ||= "master"
end
# @see AbstractDownloadStrategy#source_modified_time
# Returns the most recent modified time for all files in the current working directory after stage.
#
# @api public
sig { returns(Time) }
def source_modified_time
@ -855,7 +853,8 @@ class GitDownloadStrategy < VCSDownloadStrategy
Time.parse(out)
end
# @see VCSDownloadStrategy#last_commit
# Return last commit's unique identifier for the repository.
#
# @api public
sig { returns(String) }
def last_commit
@ -932,8 +931,8 @@ class GitDownloadStrategy < VCSDownloadStrategy
args << "--no-checkout" << "--filter=blob:none" if partial_clone_sparse_checkout?
args << "--config" << "advice.detachedHead=false" # silences detached head warning
args << "--config" << "core.fsmonitor=false" # prevent fsmonitor from watching this repo
args << "--config" << "advice.detachedHead=false" # Silences “detached head” warning.
args << "--config" << "core.fsmonitor=false" # Prevent `fsmonitor` from watching this repository.
args << @url << cached_location.to_s
end
@ -1165,7 +1164,8 @@ class CVSDownloadStrategy < VCSDownloadStrategy
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
sig { returns(Time) }
def source_modified_time
@ -1240,7 +1240,8 @@ class MercurialDownloadStrategy < VCSDownloadStrategy
@url = @url.sub(%r{^hg://}, "")
end
# @see AbstractDownloadStrategy#source_modified_time
# Returns the most recent modified time for all files in the current working directory after stage.
#
# @api public
sig { returns(Time) }
def source_modified_time
@ -1250,7 +1251,8 @@ class MercurialDownloadStrategy < VCSDownloadStrategy
Time.parse(out)
end
# @see VCSDownloadStrategy#last_commit
# Return last commit's unique identifier for the repository.
#
# @api public
sig { returns(String) }
def last_commit
@ -1327,7 +1329,8 @@ class BazaarDownloadStrategy < VCSDownloadStrategy
@url = @url.sub(%r{^bzr://}, "")
end
# @see AbstractDownloadStrategy#source_modified_time
# Returns the most recent modified time for all files in the current working directory after stage.
#
# @api public
sig { returns(Time) }
def source_modified_time
@ -1338,7 +1341,8 @@ class BazaarDownloadStrategy < VCSDownloadStrategy
Time.parse(timestamp)
end
# @see VCSDownloadStrategy#last_commit
# Return last commit's unique identifier for the repository.
#
# @api public
sig { returns(String) }
def last_commit
@ -1390,7 +1394,8 @@ class FossilDownloadStrategy < VCSDownloadStrategy
@url = @url.sub(%r{^fossil://}, "")
end
# @see AbstractDownloadStrategy#source_modified_time
# Returns the most recent modified time for all files in the current working directory after stage.
#
# @api public
sig { returns(Time) }
def source_modified_time
@ -1398,7 +1403,8 @@ class FossilDownloadStrategy < VCSDownloadStrategy
Time.parse(out[/^uuid: +\h+ (.+)$/, 1])
end
# @see VCSDownloadStrategy#last_commit
# Return last commit's unique identifier for the repository.
#
# @api public
sig { returns(String) }
def last_commit

View File

@ -16,7 +16,6 @@ class UsageError < RuntimeError
@reason = reason
end
# @!visibility private
sig { returns(String) }
def to_s
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 "}?"
end
# @!visibility private
sig { returns(String) }
def to_s
s = "No available formula or cask with the name \"#{name}\". #{did_you_mean}".strip
@ -129,7 +127,6 @@ class TapFormulaOrCaskUnavailableError < FormulaOrCaskUnavailableError
@tap = tap
end
# @!visibility private
sig { returns(String) }
def to_s
s = super
@ -149,7 +146,6 @@ class FormulaUnavailableError < FormulaOrCaskUnavailableError
" (dependency of #{dependent})" if dependent && dependent != name
end
# @!visibility private
sig { returns(String) }
def to_s
"No available formula with the name \"#{name}\"#{dependent_s}. #{did_you_mean}".strip
@ -160,7 +156,6 @@ end
module FormulaClassUnavailableErrorModule
attr_reader :path, :class_name, :class_list
# @!visibility private
sig { returns(String) }
def to_s
s = super
@ -204,7 +199,6 @@ end
module FormulaUnreadableErrorModule
attr_reader :formula_error
# @!visibility private
sig { returns(String) }
def to_s
"#{name}: " + formula_error.to_s
@ -233,7 +227,6 @@ class TapFormulaUnavailableError < FormulaUnavailableError
super "#{tap}/#{name}"
end
# @!visibility private
sig { returns(String) }
def to_s
s = super
@ -572,7 +565,7 @@ class UnbottledError < RuntimeError
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
# installation on a system without build tools to fail.
class BuildFlagsError < RuntimeError

View File

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

View File

@ -1,5 +1,6 @@
# typed: strict
# @!visibility private
module EnvMethods
include Kernel
@ -39,6 +40,7 @@ module EnvActivation
include Superenv
end
# @!visibility private
class Sorbet
module Private
module Static

View File

@ -4,6 +4,7 @@ module SharedEnvExtension
include EnvMethods
end
# @!visibility private
class Sorbet
module Private
module Static

View File

@ -2,59 +2,72 @@
# frozen_string_literal: true
class Array
# Equal to <tt>self[1]</tt>.
# Equal to `self[1]`.
#
# %w( a b c d e ).second # => "b"
# ### Example
#
# ```ruby
# %w( a b c d e ).second # => "b"
# ```
def second = self[1]
# Equal to <tt>self[2]</tt>.
# Equal to `self[2]`.
#
# %w( a b c d e ).third # => "c"
# ### Example
#
# ```ruby
# %w( a b c d e ).third # => "c"
# ```
def third = self[2]
# Equal to <tt>self[3]</tt>.
# Equal to `self[3]`.
#
# %w( a b c d e ).fourth # => "d"
# ### Example
#
# ```ruby
# %w( a b c d e ).fourth # => "d"
# ```
def fourth = self[3]
# Equal to <tt>self[4]</tt>.
# Equal to `self[4]`.
#
# %w( a b c d e ).fifth # => "e"
# ### Example
#
# ```ruby
# %w( a b c d e ).fifth # => "e"
# ```
def fifth = self[4]
# Converts the array to a comma-separated sentence where the last element is
# 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 ").
# ```ruby
# [].to_sentence # => ""
# ['one'].to_sentence # => "one"
# ['one', 'two'].to_sentence # => "one and two"
# ['one', 'two', 'three'].to_sentence # => "one, two and three"
# ['one', 'two'].to_sentence(two_words_connector: '-')
# # => "one-two"
# ```
#
# ==== Examples
# ```
# ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
# # => "one or two or at least three"
# ```
#
# [].to_sentence # => ""
# ['one'].to_sentence # => "one"
# ['one', 'two'].to_sentence # => "one and two"
# ['one', 'two', 'three'].to_sentence # => "one, two, and three"
# ['one', 'two'].to_sentence(two_words_connector: '-')
# # => "one-two"
#
# ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
# # => "one or two or at least three"
# @see https://github.com/rails/rails/blob/v7.0.4.2/activesupport/lib/active_support/core_ext/array/conversions.rb#L8-L84
# ActiveSupport Array#to_sentence monkey-patch
#
#
# Copyright (c) David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# 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
# the following conditions:
#
@ -68,6 +81,14 @@ class Array
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# 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) }
def to_sentence(words_connector: ", ", two_words_connector: " and ", last_word_connector: " and ")
case length

View File

@ -3,15 +3,20 @@
class Object
# An object is blank if it's false, empty, or a whitespace string.
# For example, +nil+, '', ' ', [], {}, and +false+ are all blank.
#
# This simplifies
# For example, `nil`, `''`, `' '`, `[]`, `{}` and `false` are all blank.
#
# !address || address.empty?
# ### Example
#
# to
# ```ruby
# !address || address.empty?
# ```
#
# address.blank?
# can be simplified to
#
# ```ruby
# address.blank?
# ```
sig { returns(T::Boolean) }
def blank?
respond_to?(:empty?) ? !!T.unsafe(self).empty? : false
@ -21,20 +26,23 @@ class Object
sig { returns(T::Boolean) }
def present? = !blank?
# Returns the receiver if it's present otherwise returns +nil+.
# <tt>object.presence</tt> is equivalent to
# Returns the receiver if it's present, otherwise returns `nil`.
#
# object.present? ? object : nil
# `object.presence` is equivalent to `object.present? ? object : nil`.
#
# For example, something like
# ### Example
#
# state = params[:state] if params[:state].present?
# country = params[:country] if params[:country].present?
# region = state || country || 'US'
# ```ruby
# state = params[:state] if params[:state].present?
# country = params[:country] if params[:country].present?
# region = state || country || 'US'
# ```
#
# becomes
# can be simplified to
#
# region = params[:state].presence || params[:country].presence || 'US'
# ```ruby
# region = params[:state].presence || params[:country].presence || 'US'
# ```
sig { returns(T.nilable(T.self_type)) }
def presence
self if present?
@ -42,9 +50,11 @@ class Object
end
class NilClass
# +nil+ is blank:
# `nil` is blank:
#
# nil.blank? # => true
# ```ruby
# nil.blank? # => true
# ```
sig { returns(TrueClass) }
def blank? = true
@ -53,9 +63,11 @@ class NilClass
end
class FalseClass
# +false+ is blank:
# `false` is blank:
#
# false.blank? # => true
# ```ruby
# false.blank? # => true
# ```
sig { returns(TrueClass) }
def blank? = true
@ -64,9 +76,11 @@ class FalseClass
end
class TrueClass
# +true+ is not blank:
# `true` is not blank:
#
# true.blank? # => false
# ```ruby
# true.blank? # => false
# ```
sig { returns(FalseClass) }
def blank? = false
@ -77,11 +91,12 @@ end
class Array
# An array is blank if it's empty:
#
# [].blank? # => true
# [1,2,3].blank? # => false
#
# @return [true, false]
alias blank? empty?
# ```ruby
# [].blank? # => true
# [1,2,3].blank? # => false
# ```
sig { returns(T::Boolean) }
def blank? = empty?
sig { returns(T::Boolean) }
def present? = !empty? # :nodoc:
@ -90,11 +105,13 @@ end
class Hash
# A hash is blank if it's empty:
#
# {}.blank? # => true
# { key: 'value' }.blank? # => false
#
# @return [true, false]
alias blank? empty?
# ```ruby
# {}.blank? # => true
# { key: 'value' }.blank? # => false
# ```
sig { returns(T::Boolean) }
def blank? = empty?
sig { returns(T::Boolean) }
def present? = !empty? # :nodoc:
@ -103,9 +120,12 @@ end
class Symbol
# A Symbol is blank if it's empty:
#
# :''.blank? # => true
# :symbol.blank? # => false
alias blank? empty?
# ```ruby
# :''.blank? # => true
# :symbol.blank? # => false
# ```
sig { returns(T::Boolean) }
def blank? = empty?
sig { returns(T::Boolean) }
def present? = !empty? # :nodoc:
@ -122,14 +142,18 @@ class String
# A string is blank if it's empty or contains whitespaces only:
#
# ''.blank? # => true
# ' '.blank? # => true
# "\t\n\r".blank? # => true
# ' blah '.blank? # => false
# ```ruby
# ''.blank? # => true
# ' '.blank? # => true
# "\t\n\r".blank? # => true
# ' blah '.blank? # => false
# ```
#
# Unicode whitespace is supported:
#
# "\u00a0".blank? # => true
# ```ruby
# "\u00a0".blank? # => true
# ```
sig { returns(T::Boolean) }
def blank?
# The regexp that matches blank strings is expensive. For the case of empty
@ -150,8 +174,10 @@ end
class Numeric # :nodoc:
# No number is blank:
#
# 1.blank? # => false
# 0.blank? # => false
# ```ruby
# 1.blank? # => false
# 0.blank? # => false
# ```
sig { returns(FalseClass) }
def blank? = false
@ -162,7 +188,9 @@ end
class Time # :nodoc:
# No Time is blank:
#
# Time.now.blank? # => false
# ```ruby
# Time.now.blank? # => false
# ```
sig { returns(FalseClass) }
def blank? = false

View File

@ -2,7 +2,7 @@
# frozen_string_literal: true
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.
sig { params(object: T.untyped).returns(T::Boolean) }
def exclude?(object) = !include?(object)
@ -10,21 +10,29 @@ module Enumerable
# Returns a new +Array+ without the blank items.
# Uses Object#blank? for determining if an item is blank.
#
# [1, "", nil, 2, " ", [], {}, false, true].compact_blank
# # => [1, 2, true]
# ### Examples
#
# Set.new([nil, "", 1, false]).compact_blank
# # => [1]
# ```
# [1, "", nil, 2, " ", [], {}, false, true].compact_blank
# # => [1, 2, true]
# ```
#
# When called on a +Hash+, returns a new +Hash+ without the blank values.
# ```ruby
# Set.new([nil, "", 1, false]).compact_blank
# # => [1]
# ```
#
# { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
# # => { b: 1, f: true }
# 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
# # => { b: 1, f: true }
# ```
sig { returns(T.self_type) }
def compact_blank = T.unsafe(self).reject(&:blank?)
end
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? }
end

View File

@ -2,25 +2,31 @@
# frozen_string_literal: true
class Hash
# Returns a new hash with +self+ and +other_hash+ merged recursively.
# Returns a new hash with `self` and `other_hash` merged recursively.
#
# h1 = { a: true, b: { c: [1, 2, 3] } }
# h2 = { a: false, b: { x: [3, 4, 5] } }
# ### Examples
#
# h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
# ```ruby
# h1 = { a: true, b: { c: [1, 2, 3] } }
# h2 = { a: false, b: { x: [3, 4, 5] } }
#
# h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
# ```
#
# Like with Hash#merge in the standard library, a block can be provided
# to merge values:
#
# h1 = { a: 100, b: 200, c: { c1: 100 } }
# h2 = { b: 250, c: { c1: 200 } }
# h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
# # => { a: 100, b: 450, c: { c1: 300 } }
# ```ruby
# h1 = { a: 100, b: 200, c: { c1: 100 } }
# h2 = { b: 250, c: { c1: 200 } }
# h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
# # => { a: 100, b: 450, c: { c1: 300 } }
# ```
def deep_merge(other_hash, &block)
dup.deep_merge!(other_hash, &block)
end
# Same as +deep_merge+, but modifies +self+.
# Same as {#deep_merge}, but modifies `self`.
def deep_merge!(other_hash, &block)
merge!(other_hash) do |key, this_val, other_val|
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
# nested hashes and arrays.
#
# @example
# hash = { person: { name: 'Rob', age: '28' } }
# ### Example
#
# hash.deep_transform_values{ |value| value.to_s.upcase }
# # => {person: {name: "ROB", age: "28"}}
# ```ruby
# hash = { person: { name: 'Rob', age: '28' } }
#
# hash.deep_transform_values{ |value| value.to_s.upcase }
# # => {person: {name: "ROB", age: "28"}}
# ```
def deep_transform_values(&block) = _deep_transform_values_in_object(self, &block)
# 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
# `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.
#
# { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age)
# # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
# { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age')
# # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
# { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
# ### Example#
#
# ```ruby
# { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age)
# # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
# { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age')
# # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
# { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
# ```
sig { params(valid_keys: T.untyped).void }
def assert_valid_keys(*valid_keys)
valid_keys.flatten!
@ -28,10 +32,14 @@ class Hash
# This includes the keys from the root hash and from all
# nested hashes and arrays.
#
# hash = { person: { name: 'Rob', age: '28' } }
# ### Example
#
# hash.deep_transform_keys{ |key| key.to_s.upcase }
# # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
# ```ruby
# hash = { person: { name: 'Rob', age: '28' } }
#
# hash.deep_transform_keys{ |key| key.to_s.upcase }
# # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
# ```
def deep_transform_keys(&block) = _deep_transform_keys_in_object(self, &block)
# 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
# nested hashes and arrays.
#
# hash = { person: { name: 'Rob', age: '28' } }
# ### Example
#
# hash.deep_stringify_keys
# # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
# ```ruby
# hash = { person: { name: 'Rob', age: '28' } }
#
# hash.deep_stringify_keys
# # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
# ```
def deep_stringify_keys = T.unsafe(self).deep_transform_keys(&:to_s)
# Destructively converts all keys to strings.
@ -55,13 +67,17 @@ class Hash
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
# 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.
#
# hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
# ### Example
#
# hash.deep_symbolize_keys
# # => {:person=>{:name=>"Rob", :age=>"28"}}
# ```ruby
# hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
#
# hash.deep_symbolize_keys
# # => {:person=>{:name=>"Rob", :age=>"28"}}
# ```
def deep_symbolize_keys
deep_transform_keys do |key|
T.unsafe(key).to_sym
@ -71,7 +87,7 @@ class Hash
end
# 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.
def deep_symbolize_keys!
deep_transform_keys! do |key|
@ -102,7 +118,7 @@ class Hash
def _deep_transform_keys_in_object!(object, &block)
case object
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
value = object.delete(key)
object[yield(key)] = _deep_transform_keys_in_object!(value, &block)

View File

@ -493,14 +493,20 @@ module Kernel
end
# Calls the given block with the passed environment variables
# added to ENV, then restores ENV afterwards.
# <pre>with_env(PATH: "/bin") do
# system "echo $PATH"
# end</pre>
# added to `ENV`, then restores `ENV` afterwards.
#
# NOTE: This method is **not** thread-safe other threads
# which happen to be scheduled during the block will also
# see these environment variables.
#
# ### Example
#
# ```ruby
# with_env(PATH: "/bin") do
# system "echo $PATH"
# end
# ```
#
# @note This method is *not* thread-safe - other threads
# which happen to be scheduled during the block will also
# see these environment variables.
# @api public
def with_env(hash)
old_values = {}

View File

@ -1,24 +1,30 @@
# typed: strict
# frozen_string_literal: true
#--
# Most objects are cloneable, but not all. For example you can't dup methods:
#
# method(:puts).dup # => TypeError: allocator undefined for Method
# ```ruby
# method(:puts).dup # => TypeError: allocator undefined for Method
# ```
#
# Classes may signal their instances are not duplicable removing +dup+/+clone+
# 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:
#
# arbitrary_object.dup rescue object
# ```ruby
# arbitrary_object.dup rescue object
# ```
#
# Rails dups objects in a few critical spots where they are not that arbitrary.
# 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.
#
# That's why we hardcode the following cases and check duplicable? instead of
# using that rescue idiom.
#++
# rubocop:disable Layout/EmptyLines
# rubocop:enable Layout/EmptyLines
class Object
# Can you safely dup this object?
#
@ -31,8 +37,10 @@ end
class Method
# Methods are not duplicable:
#
# method(:puts).duplicable? # => false
# method(:puts).dup # => TypeError: allocator undefined for Method
# ```ruby
# method(:puts).duplicable? # => false
# method(:puts).dup # => TypeError: allocator undefined for Method
# ```
sig { returns(FalseClass) }
def duplicable? = false
end
@ -40,8 +48,10 @@ end
class UnboundMethod
# Unbound methods are not duplicable:
#
# method(:puts).unbind.duplicable? # => false
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
# ```ruby
# method(:puts).unbind.duplicable? # => false
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
# ```
sig { returns(FalseClass) }
def duplicable? = false
end
@ -51,7 +61,9 @@ require "singleton"
module Singleton
# Singleton instances are not duplicable:
#
# Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
# ```ruby
# Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
# ```
sig { returns(FalseClass) }
def duplicable? = false
end

View File

@ -4,7 +4,7 @@
module Homebrew
module Install
# This is a list of known paths to the host dynamic linker on Linux if
# the host glibc is new enough. The symlink_ld_so method will fail if
# the host glibc is new enough. The symlink_ld_so method will fail if
# the host linker cannot be found in this list.
DYNAMIC_LINKERS = %w[
/lib64/ld-linux-x86-64.so.2
@ -19,7 +19,7 @@ module Homebrew
private_constant :DYNAMIC_LINKERS
# We link GCC runtime libraries that are not specifically used for Fortran,
# which are linked by the GCC formula. We only use the versioned shared libraries
# which are linked by the GCC formula. We only use the versioned shared libraries
# as the other shared and static libraries are only used at build time where
# GCC can find its own libraries.
GCC_RUNTIME_LIBS = %w[

View File

@ -16,7 +16,7 @@ module Homebrew
return unless @args.cask?
# NOTE: We don't raise an error here because we don't want
# to print the help page or a stack trace.
# to print the help page or a stack trace.
odie "Invalid `--cask` usage: Casks do not work on Linux"
end
end

View File

@ -340,7 +340,7 @@ module Homebrew
else
inject_file_list @found, <<~EOS
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
compile or link failure, especially if compiled with improper
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"
# sed is strict, and errors out when it encounters files with
# mixed character sets
# `sed` is strict and errors out when it encounters files with mixed character sets.
delete("LC_ALL")
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:)
return unless MacOS::Xcode.without_clt?
@ -42,8 +41,8 @@ module Stdenv
end
def remove_macosxsdk(version = nil)
# Clear all lib and include dirs from CFLAGS, CPPFLAGS, LDFLAGS that were
# previously added by macosxsdk
# Clear all `lib` and `include` dirs from `CFLAGS`, `CPPFLAGS`, `LDFLAGS` that were
# previously added by `macosxsdk`.
remove_from_cflags(/ ?-mmacosx-version-min=\d+\.\d+/)
delete("CPATH")
remove "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib"
@ -58,14 +57,14 @@ module Stdenv
if HOMEBREW_PREFIX.to_s == "/usr/local"
delete("CMAKE_PREFIX_PATH")
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
end
remove "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks"
end
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
min_version = version || MacOS.version
append_to_cflags("-mmacosx-version-min=#{min_version}")

View File

@ -112,7 +112,7 @@ module FormulaCellarChecks
<<~EOS
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.
#{flat_namespace_files * "\n "}
EOS

View File

@ -83,8 +83,8 @@ module Hardware
sysctl_bool("hw.optional.sse4_2")
end
# NOTE: this is more reliable than checking uname.
# `sysctl` returns the right answer even when running in Rosetta 2.
# NOTE: This is more reliable than checking `uname`. `sysctl` returns
# the right answer even when running in Rosetta 2.
def physical_cpu_arm64?
sysctl_bool("hw.optional.arm64")
end

View File

@ -126,10 +126,11 @@ class Pathname
mkpath
# 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:
# https://bugs.ruby-lang.org/issues/7707
# In that case, use the system "mv" command.
# 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
# (https://bugs.ruby-lang.org/issues/7707).
#
# In that case, use the system `mv` command.
if src.symlink?
raise unless Kernel.system "mv", src.to_s, dst
else
@ -178,7 +179,9 @@ class Pathname
T.unsafe(self).open("a", **open_args) { |f| f.puts(content) }
end
# @note This always overwrites.
# Write to a file atomically.
#
# NOTE: This always overwrites.
#
# @api public
sig { params(content: String).void }
@ -201,6 +204,7 @@ class Pathname
# Changing file ownership failed, moving on.
nil
end
begin
# This operation will affect filesystem ACL's
chmod(old_stat.mode)

View File

@ -20,7 +20,7 @@ module Homebrew
if os.present?
return true
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
end
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
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
def shell_output(cmd, result = 0)
ohai cmd
@ -28,8 +29,9 @@ module Homebrew
raise
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.
#
# @api public
def pipe_output(cmd, input = nil, result = nil)
ohai cmd

View File

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

View File

@ -37,7 +37,6 @@ class KegOnlyReason
!by_macos?
end
# @!visibility private
sig { returns(String) }
def to_s
return @explanation unless @explanation.empty?

View File

@ -25,7 +25,6 @@ module Homebrew
@text.include? string
end
# @!visibility private
sig { returns(String) }
def to_s
@text

View File

@ -537,19 +537,19 @@ module Formulary
class FormulaLoader
include Context
# The formula's name
# The formula's name.
sig { returns(String) }
attr_reader :name
# The formula's ruby file's path or filename
# The formula file's path.
sig { returns(Pathname) }
attr_reader :path
# The name used to install the formula
# The name used to install the formula.
sig { returns(T.nilable(Pathname)) }
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)) }
attr_reader :tap
@ -1019,8 +1019,8 @@ module Formulary
# Return a {Formula} instance for the given rack.
#
# @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
# installed, and discarded if it is installed because the `alias_path` used
# @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
# to install the formula will be set instead.
sig {
params(

View File

@ -106,7 +106,6 @@ class GitRepository
popen_git("log", "-1", "--pretty=%B", commit, "--", safe:, err: :out)&.strip
end
# @!visibility private
sig { returns(String) }
def to_s = pathname.to_s

View File

@ -94,12 +94,12 @@ class GitHubPackages
end
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-")
end
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
"#{prefix}#{org}/#{repo_without_prefix(repo)}"
@ -115,9 +115,9 @@ class GitHubPackages
end
def self.image_formula_name(formula_name)
# invalid docker name characters
# / makes sense because we already use it to separate repo/formula
# x makes sense because we already use it in Formulary
# Invalid docker name characters:
# - `/` makes sense because we already use it to separate repository/formula.
# - `x` makes sense because we already use it in `Formulary`.
formula_name.tr("@", "/")
.tr("+", "x")
end
@ -231,9 +231,9 @@ class GitHubPackages
inspect_args << "--creds=#{user}:#{token}"
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/)
# 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
opoo "#{image_uri} inspection returned an error, skipping upload!\n#{inspect_result.stderr}"
return
@ -241,11 +241,11 @@ class GitHubPackages
odie "#{image_uri} inspection returned an error!\n#{inspect_result.stderr}"
end
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?
# Otherwise, do nothing - the tag already existing is expected behaviour for --keep-old.
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
opoo "#{image_uri} already exists, skipping upload!"
return

View File

@ -48,7 +48,6 @@ class Keg
EOS
end
# @!visibility private
sig { returns(String) }
def to_s
s = []
@ -67,7 +66,6 @@ class Keg
# Error for when a directory is not writable.
class DirectoryNotWritableError < LinkError
# @!visibility private
sig { returns(String) }
def to_s
<<~EOS
@ -176,11 +174,9 @@ class Keg
path.parent
end
# @!visibility private
sig { returns(String) }
def to_s = path.to_s
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}:#{path}>"
@ -556,8 +552,8 @@ class Keg
src = dst.resolved_path
# 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
# `src` itself may be a symlink, so check lstat to ensure we are dealing with
# 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.
begin

View File

@ -14,7 +14,7 @@ module Language
# e.g. `resource "github.com/foo/bar"`.
sig { params(resources: T::Array[Resource], target: T.any(String, Pathname)).void }
def self.stage_deps(resources, target)
# odeprecated "Language::Go::stage_deps", "Go modules"
# odeprecated "`Language::Go.stage_deps`", "Go modules"
if resources.empty?
if Homebrew::EnvConfig.developer?
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.
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
# installing packages into a Python virtualenv.
#
# @param venv_root [Pathname, String] the path to the root of the virtualenv
# (often `libexec/"venv"`)
# @param python [String, Pathname] which interpreter to use (e.g. "python3"
# or "python3.x")
# @param python [String, Pathname] which interpreter to use (e.g. `"python3"`
# or `"python3.x"`)
# @param formula [Formula] the active {Formula}
# @return [Virtualenv] a {Virtualenv} instance
sig {
@ -166,7 +166,7 @@ module Language
def virtualenv_create(venv_root, python = "python", formula = T.cast(self, Formula),
system_site_packages: true, without_pip: true)
# 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
python_version = Language::Python.major_minor_version(python)
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
# active or if the specified python is required by the formula. Valid
# inputs are "python", "python2", and :python3. Note that
# "with-python", "without-python", "with-python@2", and "without-python@2"
# inputs are `"python"`, `"python2"` and `:python3`. Note that
# `"with-python"`, `"without-python"`, `"with-python@2"` and `"without-python@2"`
# formula options are handled correctly even if not associated with any
# corresponding depends_on statement.
sig { params(python: String).returns(T::Boolean) }
@ -211,7 +211,7 @@ module Language
# Helper method for the common case of installing a Python application.
# 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
# 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

View File

@ -16,15 +16,20 @@ class LazyObject < Delegator
@__delegate__ = @__callable__.call
# rubocop:enable Naming/MemoizedInstanceVariableName
end
private :__getobj__
def __setobj__(callable)
@__callable__ = callable
end
private :__setobj__
# Forward to the inner object to make lazy objects type-checkable.
#
# @!visibility private
def is_a?(klass)
# see https://sorbet.org/docs/faq#how-can-i-fix-type-errors-that-arise-from-super
T.bind(self, T.untyped)
__getobj__.is_a?(klass) || super
end
end

View File

@ -39,9 +39,11 @@ module Homebrew
) do
extend Forwardable
# @!attribute [r] version
# @api public
delegate version: :bundle_version
# @!attribute [r] short_version
# @api public
delegate short_version: :bundle_version
end

View File

@ -13,7 +13,7 @@ module Homebrew
# Livecheck has historically prioritized the {Git} strategy over others
# and this behavior was continued when the priority setup was created.
# 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
# behavior.
#

View File

@ -4,7 +4,7 @@
module Homebrew
module Livecheck
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
# in the `livecheck` block, it should be passed as the second argument to
# the `strategy` block.

View File

@ -54,12 +54,15 @@ module Homebrew
) do
extend Forwardable
# @!attribute [r] version
# @api public
delegate version: :bundle_version
# @!attribute [r] short_version
# @api public
delegate short_version: :bundle_version
# @!attribute [r] nice_version
# @api public
delegate nice_version: :bundle_version
end

View File

@ -5,7 +5,7 @@ module Homebrew
module Livecheck
module Strategy
# 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
# as the second argument to the `strategy` block.
#

View File

@ -4,7 +4,7 @@
module Homebrew
module Livecheck
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
# in the `livecheck` block, it should be passed as the second argument to
# the `strategy` block.

View File

@ -106,7 +106,6 @@ class Locale
locale_groups.find { |locales| locales.any? { |locale| include?(locale) } }
end
# @!visibility private
sig { returns(String) }
def to_s
[@language, @script, @region].compact.join("-")

View File

@ -132,6 +132,7 @@ class MacOSVersion < Version
alias requires_popcnt? requires_nehalem_cpu?
# Represents the absence of a version.
#
# 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
end
@ -141,7 +142,7 @@ require "lazy_object"
module MacOSVersionErrorCompat
def const_missing(name)
if name == :MacOSVersionError
odisabled "MacOSVersionError", "MacOSVersion::Error"
odisabled "`MacOSVersionError`", "`MacOSVersion::Error`"
return MacOSVersion::Error
end
@ -158,7 +159,7 @@ end
module MacOSVersions
SYMBOLS = LazyObject.new do # rubocop:disable Style/MutableConstant
odisabled "MacOSVersions::SYMBOLS", "MacOSVersion::SYMBOLS"
odisabled "`MacOSVersions::SYMBOLS`", "`MacOSVersion::SYMBOLS`"
MacOSVersion::SYMBOLS
end
end
@ -167,7 +168,7 @@ module OS
module Mac
# TODO: Replace `::Version` with `Version` when this is removed.
Version = LazyObject.new do # rubocop:disable Style/MutableConstant
odisabled "OS::Mac::Version", "MacOSVersion"
odisabled "`OS::Mac::Version`", "`MacOSVersion`"
MacOSVersion
end
end

View File

@ -142,7 +142,7 @@ module Homebrew
sig { returns(String) }
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"]
lines += Homebrew::CLI::Parser.global_cask_options.map do |_, long, kwargs|
generate_option_doc(nil, long.chomp("="), kwargs.fetch(:description))

View File

@ -287,17 +287,18 @@ class Migrator
def repin
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
# <dir>/../<...>/../Cellar/name/version.
# To repin formula we need to update the link thus that it points to
# 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
# Pathname#make_relative_symlink, where Pathname#relative_path_from
# is used to find relative path from source to destination parent and
# it assumes no symlinks.
# `Pathname#make_relative_symlink`, where `Pathname#relative_path_from`
# is used to find the relative path from source to destination parent
# and it assumes no symlinks.
src_oldname = (old_pin_record.dirname/old_pin_link_record).expand_path
new_pin_record.make_relative_symlink(src_oldname.sub(oldname, newname))
old_pin_record.delete

View File

@ -1,7 +1,7 @@
# typed: 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.
class Mktemp
include FileUtils
@ -38,7 +38,6 @@ class Mktemp
@quiet = true
end
# @!visibility private
sig { returns(String) }
def to_s
"[Mktemp: #{tmpdir} retain=#{@retain} quiet=#{@quiet}]"

View File

@ -11,7 +11,6 @@ class Option
@description = description
end
# @!visibility private
sig { returns(String) }
def to_s = flag
@ -30,7 +29,6 @@ class Option
name.hash
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: #{flag.inspect}>"
@ -134,13 +132,11 @@ class Options
alias to_ary to_a
# @!visibility private
sig { returns(String) }
def to_s
@options.map(&:to_s).join(" ")
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: #{to_a.inspect}>"

View File

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

View File

@ -51,7 +51,6 @@ class EmbeddedPatch
Utils.safe_popen_write("patch", *args) { |p| p.write(data) }
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: #{strip.inspect}>"
@ -151,7 +150,6 @@ class ExternalPatch
raise BuildError.new(f, cmd, args, ENV.to_hash)
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: #{strip.inspect} #{url.inspect}>"

View File

@ -39,7 +39,6 @@ class PkgVersion
end
end
# @!visibility private
sig { returns(String) }
def to_s = to_str

View File

@ -140,7 +140,6 @@ class Requirement
[self.class, name, tags].hash
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: #{tags.inspect}>"

View File

@ -27,7 +27,6 @@ class ArchRequirement < Requirement
"The #{@arch} architecture is required for this software."
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: arch=#{@arch.to_s.inspect} #{tags.inspect}>"

View File

@ -96,7 +96,6 @@ class MacOSRequirement < Requirement
[super, comparator, version].hash
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: version#{@comparator}#{@version.to_s.inspect} #{tags.inspect}>"

View File

@ -48,7 +48,6 @@ class XcodeRequirement < Requirement
end
end
# @!visibility private
sig { returns(String) }
def inspect
"#<#{self.class.name}: version>=#{@version.inspect} #{tags.inspect}>"

View File

@ -146,17 +146,22 @@ class Resource < Downloadable
super(verify_download_integrity:)
end
# @!attribute [w] livecheck
# {Livecheck} can be used to check for newer versions of the software.
# This method evaluates the DSL specified in the livecheck block of the
# {Resource} (if it exists) and sets the instance variables of a {Livecheck}
# object accordingly. This is used by `brew livecheck` to check for newer
# versions of the software.
#
# <pre>livecheck do
# ### Example
#
# ```ruby
# livecheck do
# url "https://example.com/foo/releases"
# regex /foo-(\d+(?:\.\d+)+)\.tar/
# end</pre>
# end
# ```
#
# @!attribute [w] livecheck
def livecheck(&block)
return @livecheck unless block
@ -165,8 +170,8 @@ class Resource < Downloadable
end
# Whether a livecheck specification is defined or not.
# It returns true when a livecheck block is present in the {Resource} and
# false otherwise, and is used by livecheck.
# It returns true when a `livecheck` block is present in the {Resource} and
# false otherwise and is used by livecheck.
def livecheckable?
@livecheckable == true
end
@ -302,7 +307,6 @@ class ResourceStageContext
@staging = staging
end
# @!visibility private
sig { returns(String) }
def to_s
"<#{self.class}: resource=#{resource} staging=#{staging}>"

View File

@ -4,27 +4,26 @@
module RuboCop
module Cop
module Homebrew
# Checks for code that can be written with simpler conditionals
# using `Object#blank?`.
# Checks for code that can be simplified using `Object#blank?`.
#
# @note
# This cop is unsafe autocorrection, because `' '.empty?` returns false,
# but `' '.blank?` returns true. Therefore, autocorrection is not compatible
# if the receiver is a non-empty blank string, tab, or newline meta characters.
# NOTE: Auto-correction for this cop is unsafe because `' '.empty?` returns `false`,
# but `' '.blank?` returns `true`. Therefore, auto-correction is not compatible
# if the receiver is a non-empty blank string.
#
# @example
# # Converts usages of `nil? || empty?` to `blank?`
# ### Example
#
# # bad
# foo.nil? || foo.empty?
# foo == nil || foo.empty?
# ```ruby
# # bad
# foo.nil? || foo.empty?
# foo == nil || foo.empty?
#
# # good
# foo.blank?
# # good
# foo.blank?
# ```
class Blank < Base
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
# that have a single method call on the left hand side
@ -49,7 +48,7 @@ module RuboCop
nil_or_empty?(node) do |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|
autocorrect(corrector, node)
end

View File

@ -44,7 +44,7 @@ module RuboCop
end
# 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?("]") }
# Sort the lines that should be sorted

View File

@ -9,20 +9,23 @@ module RuboCop
module Cask
# This cop makes sure that OS conditionals are consistent.
#
# @example
# # bad
# cask 'foo' do
# if MacOS.version == :high_sierra
# sha256 "..."
# end
# end
# ### Example
#
# # good
# cask 'foo' do
# on_high_sierra do
# sha256 "..."
# end
# ```ruby
# # bad
# cask 'foo' do
# if MacOS.version == :high_sierra
# sha256 "..."
# end
# end
#
# # good
# cask 'foo' do
# on_high_sierra do
# sha256 "..."
# end
# end
# ```
class OnSystemConditionals < Base
extend Forwardable
extend AutoCorrector

View File

@ -6,16 +6,17 @@ module RuboCop
module Cask
# This cop checks that a cask's `url` stanza is formatted correctly.
#
# @example
# # bad
# url "https://example.com/download/foo.dmg",
# verified: "https://example.com/download"
# ### Example
#
# ```ruby
# # bad
# url "https://example.com/download/foo.dmg",
# verified: "https://example.com/download"
#
# # good
# url "https://example.com/download/foo.dmg",
# verified: "example.com/download/"
#
# # good
# url "https://example.com/download/foo.dmg",
# verified: "example.com/download/"
# ```
class Url < Base
extend AutoCorrector
extend Forwardable
@ -43,7 +44,7 @@ module RuboCop
# Skip if the URL and the verified value are the same.
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
# Skip if the verified value ends with a slash.
next if value_node.str_content.end_with?("/")

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