Merge branch 'Homebrew:master' into patch-1

This commit is contained in:
Leo Heitmann Ruiz 2024-04-01 21:37:10 +02:00 committed by GitHub
commit bd81853c84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
65 changed files with 798 additions and 325 deletions

View File

@ -68,15 +68,19 @@ module Cask
rescue
# in case of permissions problems
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
# dependent on whether the file argument has a trailing
# slash. This should do the right thing, but is fragile.
command.run("/usr/bin/chflags",
print_stderr:,
args: command_args + ["--", "000", path])
command.run("/bin/chmod",
print_stderr:,
args: command_args + ["--", "u+rwx", path])
command.run("/bin/chmod",
print_stderr:,
args: command_args + ["-N", path])
tried_permissions = true
retry # rmtree

View File

@ -140,6 +140,15 @@ module Homebrew
rescue FormulaUnavailableError, TapFormulaAmbiguityError
nil
end
return false if formula.blank?
# We can't determine an installed rebuild and parsing manifest version cannot be reliably done.
return false unless formula.latest_version_installed?
return true if (bottle = formula.bottle).blank?
return version != GitHubPackages.version_rebuild(bottle.resource.version, bottle.rebuild)
end
return false if formula.blank?
@ -151,7 +160,8 @@ module Homebrew
return true unless patch_hashes&.include?(Checksum.new(version.to_s))
elsif resource_name && (resource_version = formula.stable&.resources&.dig(resource_name)&.version)
return true if resource_version != version
elsif (formula.latest_version_installed? && formula.version != version) || formula.version > version
elsif (formula.latest_version_installed? && formula.pkg_version.to_s != version) ||
formula.pkg_version.to_s > version
return true
end

View File

@ -381,7 +381,7 @@ module Homebrew
end
end
Keg.sort(stable_kegs).first
stable_kegs.max_by(&:scheme_and_version)
end
def resolve_default_keg(name)

View File

@ -296,7 +296,7 @@ module Homebrew
heads, versioned = kegs.partition { |k| k.version.head? }
kegs = [
*heads.sort_by { |k| -Tab.for_keg(k).time.to_i },
*Keg.sort(versioned),
*versioned.sort_by(&:scheme_and_version),
]
if kegs.empty?
puts "Not installed"

View File

@ -175,7 +175,7 @@ module Homebrew
end
not_outdated.each do |f|
latest_keg = Keg.sort(f.installed_kegs).first
latest_keg = f.installed_kegs.max_by(&:scheme_and_version)
if latest_keg.nil?
ofail "#{f.full_specified_name} not installed"
else

View File

@ -474,7 +474,10 @@ module Homebrew
def check_throttle(formula, new_version)
throttled_rate = formula.livecheck.throttle
throttled_rate ||= formula.tap.audit_exceptions.dig(:throttled_formulae, formula.name)
throttled_rate ||= if (rate = formula.tap.audit_exceptions.dig(:throttled_formulae, formula.name))
odeprecated "throttled_formulae.json", "Livecheck#throttle"
rate
end
return if throttled_rate.blank?
formula_suffix = Version.new(new_version).patch.to_i

View File

@ -37,7 +37,7 @@ module Homebrew
switch "--cask", "--casks",
description: "Only check casks."
switch "--extract-plist",
description: "Include casks using the ExtractPlist livecheck strategy."
description: "Enable checking multiple casks with ExtractPlist strategy."
conflicts "--debug", "--json"
conflicts "--tap=", "--eval-all", "--installed"

View File

