diff --git a/Library/Homebrew/cask/cask.rb b/Library/Homebrew/cask/cask.rb index 1b4a5309d0..c2d581aaa2 100644 --- a/Library/Homebrew/cask/cask.rb +++ b/Library/Homebrew/cask/cask.rb @@ -20,7 +20,17 @@ module Cask extend APIHashable include Metadata - attr_reader :token, :sourcefile_path, :source, :config, :default_config, :loader + # The token of this {Cask}. + # + # @api public + attr_reader :token + + # The configuration of this {Cask}. + # + # @api internal + attr_reader :config + + attr_reader :sourcefile_path, :source, :default_config, :loader attr_accessor :download, :allow_reassignment attr_predicate :loaded_from_api? @@ -124,13 +134,21 @@ module Cask .map { |p| p.split.map(&:to_s) } end - def full_name + # The fully-qualified token of this {Cask}. + # + # @api public + def full_token return token if tap.nil? return token if tap.core_cask_tap? "#{tap.name}/#{token}" end + # Alias for {#full_token}. + # + # @api internal + def full_name = full_token + sig { returns(T::Boolean) } def installed? installed_caskfile&.exist? || false @@ -226,6 +244,9 @@ module Cask @caskroom_path ||= Caskroom.path.join(token) end + # Check if the installed cask is outdated. + # + # @api internal def outdated?(greedy: false, greedy_latest: false, greedy_auto_updates: false) !outdated_version(greedy:, greedy_latest:, greedy_auto_updates:).nil? @@ -304,9 +325,10 @@ module Cask @ruby_source_checksum = { sha256: ruby_source_sha256 } end - def to_s - @token - end + # Alias for {#token}. + # + # @api public + def to_s = token def inspect "#" diff --git a/Library/Homebrew/cask/caskroom.rb b/Library/Homebrew/cask/caskroom.rb index d83c53804a..1c2d4dd091 100644 --- a/Library/Homebrew/cask/caskroom.rb +++ b/Library/Homebrew/cask/caskroom.rb @@ -6,7 +6,7 @@ require "utils/user" module Cask # Helper functions for interacting with the `Caskroom` directory. # - # @api private + # @api internal module Caskroom sig { returns(Pathname) } def self.path @@ -50,6 +50,9 @@ module Cask SystemCommand.run("/usr/bin/chgrp", args: ["admin", path], sudo:) end + # Get all installed casks. + # + # @api internal sig { params(config: T.nilable(Config)).returns(T::Array[Cask]) } def self.casks(config: nil) tokens.sort.filter_map do |token| diff --git a/Library/Homebrew/cask/config.rb b/Library/Homebrew/cask/config.rb index 37854d8ec5..d3a39ba253 100644 --- a/Library/Homebrew/cask/config.rb +++ b/Library/Homebrew/cask/config.rb @@ -10,7 +10,7 @@ require "extend/hash/keys" module Cask # Configuration for installing casks. # - # @api private + # @api internal class Config DEFAULT_DIRS = { appdir: "/Applications", @@ -88,6 +88,9 @@ module Cask end end + # Get the explicit configuration. + # + # @api internal sig { returns(T::Hash[Symbol, T.any(String, Pathname, T::Array[String])]) } attr_accessor :explicit @@ -184,6 +187,11 @@ module Cask self.class.new(explicit: other.explicit.merge(explicit)) end + # Get explicit configuration as a string. + # + # @api internal + # + # TODO: This is only used by `homebrew/bundle`, so move it there. sig { returns(String) } def explicit_s explicit.map do |key, value| diff --git a/Library/Homebrew/development_tools.rb b/Library/Homebrew/development_tools.rb index b9976befff..15dbd24612 100644 --- a/Library/Homebrew/development_tools.rb +++ b/Library/Homebrew/development_tools.rb @@ -83,6 +83,9 @@ class DevelopmentTools end end + # Get the GCC version. + # + # @api internal sig { params(cc: String).returns(Version) } def gcc_version(cc) (@gcc_version ||= {}).fetch(cc) do diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index c7eccd09e3..49e46094c7 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -6,7 +6,7 @@ require "set" module Homebrew # Helper module for querying Homebrew-specific environment variables. # - # @api private + # @api internal module EnvConfig module_function diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index 1094c7e517..c8c65fce31 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -5,6 +5,8 @@ require "shellwords" require "utils" # Raised when a command is used wrong. +# +# @api internal class UsageError < RuntimeError attr_reader :reason @@ -133,6 +135,8 @@ class TapFormulaOrCaskUnavailableError < FormulaOrCaskUnavailableError end # Raised when a formula is not available. +# +# @api internal class FormulaUnavailableError < FormulaOrCaskUnavailableError attr_accessor :dependent diff --git a/Library/Homebrew/extend/kernel.rb b/Library/Homebrew/extend/kernel.rb index 058f582a2e..fd651ad2b7 100644 --- a/Library/Homebrew/extend/kernel.rb +++ b/Library/Homebrew/extend/kernel.rb @@ -58,31 +58,42 @@ module Kernel puts oh1_title(title, truncate:) end - # Print a message prefixed with "Warning" (do this rarely). + # Print a warning message. + # + # @api public def opoo(message) Tty.with($stderr) do |stderr| stderr.puts Formatter.warning(message, label: "Warning") end end - # Print a message prefixed with "Error". + # Print an error message. + # + # @api public def onoe(message) Tty.with($stderr) do |stderr| stderr.puts Formatter.error(message, label: "Error") end end + # Print an error message and fail at the end of the program. + # + # @api public def ofail(error) onoe error Homebrew.failed = true end + # Print an error message and fail immediately. + # + # @api public sig { params(error: T.any(String, Exception)).returns(T.noreturn) } def odie(error) onoe error exit 1 end + # Output a deprecation warning/error message. def odeprecated(method, replacement = nil, disable: false, disable_on: nil, @@ -254,6 +265,9 @@ module Kernel end end + # Find a command. + # + # @api public def which(cmd, path = ENV.fetch("PATH")) PATH.new(path).each do |p| begin diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 55d114beec..99643f348d 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -72,6 +72,8 @@ class Formula # The name of this {Formula}. # e.g. `this-formula` + # + # @api public sig { returns(String) } attr_reader :name @@ -88,6 +90,8 @@ class Formula # The fully-qualified name of this {Formula}. # For core formulae it's the same as {#name}. # e.g. `homebrew/tap-name/this-formula` + # + # @api public sig { returns(String) } attr_reader :full_name @@ -99,19 +103,23 @@ class Formula # The full path to this {Formula}. # e.g. `/usr/local/Library/Taps/homebrew/homebrew-core/Formula/t/this-formula.rb` + # + # @api public sig { returns(Pathname) } attr_reader :path # The {Tap} instance associated with this {Formula}. # If it's `nil`, then this formula is loaded from a path or URL. - # @private + # + # @api internal sig { returns(T.nilable(Tap)) } attr_reader :tap # The stable (and default) {SoftwareSpec} for this {Formula}. # This contains all the attributes (e.g. URL, checksum) that apply to the # stable version of this formula. - # @private + # + # @api internal sig { returns(T.nilable(SoftwareSpec)) } attr_reader :stable @@ -120,8 +128,10 @@ class Formula # This is always installed with the version `HEAD` and taken from the latest # commit in the version control system. # `nil` if there is no HEAD version. + # # @see #stable - # @private + # + # @api private sig { returns(T.nilable(SoftwareSpec)) } attr_reader :head @@ -549,6 +559,8 @@ class Formula end # Old names for the formula. + # + # @api internal sig { returns(T::Array[String]) } def oldnames @oldnames ||= if (tap = self.tap) @@ -560,6 +572,8 @@ class Formula end # All aliases for the formula. + # + # @api internal sig { returns(T::Array[String]) } def aliases @aliases ||= tap&.alias_reverse_table&.dig(full_name)&.map { _1.split("/").last } || [] @@ -570,6 +584,8 @@ class Formula def_delegator :"active_spec.resources", :values, :resources # The {Dependency}s for the currently active {SoftwareSpec}. + # + # @api internal delegate deps: :active_spec # The declared {Dependency}s for the currently active {SoftwareSpec} (i.e. including those provided by macOS) @@ -627,9 +643,10 @@ class Formula installed_prefixes.any? { |keg| (keg/Tab::FILENAME).file? } end - # @private # The link status symlink directory for this {Formula}. # You probably want {#opt_prefix} instead. + # + # @api internal def linked_keg linked_keg = possible_names.map { |name| HOMEBREW_LINKED_KEGS/name } .find(&:directory?) @@ -696,6 +713,8 @@ class Formula end # Is the formula linked? + # + # @api internal sig { returns(T::Boolean) } def linked? linked_keg.symlink? @@ -754,6 +773,8 @@ class Formula # # No `make install` available? #
bin.install "binary1"
+ # + # @api public sig { returns(Pathname) } def bin prefix/"bin" @@ -762,6 +783,8 @@ class Formula # The directory where the formula's documentation should be installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def doc share/"doc"/name @@ -773,6 +796,8 @@ class Formula # # No `make install` available? #
include.install "example.h"
+ # + # @api public sig { returns(Pathname) } def include prefix/"include" @@ -781,6 +806,8 @@ class Formula # The directory where the formula's info files should be installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def info share/"info" @@ -792,6 +819,8 @@ class Formula # # No `make install` available? #
lib.install "example.dylib"
+ # + # @api public sig { returns(Pathname) } def lib prefix/"lib" @@ -805,6 +834,8 @@ class Formula #
libexec.install "foo.jar"
   # bin.write_jar_script libexec/"foo.jar", "foo"
   # 