@ -1508,7 +1508,7 @@ class Formula
[]
else
all_kegs += old_installed_formulae.flat_map(&:installed_kegs)
Keg.sort(all_kegs)
all_kegs.sort_by(&:scheme_and_version)
end
end
end
@ -2268,7 +2268,7 @@ class Formula
hsh.merge!(dependencies_hash)
hsh["installed"] = Keg.sort(installed_kegs).map do |keg|
hsh["installed"] = installed_kegs.sort_by(&:scheme_and_version).map do |keg|
tab = Tab.for_keg keg
{
"version" => keg.version.to_s,
@ -2841,7 +2841,7 @@ class Formula
eligible_kegs = if head? && (head_prefix = latest_head_prefix)
head, stable = installed_kegs.partition { |k| k.version.head? }
# Remove newest head and stable kegs
head - [Keg.new(head_prefix)] + Keg.sort(stable).drop(1)
head - [Keg.new(head_prefix)] + stable.sort_by(&:scheme_and_version).slice(0...-1)
else
installed_kegs.select do |keg|
tab = Tab.for_keg(keg)
@ -3324,6 +3324,7 @@ class Formula
end
def go_resource(name, &block)
# odeprecated "Formula#go_resource", "Go modules"
specs.each { |spec| spec.go_resource(name, &block) }
end

View File

@ -5,6 +5,7 @@ require "deprecate_disable"
require "formula_text_auditor"
require "formula_versions"
require "resource_auditor"
require "utils/shared_audits"
module Homebrew
# Auditor for checking common violations in {Formula}e.
@ -737,7 +738,7 @@ module Homebrew
stable_url_minor_version = stable_url_version.minor.to_i
formula_suffix = stable.version.patch.to_i
throttled_rate = formula.tap&.audit_exception(:throttled_formulae, formula.name)
throttled_rate = formula.livecheck.throttle
if throttled_rate && formula_suffix.modulo(throttled_rate).nonzero?
problem "should only be updated every #{throttled_rate} releases on multiples of #{throttled_rate}"
end

View File

@ -22,7 +22,7 @@ class FormulaPin
end
def pin
latest_keg = Keg.sort(@formula.installed_kegs).first
latest_keg = @formula.installed_kegs.max_by(&:scheme_and_version)
return if latest_keg.nil?
pin_at(latest_keg.version)

View File

@ -994,7 +994,7 @@ module Formulary
flags: T.unsafe(nil)
)
kegs = rack.directory? ? rack.subdirs.map { |d| Keg.new(d) } : []
keg = kegs.find(&:linked?) || kegs.find(&:optlinked?) || Keg.sort(kegs).first
keg = kegs.find(&:linked?) || kegs.find(&:optlinked?) || kegs.max_by(&:scheme_and_version)
options = {
alias_path:,

View File

@ -56,7 +56,7 @@ module InstalledDependents
f_kegs = kegs_by_source[[f.name, f.tap]]
next unless f_kegs
Keg.sort(f_kegs).first
f_kegs.max_by(&:scheme_and_version)
end
next if required_kegs.empty?

View File

@ -148,11 +148,6 @@ class Keg
Formula.racks.flat_map(&:subdirs).map { |d| new(d) }
end
sig { params(kegs: T::Array[Keg]).returns(T::Array[Keg]) }
def self.sort(kegs)
kegs.sort_by { |keg| [keg.version_scheme, keg.version] }.reverse!
end
attr_reader :path, :name, :linked_keg_record, :opt_record
protected :path
@ -396,6 +391,12 @@ class Keg
@version_scheme ||= tab.version_scheme
end
# For ordering kegs by version with `.sort_by`, `.max_by`, etc.
# @see Formula.version_scheme
def scheme_and_version
[version_scheme, version]
end
def to_formula
Formulary.from_keg(self)
end

View File

@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true
require "resource"
@ -12,7 +12,9 @@ module Language
# building Go software.
# The resource names should be the import name of the package,
# 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"
if resources.empty?
if Homebrew::EnvConfig.developer?
odie "Tried to stage empty Language::Go resources array"

View File

@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true
module Language
@ -11,6 +11,7 @@ module Language
"cache=#{HOMEBREW_CACHE}/npm_cache"
end
sig { returns(String) }
def self.pack_for_installation
# Homebrew assumes the buildpath/testpath will always be disposable
# and from npm 5.0.0 the logic changed so that when a directory is
@ -36,11 +37,12 @@ module Language
output.lines.last.chomp
end
sig { void }
def self.setup_npm_environment
# guard that this is only run once
return if @env_set
@env_set = true
@env_set = T.let(true, T.nilable(T::Boolean))
# explicitly use our npm and node-gyp executables instead of the user
# managed ones in HOMEBREW_PREFIX/lib/node_modules which might be broken
begin
@ -50,6 +52,7 @@ module Language
end
end
sig { params(libexec: Pathname).returns(T::Array[String]) }
def self.std_npm_install_args(libexec)
setup_npm_environment
# tell npm to not install .brew_home by adding it to the .npmignore file
@ -95,7 +98,7 @@ module Language
NODE_SHEBANG_REGEX = %r{^#! ?/usr/bin/(?:env )?node( |$)}
# The length of the longest shebang matching `SHEBANG_REGEX`.
NODE_SHEBANG_MAX_LENGTH = "#! /usr/bin/env node ".length
NODE_SHEBANG_MAX_LENGTH = T.let("#! /usr/bin/env node ".length, Integer)
# @private
sig { params(node_path: T.any(String, Pathname)).returns(Utils::Shebang::RewriteInfo) }
@ -107,8 +110,8 @@ module Language
)
end
sig { params(formula: T.untyped).returns(Utils::Shebang::RewriteInfo) }
def detected_node_shebang(formula = self)
sig { params(formula: Formula).returns(Utils::Shebang::RewriteInfo) }
def detected_node_shebang(formula = T.cast(self, Formula))
node_deps = formula.deps.map(&:name).grep(/^node(@.+)?$/)
raise ShebangDetectionError.new("Node", "formula does not depend on Node") if node_deps.empty?
raise ShebangDetectionError.new("Node", "formula has multiple Node dependencies") if node_deps.length > 1

View File

@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true
module Language
@ -14,7 +14,7 @@ module Language
PERL_SHEBANG_REGEX = %r{^#! ?/usr/bin/(?:env )?perl( |$)}
# The length of the longest shebang matching `SHEBANG_REGEX`.
PERL_SHEBANG_MAX_LENGTH = "#! /usr/bin/env perl ".length
PERL_SHEBANG_MAX_LENGTH = T.let("#! /usr/bin/env perl ".length, Integer)
# @private
sig { params(perl_path: T.any(String, Pathname)).returns(Utils::Shebang::RewriteInfo) }
@ -26,8 +26,8 @@ module Language
)
end
sig { params(formula: T.untyped).returns(Utils::Shebang::RewriteInfo) }
def detected_perl_shebang(formula = self)
sig { params(formula: Formula).returns(Utils::Shebang::RewriteInfo) }
def detected_perl_shebang(formula = T.cast(self, Formula))
perl_deps = formula.declared_deps.select { |dep| dep.name == "perl" }
raise ShebangDetectionError.new("Perl", "formula does not depend on Perl") if perl_deps.empty?

View File

@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true
module Language
@ -28,6 +28,12 @@ module Language
end
end
sig {
params(
build: T.any(BuildOptions, Tab),
block: T.nilable(T.proc.params(python: String, version: T.nilable(Version)).void),
).void
}
def self.each_python(build, &block)
original_pythonpath = ENV.fetch("PYTHONPATH", nil)
pythons = { "python@3" => "python3",
@ -48,6 +54,7 @@ module Language
ENV["PYTHONPATH"] = original_pythonpath
end
sig { params(python: T.any(String, Pathname)).returns(T::Boolean) }
def self.reads_brewed_pth_files?(python)
return false unless homebrew_site_packages(python).directory?
return false unless homebrew_site_packages(python).writable?
@ -61,10 +68,12 @@ module Language
end
end
sig { params(python: T.any(String, Pathname)).returns(Pathname) }
def self.user_site_packages(python)
Pathname.new(`#{python} -c "import site; print(site.getusersitepackages())"`.chomp)
end
sig { params(python: T.any(String, Pathname), path: T.any(String, Pathname)).returns(T::Boolean) }
def self.in_sys_path?(python, path)
script = <<~PYTHON
import os, sys
@ -102,7 +111,7 @@ module Language
PYTHON_SHEBANG_REGEX = %r{^#! ?/usr/bin/(?:env )?python(?:[23](?:\.\d{1,2})?)?( |$)}
# The length of the longest shebang matching `SHEBANG_REGEX`.
PYTHON_SHEBANG_MAX_LENGTH = "#! /usr/bin/env pythonx.yyy ".length
PYTHON_SHEBANG_MAX_LENGTH = T.let("#! /usr/bin/env pythonx.yyy ".length, Integer)
# @private
sig { params(python_path: T.any(String, Pathname)).returns(Utils::Shebang::RewriteInfo) }
@ -254,7 +263,7 @@ module Language
sig { params(formula: Formula, venv_root: T.any(String, Pathname), python: T.any(String, Pathname)).void }
def initialize(formula, venv_root, python)
@formula = formula
@venv_root = Pathname.new(venv_root)
@venv_root = T.let(Pathname(venv_root), Pathname)
@python = python
end

View File

@ -202,7 +202,6 @@ module Homebrew
has_a_newer_upstream_version = T.let(false, T::Boolean)
formulae_and_casks_total = formulae_and_casks_to_check.count
if json && !quiet && $stderr.tty?
Tty.with($stderr) do |stderr|
stderr.puts Formatter.headline("Running checks", color: :blue)
@ -218,7 +217,7 @@ module Homebrew
)
end
# If only one formula/cask is being checked, we enable extract-plist
# Allow ExtractPlist strategy if only one formula/cask is being checked.
extract_plist = true if formulae_and_casks_total == 1
formulae_checked = formulae_and_casks_to_check.map.with_index do |formula_or_cask, i|
@ -241,29 +240,23 @@ module Homebrew
puts
end
if cask && !extract_plist && formula_or_cask.livecheck.strategy == :extract_plist
skip_info = {
cask: cask.token,
status: "skipped",
messages: ["Livecheck skipped due to the ExtractPlist strategy"],
meta: { livecheckable: true },
}
SkipConditions.print_skip_information(skip_info) if !newer_only && !quiet
next
end
# Check skip conditions for a referenced formula/cask
if referenced_formula_or_cask
skip_info = SkipConditions.referenced_skip_information(
referenced_formula_or_cask,
name,
full_name: use_full_name,
full_name: use_full_name,
verbose:,
extract_plist:,
)
end
skip_info ||= SkipConditions.skip_information(formula_or_cask, full_name: use_full_name, verbose:)
skip_info ||= SkipConditions.skip_information(
formula_or_cask,
full_name: use_full_name,
verbose:,
extract_plist:,
)
if skip_info.present?
next skip_info if json && !newer_only

View File

@ -151,6 +151,27 @@ module Homebrew
Livecheck.status_hash(cask, "disabled", full_name:, verbose:)
end
sig {
params(
cask: Cask::Cask,
_livecheckable: T::Boolean,
full_name: T::Boolean,
verbose: T::Boolean,
extract_plist: T::Boolean,
).returns(Hash)
}
def cask_extract_plist(cask, _livecheckable, full_name: false, verbose: false, extract_plist: false)
return {} if extract_plist || cask.livecheck.strategy != :extract_plist
Livecheck.status_hash(
cask,
"skipped",
["Use `--extract-plist` to enable checking multiple casks with ExtractPlist strategy"],
full_name:,
verbose:,
)
end
sig {
params(
cask: Cask::Cask,
@ -194,6 +215,7 @@ module Homebrew
:cask_discontinued,
:cask_deprecated,
:cask_disabled,
:cask_extract_plist,
:cask_version_latest,
:cask_url_unversioned,
].freeze
@ -211,9 +233,10 @@ module Homebrew
package_or_resource: T.any(Formula, Cask::Cask, Resource),
full_name: T::Boolean,
verbose: T::Boolean,
extract_plist: T::Boolean,
).returns(Hash)
}
def skip_information(package_or_resource, full_name: false, verbose: false)
def skip_information(package_or_resource, full_name: false, verbose: false, extract_plist: true)
livecheckable = package_or_resource.livecheckable?
checks = case package_or_resource
@ -227,7 +250,12 @@ module Homebrew
return {} unless checks
checks.each do |method_name|
skip_hash = send(method_name, package_or_resource, livecheckable, full_name:, verbose:)
skip_hash = case method_name
when :cask_extract_plist
send(method_name, package_or_resource, livecheckable, full_name:, verbose:, extract_plist:)
else
send(method_name, package_or_resource, livecheckable, full_name:, verbose:)
end
return skip_hash if skip_hash.present?
end
@ -244,18 +272,21 @@ module Homebrew
original_package_or_resource_name: String,
full_name: T::Boolean,
verbose: T::Boolean,
extract_plist: T::Boolean,
).returns(T.nilable(Hash))
}
def referenced_skip_information(
livecheck_package_or_resource,
original_package_or_resource_name,
full_name: false,
verbose: false
verbose: false,
extract_plist: true
)
skip_info = SkipConditions.skip_information(
livecheck_package_or_resource,
full_name:,
verbose:,
extract_plist:,
)
return if skip_info.blank?