+ # + # @api public sig { returns(Pathname) } def libexec prefix/"libexec" @@ -815,6 +846,8 @@ class Formula # `brew link` for formulae that are not keg-only. # Often one of the more specific `man` functions should be used instead, # e.g. {#man1}. + # + # @api public sig { returns(Pathname) } def man share/"man" @@ -826,6 +859,8 @@ class Formula # # No `make install` available? #
man1.install "example.1"
+ # + # @api public sig { returns(Pathname) } def man1 man/"man1" @@ -834,6 +869,8 @@ class Formula # The directory where the formula's man2 pages should be installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def man2 man/"man2" @@ -845,6 +882,8 @@ class Formula # # No `make install` available? #
man3.install "man.3"
+ # + # @api public sig { returns(Pathname) } def man3 man/"man3" @@ -853,6 +892,8 @@ class Formula # The directory where the formula's man4 pages should be installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def man4 man/"man4" @@ -861,6 +902,8 @@ class Formula # The directory where the formula's man5 pages should be installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def man5 man/"man5" @@ -869,6 +912,8 @@ class Formula # The directory where the formula's man6 pages should be installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def man6 man/"man6" @@ -877,6 +922,8 @@ class Formula # The directory where the formula's man7 pages should be installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def man7 man/"man7" @@ -885,6 +932,8 @@ class Formula # The directory where the formula's man8 pages should be installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def man8 man/"man8" @@ -894,6 +943,8 @@ class Formula # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. # Generally we try to migrate these to {#bin} instead. + # + # @api public sig { returns(Pathname) } def sbin prefix/"sbin" @@ -914,6 +965,8 @@ class Formula # # Install `./example_code/simple/ones` to `share/demos/examples`: #
(share/"demos").install "example_code/simple/ones" => "examples"
+ # + # @api public sig { returns(Pathname) } def share prefix/"share" @@ -926,6 +979,8 @@ class Formula # # No `make install` available? #
pkgshare.install "examples"
+ # + # @api public sig { returns(Pathname) } def pkgshare prefix/"share"/name @@ -936,6 +991,8 @@ class Formula # # To install an Emacs mode included with a software package: #
elisp.install "contrib/emacs/example-mode.el"
+ # + # @api public sig { returns(Pathname) } def elisp prefix/"share/emacs/site-lisp"/name @@ -945,6 +1002,8 @@ class Formula # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. # This is not symlinked into `HOMEBREW_PREFIX`. + # + # @api public sig { returns(Pathname) } def frameworks prefix/"Frameworks" @@ -954,6 +1013,8 @@ class Formula # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. # This is not symlinked into `HOMEBREW_PREFIX`. + # + # @api public sig { returns(Pathname) } def kext_prefix prefix/"Library/Extensions" @@ -964,6 +1025,8 @@ class Formula # but will write a new file named `*.default`. # This directory is not inside the `HOMEBREW_CELLAR` so it persists # across upgrades. + # + # @api public sig { returns(Pathname) } def etc (HOMEBREW_PREFIX/"etc").extend(InstallRenamed) @@ -973,6 +1036,8 @@ class Formula # e.g. `$HOMEBREW_PREFIX/etc/openssl@1.1` # Anything using `pkgetc.install` will not overwrite other files on # e.g. upgrades but will write a new file named `*.default`. + # + # @api public sig { returns(Pathname) } def pkgetc (HOMEBREW_PREFIX/"etc"/name).extend(InstallRenamed) @@ -981,6 +1046,8 @@ class Formula # The directory where the formula's variable files should be installed. # This directory is not inside the `HOMEBREW_CELLAR` so it persists # across upgrades. + # + # @api public sig { returns(Pathname) } def var HOMEBREW_PREFIX/"var" @@ -990,6 +1057,8 @@ class Formula # installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def zsh_function share/"zsh/site-functions" @@ -999,6 +1068,8 @@ class Formula # installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def fish_function share/"fish/vendor_functions.d" @@ -1008,6 +1079,8 @@ class Formula # installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def bash_completion prefix/"etc/bash_completion.d" @@ -1017,6 +1090,8 @@ class Formula # installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def zsh_completion share/"zsh/site-functions" @@ -1026,6 +1101,8 @@ class Formula # installed. # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. + # + # @api public sig { returns(Pathname) } def fish_completion share/"fish/vendor_completions.d" @@ -1141,51 +1218,80 @@ class Formula # This is the preferred way to refer to a formula in plists or from another # formula, as the path is stable even when the software is updated. #
args << "--with-readline=#{Formula["readline"].opt_prefix}" if build.with? "readline"
+ # + # @api public sig { returns(Pathname) } def opt_prefix HOMEBREW_PREFIX/"opt"/name end + # Same as {#bin}, but relative to {#opt_prefix} instead of {#prefix}. + # + # @api public sig { returns(Pathname) } def opt_bin opt_prefix/"bin" end + # Same as {#include}, but relative to {#opt_prefix} instead of {#prefix}. + # + # @api public sig { returns(Pathname) } def opt_include opt_prefix/"include" end + # Same as {#lib}, but relative to {#opt_prefix} instead of {#prefix}. + # + # @api public sig { returns(Pathname) } def opt_lib opt_prefix/"lib" end + # Same as {#libexec}, but relative to {#opt_prefix} instead of {#prefix}. + # + # @api public sig { returns(Pathname) } def opt_libexec opt_prefix/"libexec" end + # Same as {#sbin}, but relative to {#opt_prefix} instead of {#prefix}. + # + # @api public sig { returns(Pathname) } def opt_sbin opt_prefix/"sbin" end + # Same as {#share}, but relative to {#opt_prefix} instead of {#prefix}. + # + # @api public sig { returns(Pathname) } def opt_share opt_prefix/"share" end + # Same as {#pkgshare}, but relative to {#opt_prefix} instead of {#prefix}. + # + # @api public sig { returns(Pathname) } def opt_pkgshare opt_prefix/"share"/name end + # Same as {#elisp}, but relative to {#opt_prefix} instead of {#prefix}. + # + # @api public sig { returns(Pathname) } def opt_elisp opt_prefix/"share/emacs/site-lisp"/name end + # Same as {#frameworks}, but relative to {#opt_prefix} instead of {#prefix}. + # + # @api public sig { returns(Pathname) } def opt_frameworks opt_prefix/"Frameworks" @@ -1285,6 +1391,8 @@ class Formula # Rarely, you don't want your library symlinked into the main prefix. # See `gettext.rb` for an example. # @see .keg_only + # + # @api internal sig { returns(T::Boolean) } def keg_only? return false unless keg_only_reason @@ -1560,7 +1668,9 @@ class Formula self.class.installed_with_alias_path(alias_path).reject { |f| f.name == name } end - # @private + # Check whether the installed formula is outdated. + # + # @api internal sig { params(fetch_head: T::Boolean).returns(T::Boolean) } def outdated?(fetch_head: false) !outdated_kegs(fetch_head:).empty? @@ -1571,7 +1681,7 @@ class Formula # @private delegate pinnable?: :@pin - # @private + # @api internal delegate pinned?: :@pin # @private @@ -2069,19 +2179,21 @@ class Formula # @private delegate env: :"self.class" - # @private + # @api internal delegate conflicts: :"self.class" # Returns a list of Dependency objects in an installable order, which # means if a depends on b then b will be ordered before a in this list - # @private + # + # @api internal def recursive_dependencies(&block) cache_key = "Formula#recursive_dependencies" unless block Dependency.expand(self, cache_key:, &block) end # The full set of Requirements for this formula's dependency tree. - # @private + # + # @api internal def recursive_requirements(&block) cache_key = "Formula#recursive_requirements" unless block Requirement.expand(self, cache_key:, &block) @@ -2097,6 +2209,10 @@ class Formula end end + # Get the path of any installed prefix. + # + # @api internal + sig { returns(T.nilable(Pathname)) } def any_installed_prefix if optlinked? && opt_prefix.exist? opt_prefix @@ -2112,7 +2228,8 @@ class Formula end # Returns a list of Dependency objects that are required at runtime. - # @private + # + # @api internal def runtime_dependencies(read_from_tab: true, undeclared: true) deps = if read_from_tab && undeclared && (tab_deps = any_installed_keg&.runtime_dependencies) @@ -3069,6 +3186,8 @@ class Formula # Shows when running `brew info`. # #
desc "Example formula"
+ # + # @api public attr_rw :desc # @!attribute [w] license @@ -3094,6 +3213,8 @@ class Formula # all_of: ["0BSD", "Zlib", "Artistic-1.0+"], # "Apache-2.0" => { with: "LLVM-exception" }, # ] + # + # @api public def license(args = nil) if args.nil? @licenses @@ -3109,6 +3230,8 @@ class Formula # Can be opened with running `brew home`. # #
homepage "https://www.example.com"
+ # + # @api public attr_rw :homepage # Whether a livecheck specification is defined or not. @@ -3149,6 +3272,8 @@ class Formula # `0` if unset. # #
revision 1
+ # + # @api public attr_rw :revision # @!attribute [w] version_scheme @@ -3161,6 +3286,8 @@ class Formula # `0` if unset. # #
version_scheme 1
+ # + # @api public attr_rw :version_scheme # @private @@ -3191,6 +3318,8 @@ class Formula # using: :git, # tag: "1.2.3", # revision: "db8e4de5b2d6653f66aea53094624468caad15d2" + # + # @api public def url(val, specs = {}) stable.url(val, specs) end @@ -3201,6 +3330,8 @@ class Formula # declared if it cannot be autodetected correctly. # #
version "1.2-final"
+ # + # @api public def version(val = nil) stable.version(val) end @@ -3214,6 +3345,8 @@ class Formula # #
mirror "https://in.case.the.host.is.down.example.com"
     # mirror "https://in.case.the.mirror.is.down.example.com