View File

@ -67,10 +67,10 @@ module Homebrew
sig {
params(
command: T.nilable(T.any(T::Array[String], String, Pathname)),
macos: T.nilable(T.any(T::Array[String], String, Pathname)),
linux: T.nilable(T.any(T::Array[String], String, Pathname)),
).returns(T.nilable(Array))
command: T.nilable(T.any(T::Array[T.any(String, Pathname)], String, Pathname)),
macos: T.nilable(T.any(T::Array[T.any(String, Pathname)], String, Pathname)),
linux: T.nilable(T.any(T::Array[T.any(String, Pathname)], String, Pathname)),
).returns(T.nilable(T::Array[T.any(String, Pathname)]))
}
def run(command = nil, macos: nil, linux: nil)
# Save parameters for serialization

View File

@ -0,0 +1,19 @@
#!/bin/bash
# This shim is a workaround for the missing `m4` in Xcode CLT 15.3.
# It can be removed after Apple provides a new CLT with a fix for FB13679972.
# See https://github.com/Homebrew/homebrew-core/issues/165388
# HOMEBREW_LIBRARY is set by bin/brew
# HOMEBREW_DEVELOPER_DIR is set by extend/ENV/super.rb
# shellcheck disable=SC2154
source "${HOMEBREW_LIBRARY}/Homebrew/shims/utils.sh"
try_exec_non_system "${SHIM_FILE}" "$@"
if [[ -n "${HOMEBREW_DEVELOPER_DIR}" && ! -x "${HOMEBREW_DEVELOPER_DIR}/usr/bin/m4" ]]
then
safe_exec "/usr/bin/gm4" "$@"
fi
exec "/usr/bin/m4" "$@"

View File

@ -138,6 +138,7 @@ class SoftwareSpec
end
def go_resource(name, &block)
# odeprecated "SoftwareSpec#go_resource", "Go modules"
resource name, Resource::Go, &block
end

View File

@ -5,9 +5,6 @@
# Please instead update this file by running `bin/tapioca dsl Homebrew::CLI::Args`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def D?; end
sig { returns(T::Boolean) }
def HEAD?; end
@ -17,12 +14,6 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def aliases?; end
sig { returns(T::Boolean) }
def analytics?; end
sig { returns(T::Boolean) }
def annotate?; end
sig { returns(T.nilable(String)) }
def appdir; end
@ -35,24 +26,15 @@ class Homebrew::CLI::Args
sig { returns(T.nilable(String)) }
def audio_unit_plugindir; end
sig { returns(T::Boolean) }
def audit_debug?; end
sig { returns(T::Boolean) }
def auto_update?; end
sig { returns(T::Boolean) }
def binaries?; end
sig { returns(T.nilable(String)) }
def bottle_arch; end
sig { returns(T.nilable(String)) }
def bottle_tag; end
sig { returns(T::Boolean) }
def build_bottle?; end
sig { returns(T::Boolean) }
def build_from_source?; end
@ -62,12 +44,6 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def casks?; end
sig { returns(T.nilable(String)) }
def category; end
sig { returns(T.nilable(String)) }
def cc; end
sig { returns(T::Boolean) }
def closed?; end
@ -83,45 +59,24 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def custom_remote?; end
sig { returns(T.nilable(String)) }
def days; end
sig { returns(T::Boolean) }
def debian?; end
sig { returns(T::Boolean) }
def debug_symbols?; end
sig { returns(T::Boolean) }
def declared?; end
sig { returns(T::Boolean) }
def deps?; end
sig { returns(T::Boolean) }
def desc?; end
sig { returns(T::Boolean) }
def description?; end
sig { returns(T.nilable(String)) }
def dictionarydir; end
sig { returns(T::Boolean) }
def direct?; end
sig { returns(T::Boolean) }
def display_times?; end
sig { returns(T::Boolean) }
def dot?; end
sig { returns(T::Boolean) }
def dry_run?; end
sig { returns(T.nilable(String)) }
def env; end
sig { returns(T::Boolean) }
def eval_all?; end
@ -140,9 +95,6 @@ class Homebrew::CLI::Args
sig { returns(T.nilable(String)) }
def fontdir; end
sig { returns(T::Boolean) }
def for_each?; end
sig { returns(T::Boolean) }
def force?; end
@ -158,24 +110,12 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def formulae?; end
sig { returns(T::Boolean) }
def full_name?; end
sig { returns(T::Boolean) }
def g?; end
sig { returns(T::Boolean) }
def git?; end
sig { returns(T::Boolean) }
def github?; end
sig { returns(T::Boolean) }
def github_packages_downloads?; end
sig { returns(T::Boolean) }
def graph?; end
sig { returns(T::Boolean) }
def greedy?; end
@ -197,18 +137,12 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def ignore_pinned?; end
sig { returns(T::Boolean) }
def include_aliases?; end
sig { returns(T::Boolean) }
def include_build?; end
sig { returns(T::Boolean) }
def include_optional?; end
sig { returns(T::Boolean) }
def include_requirements?; end
sig { returns(T::Boolean) }
def include_test?; end
@ -218,12 +152,6 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def installed?; end
sig { returns(T::Boolean) }
def installed_as_dependency?; end
sig { returns(T::Boolean) }
def installed_on_request?; end
sig { returns(T::Boolean) }
def interactive?; end
@ -242,9 +170,6 @@ class Homebrew::CLI::Args
sig { returns(T.nilable(T::Array[String])) }
def language; end
sig { returns(T::Boolean) }
def list_checks?; end
sig { returns(T::Boolean) }
def macports?; end
@ -263,21 +188,12 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def n?; end
sig { returns(T::Boolean) }
def name?; end
sig { returns(T::Boolean) }
def new_issue?; end
sig { returns(T::Boolean) }
def no_simulate?; end
sig { returns(T::Boolean) }
def oneline?; end
sig { returns(T::Boolean) }
def only_dependencies?; end
sig { returns(T::Boolean) }
def open?; end
@ -305,15 +221,6 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def preinstall?; end
sig { returns(T::Boolean) }
def private?; end
sig { returns(T.nilable(String)) }
def prune; end
sig { returns(T::Boolean) }
def prune_prefix?; end
sig { returns(T::Boolean) }
def pull_request?; end
@ -323,9 +230,6 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def quarantine?; end
sig { returns(T::Boolean) }
def r?; end
sig { returns(T::Boolean) }
def recursive?; end
@ -338,18 +242,12 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def require_sha?; end
sig { returns(T::Boolean) }
def retry?; end
sig { returns(T::Boolean) }
def s?; end
sig { returns(T.nilable(String)) }
def screen_saverdir; end
sig { returns(T::Boolean) }
def search?; end
sig { returns(T.nilable(String)) }
def servicedir; end
@ -359,9 +257,6 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def skip_cask_deps?; end
sig { returns(T::Boolean) }
def skip_post_install?; end
sig { returns(T::Boolean) }
def skip_recommended?; end
@ -371,12 +266,6 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def syntax?; end
sig { returns(T::Boolean) }
def topological?; end
sig { returns(T::Boolean) }
def tree?; end
sig { returns(T::Boolean) }
def u?; end
@ -386,21 +275,12 @@ class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def unbrewed?; end
sig { returns(T::Boolean) }
def union?; end
sig { returns(T::Boolean) }
def variations?; end
sig { returns(T.nilable(String)) }
def vst3_plugindir; end
sig { returns(T.nilable(String)) }
def vst_plugindir; end
sig { returns(T::Boolean) }
def with_hostname?; end
sig { returns(T::Boolean) }
def zap?; end
end

View File

@ -0,0 +1,7 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Analytics`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Analytics`.
class Homebrew::CLI::Args; end

View File

@ -0,0 +1,13 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Autoremove`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Autoremove`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def dry_run?; end
sig { returns(T::Boolean) }
def n?; end
end

View File

@ -0,0 +1,22 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::CleanupCmd`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::CleanupCmd`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def dry_run?; end
sig { returns(T::Boolean) }
def n?; end
sig { returns(T.nilable(String)) }
def prune; end
sig { returns(T::Boolean) }
def prune_prefix?; end
sig { returns(T::Boolean) }
def s?; end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::CommandsCmd`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::CommandsCmd`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def include_aliases?; end
end