+ # + # @api public def mirror(val) stable.mirror(val) end @@ -3226,6 +3359,8 @@ class Formula # tell you the currently valid value. # #
sha256 "2a2ba417eebaadcb4418ee7b12fe2998f26d6e6f7fda7983412ff66a741ab6f7"
+ # + # @api public def sha256(val) stable.sha256(val) end @@ -3251,6 +3386,8 @@ class Formula # end # # Homebrew maintainers aim to bottle all formulae. + # + # @api public sig { params(block: T.proc.bind(BottleSpecification).void).void } def bottle(&block) stable.bottle(&block) @@ -3283,6 +3420,8 @@ class Formula # depends_on "libxml2" # depends_on "libffi" # end + # + # @api public def stable(&block) return @stable unless block @@ -3318,12 +3457,15 @@ class Formula # url "https://example.com/additional-stuff.tar.gz" # sha256 "c6bc3f48ce8e797854c4b865f6a8ff969867bbcaebd648ae6fd825683e59fef2" # end + # + # @api public def resource(name, klass = Resource, &block) specs.each do |spec| spec.resource(name, klass, &block) unless spec.resource_defined?(name) end end + # @api public def go_resource(name, &block) # odeprecated "Formula#go_resource", "Go modules" specs.each { |spec| spec.go_resource(name, &block) } @@ -3365,6 +3507,8 @@ class Formula # It is possible to only depend on something if # `build.with?` or `build.without? "another_formula"`: #
depends_on "postgresql" if build.without? "sqlite"
+ # + # @api public def depends_on(dep) specs.each { |spec| spec.depends_on(dep) } end @@ -3373,6 +3517,8 @@ class Formula # On macOS this is a no-op (as we use the provided system libraries) unless # `:since` specifies a minimum macOS version. # On Linux this will act as {.depends_on}. + # + # @api public sig { params( dep: T.any(String, T::Hash[T.any(String, Symbol), T.any(Symbol, T::Array[Symbol])]), @@ -3397,6 +3543,8 @@ class Formula #
option "with-spam", "The description goes here without a dot at the end"
#
option "with-qt", "Text here overwrites what's autogenerated by 'depends_on "qt" => :optional'"
#
option :universal
+ # + # @api public def option(name, description = "") specs.each { |spec| spec.option(name, description) } end @@ -3406,6 +3554,8 @@ class Formula # them to newer ones. They are mostly used for migrating non-`with` options # (e.g. `enable-debug`) to `with` options (e.g. `with-debug`). #
deprecated_option "enable-debug" => "with-debug"
+ # + # @api public def deprecated_option(hash) specs.each { |spec| spec.deprecated_option(hash) } end @@ -3441,12 +3591,16 @@ class Formula # conditional. #
patch :p0, "..."
# @see https://docs.brew.sh/Formula-Cookbook#patches Patches + # + # @api public def patch(strip = :p1, src = nil, &block) specs.each { |spec| spec.patch(strip, src, &block) } end # One or more formulae that conflict with this one and why. #
conflicts_with "imagemagick", because: "both install `convert` binaries"
+ # + # @api public def conflicts_with(*names) opts = names.last.is_a?(Hash) ? names.pop : {} names.each { |name| conflicts << FormulaConflict.new(name, opts[:because]) } @@ -3459,6 +3613,8 @@ class Formula #
skip_clean "bin/foo", "lib/bar"
# Keep .la files with: #
skip_clean :la
+ # + # @api public def skip_clean(*paths) paths.flatten! # Specifying :all is deprecated and will become an error @@ -3476,11 +3632,15 @@ class Formula #
keg_only :provided_by_macos
#
keg_only :versioned_formulae
#
keg_only "because I want it so"
+ # + # @api public def keg_only(reason, explanation = "") @keg_only_reason = KegOnlyReason.new(reason, explanation) end # Pass `:skip` to this method to disable post-install stdlib checking. + # + # @api public def cxxstdlib_check(check_type) define_method(:skip_cxxstdlib_check?) { true } if check_type == :skip end @@ -3506,6 +3666,8 @@ class Formula #
fails_with :gcc => '7' do
     #   version '7.1'
     # end