View File

@ -0,0 +1,7 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::CompletionsCmd`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::CompletionsCmd`.
class Homebrew::CLI::Args; end

View File

@ -0,0 +1,7 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Config`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Config`.
class Homebrew::CLI::Args; end

View File

@ -0,0 +1,79 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Deps`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Deps`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def HEAD?; end
sig { returns(T::Boolean) }
def annotate?; end
sig { returns(T::Boolean) }
def cask?; end
sig { returns(T::Boolean) }
def casks?; end
sig { returns(T::Boolean) }
def declared?; end
sig { returns(T::Boolean) }
def direct?; end
sig { returns(T::Boolean) }
def dot?; end
sig { returns(T::Boolean) }
def eval_all?; end
sig { returns(T::Boolean) }
def for_each?; end
sig { returns(T::Boolean) }
def formula?; end
sig { returns(T::Boolean) }
def formulae?; end
sig { returns(T::Boolean) }
def full_name?; end
sig { returns(T::Boolean) }
def graph?; end
sig { returns(T::Boolean) }
def include_build?; end
sig { returns(T::Boolean) }
def include_optional?; end
sig { returns(T::Boolean) }
def include_requirements?; end
sig { returns(T::Boolean) }
def include_test?; end
sig { returns(T::Boolean) }
def installed?; end
sig { returns(T::Boolean) }
def missing?; end
sig { returns(T::Boolean) }
def n?; end
sig { returns(T::Boolean) }
def skip_recommended?; end
sig { returns(T::Boolean) }
def topological?; end
sig { returns(T::Boolean) }
def tree?; end
sig { returns(T::Boolean) }
def union?; end
end

View File

@ -0,0 +1,37 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Desc`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Desc`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def cask?; end
sig { returns(T::Boolean) }
def casks?; end
sig { returns(T::Boolean) }
def description?; end
sig { returns(T::Boolean) }
def eval_all?; end
sig { returns(T::Boolean) }
def formula?; end
sig { returns(T::Boolean) }
def formulae?; end
sig { returns(T::Boolean) }
def n?; end
sig { returns(T::Boolean) }
def name?; end
sig { returns(T::Boolean) }
def s?; end
sig { returns(T::Boolean) }
def search?; end
end

View File

@ -0,0 +1,7 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Developer`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Developer`.
class Homebrew::CLI::Args; end

View File

@ -0,0 +1,7 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Docs`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Docs`.
class Homebrew::CLI::Args; end

View File

@ -0,0 +1,16 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Doctor`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Doctor`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def D?; end
sig { returns(T::Boolean) }
def audit_debug?; end
sig { returns(T::Boolean) }
def list_checks?; end
end

View File

@ -0,0 +1,58 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::FetchCmd`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::FetchCmd`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def HEAD?; end
sig { returns(T.nilable(String)) }
def arch; end
sig { returns(T.nilable(String)) }
def bottle_tag; end
sig { returns(T::Boolean) }
def build_bottle?; end
sig { returns(T::Boolean) }
def build_from_source?; end
sig { returns(T::Boolean) }
def cask?; end
sig { returns(T::Boolean) }
def casks?; end
sig { returns(T::Boolean) }
def deps?; end
sig { returns(T::Boolean) }
def f?; end
sig { returns(T::Boolean) }
def force?; end
sig { returns(T::Boolean) }
def force_bottle?; end
sig { returns(T::Boolean) }
def formula?; end
sig { returns(T::Boolean) }
def formulae?; end
sig { returns(T.nilable(String)) }
def os; end
sig { returns(T::Boolean) }
def quarantine?; end
sig { returns(T::Boolean) }
def retry?; end
sig { returns(T::Boolean) }
def s?; end
end

View File

@ -0,0 +1,22 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::GistLogs`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::GistLogs`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def n?; end
sig { returns(T::Boolean) }
def new_issue?; end
sig { returns(T::Boolean) }
def p?; end
sig { returns(T::Boolean) }
def private?; end
sig { returns(T::Boolean) }
def with_hostname?; end
end

View File

@ -0,0 +1,7 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::HelpCmd`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::HelpCmd`.
class Homebrew::CLI::Args; end

View File

@ -0,0 +1,19 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Home`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Home`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def cask?; end
sig { returns(T::Boolean) }
def casks?; end
sig { returns(T::Boolean) }
def formula?; end
sig { returns(T::Boolean) }
def formulae?; end
end

View File

@ -0,0 +1,46 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Info`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Info`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def analytics?; end
sig { returns(T::Boolean) }
def cask?; end
sig { returns(T::Boolean) }
def casks?; end
sig { returns(T.nilable(String)) }
def category; end
sig { returns(T.nilable(String)) }
def days; end
sig { returns(T::Boolean) }
def eval_all?; end
sig { returns(T::Boolean) }
def formula?; end
sig { returns(T::Boolean) }
def formulae?; end
sig { returns(T::Boolean) }
def github?; end
sig { returns(T::Boolean) }
def github_packages_downloads?; end
sig { returns(T::Boolean) }
def installed?; end
sig { returns(T.nilable(String)) }
def json; end
sig { returns(T::Boolean) }
def variations?; end
end

View File

@ -0,0 +1,160 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::InstallCmd`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::InstallCmd`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def HEAD?; end
sig { returns(T::Boolean) }
def adopt?; end
sig { returns(T.nilable(String)) }
def appdir; end
sig { returns(T.nilable(String)) }
def audio_unit_plugindir; end
sig { returns(T::Boolean) }
def binaries?; end
sig { returns(T.nilable(String)) }
def bottle_arch; end
sig { returns(T::Boolean) }
def build_bottle?; end
sig { returns(T::Boolean) }
def build_from_source?; end
sig { returns(T::Boolean) }
def cask?; end
sig { returns(T::Boolean) }
def casks?; end
sig { returns(T.nilable(String)) }
def cc; end
sig { returns(T.nilable(String)) }
def colorpickerdir; end
sig { returns(T::Boolean) }
def debug_symbols?; end
sig { returns(T.nilable(String)) }
def dictionarydir; end
sig { returns(T::Boolean) }
def display_times?; end
sig { returns(T::Boolean) }
def dry_run?; end
sig { returns(T.nilable(String)) }
def env; end
sig { returns(T::Boolean) }
def f?; end
sig { returns(T::Boolean) }
def fetch_HEAD?; end
sig { returns(T.nilable(String)) }
def fontdir; end
sig { returns(T::Boolean) }
def force?; end
sig { returns(T::Boolean) }
def force_bottle?; end
sig { returns(T::Boolean) }
def formula?; end
sig { returns(T::Boolean) }
def formulae?; end
sig { returns(T::Boolean) }
def g?; end
sig { returns(T::Boolean) }
def git?; end
sig { returns(T::Boolean) }
def i?; end
sig { returns(T::Boolean) }
def ignore_dependencies?; end
sig { returns(T::Boolean) }
def include_test?; end
sig { returns(T.nilable(String)) }
def input_methoddir; end
sig { returns(T::Boolean) }
def interactive?; end
sig { returns(T.nilable(String)) }
def internet_plugindir; end
sig { returns(T::Boolean) }
def keep_tmp?; end
sig { returns(T.nilable(String)) }
def keyboard_layoutdir; end
sig { returns(T.nilable(T::Array[String])) }
def language; end
sig { returns(T.nilable(String)) }
def mdimporterdir; end
sig { returns(T::Boolean) }
def n?; end
sig { returns(T::Boolean) }
def only_dependencies?; end
sig { returns(T::Boolean) }
def overwrite?; end
sig { returns(T.nilable(String)) }
def prefpanedir; end
sig { returns(T.nilable(String)) }
def qlplugindir; end
sig { returns(T::Boolean) }
def quarantine?; end
sig { returns(T::Boolean) }
def require_sha?; end
sig { returns(T::Boolean) }
def s?; end
sig { returns(T.nilable(String)) }
def screen_saverdir; end
sig { returns(T.nilable(String)) }
def servicedir; end
sig { returns(T::Boolean) }
def skip_cask_deps?; end
sig { returns(T::Boolean) }
def skip_post_install?; end
sig { returns(T.nilable(String)) }
def vst3_plugindir; end
sig { returns(T.nilable(String)) }
def vst_plugindir; end
sig { returns(T::Boolean) }
def zap?; end
end

View File

@ -0,0 +1,19 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Leaves`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Leaves`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def installed_as_dependency?; end
sig { returns(T::Boolean) }
def installed_on_request?; end
sig { returns(T::Boolean) }
def p?; end
sig { returns(T::Boolean) }
def r?; end
end

View File

@ -0,0 +1,25 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::Link`.
# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::Link`.
class Homebrew::CLI::Args
sig { returns(T::Boolean) }
def HEAD?; end
sig { returns(T::Boolean) }
def dry_run?; end
sig { returns(T::Boolean) }
def f?; end
sig { returns(T::Boolean) }
def force?; end
sig { returns(T::Boolean) }
def n?; end
sig { returns(T::Boolean) }
def overwrite?; end
end

View File

@ -7,8 +7,6 @@ RSpec.describe Homebrew::API::Cask do
before do
stub_const("Homebrew::API::HOMEBREW_CACHE_API", cache_dir)
Homebrew::API.clear_cache
described_class.clear_cache
end
def mock_curl_download(stdout:)

View File

@ -7,7 +7,6 @@ RSpec.describe Homebrew::API::Formula do
before do
stub_const("Homebrew::API::HOMEBREW_CACHE_API", cache_dir)
described_class.clear_cache
end
def mock_curl_download(stdout:)

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true
RSpec.describe "Internal Tap JSON -- Formula" do
include FileUtils
let(:internal_tap_json) { File.read(TEST_FIXTURE_DIR/"internal_tap_json/homebrew-core.json").chomp }
let(:tap_git_head) { "9977471165641744a829d3e494fa563407503297" }
@ -42,12 +44,6 @@ RSpec.describe "Internal Tap JSON -- Formula" do
# To allow `formula_names.txt` to be written to the cache.
(HOMEBREW_CACHE/"api").mkdir
Homebrew::API::Formula.clear_cache
end
after do
Homebrew::API::Formula.clear_cache
end
it "loads tap aliases" do

View File

@ -8,10 +8,6 @@ RSpec.describe Homebrew::API do
let(:json_hash) { JSON.parse(json) }
let(:json_invalid) { '{"foo":"bar"' }
before do
described_class.clear_cache
end
def mock_curl_output(stdout: "", success: true)
curl_output = instance_double(SystemCommand::Result, stdout:, success?: success)
allow(Utils::Curl).to receive(:curl_output).and_return curl_output

View File

@ -171,12 +171,7 @@ RSpec.describe Cask::Artifact::App, :cask do
end
it "overwrites the existing app" do
expect(command).to receive(:run).with("/usr/bin/chflags",
args: ["-R", "--", "000", target_path]).and_call_original
expect(command).to receive(:run).with("/bin/chmod",
args: ["-R", "--", "u+rwx", target_path]).and_call_original
expect(command).to receive(:run).with("/bin/chmod",
args: ["-R", "-N", target_path]).and_call_original
expect(command).to receive(:run).and_call_original.at_least(:once)
stdout = <<~EOS
==> Removing App '#{target_path}'

View File

@ -4,6 +4,8 @@ require "cmd/deps"
require "cmd/shared_examples/args_parse"
RSpec.describe Homebrew::Cmd::Deps do
include FileUtils
it_behaves_like "parseable arguments"
it "outputs all of a Formula's dependencies and their dependencies on separate lines", :integration_test do

View File

@ -4,6 +4,15 @@ require "cmd/info"
require "cmd/shared_examples/args_parse"
RSpec.describe Homebrew::Cmd::Info do
RSpec::Matchers.define :a_json_string do
match do |actual|
JSON.parse(actual)
true
rescue JSON::ParserError
false
end
end
it_behaves_like "parseable arguments"
it "prints as json with the --json=v1 flag", :integration_test do

View File

@ -3,6 +3,8 @@
require "cmd/shared_examples/args_parse"
RSpec.describe "brew uses" do
include FileUtils
it_behaves_like "parseable arguments"
it "prints the Formulae a given Formula is used by", :integration_test do

View File

@ -6,6 +6,8 @@ require "tap"
require "cmd/shared_examples/args_parse"
RSpec.describe Homebrew::DevCmd::PrPull do
include FileUtils
let(:pr_pull) { described_class.new(["foo"]) }
let(:formula_rebuild) do
<<~EOS

View File