+ # + # @api public def fails_with(compiler, &block) specs.each { |spec| spec.fails_with(compiler, &block) } end @@ -3519,6 +3681,8 @@ class Formula # rather than implicitly finding a suitable compiler with `needs`. # # @see .fails_with + # + # @api public def needs(*standards) specs.each { |spec| spec.needs(*standards) } end @@ -3551,6 +3715,8 @@ class Formula # # The test will fail if it returns false, or if an exception is raised. # Failed assertions and failed `system` commands will raise exceptions. + # + # @api public def test(&block) define_method(:test, &block) end @@ -3567,6 +3733,8 @@ class Formula # url "https://example.com/foo/releases" # regex /foo-(\d+(?:\.\d+)+)\.tar/ # end + # + # @api public def livecheck(&block) return @livecheck unless block @@ -3583,6 +3751,8 @@ class Formula #
service do
     #   run [opt_bin/"foo"]
     # end
+ # + # @api public def service(&block) return @service_block unless block @@ -3604,6 +3774,8 @@ class Formula # # Alternatively, a preset reason can be passed as a symbol: #
pour_bottle? only_if: :clt_installed
+ # + # @api public def pour_bottle?(only_if: nil, &block) @pour_bottle_check = PourBottleCheck.new(self) @pour_bottle_only_if = only_if @@ -3650,6 +3822,8 @@ class Formula #
deprecate! date: "2020-08-27", because: "has been replaced by foo"
# @see https://docs.brew.sh/Deprecating-Disabling-and-Removing-Formulae # @see DeprecateDisable::FORMULA_DEPRECATE_DISABLE_REASONS + # + # @api public def deprecate!(date:, because:) @deprecation_date = Date.parse(date) return if @deprecation_date > Date.today @@ -3685,6 +3859,8 @@ class Formula #
disable! date: "2020-08-27", because: "has been replaced by foo"
# @see https://docs.brew.sh/Deprecating-Disabling-and-Removing-Formulae # @see DeprecateDisable::FORMULA_DEPRECATE_DISABLE_REASONS + # + # @api public def disable!(date:, because:) @disable_date = Date.parse(date) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index b8777abd55..6beb8d90f8 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -24,6 +24,9 @@ module Formulary # :codesign and custom requirement classes are not supported API_SUPPORTED_REQUIREMENTS = [:arch, :linux, :macos, :maximum_macos, :xcode].freeze + # Enable the factory cache. + # + # @api internal sig { void } def self.enable_factory_cache! @factory_cache = true @@ -927,6 +930,8 @@ module Formulary # * a formula pathname # * a formula URL # * a local bottle reference + # + # @api internal sig { params( ref: T.any(Pathname, String), diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb index fdebb4a470..ad3b832b5b 100644 --- a/Library/Homebrew/global.rb +++ b/Library/Homebrew/global.rb @@ -84,6 +84,10 @@ module Homebrew class << self attr_writer :failed, :raise_deprecation_exceptions, :auditing + # Check whether Homebrew is using the default prefix. + # + # @api internal + sig { params(prefix: T.any(Pathname, String)).returns(T::Boolean) } def default_prefix?(prefix = HOMEBREW_PREFIX) prefix.to_s == DEFAULT_PREFIX end diff --git a/Library/Homebrew/hardware.rb b/Library/Homebrew/hardware.rb index 1e49ea61bf..c5b1eab07d 100644 --- a/Library/Homebrew/hardware.rb +++ b/Library/Homebrew/hardware.rb @@ -144,6 +144,10 @@ module Hardware ppc? && is_64_bit? && big_endian? end + # Check whether the CPU architecture is ARM. + # + # @api internal + sig { returns(T::Boolean) } def arm? type == :arm end diff --git a/Library/Homebrew/os.rb b/Library/Homebrew/os.rb index 899fbf10b7..66e2d62a3e 100644 --- a/Library/Homebrew/os.rb +++ b/Library/Homebrew/os.rb @@ -7,7 +7,7 @@ require "version" # # @api private module OS - # Check if the operating system is macOS. + # Check whether the operating system is macOS. # # @api public sig { returns(T::Boolean) } @@ -17,7 +17,7 @@ module OS RbConfig::CONFIG["host_os"].include? "darwin" end - # Check if the operating system is Linux. + # Check whether the operating system is Linux. # # @api public sig { returns(T::Boolean) } diff --git a/Library/Homebrew/os/linux.rb b/Library/Homebrew/os/linux.rb index 197c5ebda2..3fab83e525 100644 --- a/Library/Homebrew/os/linux.rb +++ b/Library/Homebrew/os/linux.rb @@ -6,6 +6,9 @@ require "utils" module OS # Helper module for querying system information on Linux. module Linux + # Get the OS version. + # + # @api internal sig { returns(String) } def self.os_version if which("lsb_release") diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb index e55849a259..ebb0003b77 100644 --- a/Library/Homebrew/os/mac.rb +++ b/Library/Homebrew/os/mac.rb @@ -22,6 +22,8 @@ module OS # This can be compared to numerics, strings, or symbols # using the standard Ruby Comparable methods. + # + # @api internal sig { returns(MacOSVersion) } def self.version odeprecated "`MacOS.version` on Linux" if Homebrew::SimulateSystem.simulating_or_running_on_linux? @@ -30,6 +32,8 @@ module OS # This can be compared to numerics, strings, or symbols # using the standard Ruby Comparable methods. + # + # @api internal sig { returns(MacOSVersion) } def self.full_version odeprecated "`MacOS.full_version` on Linux" if Homebrew::SimulateSystem.simulating_or_running_on_linux? diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index aa159b69f9..24d3e01530 100644 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -172,6 +172,9 @@ module OS end end + # Get the Xcode version. + # + # @api internal sig { returns(::Version) } def self.version odeprecated "`MacOS::Xcode.version` on Linux" if Homebrew::SimulateSystem.simulating_or_running_on_linux? @@ -406,6 +409,8 @@ module OS # Version string (a pretty long one) of the CLT package. # Note that the different ways of installing the CLTs lead to different # version numbers. + # + # @api internal sig { returns(::Version) } def self.version odeprecated "`MacOS::CLT.version` on Linux" if Homebrew::SimulateSystem.simulating_or_running_on_linux? diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index 1431c8fdcd..e39163d0c8 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -13,10 +13,22 @@ class Tab FILENAME = "INSTALL_RECEIPT.json" - attr_accessor :homebrew_version, :tabfile, :built_as_bottle, :installed_as_dependency, :installed_on_request, - :changed_files, :poured_from_bottle, :loaded_from_api, :time, :stdlib, :aliases, :arch, :source, + # @api internal + attr_accessor :installed_as_dependency + + # @api internal + attr_accessor :installed_on_request + + # @api internal + attr_accessor :poured_from_bottle + + attr_accessor :homebrew_version, :tabfile, :built_as_bottle, + :changed_files, :loaded_from_api, :time, :stdlib, :aliases, :arch, :source, :built_on - attr_writer :used_options, :unused_options, :compiler, :runtime_dependencies, :source_modified_time + attr_writer :used_options, :unused_options, :compiler, :source_modified_time + + # @api internal + attr_writer :runtime_dependencies # Instantiates a {Tab} for a new installation of a formula. def self.create(formula, compiler, stdlib) @@ -116,6 +128,7 @@ class Tab new(attributes) end + # @api internal def self.for_keg(keg) path = keg/FILENAME @@ -265,6 +278,7 @@ class Tab spec == :stable end + # @api internal def used_options Options.create(@used_options) end diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index b3a799d43c..22d8af5706 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -19,15 +19,24 @@ class Tap TAP_DIRECTORY = (HOMEBREW_LIBRARY/"Taps").freeze HOMEBREW_TAP_CASK_RENAMES_FILE = "cask_renames.json" + private_constant :HOMEBREW_TAP_CASK_RENAMES_FILE HOMEBREW_TAP_FORMULA_RENAMES_FILE = "formula_renames.json" + private_constant :HOMEBREW_TAP_FORMULA_RENAMES_FILE HOMEBREW_TAP_MIGRATIONS_FILE = "tap_migrations.json" + private_constant :HOMEBREW_TAP_MIGRATIONS_FILE HOMEBREW_TAP_AUTOBUMP_FILE = ".github/autobump.txt" + private_constant :HOMEBREW_TAP_AUTOBUMP_FILE HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS_FILE = "pypi_formula_mappings.json" + private_constant :HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS_FILE HOMEBREW_TAP_SYNCED_VERSIONS_FORMULAE_FILE = "synced_versions_formulae.json" + private_constant :HOMEBREW_TAP_SYNCED_VERSIONS_FORMULAE_FILE HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR = "audit_exceptions" + private_constant :HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR HOMEBREW_TAP_STYLE_EXCEPTIONS_DIR = "style_exceptions" + private_constant :HOMEBREW_TAP_STYLE_EXCEPTIONS_DIR TAP_MIGRATIONS_STALE_SECONDS = 86400 # 1 day + private_constant :TAP_MIGRATIONS_STALE_SECONDS HOMEBREW_TAP_JSON_FILES = %W[ #{HOMEBREW_TAP_FORMULA_RENAMES_FILE} @@ -41,6 +50,9 @@ class Tap class InvalidNameError < ArgumentError; end + # Fetch a {Tap} by name. + # + # @api public sig { params(user: String, repo: String).returns(Tap) } def self.fetch(user, repo = T.unsafe(nil)) user, repo = user.split("/", 2) if repo.nil? @@ -63,6 +75,9 @@ class Tap cache.fetch(cache_key) { |key| cache[key] = new(user, repo) } end + # Get a {Tap} from it's path or a path inside of it. + # + # @api public def self.from_path(path) match = File.expand_path(path).match(HOMEBREW_TAP_PATH_REGEX) @@ -119,27 +134,43 @@ class Tap false end + # @api public extend Enumerable # The user name of this {Tap}. Usually, it's the GitHub username of # this {Tap}'s remote repository. + # + # @api public attr_reader :user # The repository name of this {Tap} without the leading `homebrew-`. + # + # @api public attr_reader :repo # The name of this {Tap}. It combines {#user} and {#repo} with a slash. # {#name} is always in lowercase. # e.g. `user/repo` + # + # @api public attr_reader :name + # Alias for {#name}. + # + # @api public + def to_s = name + # The full name of this {Tap}, including the `homebrew-` prefix. # It combines {#user} and 'homebrew-'-prefixed {#repo} with a slash. # e.g. `user/homebrew-repo` + # + # @api public attr_reader :full_name # The local path to this {Tap}. # e.g. `/usr/local/Library/Taps/user/homebrew-repo` + # + # @api public sig { returns(Pathname) } attr_reader :path @@ -211,6 +242,8 @@ class Tap # The remote path to this {Tap}. # e.g. `https://github.com/user/homebrew-repo` + # + # @api public def remote return default_remote unless installed? @@ -219,6 +252,8 @@ class Tap # The remote repository name of this {Tap}. # e.g. `user/homebrew-repo` + # + # @api public sig { returns(T.nilable(String)) } def remote_repo return unless (remote = self.remote) @@ -243,12 +278,16 @@ class Tap .upcase end - # True if this {Tap} is a Git repository. + # Check whether this {Tap} is a Git repository. + # + # @api public def git? git_repo.git_repo? end # Git branch for this {Tap}. + # + # @api public def git_branch raise TapUnavailableError, name unless installed? @@ -256,6 +295,8 @@ class Tap end # Git HEAD for this {Tap}. + # + # @api public def git_head raise TapUnavailableError, name unless installed? @@ -263,6 +304,8 @@ class Tap end # Time since last git commit for this {Tap}. + # + # @api public def git_last_commit raise TapUnavailableError, name unless installed? @@ -271,6 +314,8 @@ class Tap # The issues URL of this {Tap}. # e.g. `https://github.com/user/homebrew-repo/issues` + # + # @api public sig { returns(T.nilable(String)) } def issues_url return if !official? && custom_remote? @@ -278,16 +323,16 @@ class Tap "#{default_remote}/issues" end - def to_s - name - end - - # True if this {Tap} is an official Homebrew tap. + # Check whether this {Tap} is an official Homebrew tap. + # + # @api public def official? user == "Homebrew" end # Check whether the remote of this {Tap} is a private repository. + # + # @api public sig { returns(T::Boolean) } def private? return @private if defined?(@private) @@ -322,13 +367,15 @@ class Tap end end - # True if this {Tap} has been installed. + # Check whether this {Tap} is installed. + # + # @api public sig { returns(T::Boolean) } def installed? path.directory? end - # True if this {Tap} is not a full clone. + # Check whether this {Tap} is a shallow clone. def shallow? (path/".git/shallow").exist? end @@ -352,6 +399,8 @@ class Tap # @param custom_remote [Boolean] If set, change the tap's remote if already installed. # @param verify [Boolean] If set, verify all the formula, casks and aliases in the tap are valid. # @param force [Boolean] If set, force core and cask taps to install even under API mode. + # + # @api public def install(quiet: false, clone_target: nil, custom_remote: false, verify: false, force: false) require "descriptions" @@ -514,6 +563,8 @@ class Tap end # Uninstall this {Tap}. + # + # @api public def uninstall(manual: false) require "descriptions" raise TapUnavailableError, name unless installed? @@ -550,7 +601,9 @@ class Tap Homebrew::Settings.write :untapped, untapped.join(";") end - # True if the {#remote} of {Tap} is customized. + # Check whether the {#remote} of {Tap} is customized. + # + # @api public sig { returns(T::Boolean) } def custom_remote? return true unless (remote = self.remote) @@ -559,6 +612,8 @@ class Tap end # Path to the directory of all {Formula} files for this {Tap}. + # + # @api public sig { returns(Pathname) } def formula_dir # Official formulae taps always use this directory, saves time to hardcode. @@ -580,6 +635,8 @@ class Tap end # Path to the directory of all {Cask} files for this {Tap}. + # + # @api public sig { returns(Pathname) } def cask_dir @cask_dir ||= path/"Casks" @@ -666,15 +723,15 @@ class Tap end end - # returns true if the file has a Ruby extension + # Check whether the file has a Ruby extension. # @private sig { params(file: Pathname).returns(T::Boolean) } def ruby_file?(file) file.extname == ".rb" end - # returns true if given path would present a {Formula} file in this {Tap}. - # accepts both absolute path and relative path (relative to this {Tap}'s path) + # Check whether the given path would present a {Formula} file in this {Tap}. + # Accepts either an absolute path or a path relative to this {Tap}'s path. # @private sig { params(file: T.any(String, Pathname)).returns(T::Boolean) } def formula_file?(file) @@ -686,8 +743,8 @@ class Tap file.to_s.start_with?("#{formula_dir}/") end - # returns true if given path would present a {Cask} file in this {Tap}. - # accepts both absolute path and relative path (relative to this {Tap}'s path) + # Check whether the given path would present a {Cask} file in this {Tap}. + # Accepts either an absolute path or a path relative to this {Tap}'s path. # @private sig { params(file: T.any(String, Pathname)).returns(T::Boolean) } def cask_file?(file) @@ -716,26 +773,27 @@ class Tap end # An array of all {Cask} tokens of this {Tap}. + # @private sig { returns(T::Array[String]) } def cask_tokens @cask_tokens ||= cask_files.map { formula_file_to_name(_1) } end - # path to the directory of all alias files for this {Tap}. + # Path to the directory of all alias files for this {Tap}. # @private sig { returns(Pathname) } def alias_dir @alias_dir ||= path/"Aliases" end - # an array of all alias files of this {Tap}. + # An array of all alias files of this {Tap}. # @private sig { returns(T::Array[Pathname]) } def alias_files @alias_files ||= Pathname.glob("#{alias_dir}/*").select(&:file?) end - # an array of all aliases of this {Tap}. + # An array of all aliases of this {Tap}. # @private sig { returns(T::Array[String]) } def aliases @@ -743,7 +801,6 @@ class Tap end # Mapping from aliases to formula names. - # # @private sig { returns(T::Hash[String, String]) } def alias_table @@ -943,6 +1000,8 @@ class Tap end # All locally installed taps. + # + # @api public sig { returns(T::Array[Tap]) } def self.installed cache[:installed] ||= if TAP_DIRECTORY.directory? @@ -965,6 +1024,9 @@ class Tap end end + # Enumerate all available {Tap}s. + # + # @api public def self.each(&block) if Homebrew::EnvConfig.no_install_from_api? installed.each(&block) @@ -1058,6 +1120,9 @@ class AbstractCoreTap < Tap private_class_method :fetch + # Get the singleton instance for this {Tap}. + # + # @api internal sig { returns(T.attached_class) } def self.instance @instance ||= T.unsafe(self).new diff --git a/Library/Homebrew/utils/bottles.rb b/Library/Homebrew/utils/bottles.rb index 20f1f965fe..b82dbf59e3 100644 --- a/Library/Homebrew/utils/bottles.rb +++ b/Library/Homebrew/utils/bottles.rb @@ -6,10 +6,12 @@ require "tab" module Utils # Helper functions for bottles. # - # @api private + # @api internal module Bottles class << self # Gets the tag for the running OS. + # + # @api internal sig { params(tag: T.nilable(T.any(Symbol, Tag))).returns(Tag) } def tag(tag = nil) case tag diff --git a/Library/Homebrew/utils/formatter.rb b/Library/Homebrew/utils/formatter.rb index c4dc5dbf6e..2d699bdef1 100644 --- a/Library/Homebrew/utils/formatter.rb +++ b/Library/Homebrew/utils/formatter.rb @@ -5,7 +5,7 @@ require "utils/tty" # Helper module for formatting output. # -# @api private +# @api internal module Formatter def self.arrow(string, color: nil) prefix("==>", string, color) @@ -23,14 +23,23 @@ module Formatter "#{Tty.bold}#{string}#{Tty.reset}" end + # Format a string as success, with an optional label. + # + # @api internal def self.success(string, label: nil) label(label, string, :green) end + # Format a string as warning, with an optional label. + # + # @api internal def self.warning(string, label: nil) label(label, string, :yellow) end + # Format a string as error, with an optional label. + # + # @api internal def self.error(string, label: nil) label(label, string, :red) end @@ -81,6 +90,9 @@ module Formatter end private_class_method :prefix + # Layout objects in columns that fit the current terminal width. + # + # @api internal def self.columns(*objects, gap_size: 2) objects = objects.flatten.map(&:to_s)