@ -3,6 +3,8 @@
require "formula_auditor"
RSpec.describe Homebrew::FormulaAuditor do
include FileUtils
let(:dir) { mktmpdir }
let(:foo_version) do
@count ||= 0
@ -655,7 +657,7 @@ RSpec.describe Homebrew::FormulaAuditor do
end
describe "#audit_specs" do
let(:throttle_list) { { throttled_formulae: { "foo" => 10 } } }
let(:livecheck_throttle) { "livecheck do\n throttle 10\n end" }
let(:versioned_head_spec_list) { { versioned_head_spec_allowlist: ["foo"] } }
it "doesn't allow to miss a checksum" do
@ -694,7 +696,7 @@ RSpec.describe Homebrew::FormulaAuditor do
end
it "allows versions with no throttle rate" do
fa = formula_auditor "bar", <<~RUBY, core_tap: true, tap_audit_exceptions: throttle_list
fa = formula_auditor "bar", <<~RUBY, core_tap: true
class Bar < Formula
url "https://brew.sh/foo-1.0.1.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
@ -706,10 +708,11 @@ RSpec.describe Homebrew::FormulaAuditor do
end
it "allows major/minor versions with throttle rate" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true, tap_audit_exceptions: throttle_list
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/foo-1.0.0.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
#{livecheck_throttle}
end
RUBY
@ -718,10 +721,11 @@ RSpec.describe Homebrew::FormulaAuditor do
end
it "allows patch versions to be multiples of the throttle rate" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true, tap_audit_exceptions: throttle_list
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/foo-1.0.10.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
#{livecheck_throttle}
end
RUBY
@ -730,10 +734,11 @@ RSpec.describe Homebrew::FormulaAuditor do
end
it "doesn't allow patch versions that aren't multiples of the throttle rate" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true, tap_audit_exceptions: throttle_list
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/foo-1.0.1.tgz"
sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e"
#{livecheck_throttle}
end
RUBY

View File

@ -81,8 +81,6 @@ RSpec.describe Formulary do
end
context "with sharded Formula directory" do
before { CoreTap.instance.clear_cache }
let(:formula_name) { "testball_sharded" }
let(:formula_path) do
core_tap = CoreTap.instance
@ -236,7 +234,6 @@ RSpec.describe Formulary do
before do
alias_dir.mkpath
FileUtils.ln_s formula_path, alias_path
tap.clear_cache
end
it "returns a Formula when given a name" do

View File

@ -4,6 +4,8 @@ require "keg"
require "stringio"
RSpec.describe Keg do
include FileUtils
def setup_test_keg(name, version)
path = HOMEBREW_CELLAR/name/version
(path/"bin").mkpath

View File

@ -15,17 +15,20 @@ RSpec.describe Language::Node do
expect(ENV).to receive(:prepend_path)
end
described_class.instance_variable_set(:@env_set, false)
expect(described_class.setup_npm_environment).to be_nil
described_class.setup_npm_environment
expect(described_class.instance_variable_get(:@env_set)).to be(true)
without_partial_double_verification do
expect(ENV).not_to receive(:prepend_path)
end
expect(described_class.setup_npm_environment).to be_nil
described_class.setup_npm_environment
end
it "does not call prepend_path when node formula does not exist" do
expect(described_class.setup_npm_environment).to be_nil
without_partial_double_verification do
expect(ENV).not_to receive(:prepend_path)
end
described_class.setup_npm_environment
end
end

View File

@ -31,11 +31,6 @@ RSpec.describe Homebrew::Livecheck::SkipConditions do
url "https://brew.sh/test-0.0.1.tgz"
disable! date: "2020-06-25", because: :unmaintained
end,
versioned: formula("test@0.0.1") do
desc "Versioned test formula"
homepage "https://brew.sh"
url "https://brew.sh/test-0.0.1.tgz"
end,
head_only: formula("test_head_only") do
desc "HEAD-only test formula"
homepage "https://brew.sh"
@ -74,6 +69,11 @@ RSpec.describe Homebrew::Livecheck::SkipConditions do
skip "Not maintained"
end
end,
versioned: formula("test@0.0.1") do
desc "Versioned test formula"
homepage "https://brew.sh"
url "https://brew.sh/test-0.0.1.tgz"
end,
}
end
@ -127,6 +127,18 @@ RSpec.describe Homebrew::Livecheck::SkipConditions do
disable! date: "2020-06-25", because: :discontinued
end,
extract_plist: Cask::Cask.new("test_extract_plist_skip") do
version "0.0.1"
url "https://brew.sh/test-0.0.1.tgz"
name "Test ExtractPlist Skip"
desc "Skipped test cask"
homepage "https://brew.sh"
livecheck do
strategy :extract_plist
end
end,
latest: Cask::Cask.new("test_latest") do
version :latest
sha256 :no_check
@ -267,6 +279,14 @@ RSpec.describe Homebrew::Livecheck::SkipConditions do
livecheckable: false,
},
},
extract_plist: {
cask: "test_extract_plist_skip",
status: "skipped",
messages: ["Use `--extract-plist` to enable checking multiple casks with ExtractPlist strategy"],
meta: {
livecheckable: true,
},
},
latest: {
cask: "test_latest",
status: "latest",
@ -381,6 +401,13 @@ RSpec.describe Homebrew::Livecheck::SkipConditions do
end
end
context "when a cask has a `livecheck` block using `ExtractPlist` and `--extract-plist` is not used" do
it "skips" do
expect(skip_conditions.skip_information(casks[:extract_plist], extract_plist: false))
.to eq(status_hashes[:cask][:extract_plist])
end
end
context "when a cask without a livecheckable has `version :latest`" do
it "skips" do
expect(skip_conditions.skip_information(casks[:latest]))
@ -497,6 +524,15 @@ RSpec.describe Homebrew::Livecheck::SkipConditions do
end
end
context "when a cask has a `livecheck` block using `ExtractPlist` and `--extract-plist` is not used" do
it "skips" do
expect do
skip_conditions.referenced_skip_information(casks[:extract_plist], original_name, extract_plist: false)
end
.to raise_error(RuntimeError, "Referenced cask (test_extract_plist_skip) is automatically skipped")
end
end
context "when a cask without a livecheckable has `version :latest`" do
it "errors" do
expect { skip_conditions.referenced_skip_information(casks[:latest], original_name) }

View File

@ -44,7 +44,6 @@ require "test/support/helper/files"
require "test/support/helper/fixtures"
require "test/support/helper/formula"
require "test/support/helper/mktmpdir"
require "test/support/helper/output_as_tty"
require "test/support/helper/spec/shared_context/homebrew_cask" if OS.mac?
require "test/support/helper/spec/shared_context/integration_test"
@ -129,17 +128,12 @@ RSpec.configure do |config|
# Never truncate output objects.
RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = nil
config.include(FileUtils)
config.include(Context)
config.include(RuboCop::RSpec::ExpectOffense)
config.include(Test::Helper::Cask)
config.include(Test::Helper::Fixtures)
config.include(Test::Helper::Formula)
config.include(Test::Helper::MkTmpDir)
config.include(Test::Helper::OutputAsTTY)
config.before(:each, :needs_linux) do
skip "Not running on Linux." unless OS.linux?
@ -310,16 +304,6 @@ end
RSpec::Matchers.define_negated_matcher :not_to_output, :output
RSpec::Matchers.alias_matcher :have_failed, :be_failed
RSpec::Matchers.alias_matcher :a_string_containing, :include
RSpec::Matchers.define :a_json_string do
match do |actual|
JSON.parse(actual)
true
rescue JSON::ParserError
false
end
end
# Match consecutive elements in an array.
RSpec::Matchers.define :array_including_cons do |*cons|

View File

@ -1,88 +0,0 @@
# frozen_string_literal: true
require "delegate"
module Test
module Helper
module OutputAsTTY
# This is a custom wrapper for the `output` matcher,
# used for testing output to a TTY:
#
# expect {
# print "test" if $stdout.tty?
# }.to output("test").to_stdout.as_tty
#
# expect {
# # command
# }.to output(...).to_stderr.as_tty.with_color
#
class Output < SimpleDelegator
def matches?(block)
return super(block) unless @tty
colored_tty_block = lambda do
instance_eval("$#{@output} # $stdout", __FILE__, __LINE__).extend(Module.new do
def tty?
true
end
alias_method :isatty, :tty?
end)
block.call
end
return super(colored_tty_block) if @colors
uncolored_tty_block = lambda do
instance_eval <<-EOS, __FILE__, __LINE__ + 1
begin # begin
captured_stream = StringIO.new # captured_stream = StringIO.new
original_stream = $#{@output} # original_stream = $stdout
$#{@output} = captured_stream # $stdout = captured_stream
colored_tty_block.call # colored_tty_block.call
ensure # ensure
$#{@output} = original_stream # $stdout = original_stream
$#{@output}.print Tty.strip_ansi(captured_stream.string) # $stdout.print Tty.strip_ansi(captured_stream.string)
end # end
EOS
end
super(uncolored_tty_block)
end
def to_stdout
@output = :stdout
super
self
end
def to_stderr
@output = :stderr
super
self
end
def as_tty
@tty = true
return self if [:stdout, :stderr].include?(@output)
raise "`as_tty` can only be chained to `stdout` or `stderr`."
end
def with_color
@colors = true
return self if @tty
raise "`with_color` can only be chained to `as_tty`."
end
end
def output(*args)
core_matcher = super(*args)
Output.new(core_matcher)
end
end
end
end

View File

@ -3,6 +3,8 @@
require "system_command"
RSpec.describe SystemCommand::Result do
RSpec::Matchers.alias_matcher :a_string_containing, :include
subject(:result) do
described_class.new([], output_array, instance_double(Process::Status, exitstatus: 0, success?: true),
secrets: [])

View File

@ -194,6 +194,8 @@ RSpec.describe SystemCommand do
end
context "when `debug?` is true" do
include Context
let(:options) do
{ args: [
"-c",

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true
RSpec.describe Tap do
include FileUtils
alias_matcher :have_formula_file, :be_formula_file
alias_matcher :have_custom_remote, :be_custom_remote

View File

@ -4,10 +4,6 @@ require "utils/analytics"
require "formula_installer"
RSpec.describe Utils::Analytics do
before do
described_class.clear_cache
end
describe "::default_package_tags" do
let(:ci) { ", CI" if ENV["CI"] }

View File

@ -3,6 +3,8 @@
require "utils/gzip"
RSpec.describe Utils::Gzip do
include FileUtils
describe "compress_with_options" do
it "uses the explicitly specified mtime, orig_name, and output path when passed" do
mktmpdir do |path|

View File

@ -147,8 +147,16 @@ module UnpackStrategy
verbose:
end
bomfile_path = T.must(bomfile.path)
# Ditto will try to write as the UID, not the EUID and the Tempfile has 0700 permissions.
if Process.euid != Process.uid
FileUtils.chown(nil, Process.gid, bomfile_path)
FileUtils.chmod "g+rw", bomfile_path
end
system_command!("ditto",
args: ["--bom", bomfile.path, "--", path, unpack_dir],
args: ["--bom", bomfile_path, "--", path, unpack_dir],
verbose:)
FileUtils.chmod "u+w", Pathname.glob(unpack_dir/"**/*", File::FNM_DOTMATCH).reject(&:symlink?)

View File

@ -16,6 +16,8 @@ module Utils
INFLUX_HOST = "https://eu-central-1-1.aws.cloud2.influxdata.com"
INFLUX_ORG = "d81a3e6d582d485f"
extend Cachable
class << self
include Context
@ -277,14 +279,9 @@ module Utils
nil
end
def clear_cache
remove_instance_variable(:@default_package_tags) if instance_variable_defined?(:@default_package_tags)
remove_instance_variable(:@default_package_fields) if instance_variable_defined?(:@default_package_fields)
end
sig { returns(T::Hash[Symbol, String]) }
def default_package_tags
@default_package_tags ||= begin
cache[:default_package_tags] ||= begin
# Only display default prefixes to reduce cardinality and improve privacy
prefix = Homebrew.default_prefix? ? HOMEBREW_PREFIX.to_s : "custom-prefix"
@ -305,7 +302,7 @@ module Utils
# remove macOS patch release
sig { returns(T::Hash[Symbol, String]) }
def default_package_fields
@default_package_fields ||= begin
cache[:default_package_fields] ||= begin
version = if (match_data = HOMEBREW_VERSION.match(/^[\d.]+/))
suffix = "-dev" if HOMEBREW_VERSION.include?("-")
match_data[0] + suffix.to_s