diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml
index 841ecfabee..dc51cd15ec 100644
--- a/.github/workflows/triage.yml
+++ b/.github/workflows/triage.yml
@@ -19,7 +19,7 @@ jobs:
steps:
- name: Re-run this workflow
if: github.event_name == 'schedule' || github.event.action == 'closed'
- uses: reitermarkus/rerun-workflow@cf91bee6964dfde64eccbf5600c3ea206af11359
+ uses: reitermarkus/rerun-workflow@e2647e8885422412d5acbd61f9add5b1e77ad3ab
with:
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
continuous-label: waiting for feedback
@@ -101,6 +101,30 @@ jobs:
}
}
+ function offsetDate(start, offsetHours, skippedDays) {
+ let end = new Date(start)
+
+ end.setUTCHours(end.getUTCHours() + (offsetHours % 24))
+
+ while (skippedDays.includes(end.getUTCDay()) || offsetHours >= 24) {
+ if (!skippedDays.includes(end.getUTCDay())) {
+ offsetHours -= 24
+ }
+
+ end.setUTCDate(end.getUTCDate() + 1)
+ }
+
+ if (skippedDays.includes(start.getUTCDay())) {
+ end.setUTCHours(offsetHours, 0, 0)
+ }
+
+ return end
+ }
+
+ function formatDate(date) {
+ return date.toISOString().replace(/\.\d+Z$/, ' UTC').replace('T', ' at ')
+ }
+
async function reviewPullRequest(pullRequestNumber) {
const { data: pullRequest } = await github.pulls.get({
owner: context.repo.owner,
@@ -108,6 +132,12 @@ jobs:
pull_number: pullRequestNumber,
})
+ const { data: user } = await github.users.getAuthenticated()
+ if (pullRequest.user.login == user) {
+ core.warning('Pull request author is a bot.')
+ return
+ }
+
if (pullRequest.author_association != 'MEMBER') {
core.warning('Pull request author is not a member.')
return
@@ -120,38 +150,21 @@ jobs:
const hasReviewLabel = labels.includes(reviewLabel)
const hasCriticalLabel = labels.includes(criticalLabel)
- const reviewStartDate = new Date(pullRequest.created_at)
- const reviewEndDate = new Date(reviewStartDate)
- switch (reviewStartDate.getDay()) {
- // Skip from Friday to Monday and from Saturday to Tuesday.
- case 5:
- case 6:
- reviewEndDate.setDate(reviewStartDate.getDate() + 3)
- break
- // Skip from Sunday to Tuesday.
- case 0:
- reviewEndDate.setDate(reviewStartDate.getDate() + 2)
- break
- default:
- reviewEndDate.setDate(reviewStartDate.getDate() + 1)
- break
- }
+ const offsetHours = 24
+ const skippedDays = [
+ 6, // Saturday
+ 0, // Sunday
+ ]
const currentDate = new Date()
+ const reviewStartDate = new Date(pullRequest.created_at)
+ const reviewEndDate = offsetDate(reviewStartDate, offsetHours, skippedDays)
const reviewEnded = currentDate > reviewEndDate
- function formatDate(date) {
- return date.toISOString().replace(/\.\d+Z$/, ' UTC').replace('T', ' at ')
- }
-
if (reviewEnded || hasCriticalLabel) {
let message
if (hasCriticalLabel && !reviewEnded) {
- if (hasReviewLabel) {
- message = `Review period cancelled due to \`${criticalLabel}\` label.`
- } else {
- message = `Review period skipped due to \`${criticalLabel}\` label.`
- }
+ message = `Review period skipped due to \`${criticalLabel}\` label.`
} else {
message = 'Review period ended.'
}
@@ -169,7 +182,7 @@ jobs:
await approvePullRequest(pullRequestNumber)
} else {
const message = `Review period will end on ${formatDate(reviewEndDate)}.`
- core.warning(message)
+ core.info(message)
await dismissApprovals(pullRequestNumber, 'Review period has not ended yet.')
await createOrUpdateComment(pullRequestNumber, 'review-period-begin', message)
diff --git a/Library/Homebrew/Gemfile.lock b/Library/Homebrew/Gemfile.lock
index 224c2cad66..f013bc21ef 100644
--- a/Library/Homebrew/Gemfile.lock
+++ b/Library/Homebrew/Gemfile.lock
@@ -54,8 +54,8 @@ GEM
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
ntlm-http (0.1.1)
- parallel (1.20.0)
- parallel_tests (3.3.0)
+ parallel (1.20.1)
+ parallel_tests (3.4.0)
parallel
parlour (4.0.1)
commander (~> 4.5)
@@ -126,11 +126,11 @@ GEM
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov-html (0.12.3)
- sorbet (0.5.6100)
- sorbet-static (= 0.5.6100)
- sorbet-runtime (0.5.6100)
+ sorbet (0.5.6101)
+ sorbet-static (= 0.5.6101)
+ sorbet-runtime (0.5.6101)
sorbet-runtime-stub (0.2.0)
- sorbet-static (0.5.6100-universal-darwin-14)
+ sorbet-static (0.5.6101-universal-darwin-14)
spoom (1.0.6)
colorize
sorbet (~> 0.5.5)
diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh
index 4e4a55c8a7..c9d64f1c04 100644
--- a/Library/Homebrew/brew.sh
+++ b/Library/Homebrew/brew.sh
@@ -160,7 +160,7 @@ update-preinstall() {
fi
if [[ "$HOMEBREW_COMMAND" = "install" || "$HOMEBREW_COMMAND" = "upgrade" ||
- "$HOMEBREW_COMMAND" = "bump-formula-pr" ||
+ "$HOMEBREW_COMMAND" = "bump-formula-pr" || "$HOMEBREW_COMMAND" = "bump-cask-pr" ||
"$HOMEBREW_COMMAND" = "bundle" ||
"$HOMEBREW_COMMAND" = "tap" && $HOMEBREW_ARG_COUNT -gt 1 ||
"$HOMEBREW_CASK_COMMAND" = "install" || "$HOMEBREW_CASK_COMMAND" = "upgrade" ]]
@@ -345,7 +345,7 @@ else
: "${HOMEBREW_OS_VERSION:=$(uname -r)}"
HOMEBREW_OS_USER_AGENT_VERSION="$HOMEBREW_OS_VERSION"
- if [[ -n $HOMEBREW_FORCE_HOMEBREW_ON_LINUX && -n $HOMEBREW_DEVELOPER && -n $HOMEBREW_ON_DEBIAN7 ]]
+ if [[ -n "$HOMEBREW_FORCE_HOMEBREW_ON_LINUX" && -n "$HOMEBREW_ON_DEBIAN7" ]]
then
# Special version for our debian 7 docker container used to build patchelf and binutils
HOMEBREW_MINIMUM_CURL_VERSION="7.25.0"
diff --git a/Library/Homebrew/build_options.rb b/Library/Homebrew/build_options.rb
index af06250a32..36ae1d613e 100644
--- a/Library/Homebrew/build_options.rb
+++ b/Library/Homebrew/build_options.rb
@@ -13,9 +13,8 @@ class BuildOptions
# TODO: rename private_include? when include? is removed.
# @deprecated
- def include?(name)
- odeprecated "BuildOptions#include?"
- private_include?("--#{name}")
+ def include?(_)
+ odisabled "BuildOptions#include?"
end
# True if a {Formula} is being built with a specific option.
@@ -65,11 +64,6 @@ class BuildOptions
private_include? "HEAD"
end
- # @private
- def devel?
- odisabled "BuildOptions#devel?"
- end
-
# True if a {Formula} is being built with {Formula.stable} instead of {Formula.head}.
# This is the default.
#
args << "--some-beta" if build.head?
@@ -81,14 +75,12 @@ class BuildOptions
# e.g. on newer Intel Macs this means a combined x86_64/x86 binary/library.
# args << "--universal-binary" if build.universal?
def universal?
- odeprecated "BuildOptions#universal?"
- private_include?("universal") && option_defined?("universal")
+ odisabled "BuildOptions#universal?"
end
# True if a {Formula} is being built in C++11 mode.
def cxx11?
- odeprecated "BuildOptions#cxx11?"
- private_include?("c++11") && option_defined?("c++11")
+ odisabled "BuildOptions#cxx11?"
end
# True if the build has any arguments or options specified.
diff --git a/Library/Homebrew/cli/args.rb b/Library/Homebrew/cli/args.rb
index c9bdd72ccf..2e878ceed8 100644
--- a/Library/Homebrew/cli/args.rb
+++ b/Library/Homebrew/cli/args.rb
@@ -63,48 +63,39 @@ module Homebrew
end
def formulae
- odeprecated "args.formulae", "args.named.to_formulae"
- named.to_formulae
+ odisabled "args.formulae", "args.named.to_formulae"
end
def formulae_and_casks
- odeprecated "args.formulae_and_casks", "args.named.to_formulae_and_casks"
- named.to_formulae_and_casks
+ odisabled "args.formulae_and_casks", "args.named.to_formulae_and_casks"
end
def resolved_formulae
- odeprecated "args.resolved_formulae", "args.named.to_resolved_formulae"
- named.to_resolved_formulae
+ odisabled "args.resolved_formulae", "args.named.to_resolved_formulae"
end
def resolved_formulae_casks
- odeprecated "args.resolved_formulae_casks", "args.named.to_resolved_formulae_to_casks"
- named.to_resolved_formulae_to_casks
+ odisabled "args.resolved_formulae_casks", "args.named.to_resolved_formulae_to_casks"
end
def formulae_paths
- odeprecated "args.formulae_paths", "args.named.to_formulae_paths"
- named.to_formulae_paths
+ odisabled "args.formulae_paths", "args.named.to_formulae_paths"
end
def casks
- odeprecated "args.casks", "args.named.homebrew_tap_cask_names"
- named.homebrew_tap_cask_names
+ odisabled "args.casks", "args.named.homebrew_tap_cask_names"
end
def loaded_casks
- odeprecated "args.loaded_casks", "args.named.to_cask"
- named.to_casks
+ odisabled "args.loaded_casks", "args.named.to_cask"
end
def kegs
- odeprecated "args.kegs", "args.named.to_kegs"
- named.to_kegs
+ odisabled "args.kegs", "args.named.to_kegs"
end
def kegs_casks
- odeprecated "args.kegs", "args.named.to_kegs_to_casks"
- named.to_kegs_to_casks
+ odisabled "args.kegs", "args.named.to_kegs_to_casks"
end
def build_stable?
diff --git a/Library/Homebrew/cmd/gist-logs.rb b/Library/Homebrew/cmd/gist-logs.rb
index d590fb3526..a42d2457f9 100644
--- a/Library/Homebrew/cmd/gist-logs.rb
+++ b/Library/Homebrew/cmd/gist-logs.rb
@@ -57,16 +57,7 @@ module Homebrew
files["00.tap.out"] = { content: tap }
end
- if GitHub.api_credentials_type == :none
- puts <<~EOS
- You can create a new personal access token:
- #{GitHub::ALL_SCOPES_URL}
- #{Utils::Shell.set_variable_in_profile("HOMEBREW_GITHUB_API_TOKEN", "your_token_here")}
-
- EOS
- odeprecated "`brew gist-logs` with a password", "HOMEBREW_GITHUB_API_TOKEN"
- login!
- end
+ odisabled "`brew gist-logs` with a password", "HOMEBREW_GITHUB_API_TOKEN" if GitHub.api_credentials_type == :none
# Description formatted to work well as page title when viewing gist
descr = if f.core_formula?
diff --git a/Library/Homebrew/cmd/list.rb b/Library/Homebrew/cmd/list.rb
index e7e5a97536..c67ed6e223 100644
--- a/Library/Homebrew/cmd/list.rb
+++ b/Library/Homebrew/cmd/list.rb
@@ -103,8 +103,7 @@ module Homebrew
ls_args << "-t" if args.t?
if !$stdout.tty? && !args.formula?
- odeprecated "`brew list` to only list formulae", "`brew list --formula`"
- safe_system "ls", *ls_args, HOMEBREW_CELLAR
+ odisabled "`brew list` to only list formulae", "`brew list --formula`"
else
safe_system "ls", *ls_args, HOMEBREW_CELLAR
list_casks(args: args) unless args.formula?
diff --git a/Library/Homebrew/cmd/outdated.rb b/Library/Homebrew/cmd/outdated.rb
index 6cb52621cb..ea40aad78f 100644
--- a/Library/Homebrew/cmd/outdated.rb
+++ b/Library/Homebrew/cmd/outdated.rb
@@ -50,16 +50,7 @@ module Homebrew
case (j = json_version(args.json))
when :v1, :default
- odeprecated "brew outdated --json#{j == :v1 ? "=v1" : ""}", "brew outdated --json=v2"
-
- outdated = if args.formula? || !args.cask?
- outdated_formulae args: args
- else
- outdated_casks args: args
- end
-
- puts JSON.generate(json_info(outdated, args: args))
-
+ odisabled "brew outdated --json#{j == :v1 ? "=v1" : ""}", "brew outdated --json=v2"
when :v2
formulae, casks = if args.formula?
[outdated_formulae(args: args), []]
diff --git a/Library/Homebrew/cmd/switch.rb b/Library/Homebrew/cmd/switch.rb
index a78ef0a907..3f3e4baaf3 100644
--- a/Library/Homebrew/cmd/switch.rb
+++ b/Library/Homebrew/cmd/switch.rb
@@ -32,7 +32,7 @@ module Homebrew
odie "#{name} not found in the Cellar." unless rack.directory?
- # odeprecated "`brew switch`", "`brew link` @-versioned formulae"
+ odeprecated "`brew switch`", "`brew link` @-versioned formulae"
versions = rack.subdirs
.map { |d| Keg.new(d).version }
diff --git a/Library/Homebrew/compat.rb b/Library/Homebrew/compat.rb
index c9ad444268..583726728f 100644
--- a/Library/Homebrew/compat.rb
+++ b/Library/Homebrew/compat.rb
@@ -1,12 +1,6 @@
# typed: strict
# frozen_string_literal: true
-require "compat/dependencies_helpers"
require "compat/cli/parser"
-require "compat/extend/nil"
-require "compat/extend/string"
require "compat/formula"
require "compat/global"
-require "compat/language/java"
-require "compat/language/python"
-require "compat/os/mac" if OS.mac?
diff --git a/Library/Homebrew/compat/dependencies_helpers.rb b/Library/Homebrew/compat/dependencies_helpers.rb
deleted file mode 100644
index 21122e4c35..0000000000
--- a/Library/Homebrew/compat/dependencies_helpers.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# typed: true
-# frozen_string_literal: true
-
-require "cli/args"
-
-module DependenciesHelpers
- module Compat
- def argv_includes_ignores(argv = nil)
- unless @printed_includes_ignores_warning
- odisabled "Homebrew.argv_includes_ignores", "Homebrew.args_includes_ignores"
- @printed_includes_ignores_warning = true
- end
- args_includes_ignores(argv ? Homebrew::CLI::Args.new : Homebrew.args)
- end
- end
-
- prepend Compat
-end
diff --git a/Library/Homebrew/compat/dependencies_helpers.rbi b/Library/Homebrew/compat/dependencies_helpers.rbi
deleted file mode 100644
index 3ea83b62b9..0000000000
--- a/Library/Homebrew/compat/dependencies_helpers.rbi
+++ /dev/null
@@ -1,9 +0,0 @@
-# typed: strict
-
-module DependenciesHelpers
- module Compat
- include Kernel
-
- def args_includes_ignores(args); end
- end
-end
diff --git a/Library/Homebrew/compat/extend/nil.rb b/Library/Homebrew/compat/extend/nil.rb
deleted file mode 100644
index 5e521a4367..0000000000
--- a/Library/Homebrew/compat/extend/nil.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# typed: true
-# frozen_string_literal: true
-
-class NilClass
- module Compat
- def chuzzle
- odisabled ".chuzzle", "&.chomp.presence"
- end
- end
-
- prepend Compat
-end
diff --git a/Library/Homebrew/compat/extend/nil.rbi b/Library/Homebrew/compat/extend/nil.rbi
deleted file mode 100644
index 0a0adb9756..0000000000
--- a/Library/Homebrew/compat/extend/nil.rbi
+++ /dev/null
@@ -1,7 +0,0 @@
-# typed: strict
-
-class NilClass
- module Compat
- include Kernel
- end
-end
diff --git a/Library/Homebrew/compat/extend/string.rb b/Library/Homebrew/compat/extend/string.rb
deleted file mode 100644
index bdbed56112..0000000000
--- a/Library/Homebrew/compat/extend/string.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# typed: true
-# frozen_string_literal: true
-
-class String
- module Compat
- def chuzzle
- odisabled ".chuzzle", "&.chomp.presence"
- end
- end
-
- prepend Compat
-end
diff --git a/Library/Homebrew/compat/extend/string.rbi b/Library/Homebrew/compat/extend/string.rbi
deleted file mode 100644
index 4851c5b127..0000000000
--- a/Library/Homebrew/compat/extend/string.rbi
+++ /dev/null
@@ -1,7 +0,0 @@
-# typed: strict
-
-class String
- module Compat
- include Kernel
- end
-end
diff --git a/Library/Homebrew/compat/formula.rb b/Library/Homebrew/compat/formula.rb
index 0f08e86d9f..fd5f98f979 100644
--- a/Library/Homebrew/compat/formula.rb
+++ b/Library/Homebrew/compat/formula.rb
@@ -3,33 +3,20 @@
class Formula
module Compat
- def installed?
- odisabled "Formula#installed?",
- "Formula#latest_version_installed? (or Formula#any_version_installed? )"
- end
-
- def prepare_patches
- odisabled "patches", "patch do" if respond_to?(:patches)
- super
- end
-
def installed_prefix
- odeprecated "Formula#installed_prefix",
- "Formula#latest_installed_prefix (or Formula#any_installed_prefix)"
- latest_installed_prefix
+ odisabled "Formula#installed_prefix",
+ "Formula#latest_installed_prefix (or Formula#any_installed_prefix)"
end
# The currently installed version for this formula. Will raise an exception
# if the formula is not installed.
# @private
def installed_version
- odeprecated "Formula#installed_version"
- Keg.new(latest_installed_prefix).version
+ odisabled "Formula#installed_version"
end
def opt_or_installed_prefix_keg
- odeprecated "Formula#opt_or_installed_prefix_keg", "Formula#any_installed_keg"
- any_installed_keg
+ odisabled "Formula#opt_or_installed_prefix_keg", "Formula#any_installed_keg"
end
end
diff --git a/Library/Homebrew/compat/global.rb b/Library/Homebrew/compat/global.rb
index 3ab5383e60..e229b7cc6e 100644
--- a/Library/Homebrew/compat/global.rb
+++ b/Library/Homebrew/compat/global.rb
@@ -7,8 +7,7 @@ module Homebrew
def args
unless @printed_args_warning
- odeprecated "Homebrew.args", "`args = _args.parse` and pass `args` along the call chain"
- @printed_args_warning = true
+ odisabled "Homebrew.args", "`args = _args.parse` and pass `args` along the call chain"
end
@args ||= CLI::Args.new
diff --git a/Library/Homebrew/compat/language/haskell.rb b/Library/Homebrew/compat/language/haskell.rb
index 3619e88c02..00f6466807 100644
--- a/Library/Homebrew/compat/language/haskell.rb
+++ b/Library/Homebrew/compat/language/haskell.rb
@@ -4,35 +4,9 @@
module Language
module Haskell
module Cabal
- module Compat
- def cabal_sandbox(_options = {})
- odisabled "Language::Haskell::Cabal.cabal_sandbox"
- end
-
- def cabal_sandbox_add_source(*_args)
- odisabled "Language::Haskell::Cabal.cabal_sandbox_add_source"
- end
-
- def cabal_install(*_args)
- odisabled "Language::Haskell::Cabal.cabal_install",
- "cabal v2-install directly with std_cabal_v2_args"
- end
-
- def cabal_configure(_flags)
- odisabled "Language::Haskell::Cabal.cabal_configure"
- end
-
- def cabal_install_tools(*_tools)
- odisabled "Language::Haskell::Cabal.cabal_install_tools"
- end
-
- def install_cabal_package(*_args, **_options)
- odisabled "Language::Haskell::Cabal.install_cabal_package",
- "cabal v2-update directly followed by v2-install with std_cabal_v2_args"
- end
+ def self.included(_)
+ odisabled "include Language::Haskell::Cabal"
end
-
- prepend Compat
end
end
end
diff --git a/Library/Homebrew/compat/language/java.rb b/Library/Homebrew/compat/language/java.rb
deleted file mode 100644
index 4a23f7a6c2..0000000000
--- a/Library/Homebrew/compat/language/java.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# typed: false
-# frozen_string_literal: true
-
-module Language
- module Java
- class << self
- module Compat
- def java_home_cmd(_version = nil)
- odisabled "Language::Java.java_home_cmd",
- "Language::Java.java_home or Language::Java.overridable_java_home_env"
- end
- end
-
- prepend Compat
- end
- end
-end
diff --git a/Library/Homebrew/compat/language/python.rb b/Library/Homebrew/compat/language/python.rb
deleted file mode 100644
index abb4673f6b..0000000000
--- a/Library/Homebrew/compat/language/python.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# typed: false
-# frozen_string_literal: true
-
-module Language
- module Python
- class << self
- module Compat
- def rewrite_python_shebang(_python_path)
- odisabled "Language::Python.rewrite_python_shebang",
- "Utils::Shebang.rewrite_shebang and Shebang.python_shebang_rewrite_info(python_path)"
- end
- end
-
- prepend Compat
- end
- end
-end
diff --git a/Library/Homebrew/compat/os/mac.rb b/Library/Homebrew/compat/os/mac.rb
deleted file mode 100644
index ab64aeac96..0000000000
--- a/Library/Homebrew/compat/os/mac.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# typed: true
-# frozen_string_literal: true
-
-module OS
- module Mac
- class << self
- module Compat
- def preferred_arch
- odisabled "MacOS.preferred_arch", "Hardware::CPU.arch (or ideally let the compiler handle it)"
- end
-
- def tcc_db
- odisabled "MacOS.tcc_db"
- end
-
- def pre_mavericks_accessibility_dotfile
- odisabled "MacOS.pre_mavericks_accessibility_dotfile"
- end
- end
-
- prepend Compat
- end
- end
-end
diff --git a/Library/Homebrew/compat/os/mac.rbi b/Library/Homebrew/compat/os/mac.rbi
deleted file mode 100644
index b6156fa2e8..0000000000
--- a/Library/Homebrew/compat/os/mac.rbi
+++ /dev/null
@@ -1,11 +0,0 @@
-# typed: strict
-
-module OS
- module Mac
- class << self
- module Compat
- include Kernel
- end
- end
- end
-end
diff --git a/Library/Homebrew/context.rb b/Library/Homebrew/context.rb
index 60c354af1e..7655c8eaa7 100644
--- a/Library/Homebrew/context.rb
+++ b/Library/Homebrew/context.rb
@@ -34,15 +34,15 @@ module Context
end
def debug?
- @debug
+ @debug == true
end
def quiet?
- @quiet
+ @quiet == true
end
def verbose?
- @verbose
+ @verbose == true
end
end
diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb
index c7082b7f42..8072739efe 100644
--- a/Library/Homebrew/dev-cmd/audit.rb
+++ b/Library/Homebrew/dev-cmd/audit.rb
@@ -180,7 +180,7 @@ module Homebrew
except: args.except,
spdx_license_data: spdx_license_data,
spdx_exception_data: spdx_exception_data,
- tap_audit_exceptions: f.tap.audit_exceptions,
+ tap_audit_exceptions: f.tap&.audit_exceptions,
style_offenses: style_offenses ? style_offenses.for_path(f.path) : nil,
display_cop_names: args.display_cop_names?,
build_stable: args.build_stable?,
diff --git a/Library/Homebrew/dev-cmd/bump-cask-pr.rb b/Library/Homebrew/dev-cmd/bump-cask-pr.rb
index f34f0c762b..1a70fed47f 100644
--- a/Library/Homebrew/dev-cmd/bump-cask-pr.rb
+++ b/Library/Homebrew/dev-cmd/bump-cask-pr.rb
@@ -74,7 +74,7 @@ module Homebrew
new_hash = args.sha256
old_version = cask.version
- old_hash = cask.sha256
+ old_hash = cask.sha256.to_s
tap_full_name = cask.tap&.full_name
origin_branch = Utils::Git.origin_branch(cask.tap.path) if cask.tap
@@ -159,7 +159,7 @@ module Homebrew
lang_cask = Cask::CaskLoader.load(tmp_contents)
lang_cask.config = lang_config
lang_url = lang_cask.url.to_s
- lang_old_hash = lang_cask.sha256
+ lang_old_hash = lang_cask.sha256.to_s
resource_path = fetch_resource(cask, new_version, lang_url)
Utils::Tar.validate_file(resource_path)
diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb
index 4e648874f2..dffc4dcdf3 100644
--- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb
+++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb
@@ -336,7 +336,7 @@ module Homebrew
end
unless args.dry_run?
- resources_checked = PyPI.update_python_resources! formula, new_formula_version,
+ resources_checked = PyPI.update_python_resources! formula, version: new_formula_version,
silent: args.quiet?, ignore_non_pypi_packages: true
end
diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb
index ea4b8a38a1..3575710c4d 100644
--- a/Library/Homebrew/dev-cmd/create.rb
+++ b/Library/Homebrew/dev-cmd/create.rb
@@ -6,6 +6,7 @@ require "formula_creator"
require "missing_formula"
require "cli/parser"
require "utils/pypi"
+require "cask/cask_loader"
module Homebrew
extend T::Sig
@@ -18,14 +19,16 @@ module Homebrew
usage_banner <<~EOS
`create` []
- Generate a formula for the downloadable file at and open it in the editor.
- Homebrew will attempt to automatically derive the formula name and version, but
- if it fails, you'll have to make your own template. The `wget` formula serves as
- a simple example. For the complete API, see:
+ Generate a formula or, with `--cask`, a cask for the downloadable file at
+ and open it in the editor. Homebrew will attempt to automatically derive the
+ formula name and version, but if it fails, you'll have to make your own template.
+ The `wget` formula serves as a simple example. For the complete API, see:
EOS
switch "--autotools",
description: "Create a basic template for an Autotools-style build."
+ switch "--cask",
+ description: "Create a basic template for a cask."
switch "--cmake",
description: "Create a basic template for a CMake-style build."
switch "--crystal",
@@ -51,9 +54,10 @@ module Homebrew
switch "--HEAD",
description: "Indicate that points to the package's repository rather than a file."
flag "--set-name=",
- description: "Explicitly set the of the new formula."
+ description: "Explicitly set the of the new formula or cask.",
+ required_for: "--cask"
flag "--set-version=",
- description: "Explicitly set the of the new formula."
+ description: "Explicitly set the of the new formula or cask."
flag "--set-license=",
description: "Explicitly set the of the new formula."
flag "--tap=",
@@ -61,7 +65,12 @@ module Homebrew
switch "-f", "--force",
description: "Ignore errors for disallowed formula names and names that shadow aliases."
- conflicts "--autotools", "--cmake", "--crystal", "--go", "--meson", "--node", "--perl", "--python", "--rust"
+ conflicts "--autotools", "--cmake", "--crystal", "--go", "--meson", "--node",
+ "--perl", "--python", "--ruby", "--rust", "--cask"
+ conflicts "--cask", "--HEAD"
+ conflicts "--cask", "--set-license"
+ conflicts "--cask", "--tap"
+
named 1
end
end
@@ -70,24 +79,73 @@ module Homebrew
def create
args = create_args.parse
- # Ensure that the cache exists so we can fetch the tarball
- HOMEBREW_CACHE.mkpath
+ path = if args.cask?
+ create_cask(args: args)
+ else
+ create_formula(args: args)
+ end
- url = args.named.first # Pull the first (and only) url from ARGV
+ exec_editor path
+ end
- version = args.set_version
- name = args.set_name
- license = args.set_license
- tap = args.tap
+ def create_cask(args:)
+ url = args.named.first
+ if (token = args.set_name).nil?
+ raise UsageError, "The `--set-name` flag is required for creating casks."
+ end
+
+ cask_path = Cask::CaskLoader.path(token)
+ raise Cask::CaskAlreadyCreatedError, token if cask_path.exist?
+
+ version = if args.set_version
+ Version.create(args.set_version)
+ else
+ Version.detect(url.gsub(token, ""))
+ end
+
+ interpolated_url, sha256 = if version.null?
+ [url, ""]
+ else
+ sha256 = if args.no_fetch?
+ ""
+ else
+ strategy = DownloadStrategyDetector.detect(url)
+ downloader = strategy.new(url, token, version.to_s, cache: Cask::Cache.path)
+ downloader.fetch
+ downloader.cached_location.sha256
+ end
+
+ [url.gsub(version.to_s, "\#{version}"), sha256]
+ end
+
+ cask_path.atomic_write <<~RUBY
+ cask "#{token}" do
+ version "#{version}"
+ sha256 "#{sha256}"
+
+ url "#{interpolated_url}"
+ name ""
+ desc ""
+ homepage ""
+
+ app ""
+ end
+ RUBY
+
+ puts "Please run `brew audit --cask --new #{token}` before submitting, thanks."
+ cask_path
+ end
+
+ def create_formula(args:)
fc = FormulaCreator.new(args)
- fc.name = name
- fc.version = version
- fc.license = license
- fc.tap = Tap.fetch(tap || "homebrew/core")
+ fc.name = args.name
+ fc.version = args.version
+ fc.license = args.license
+ fc.tap = Tap.fetch(args.tap || "homebrew/core")
raise TapUnavailableError, tap unless fc.tap.installed?
- fc.url = url
+ fc.url = args.named.first # Pull the first (and only) url from ARGV
fc.mode = if args.cmake?
:cmake
@@ -143,8 +201,8 @@ module Homebrew
PyPI.update_python_resources! Formula[fc.name], ignore_non_pypi_packages: true if args.python?
- puts "Please run `brew audit --new-formula #{fc.name}` before submitting, thanks."
- exec_editor fc.path
+ puts "Please run `brew audit --new #{fc.name}` before submitting, thanks."
+ fc.path
end
def __gets
diff --git a/Library/Homebrew/dev-cmd/diy.rb b/Library/Homebrew/dev-cmd/diy.rb
index 55696b2352..aba0a000ff 100644
--- a/Library/Homebrew/dev-cmd/diy.rb
+++ b/Library/Homebrew/dev-cmd/diy.rb
@@ -25,13 +25,14 @@ module Homebrew
description: "Explicitly set the of the package being installed."
max_named 0
+ hide_from_man_page!
end
end
def diy
args = diy_args.parse
- # odeprecated "`brew diy`"
+ odeprecated "`brew diy`"
path = Pathname.getwd
diff --git a/Library/Homebrew/dev-cmd/mirror.rb b/Library/Homebrew/dev-cmd/mirror.rb
index a6c2b45b1a..29c238f6a9 100644
--- a/Library/Homebrew/dev-cmd/mirror.rb
+++ b/Library/Homebrew/dev-cmd/mirror.rb
@@ -25,7 +25,6 @@ module Homebrew
description: "Upload to Bintray, but don't publish."
min_named :formula
- hide_from_man_page!
end
end
diff --git a/Library/Homebrew/dev-cmd/pr-pull.rb b/Library/Homebrew/dev-cmd/pr-pull.rb
index 010d3e6acc..7e059fc478 100644
--- a/Library/Homebrew/dev-cmd/pr-pull.rb
+++ b/Library/Homebrew/dev-cmd/pr-pull.rb
@@ -50,7 +50,8 @@ module Homebrew
depends_on: "--autosquash",
description: "Message to include when autosquashing revision bumps, deletions, and rebuilds."
flag "--workflow=",
- description: "Retrieve artifacts from the specified workflow (default: `tests.yml`)."
+ description: "Retrieve artifacts from the specified workflow (default: `tests.yml`). "\
+ "Legacy: use --workflows instead"
flag "--artifact=",
description: "Download artifacts with the specified name (default: `bottles`)."
flag "--bintray-org=",
@@ -62,6 +63,11 @@ module Homebrew
flag "--bintray-mirror=",
description: "Use the specified Bintray repository to automatically mirror stable URLs "\
"defined in the formulae (default: `mirror`)."
+ comma_array "--workflows=",
+ description: "Retrieve artifacts from the specified workflow (default: `tests.yml`) "\
+ "Comma-separated list to include multiple workflows."
+ comma_array "--ignore-missing-artifacts=",
+ description: "Comma-separated list of workflows which can be ignored if they have not been run."
conflicts "--clean", "--autosquash"
min_named 1
@@ -357,7 +363,13 @@ module Homebrew
def pr_pull
args = pr_pull_args.parse
- workflow = args.workflow || "tests.yml"
+ odeprecated "`brew pr-pull --workflow`", "`brew pr-pull --workflows=`" if args.workflow.presence
+
+ workflows = if args.workflow.blank?
+ args.workflows.presence || ["tests.yml"]
+ else
+ [args.workflow].compact.presence || ["tests.yml"]
+ end
artifact = args.artifact || "bottles"
bintray_org = args.bintray_org || "homebrew"
mirror_repo = args.bintray_mirror || "mirror"
@@ -401,8 +413,22 @@ module Homebrew
next
end
- url = GitHub.get_artifact_url(user, repo, pr, workflow_id: workflow, artifact_name: artifact)
- download_artifact(url, dir, pr)
+ workflows.each do |workflow|
+ workflow_run = GitHub.get_workflow_run(
+ user, repo, pr, workflow_id: workflow, artifact_name: artifact
+ )
+ if args.ignore_missing_artifacts.present? &&
+ args.ignore_missing_artifacts.include?(workflow) &&
+ workflow_run.empty?
+ # Ignore that workflow as it was not executed and we specified
+ # that we could skip it.
+ next
+ end
+
+ ohai "Downloading bottles for workflow: #{workflow}"
+ url = GitHub.get_artifact_url(workflow_run)
+ download_artifact(url, dir, pr)
+ end
next if args.no_upload?
diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb
deleted file mode 100644
index ce6f69c358..0000000000
--- a/Library/Homebrew/dev-cmd/pull.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# typed: false
-# frozen_string_literal: true
-
-require "net/http"
-require "net/https"
-require "json"
-require "cli/parser"
-require "formula"
-require "formulary"
-require "version"
-require "pkg_version"
-require "formula_info"
-
-module Homebrew
- extend T::Sig
-
- module_function
-
- sig { returns(CLI::Parser) }
- def pull_args
- Homebrew::CLI::Parser.new do
- usage_banner <<~EOS
- `pull` []
-
- Get a patch from a GitHub commit or pull request and apply it to Homebrew.
-
- Each may be the number of a pull request in `homebrew/core`
- or the URL of any pull request or commit on GitHub.
- EOS
- switch "--bump",
- description: "For one-formula PRs, automatically reword commit message to our preferred format."
- switch "--clean",
- description: "Do not rewrite or otherwise modify the commits found in the pulled PR."
- switch "--ignore-whitespace",
- description: "Silently ignore whitespace discrepancies when applying diffs."
- switch "--resolve",
- description: "When a patch fails to apply, leave in progress and allow user to resolve, instead "\
- "of aborting."
- switch "--branch-okay",
- description: "Do not warn if pulling to a branch besides master (useful for testing)."
- switch "--no-pbcopy",
- description: "Do not copy anything to the system clipboard."
-
- min_named 1
- hide_from_man_page!
- end
- end
-
- def pull
- odisabled "brew pull", "gh pr checkout"
- end
-end
diff --git a/Library/Homebrew/dev-cmd/sh.rb b/Library/Homebrew/dev-cmd/sh.rb
index 3c56c13dd0..b97e2a5a48 100644
--- a/Library/Homebrew/dev-cmd/sh.rb
+++ b/Library/Homebrew/dev-cmd/sh.rb
@@ -54,7 +54,9 @@ module Homebrew
safe_system(ENV["SHELL"], args.named.first)
else
subshell = if ENV["SHELL"].include?("zsh")
- "PS1='brew %B%F{green}%~%f%b$ ' #{ENV["SHELL"]} -d"
+ "PS1='brew %B%F{green}%~%f%b$ ' #{ENV["SHELL"]} -d -f"
+ elsif ENV["SHELL"].include?("bash")
+ "PS1=\"brew \\[\\033[1;32m\\]\\w\\[\\033[0m\\]$ \" #{ENV["SHELL"]} --noprofile --norc"
else
"PS1=\"brew \\[\\033[1;32m\\]\\w\\[\\033[0m\\]$ \" #{ENV["SHELL"]}"
end
diff --git a/Library/Homebrew/dev-cmd/update-python-resources.rb b/Library/Homebrew/dev-cmd/update-python-resources.rb
index ee3cd4be19..936dad5aba 100644
--- a/Library/Homebrew/dev-cmd/update-python-resources.rb
+++ b/Library/Homebrew/dev-cmd/update-python-resources.rb
@@ -26,6 +26,13 @@ module Homebrew
flag "--version=",
description: "Use the specified when finding resources for . "\
"If no version is specified, the current version for will be used."
+ flag "--package-name=",
+ description: "Use the specified when finding resources for . "\
+ "If no package name is specified, it will be inferred from the formula's stable URL."
+ comma_array "--extra-packages=",
+ description: "Include these additional packages when finding resources."
+ comma_array "--exclude-packages=",
+ description: "Exclude these packages when finding resources."
min_named :formula
end
@@ -35,7 +42,13 @@ module Homebrew
args = update_python_resources_args.parse
args.named.to_formulae.each do |formula|
- PyPI.update_python_resources! formula, args.version, print_only: args.print_only?, silent: args.silent?,
+ PyPI.update_python_resources! formula,
+ version: args.version,
+ package_name: args.package_name,
+ extra_packages: args.extra_packages,
+ exclude_packages: args.exclude_packages,
+ print_only: args.print_only?,
+ silent: args.silent?,
ignore_non_pypi_packages: args.ignore_non_pypi_packages?
end
end
diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb
index 713c460222..e6675f14f0 100644
--- a/Library/Homebrew/env_config.rb
+++ b/Library/Homebrew/env_config.rb
@@ -351,6 +351,7 @@ module Homebrew
end
# Needs a custom implementation.
+ sig { returns(String) }
def make_jobs
jobs = ENV["HOMEBREW_MAKE_JOBS"].to_i
return jobs.to_s if jobs.positive?
diff --git a/Library/Homebrew/extend/ENV.rb b/Library/Homebrew/extend/ENV.rb
index 17a6fd1227..d83beea7dc 100644
--- a/Library/Homebrew/extend/ENV.rb
+++ b/Library/Homebrew/extend/ENV.rb
@@ -1,4 +1,4 @@
-# typed: false
+# typed: strict
# frozen_string_literal: true
require "hardware"
@@ -7,11 +7,22 @@ require "extend/ENV/shared"
require "extend/ENV/std"
require "extend/ENV/super"
-def superenv?(env)
- env != "std" && Superenv.bin
+module Kernel
+ extend T::Sig
+
+ sig { params(env: T.nilable(String)).returns(T::Boolean) }
+ def superenv?(env)
+ return false if env == "std"
+
+ !Superenv.bin.nil?
+ end
+ private :superenv?
end
module EnvActivation
+ extend T::Sig
+
+ sig { params(env: T.nilable(String)).void }
def activate_extensions!(env: nil)
if superenv?(env)
extend(Superenv)
@@ -20,25 +31,41 @@ module EnvActivation
end
end
- def with_build_environment(env: nil, cc: nil, build_bottle: false, bottle_arch: nil)
+ sig do
+ params(
+ env: T.nilable(String),
+ cc: T.nilable(String),
+ build_bottle: T.nilable(T::Boolean),
+ bottle_arch: T.nilable(String),
+ _block: T.proc.returns(T.untyped),
+ ).returns(T.untyped)
+ end
+ def with_build_environment(env: nil, cc: nil, build_bottle: false, bottle_arch: nil, &_block)
old_env = to_hash.dup
tmp_env = to_hash.dup.extend(EnvActivation)
- tmp_env.activate_extensions!(env: env)
- tmp_env.setup_build_environment(cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch)
+ T.cast(tmp_env, EnvActivation).activate_extensions!(env: env)
+ T.cast(tmp_env, T.any(Superenv, Stdenv))
+ .setup_build_environment(cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch)
replace(tmp_env)
- yield
- ensure
- replace(old_env)
+
+ begin
+ yield
+ ensure
+ replace(old_env)
+ end
end
+ sig { params(key: T.any(String, Symbol)).returns(T::Boolean) }
def sensitive?(key)
- /(cookie|key|token|password)/i =~ key
+ key.match?(/(cookie|key|token|password)/i)
end
+ sig { returns(T::Hash[String, String]) }
def sensitive_environment
select { |key, _| sensitive?(key) }
end
+ sig { void }
def clear_sensitive_environment!
each_key { |key| delete key if sensitive?(key) }
end
diff --git a/Library/Homebrew/extend/ENV.rbi b/Library/Homebrew/extend/ENV.rbi
new file mode 100644
index 0000000000..edee664dba
--- /dev/null
+++ b/Library/Homebrew/extend/ENV.rbi
@@ -0,0 +1,49 @@
+# typed: strict
+
+module EnvMethods
+ include Kernel
+
+ sig { params(key: String).returns(T::Boolean) }
+ def key?(key); end
+
+ sig { params(key: String).returns(T.nilable(String)) }
+ def [](key); end
+
+ sig { params(key: String).returns(String) }
+ def fetch(key); end
+
+ sig { params(key: String, value: T.nilable(T.any(String, PATH))).returns(T.nilable(String)) }
+ def []=(key, value); end
+
+ sig { params(block: T.proc.params(arg0: [String, String]).returns(T::Boolean)).returns(T::Hash[String, String]) }
+ def select(&block); end
+
+ sig { params(block: T.proc.params(arg0: String).void).void }
+ def each_key(&block); end
+
+ sig { params(key: String).returns(T.nilable(String)) }
+ def delete(key); end
+
+ sig do
+ params(other: T.any(T::Hash[String, String], Sorbet::Private::Static::ENVClass))
+ .returns(Sorbet::Private::Static::ENVClass)
+ end
+ def replace(other); end
+
+ sig { returns(T::Hash[String, String]) }
+ def to_hash; end
+end
+
+module EnvActivation
+ include EnvMethods
+end
+
+class Sorbet
+ module Private
+ module Static
+ class ENVClass
+ include EnvActivation
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb
index ae49480479..eac0a305d4 100644
--- a/Library/Homebrew/extend/ENV/shared.rb
+++ b/Library/Homebrew/extend/ENV/shared.rb
@@ -1,4 +1,4 @@
-# typed: false
+# typed: true
# frozen_string_literal: true
require "compilers"
@@ -11,13 +11,16 @@ require "development_tools"
# @see Stdenv
# @see https://www.rubydoc.info/stdlib/Env Ruby's ENV API
module SharedEnvExtension
+ extend T::Sig
+
include CompilerConstants
- # @private
CC_FLAG_VARS = %w[CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS].freeze
- # @private
+ private_constant :CC_FLAG_VARS
+
FC_FLAG_VARS = %w[FCFLAGS FFLAGS].freeze
- # @private
+ private_constant :FC_FLAG_VARS
+
SANITIZED_VARS = %w[
CDPATH CLICOLOR_FORCE
CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH OBJC_INCLUDE_PATH
@@ -28,8 +31,16 @@ module SharedEnvExtension
GOBIN GOPATH GOROOT PERL_MB_OPT PERL_MM_OPT
LIBRARY_PATH LD_LIBRARY_PATH LD_PRELOAD LD_RUN_PATH
].freeze
+ private_constant :SANITIZED_VARS
- # @private
+ sig do
+ params(
+ formula: T.nilable(Formula),
+ cc: T.nilable(String),
+ build_bottle: T.nilable(T::Boolean),
+ bottle_arch: T.nilable(T::Boolean),
+ ).void
+ end
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil)
@formula = formula
@cc = cc
@@ -37,57 +48,62 @@ module SharedEnvExtension
@bottle_arch = bottle_arch
reset
end
+ private :setup_build_environment
- # @private
+ sig { void }
def reset
SANITIZED_VARS.each { |k| delete(k) }
end
+ private :reset
+ sig { returns(T::Hash[String, String]) }
def remove_cc_etc
keys = %w[CC CXX OBJC OBJCXX LD CPP CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS]
- removed = Hash[*keys.flat_map { |key| [key, self[key]] }]
- keys.each do |key|
- delete(key)
- end
- removed
+ keys.map { |key| [key, delete(key)] }.to_h
end
+ sig { params(newflags: String).void }
def append_to_cflags(newflags)
append(CC_FLAG_VARS, newflags)
end
+ sig { params(val: T.any(Regexp, String)).void }
def remove_from_cflags(val)
remove CC_FLAG_VARS, val
end
+ sig { params(value: String).void }
def append_to_cccfg(value)
append("HOMEBREW_CCCFG", value, "")
end
+ sig { params(keys: T.any(String, T::Array[String]), value: T.untyped, separator: String).void }
def append(keys, value, separator = " ")
value = value.to_s
Array(keys).each do |key|
- old = self[key]
- if old.nil? || old.empty?
- self[key] = value
+ old_value = self[key]
+ self[key] = if old_value.nil? || old_value.empty?
+ value
else
- self[key] += separator + value
+ old_value + separator + value
end
end
end
+ sig { params(keys: T.any(String, T::Array[String]), value: T.untyped, separator: String).void }
def prepend(keys, value, separator = " ")
value = value.to_s
Array(keys).each do |key|
- old = self[key]
- self[key] = if old.nil? || old.empty?
+ old_value = self[key]
+ self[key] = if old_value.nil? || old_value.empty?
value
else
- value + separator + old
+ value + separator + old_value
end
end
end
+ sig { params(key: String, path: String).void }
def append_path(key, path)
self[key] = PATH.new(self[key]).append(path)
end
@@ -99,61 +115,78 @@ module SharedEnvExtension
# Prepending a system path such as /usr/bin is a no-op so that requirements
# don't accidentally override superenv shims or formulae's `bin` directories.
# ENV.prepend_path "PATH", which("emacs").dirname
+ sig { params(key: String, path: String).void }
def prepend_path(key, path)
return if %w[/usr/bin /bin /usr/sbin /sbin].include? path.to_s
self[key] = PATH.new(self[key]).prepend(path)
end
+ sig { params(key: String, path: T.any(String, Pathname)).void }
def prepend_create_path(key, path)
- path = Pathname.new(path) unless path.is_a? Pathname
+ path = Pathname(path)
path.mkpath
prepend_path key, path
end
+ sig { params(keys: T.any(String, T::Array[String]), value: T.untyped).void }
def remove(keys, value)
return if value.nil?
Array(keys).each do |key|
- next unless self[key]
+ old_value = self[key]
+ next if old_value.nil?
- self[key] = self[key].sub(value, "")
- delete(key) if self[key].empty?
+ new_value = old_value.sub(value, "")
+ if new_value.empty?
+ delete(key)
+ else
+ self[key] = new_value
+ end
end
end
+ sig { returns(T.nilable(String)) }
def cc
self["CC"]
end
+ sig { returns(T.nilable(String)) }
def cxx
self["CXX"]
end
+ sig { returns(T.nilable(String)) }
def cflags
self["CFLAGS"]
end
+ sig { returns(T.nilable(String)) }
def cxxflags
self["CXXFLAGS"]
end
+ sig { returns(T.nilable(String)) }
def cppflags
self["CPPFLAGS"]
end
+ sig { returns(T.nilable(String)) }
def ldflags
self["LDFLAGS"]
end
+ sig { returns(T.nilable(String)) }
def fc
self["FC"]
end
+ sig { returns(T.nilable(String)) }
def fflags
self["FFLAGS"]
end
+ sig { returns(T.nilable(String)) }
def fcflags
self["FCFLAGS"]
end
@@ -164,8 +197,7 @@ module SharedEnvExtension
# # modify CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS in one go:
# ENV.append_to_cflags "-I ./missing/includes"
# end
- #
- # @return [Symbol]
+ sig { returns(T.any(Symbol, String)) }
def compiler
@compiler ||= if (cc = @cc)
warn_about_non_apple_gcc(cc) if cc.match?(GNU_GCC_REGEXP)
@@ -189,27 +221,31 @@ module SharedEnvExtension
end
end
- # @private
+ sig { returns(T.any(String, Pathname)) }
def determine_cc
COMPILER_SYMBOL_MAP.invert.fetch(compiler, compiler)
end
+ private :determine_cc
COMPILERS.each do |compiler|
define_method(compiler) do
@compiler = compiler
- self.cc = determine_cc
- self.cxx = determine_cxx
+
+ send(:cc=, send(:determine_cc))
+ send(:cxx=, send(:determine_cxx))
end
end
# Snow Leopard defines an NCURSES value the opposite of most distros.
# @see https://bugs.python.org/issue6848
# Currently only used by aalib in core.
+ sig { void }
def ncurses_define
append "CPPFLAGS", "-DNCURSES_OPAQUE=0"
end
# @private
+ sig { void }
def userpaths!
path = PATH.new(self["PATH"]).select do |p|
# put Superenv.bin and opt path at the first
@@ -228,6 +264,7 @@ module SharedEnvExtension
self["PATH"] = path
end
+ sig { void }
def fortran
# Ignore repeated calls to this function as it will misleadingly warn about
# building with an alternative Fortran compiler without optimization flags,
@@ -260,6 +297,7 @@ module SharedEnvExtension
end
# @private
+ sig { returns(Symbol) }
def effective_arch
if @build_bottle && @bottle_arch
@bottle_arch.to_sym
@@ -269,6 +307,7 @@ module SharedEnvExtension
end
# @private
+ sig { params(name: String).returns(Formula) }
def gcc_version_formula(name)
version = name[GNU_GCC_REGEXP, 1]
gcc_version_name = "gcc@#{version}"
@@ -282,6 +321,7 @@ module SharedEnvExtension
end
# @private
+ sig { params(name: String).void }
def warn_about_non_apple_gcc(name)
begin
gcc_formula = gcc_version_formula(name)
@@ -299,30 +339,40 @@ module SharedEnvExtension
EOS
end
+ sig { void }
def permit_arch_flags; end
# A no-op until we enable this by default again (which we may never do).
+ sig { void }
def permit_weak_imports; end
# @private
+ sig { params(cc: T.any(Symbol, String)).returns(T::Boolean) }
def compiler_any_clang?(cc = compiler)
%w[clang llvm_clang].include?(cc.to_s)
end
private
+ sig { params(_flags: T::Array[String], _map: T::Hash[Symbol, String]).void }
+ def set_cpu_flags(_flags, _map = {}); end
+
+ sig { params(val: T.any(String, Pathname)).returns(String) }
def cc=(val)
self["CC"] = self["OBJC"] = val.to_s
end
+ sig { params(val: T.any(String, Pathname)).returns(String) }
def cxx=(val)
self["CXX"] = self["OBJCXX"] = val.to_s
end
+ sig { returns(T.nilable(String)) }
def homebrew_cc
self["HOMEBREW_CC"]
end
+ sig { params(value: String, source: String).returns(Symbol) }
def fetch_compiler(value, source)
COMPILER_SYMBOL_MAP.fetch(value) do |other|
case other
@@ -334,10 +384,9 @@ module SharedEnvExtension
end
end
+ sig { void }
def check_for_compiler_universal_support
- return unless homebrew_cc.match?(GNU_GCC_REGEXP)
-
- raise "Non-Apple GCC can't build universal binaries"
+ raise "Non-Apple GCC can't build universal binaries" if homebrew_cc&.match?(GNU_GCC_REGEXP)
end
end
diff --git a/Library/Homebrew/extend/ENV/shared.rbi b/Library/Homebrew/extend/ENV/shared.rbi
new file mode 100644
index 0000000000..b1eac4cd3e
--- /dev/null
+++ b/Library/Homebrew/extend/ENV/shared.rbi
@@ -0,0 +1,15 @@
+# typed: strict
+
+module SharedEnvExtension
+ include EnvMethods
+end
+
+class Sorbet
+ module Private
+ module Static
+ class ENVClass
+ include SharedEnvExtension
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/extend/ENV/std.rb b/Library/Homebrew/extend/ENV/std.rb
index bea1efc156..8a8a648d81 100644
--- a/Library/Homebrew/extend/ENV/std.rb
+++ b/Library/Homebrew/extend/ENV/std.rb
@@ -1,4 +1,4 @@
-# typed: false
+# typed: strict
# frozen_string_literal: true
require "hardware"
@@ -14,8 +14,16 @@ module Stdenv
SAFE_CFLAGS_FLAGS = "-w -pipe"
# @private
- def setup_build_environment(**options)
- super(**options)
+ sig do
+ params(
+ formula: T.nilable(Formula),
+ cc: T.nilable(String),
+ build_bottle: T.nilable(T::Boolean),
+ bottle_arch: T.nilable(T::Boolean),
+ ).void
+ end
+ def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil)
+ super
self["HOMEBREW_ENV"] = "std"
@@ -49,13 +57,14 @@ module Stdenv
send(compiler)
- return unless cc.match?(GNU_GCC_REGEXP)
+ return unless cc&.match?(GNU_GCC_REGEXP)
gcc_formula = gcc_version_formula(cc)
append_path "PATH", gcc_formula.opt_bin.to_s
end
alias generic_setup_build_environment setup_build_environment
+ sig { returns(T::Array[Pathname]) }
def homebrew_extra_pkg_config_paths
[]
end
@@ -73,10 +82,11 @@ module Stdenv
# Removes the MAKEFLAGS environment variable, causing make to use a single job.
# This is useful for makefiles with race conditions.
# When passed a block, MAKEFLAGS is removed only for the duration of the block and is restored after its completion.
- def deparallelize
+ sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) }
+ def deparallelize(&block)
old = self["MAKEFLAGS"]
remove "MAKEFLAGS", /-j\d+/
- if block_given?
+ if block
begin
yield
ensure
@@ -89,30 +99,33 @@ module Stdenv
%w[O3 O2 O1 O0 Os].each do |opt|
define_method opt do
- remove_from_cflags(/-O./)
- append_to_cflags "-#{opt}"
+ send(:remove_from_cflags, /-O./)
+ send(:append_to_cflags, "-#{opt}")
end
end
- # @private
+ sig { returns(T.any(String, Pathname)) }
def determine_cc
s = super
- DevelopmentTools.locate(s) || Pathname.new(s)
+ DevelopmentTools.locate(s) || Pathname(s)
end
+ private :determine_cc
- # @private
+ sig { returns(Pathname) }
def determine_cxx
- dir, base = determine_cc.split
+ dir, base = Pathname(determine_cc).split
dir/base.to_s.sub("gcc", "g++").sub("clang", "clang++")
end
+ private :determine_cxx
GNU_GCC_VERSIONS.each do |n|
define_method(:"gcc-#{n}") do
super()
- set_cpu_cflags
+ send(:set_cpu_cflags)
end
end
+ sig { void }
def clang
super()
replace_in_cflags(/-Xarch_#{Hardware::CPU.arch_32_bit} (-march=\S*)/, '\1')
@@ -124,16 +137,19 @@ module Stdenv
set_cpu_cflags(map)
end
+ sig { void }
def m64
append_to_cflags "-m64"
append "LDFLAGS", "-arch #{Hardware::CPU.arch_64_bit}"
end
+ sig { void }
def m32
append_to_cflags "-m32"
append "LDFLAGS", "-arch #{Hardware::CPU.arch_32_bit}"
end
+ sig { void }
def universal_binary
check_for_compiler_universal_support
@@ -141,33 +157,38 @@ module Stdenv
append "LDFLAGS", Hardware::CPU.universal_archs.as_arch_flags
return if compiler_any_clang?
- return unless Hardware.is_32_bit?
+ return unless Hardware::CPU.is_32_bit?
# Can't mix "-march" for a 32-bit CPU with "-arch x86_64"
replace_in_cflags(/-march=\S*/, "-Xarch_#{Hardware::CPU.arch_32_bit} \\0")
end
+ sig { void }
def cxx11
append "CXX", "-std=c++11"
libcxx
end
+ sig { void }
def libcxx
append "CXX", "-stdlib=libc++" if compiler == :clang
end
+ sig { void }
def libstdcxx
append "CXX", "-stdlib=libstdc++" if compiler == :clang
end
# @private
+ sig { params(before: Regexp, after: String).void }
def replace_in_cflags(before, after)
CC_FLAG_VARS.each do |key|
- self[key] = self[key].sub(before, after) if key?(key)
+ self[key] = fetch(key).sub(before, after) if key?(key)
end
end
# Convenience method to set all C compiler flags in one shot.
+ sig { params(val: String).void }
def define_cflags(val)
CC_FLAG_VARS.each { |key| self[key] = val }
end
@@ -175,6 +196,7 @@ module Stdenv
# Sets architecture-specific flags for every environment variable
# given in the list `flags`.
# @private
+ sig { params(flags: T::Array[String], map: T::Hash[Symbol, String]).void }
def set_cpu_flags(flags, map = Hardware::CPU.optimization_flags)
cflags =~ /(-Xarch_#{Hardware::CPU.arch_32_bit} )-march=/
xarch = Regexp.last_match(1).to_s
@@ -186,19 +208,23 @@ module Stdenv
append flags, map.fetch(effective_arch)
end
+ sig { void }
def x11; end
# @private
+ sig { params(map: T::Hash[Symbol, String]).void }
def set_cpu_cflags(map = Hardware::CPU.optimization_flags) # rubocop:disable Naming/AccessorMethodName
set_cpu_flags(CC_FLAG_VARS, map)
end
+ sig { returns(Integer) }
def make_jobs
Homebrew::EnvConfig.make_jobs.to_i
end
# This method does nothing in stdenv since there's no arg refurbishment
# @private
+ sig { void }
def refurbish_args; end
end
diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb
index 4b1ba40b84..5e2c1da21f 100644
--- a/Library/Homebrew/extend/ENV/super.rb
+++ b/Library/Homebrew/extend/ENV/super.rb
@@ -1,4 +1,4 @@
-# typed: false
+# typed: true
# frozen_string_literal: true
require "extend/ENV/shared"
@@ -22,6 +22,7 @@ module Superenv
# @private
attr_accessor :keg_only_deps, :deps, :run_time_deps, :x11
+ sig { params(base: Superenv).void }
def self.extended(base)
base.keg_only_deps = []
base.deps = []
@@ -29,8 +30,10 @@ module Superenv
end
# @private
+ sig { returns(T.nilable(Pathname)) }
def self.bin; end
+ sig { void }
def reset
super
# Configure scripts generated by autoconf 2.61 or later export as_nl, which
@@ -39,8 +42,16 @@ module Superenv
end
# @private
- def setup_build_environment(**options)
- super(**options)
+ sig do
+ params(
+ formula: T.nilable(Formula),
+ cc: T.nilable(String),
+ build_bottle: T.nilable(T::Boolean),
+ bottle_arch: T.nilable(T::Boolean),
+ ).void
+ end
+ def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil)
+ super
send(compiler)
self["HOMEBREW_ENV"] = "super"
@@ -89,18 +100,22 @@ module Superenv
private
+ sig { params(val: T.any(String, Pathname)).returns(String) }
def cc=(val)
self["HOMEBREW_CC"] = super
end
+ sig { params(val: T.any(String, Pathname)).returns(String) }
def cxx=(val)
self["HOMEBREW_CXX"] = super
end
+ sig { returns(String) }
def determine_cxx
determine_cc.to_s.gsub("gcc", "g++").gsub("clang", "clang++")
end
+ sig { returns(T::Array[Pathname]) }
def homebrew_extra_paths
[]
end
@@ -115,7 +130,7 @@ module Superenv
path.append("/usr/bin", "/bin", "/usr/sbin", "/sbin")
begin
- path.append(gcc_version_formula(homebrew_cc).opt_bin) if homebrew_cc.match?(GNU_GCC_REGEXP)
+ path.append(gcc_version_formula(T.must(homebrew_cc)).opt_bin) if homebrew_cc&.match?(GNU_GCC_REGEXP)
rescue FormulaUnavailableError
# Don't fail and don't add these formulae to the path if they don't exist.
nil
@@ -124,6 +139,7 @@ module Superenv
path.existing
end
+ sig { returns(T::Array[Pathname]) }
def homebrew_extra_pkg_config_paths
[]
end
@@ -143,6 +159,7 @@ module Superenv
).existing
end
+ sig { returns(T::Array[Pathname]) }
def homebrew_extra_aclocal_paths
[]
end
@@ -156,6 +173,7 @@ module Superenv
).existing
end
+ sig { returns(T::Array[Pathname]) }
def homebrew_extra_isystem_paths
[]
end
@@ -173,6 +191,7 @@ module Superenv
PATH.new(keg_only_deps.map(&:opt_include)).existing
end
+ sig { returns(T::Array[Pathname]) }
def homebrew_extra_library_paths
[]
end
@@ -187,6 +206,7 @@ module Superenv
PATH.new(paths).existing
end
+ sig { returns(String) }
def determine_dependencies
deps.map(&:name).join(",")
end
@@ -199,6 +219,7 @@ module Superenv
).existing
end
+ sig { returns(T::Array[Pathname]) }
def homebrew_extra_cmake_include_paths
[]
end
@@ -208,6 +229,7 @@ module Superenv
PATH.new(homebrew_extra_cmake_include_paths).existing
end
+ sig { returns(T::Array[Pathname]) }
def homebrew_extra_cmake_library_paths
[]
end
@@ -217,6 +239,7 @@ module Superenv
PATH.new(homebrew_extra_cmake_library_paths).existing
end
+ sig { returns(T::Array[Pathname]) }
def homebrew_extra_cmake_frameworks_paths
[]
end
@@ -229,14 +252,17 @@ module Superenv
).existing
end
+ sig { returns(String) }
def determine_make_jobs
Homebrew::EnvConfig.make_jobs
end
+ sig { returns(String) }
def determine_optflags
Hardware::CPU.optimization_flags.fetch(effective_arch)
end
+ sig { returns(String) }
def determine_cccfg
""
end
@@ -246,9 +272,10 @@ module Superenv
# Removes the MAKEFLAGS environment variable, causing make to use a single job.
# This is useful for makefiles with race conditions.
# When passed a block, MAKEFLAGS is removed only for the duration of the block and is restored after its completion.
- def deparallelize
+ sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) }
+ def deparallelize(&block)
old = delete("MAKEFLAGS")
- if block_given?
+ if block
begin
yield
ensure
@@ -259,56 +286,64 @@ module Superenv
old
end
+ sig { returns(Integer) }
def make_jobs
self["MAKEFLAGS"] =~ /-\w*j(\d+)/
[Regexp.last_match(1).to_i, 1].max
end
+ sig { void }
def universal_binary
check_for_compiler_universal_support
self["HOMEBREW_ARCHFLAGS"] = Hardware::CPU.universal_archs.as_arch_flags
end
+ sig { void }
def permit_arch_flags
append_to_cccfg "K"
end
+ sig { void }
def m32
append "HOMEBREW_ARCHFLAGS", "-m32"
end
+ sig { void }
def m64
append "HOMEBREW_ARCHFLAGS", "-m64"
end
+ sig { void }
def cxx11
append_to_cccfg "x"
append_to_cccfg "g" if homebrew_cc == "clang"
end
+ sig { void }
def libcxx
append_to_cccfg "g" if compiler == :clang
end
+ sig { void }
def libstdcxx
append_to_cccfg "h" if compiler == :clang
end
# @private
+ sig { void }
def refurbish_args
append_to_cccfg "O"
end
%w[O3 O2 O1 O0 Os].each do |opt|
define_method opt do
- self["HOMEBREW_OPTIMIZATION_LEVEL"] = opt
+ send(:[]=, "HOMEBREW_OPTIMIZATION_LEVEL", opt)
end
end
+ sig { void }
def set_x11_env_if_installed; end
-
- def set_cpu_flags(_arg0, _arg1 = "", _arg2 = {}); end
end
require "extend/os/extend/ENV/super"
diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb
index 4e541a2be9..d797ff7484 100644
--- a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb
+++ b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb
@@ -27,7 +27,7 @@ module Superenv
def homebrew_extra_paths
paths = []
- paths << MacOS::XQuartz.bin.to_s if x11?
+ paths << MacOS::XQuartz.bin if x11?
paths
end
diff --git a/Library/Homebrew/extend/os/mac/hardware/cpu.rb b/Library/Homebrew/extend/os/mac/hardware/cpu.rb
index 7b10da535a..ad84a72420 100644
--- a/Library/Homebrew/extend/os/mac/hardware/cpu.rb
+++ b/Library/Homebrew/extend/os/mac/hardware/cpu.rb
@@ -69,7 +69,7 @@ module Hardware
# conflict between what `uname` reports and the underlying `sysctl` flags,
# since the `sysctl` flags don't change behaviour under Rosetta 2.
def in_rosetta2?
- intel? && physical_cpu_arm64?
+ sysctl_bool("sysctl.proc_translated")
end
def features
diff --git a/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb b/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb
index 5619850d06..dfcb9ea655 100644
--- a/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb
+++ b/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb
@@ -26,14 +26,14 @@ class JavaRequirement < Requirement
end
def java_home_cmd
- # TODO: enable for all macOS versions and Linux on next minor release
+ # TODO: disable for all macOS versions and Linux on next minor release
# but --version with ranges is broken on Big Sur today.
if MacOS.version >= :big_sur && @version&.end_with?("+")
odisabled %Q(depends_on java: "#{@version}"),
'depends_on "openjdk@11", depends_on "openjdk@8" or depends_on "openjdk"'
end
- # odeprecated "depends_on :java",
- # 'depends_on "openjdk@11", depends_on "openjdk@8" or depends_on "openjdk"'
+ odeprecated "depends_on :java",
+ 'depends_on "openjdk@11", depends_on "openjdk@8" or depends_on "openjdk"'
return unless File.executable?("/usr/libexec/java_home")
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index eaed557009..b7db312947 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -113,11 +113,6 @@ class Formula
# @private
attr_reader :stable
- # @private
- def devel
- odisabled "Formula#devel"
- end
-
# The HEAD {SoftwareSpec} for this {Formula}.
# Installed when using `brew install --HEAD`.
# This is always installed with the version `HEAD` and taken from the latest
@@ -328,11 +323,6 @@ class Formula
active_spec == stable
end
- # @private
- def devel?
- odisabled "Formula#devel?"
- end
-
# Is the currently active {SoftwareSpec} a {#head} build?
# @private
def head?
@@ -2227,10 +2217,6 @@ class Formula
raise "You cannot override Formula#brew in class #{name}"
when :test
define_method(:test_defined?) { true }
- when :patches
- odisabled "a Formula#patches definition", "'patch do' block calls"
- when :options
- odisabled "a Formula#options definition", "'option do' block calls"
end
end
@@ -2274,10 +2260,7 @@ class Formula
if args.nil?
@licenses
else
- if args.is_a? Array
- odeprecated "`license [...]`", "`license any_of: [...]`"
- args = { any_of: args }
- end
+ odisabled "`license [...]`", "`license any_of: [...]`" if args.is_a? Array
@licenses = args
end
end
@@ -2463,11 +2446,6 @@ class Formula
@stable.instance_eval(&block)
end
- # @private
- def devel
- odisabled "'devel' blocks in formulae", "'head' blocks or @-versioned formulae"
- end
-
# @!attribute [w] head
# Adds a {.head} {SoftwareSpec}.
# This can be installed by passing the `--HEAD` option to allow
diff --git a/Library/Homebrew/formula_auditor.rb b/Library/Homebrew/formula_auditor.rb
index 0392b11e7e..e86f600efd 100644
--- a/Library/Homebrew/formula_auditor.rb
+++ b/Library/Homebrew/formula_auditor.rb
@@ -1,6 +1,7 @@
# typed: false
# frozen_string_literal: true
+require "deprecate_disable"
require "formula_text_auditor"
require "resource_auditor"
@@ -325,6 +326,11 @@ module Homebrew
return if version_conflicts.empty?
+ return if formula.disabled?
+
+ return if formula.deprecated? &&
+ formula.deprecation_reason != DeprecateDisable::DEPRECATE_DISABLE_REASONS[:versioned_formula]
+
problem <<~EOS
#{formula.full_name} contains conflicting version recursive dependencies:
#{version_conflicts.to_a.join ", "}
diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb
index efe4ef24b4..23a20fbfbe 100644
--- a/Library/Homebrew/formulary.rb
+++ b/Library/Homebrew/formulary.rb
@@ -225,12 +225,12 @@ module Formulary
def load_file(flags:)
if %r{githubusercontent.com/[\w-]+/[\w-]+/[a-f0-9]{40}(?:/Formula)?/(?[\w+-.@]+).rb} =~ url # rubocop:disable Style/CaseLikeIf
- odisabled "Installation of #{formula_name} from a GitHub commit URL",
- "'brew extract #{formula_name}' to stable tap on GitHub"
+ raise UsageError, "Installation of #{formula_name} from a GitHub commit URL is unsupported! " \
+ "'brew extract #{formula_name}' to stable tap on GitHub instead."
elsif url.match?(%r{^(https?|ftp)://})
- odisabled "Non-checksummed download of #{name} formula file from an arbitrary URL",
- "'brew extract' or 'brew create' and 'brew tap-new' to create a "\
- "formula file in a tap on GitHub"
+ raise UsageError, "Non-checksummed download of #{name} formula file from an arbitrary URL is unsupported! ",
+ "'brew extract' or 'brew create' and 'brew tap-new' to create a "\
+ "formula file in a tap on GitHub instead."
end
HOMEBREW_CACHE_FORMULA.mkpath
FileUtils.rm_f(path)
diff --git a/Library/Homebrew/language/python.rb b/Library/Homebrew/language/python.rb
index 165ee1da28..5fa55214cc 100644
--- a/Library/Homebrew/language/python.rb
+++ b/Library/Homebrew/language/python.rb
@@ -7,7 +7,7 @@ module Language
# @api public
module Python
def self.major_minor_version(python)
- version = /\d\.\d/.match `#{python} --version 2>&1`
+ version = /\d\.\d+/.match `#{python} --version 2>&1`
return unless version
Version.create(version.to_s)
diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb
index 6c20bad598..2be9dfc439 100644
--- a/Library/Homebrew/os/mac.rb
+++ b/Library/Homebrew/os/mac.rb
@@ -44,13 +44,6 @@ module OS
Version.new "11.0"
end
- def latest_stable_version
- # TODO: bump version when new macOS is released and also update
- # references in docs/Installation.md and
- # https://github.com/Homebrew/install/blob/HEAD/install.sh
- Version.new "11.0"
- end
-
def outdated_release?
# TODO: bump version when new macOS is released and also update
# references in docs/Installation.md and
@@ -59,7 +52,10 @@ module OS
end
def prerelease?
- version > latest_stable_version
+ # TODO: bump version when new macOS is released or announced
+ # and also update references in docs/Installation.md and
+ # https://github.com/Homebrew/install/blob/HEAD/install.sh
+ version >= "12.0"
end
def languages
diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb
index 3ad279dc0d..daf3706fb4 100644
--- a/Library/Homebrew/os/mac/xcode.rb
+++ b/Library/Homebrew/os/mac/xcode.rb
@@ -22,7 +22,7 @@ module OS
def latest_version
latest_stable = "12.2"
case MacOS.version
- when "11.0" then latest_stable
+ when /^11\./ then latest_stable
when "10.15" then "12.2"
when "10.14" then "11.3.1"
when "10.13" then "10.1"
@@ -45,7 +45,7 @@ module OS
sig { returns(String) }
def minimum_version
case MacOS.version
- when "11.0" then "12.2"
+ when /^11\./ then "12.2"
when "10.15" then "11.0"
when "10.14" then "10.2"
when "10.13" then "9.0"
@@ -275,7 +275,7 @@ module OS
sig { returns(String) }
def latest_clang_version
case MacOS.version
- when "11.0", "10.15" then "1200.0.32.27"
+ when /^11\./, "10.15" then "1200.0.32.27"
when "10.14" then "1100.0.33.17"
when "10.13" then "1000.10.44.2"
when "10.12" then "900.0.39.2"
@@ -291,7 +291,7 @@ module OS
sig { returns(String) }
def minimum_version
case MacOS.version
- when "11.0" then "12.0.0"
+ when /^11\./ then "12.0.0"
when "10.15" then "11.0.0"
when "10.14" then "10.0.0"
when "10.13" then "9.0.0"
diff --git a/Library/Homebrew/patch.rb b/Library/Homebrew/patch.rb
index 1157c61005..ebdbe3a19d 100644
--- a/Library/Homebrew/patch.rb
+++ b/Library/Homebrew/patch.rb
@@ -41,14 +41,8 @@ module Patch
else
{}
end.each_pair do |strip, urls|
- Array(urls).each do |url|
- patch = case url
- when :DATA
- DATAPatch.new(strip)
- else
- LegacyPatch.new(strip, url)
- end
- patches << patch
+ Array(urls).each do
+ patches << DATAPatch.new(strip)
end
end
@@ -196,15 +190,3 @@ class ExternalPatch
"#<#{self.class.name}: #{strip.inspect} #{url.inspect}>"
end
end
-
-# A legacy patch.
-#
-# Legacy patches have no checksum and are not cached.
-#
-# @api private
-class LegacyPatch < ExternalPatch
- def initialize(strip, _url)
- odisabled "legacy patches", "'patch do' blocks"
- super(strip)
- end
-end
diff --git a/Library/Homebrew/requirements/java_requirement.rb b/Library/Homebrew/requirements/java_requirement.rb
index cf6b944d42..c99e82f7a5 100644
--- a/Library/Homebrew/requirements/java_requirement.rb
+++ b/Library/Homebrew/requirements/java_requirement.rb
@@ -34,6 +34,9 @@ class JavaRequirement < Requirement
end
def initialize(tags = [])
+ odeprecated "depends_on :java",
+ '"depends_on "openjdk@11", "depends_on "openjdk@8" or "depends_on "openjdk"'
+
@version = tags.shift if tags.first&.match?(/^\d/)
super(tags)
@cask = suggestion.token
diff --git a/Library/Homebrew/requirements/macos_requirement.rb b/Library/Homebrew/requirements/macos_requirement.rb
index 52b1e84b20..5284acb114 100644
--- a/Library/Homebrew/requirements/macos_requirement.rb
+++ b/Library/Homebrew/requirements/macos_requirement.rb
@@ -14,16 +14,10 @@ class MacOSRequirement < Requirement
attr_reader :comparator, :version
def initialize(tags = [], comparator: ">=")
- begin
- @version = if comparator == "==" && tags.first.respond_to?(:map)
- tags.shift.map { |s| MacOS::Version.from_symbol(s) }
- else
- MacOS::Version.from_symbol(tags.shift) unless tags.empty?
- end
- rescue MacOSVersionError => e
- raise if e.version != :mavericks
-
- odisabled "depends_on :macos => :mavericks"
+ @version = if comparator == "==" && tags.first.respond_to?(:map)
+ tags.shift.map { |s| MacOS::Version.from_symbol(s) }
+ else
+ MacOS::Version.from_symbol(tags.shift) unless tags.empty?
end
@comparator = comparator
diff --git a/Library/Homebrew/rubocops/components_order.rb b/Library/Homebrew/rubocops/components_order.rb
index 7f6613799c..84dba9a945 100644
--- a/Library/Homebrew/rubocops/components_order.rb
+++ b/Library/Homebrew/rubocops/components_order.rb
@@ -150,6 +150,8 @@ module RuboCop
valid_node ||= child.method_name.to_s == "patch"
valid_node ||= child.method_name.to_s == "resource"
+ valid_node ||= child.method_name.to_s == "deprecate!"
+ valid_node ||= child.method_name.to_s == "disable!"
@offensive_node = on_os_block
@offense_source_range = on_os_block.source_range
diff --git a/Library/Homebrew/rubocops/text.rb b/Library/Homebrew/rubocops/text.rb
index 5ace971a75..443eab7a58 100644
--- a/Library/Homebrew/rubocops/text.rb
+++ b/Library/Homebrew/rubocops/text.rb
@@ -95,21 +95,6 @@ module RuboCop
end
end
- find_strings(body_node).each do |n|
- next unless regex_match_group(n, /JAVA_HOME/i)
-
- next if @formula_name.match?(/^openjdk(@|$)/)
-
- next if find_every_method_call_by_name(body_node, :depends_on).any? do |dependency|
- dependency.each_descendant(:str).count.zero? ||
- regex_match_group(dependency.each_descendant(:str).first, /^openjdk(@|$)/) ||
- depends_on?(:java)
- end
-
- offending_node(n)
- problem "Use `depends_on :java` to set JAVA_HOME"
- end
-
prefix_path(body_node) do |prefix_node, path|
next unless match = path.match(%r{^(bin|include|libexec|lib|sbin|share|Frameworks)(?:/| |$)})
diff --git a/Library/Homebrew/sorbet/plugins/delegate.rb b/Library/Homebrew/sorbet/plugins/delegate.rb
new file mode 100644
index 0000000000..2f308cc45d
--- /dev/null
+++ b/Library/Homebrew/sorbet/plugins/delegate.rb
@@ -0,0 +1,21 @@
+# typed: strict
+# frozen_string_literal: true
+
+source = ARGV[5]
+
+methods = if (single = source[/delegate\s+([^:]+):\s+/, 1])
+ [single]
+else
+ multiple = source[/delegate\s+\[(.*?)\]\s+=>\s+/m, 1]
+ non_comments = multiple.gsub(/\#.*$/, "")
+ non_comments.scan(/:([^:,\s]+)/).flatten
+end
+
+methods.each do |method|
+ puts <<~RUBY
+ # typed: strict
+
+ sig {params(arg0: T.untyped).returns(T.untyped)}
+ def #{method}(*arg0); end
+ RUBY
+end
diff --git a/Library/Homebrew/sorbet/plugins/unpack_strategy_magic.rb b/Library/Homebrew/sorbet/plugins/using.rb
similarity index 57%
rename from Library/Homebrew/sorbet/plugins/unpack_strategy_magic.rb
rename to Library/Homebrew/sorbet/plugins/using.rb
index d5c83fa8b5..e1bf761b29 100644
--- a/Library/Homebrew/sorbet/plugins/unpack_strategy_magic.rb
+++ b/Library/Homebrew/sorbet/plugins/using.rb
@@ -3,7 +3,8 @@
source = ARGV[5]
-/\busing +Magic\b/.match(source) do |_|
+case source[/\Ausing\s+(.*)\Z/, 1]
+when "Magic"
puts <<-RUBY
# typed: strict
@@ -18,4 +19,13 @@ source = ARGV[5]
def zipinfo; end
end
RUBY
+when "HashValidator"
+ puts <<-RUBY
+ # typed: strict
+
+ class ::Hash
+ sig { params(valid_keys: T.untyped).void }
+ def assert_valid_keys!(*valid_keys); end
+ end
+ RUBY
end
diff --git a/Library/Homebrew/sorbet/rbi/gems/parallel@1.20.0.rbi b/Library/Homebrew/sorbet/rbi/gems/parallel@1.20.1.rbi
similarity index 100%
rename from Library/Homebrew/sorbet/rbi/gems/parallel@1.20.0.rbi
rename to Library/Homebrew/sorbet/rbi/gems/parallel@1.20.1.rbi
diff --git a/Library/Homebrew/sorbet/rbi/gems/parallel_tests@3.3.0.rbi b/Library/Homebrew/sorbet/rbi/gems/parallel_tests@3.4.0.rbi
similarity index 100%
rename from Library/Homebrew/sorbet/rbi/gems/parallel_tests@3.3.0.rbi
rename to Library/Homebrew/sorbet/rbi/gems/parallel_tests@3.4.0.rbi
diff --git a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi
index c49adbb35a..a9699d5831 100644
--- a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi
+++ b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi
@@ -5841,22 +5841,6 @@ module Cask::Utils
extend ::T::Private::Methods::SingletonMethodHooks
end
-class Caveats
- def empty?(*args, &block); end
-
- def to_s(*args, &block); end
-end
-
-class Checksum
- def [](*args, &block); end
-
- def empty?(*args, &block); end
-
- def length(*args, &block); end
-
- def to_s(*args, &block); end
-end
-
class Class
def any_instance(); end
@@ -11897,14 +11881,6 @@ module MachO
def self.open(filename); end
end
-module MachOShim
- def delete_rpath(*args, &block); end
-
- def dylib_id(*args, &block); end
-
- def rpaths(*args, &block); end
-end
-
Markdown = RDiscount
module Marshal
@@ -15369,18 +15345,6 @@ class Pathname
extend ::T::Private::Methods::SingletonMethodHooks
end
-class PkgVersion
- def major(*args, &block); end
-
- def major_minor(*args, &block); end
-
- def major_minor_patch(*args, &block); end
-
- def minor(*args, &block); end
-
- def patch(*args, &block); end
-end
-
class Proc
include ::MethodSource::SourceLocation::ProcExtensions
include ::MethodSource::MethodExtensions
@@ -28595,6 +28559,7 @@ class Socket
IPV6_PATHMTU = ::T.let(nil, ::T.untyped)
IPV6_RECVPATHMTU = ::T.let(nil, ::T.untyped)
IPV6_USE_MIN_MTU = ::T.let(nil, ::T.untyped)
+ IP_DONTFRAG = ::T.let(nil, ::T.untyped)
IP_PORTRANGE = ::T.let(nil, ::T.untyped)
IP_RECVDSTADDR = ::T.let(nil, ::T.untyped)
IP_RECVIF = ::T.let(nil, ::T.untyped)
@@ -28686,6 +28651,7 @@ module Socket::Constants
IPV6_PATHMTU = ::T.let(nil, ::T.untyped)
IPV6_RECVPATHMTU = ::T.let(nil, ::T.untyped)
IPV6_USE_MIN_MTU = ::T.let(nil, ::T.untyped)
+ IP_DONTFRAG = ::T.let(nil, ::T.untyped)
IP_PORTRANGE = ::T.let(nil, ::T.untyped)
IP_RECVDSTADDR = ::T.let(nil, ::T.untyped)
IP_RECVIF = ::T.let(nil, ::T.untyped)
@@ -29246,6 +29212,11 @@ end
class SynchronizedDelegator
end
+class SystemCommand::Result
+ extend ::T::Private::Methods::MethodHooks
+ extend ::T::Private::Methods::SingletonMethodHooks
+end
+
class SystemCommand
extend ::T::Private::Methods::MethodHooks
extend ::T::Private::Methods::SingletonMethodHooks
diff --git a/Library/Homebrew/sorbet/triggers.yml b/Library/Homebrew/sorbet/triggers.yml
index 48a007d979..747e297c2e 100644
--- a/Library/Homebrew/sorbet/triggers.yml
+++ b/Library/Homebrew/sorbet/triggers.yml
@@ -2,5 +2,6 @@ ruby_extra_args:
- --disable-gems
triggers:
- using: sorbet/plugins/unpack_strategy_magic.rb
+ using: sorbet/plugins/using.rb
attr_predicate: sorbet/plugins/attr_predicate.rb
+ delegate: sorbet/plugins/delegate.rb
diff --git a/Library/Homebrew/system_command.rb b/Library/Homebrew/system_command.rb
index a9ef6cf6b5..33ce5069bc 100644
--- a/Library/Homebrew/system_command.rb
+++ b/Library/Homebrew/system_command.rb
@@ -9,7 +9,6 @@ require "shellwords"
require "extend/io"
require "extend/predicable"
require "extend/hash_validator"
-using HashValidator
# Class for running sub-processes and capturing their output and exit status.
#
@@ -17,14 +16,16 @@ using HashValidator
class SystemCommand
extend T::Sig
+ using HashValidator
+
# Helper functions for calling {SystemCommand.run}.
module Mixin
def system_command(*args)
- SystemCommand.run(*args)
+ T.unsafe(SystemCommand).run(*args)
end
def system_command!(*args)
- SystemCommand.run!(*args)
+ T.unsafe(SystemCommand).run!(*args)
end
end
@@ -34,11 +35,11 @@ class SystemCommand
attr_reader :pid
def self.run(executable, **options)
- new(executable, **options).run!
+ T.unsafe(self).new(executable, **options).run!
end
def self.run!(command, **options)
- run(command, **options, must_succeed: true)
+ T.unsafe(self).run(command, **options, must_succeed: true)
end
sig { returns(SystemCommand::Result) }
@@ -63,45 +64,61 @@ class SystemCommand
result
end
+ sig do
+ params(
+ executable: T.any(String, Pathname),
+ args: T::Array[T.any(String, Integer, Float, URI::Generic)],
+ sudo: T::Boolean,
+ env: T::Hash[String, String],
+ input: T.any(String, T::Array[String]),
+ must_succeed: T::Boolean,
+ print_stdout: T::Boolean,
+ print_stderr: T::Boolean,
+ verbose: T::Boolean,
+ secrets: T::Array[String],
+ chdir: T.any(String, Pathname),
+ ).void
+ end
def initialize(executable, args: [], sudo: false, env: {}, input: [], must_succeed: false,
- print_stdout: false, print_stderr: true, verbose: false, secrets: [], **options)
+ print_stdout: false, print_stderr: true, verbose: false, secrets: [], chdir: T.unsafe(nil))
require "extend/ENV"
@executable = executable
@args = args
@sudo = sudo
- @input = Array(input)
- @print_stdout = print_stdout
- @print_stderr = print_stderr
- @verbose = verbose
- @secrets = (Array(secrets) + ENV.sensitive_environment.values).uniq
- @must_succeed = must_succeed
- options.assert_valid_keys!(:chdir)
- @options = options
- @env = env
-
- @env.each_key do |name|
+ env.each_key do |name|
next if /^[\w&&\D]\w*$/.match?(name)
raise ArgumentError, "Invalid variable name: '#{name}'"
end
+ @env = env
+ @input = Array(input)
+ @must_succeed = must_succeed
+ @print_stdout = print_stdout
+ @print_stderr = print_stderr
+ @verbose = verbose
+ @secrets = (Array(secrets) + ENV.sensitive_environment.values).uniq
+ @chdir = chdir
end
+ sig { returns(T::Array[String]) }
def command
[*sudo_prefix, *env_args, executable.to_s, *expanded_args]
end
private
- attr_reader :executable, :args, :input, :options, :env
+ attr_reader :executable, :args, :input, :chdir, :env
attr_predicate :sudo?, :print_stdout?, :print_stderr?, :must_succeed?
+ sig { returns(T::Boolean) }
def verbose?
return super if @verbose.nil?
@verbose
end
+ sig { returns(T::Array[String]) }
def env_args
set_variables = env.compact.map do |name, value|
sanitized_name = Shellwords.escape(name)
@@ -114,6 +131,7 @@ class SystemCommand
["/usr/bin/env", *set_variables]
end
+ sig { returns(T::Array[String]) }
def sudo_prefix
return [] unless sudo?
@@ -121,11 +139,12 @@ class SystemCommand
["/usr/bin/sudo", *askpass_flags, "-E", "--"]
end
+ sig { returns(T::Array[String]) }
def expanded_args
@expanded_args ||= args.map do |arg|
if arg.respond_to?(:to_path)
File.absolute_path(arg)
- elsif arg.is_a?(Integer) || arg.is_a?(Float) || arg.is_a?(URI)
+ elsif arg.is_a?(Integer) || arg.is_a?(Float) || arg.is_a?(URI::Generic)
arg.to_s
else
arg.to_str
@@ -137,7 +156,7 @@ class SystemCommand
executable, *args = command
raw_stdin, raw_stdout, raw_stderr, raw_wait_thr =
- Open3.popen3(env, [executable, executable], *args, **options)
+ T.unsafe(Open3).popen3(env, [executable, executable], *args, **{ chdir: chdir }.compact)
@pid = raw_wait_thr.pid
write_input_to(raw_stdin)
@@ -158,7 +177,7 @@ class SystemCommand
loop do
readable_sources, = IO.select(sources)
- readable_sources = readable_sources.reject(&:eof?)
+ readable_sources = T.must(readable_sources).reject(&:eof?)
break if readable_sources.empty?
@@ -176,10 +195,20 @@ class SystemCommand
# Result containing the output and exit status of a finished sub-process.
class Result
+ extend T::Sig
+
include Context
attr_accessor :command, :status, :exit_status
+ sig do
+ params(
+ command: T::Array[String],
+ output: T::Array[[Symbol, String]],
+ status: Process::Status,
+ secrets: T::Array[String],
+ ).void
+ end
def initialize(command, output, status, secrets:)
@command = command
@output = output
@@ -188,57 +217,65 @@ class SystemCommand
@secrets = secrets
end
+ sig { void }
def assert_success!
return if @status.success?
raise ErrorDuringExecution.new(command, status: @status, output: @output, secrets: @secrets)
end
+ sig { returns(String) }
def stdout
@stdout ||= @output.select { |type,| type == :stdout }
.map { |_, line| line }
.join
end
+ sig { returns(String) }
def stderr
@stderr ||= @output.select { |type,| type == :stderr }
.map { |_, line| line }
.join
end
+ sig { returns(String) }
def merged_output
@merged_output ||= @output.map { |_, line| line }
.join
end
+ sig { returns(T::Boolean) }
def success?
return false if @exit_status.nil?
@exit_status.zero?
end
+ sig { returns([String, String, Process::Status]) }
def to_ary
[stdout, stderr, status]
end
+ sig { returns(T.nilable(T.any(Array, Hash))) }
def plist
@plist ||= begin
output = stdout
- if /\A(?.*?)<\?\s*xml/m =~ output
- output = output.sub(/\A#{Regexp.escape(garbage)}/m, "")
- warn_plist_garbage(garbage)
+ output = output.sub(/\A(.*?)(\s*<\?\s*xml)/m) do
+ warn_plist_garbage(T.must(Regexp.last_match(1)))
+ Regexp.last_match(2)
end
- if %r{<\s*/\s*plist\s*>(?.*?)\Z}m =~ output
- output = output.sub(/#{Regexp.escape(garbage)}\Z/, "")
- warn_plist_garbage(garbage)
+ output = output.sub(%r{(<\s*/\s*plist\s*>\s*)(.*?)\Z}m) do
+ warn_plist_garbage(T.must(Regexp.last_match(2)))
+ Regexp.last_match(1)
end
Plist.parse_xml(output)
end
end
+ sig { params(garbage: String).void }
def warn_plist_garbage(garbage)
return unless verbose?
return unless garbage.match?(/\S/)
diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb
index 8b732cae14..5cdbc92261 100644
--- a/Library/Homebrew/tab.rb
+++ b/Library/Homebrew/tab.rb
@@ -233,23 +233,17 @@ class Tab < OpenStruct
end
def universal?
- odeprecated "Tab#universal?"
- include?("universal")
+ odisabled "Tab#universal?"
end
def cxx11?
- odeprecated "Tab#cxx11?"
- include?("c++11")
+ odisabled "Tab#cxx11?"
end
def head?
spec == :head
end
- def devel?
- odisabled "Tab#devel?"
- end
-
def stable?
spec == :stable
end
@@ -314,10 +308,6 @@ class Tab < OpenStruct
Version.create(versions["stable"]) if versions["stable"]
end
- def devel_version
- odisabled "Tab#devel_version"
- end
-
def head_version
Version.create(versions["head"]) if versions["head"]
end
diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb
index d4a33d8ab7..0022617249 100644
--- a/Library/Homebrew/tap.rb
+++ b/Library/Homebrew/tap.rb
@@ -21,11 +21,13 @@ class Tap
HOMEBREW_TAP_FORMULA_RENAMES_FILE = "formula_renames.json"
HOMEBREW_TAP_MIGRATIONS_FILE = "tap_migrations.json"
HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR = "audit_exceptions"
+ HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS = "pypi_formula_mappings.json"
HOMEBREW_TAP_JSON_FILES = %W[
#{HOMEBREW_TAP_FORMULA_RENAMES_FILE}
#{HOMEBREW_TAP_MIGRATIONS_FILE}
#{HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR}/*.json
+ #{HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS}
].freeze
def self.fetch(*args)
@@ -112,6 +114,7 @@ class Tap
@formula_renames = nil
@tap_migrations = nil
@audit_exceptions = nil
+ @pypi_formula_mappings = nil
@config = nil
remove_instance_variable(:@private) if instance_variable_defined?(:@private)
end
@@ -559,23 +562,15 @@ class Tap
end
# Hash with audit exceptions
+ sig { returns(Hash) }
def audit_exceptions
- @audit_exceptions = {}
+ @audit_exceptions = read_formula_list_directory "#{HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR}/*"
+ end
- Pathname.glob(path/HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR/"*").each do |exception_file|
- list_name = exception_file.basename.to_s.chomp(".json").to_sym
- list_contents = begin
- JSON.parse exception_file.read
- rescue JSON::ParserError
- opoo "#{exception_file} contains invalid JSON"
- end
-
- next if list_contents.nil?
-
- @audit_exceptions[list_name] = list_contents
- end
-
- @audit_exceptions
+ # Hash with pypi formula mappings
+ sig { returns(Hash) }
+ def pypi_formula_mappings
+ @pypi_formula_mappings = read_formula_list path/HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS
end
def ==(other)
@@ -636,6 +631,32 @@ class Tap
end
end
end
+
+ sig { params(file: Pathname).returns(Hash) }
+ def read_formula_list(file)
+ JSON.parse file.read
+ rescue JSON::ParserError
+ opoo "#{file} contains invalid JSON"
+ {}
+ rescue Errno::ENOENT
+ {}
+ end
+
+ sig { params(directory: String).returns(Hash) }
+ def read_formula_list_directory(directory)
+ list = {}
+
+ Pathname.glob(path/directory).each do |exception_file|
+ list_name = exception_file.basename.to_s.chomp(".json").to_sym
+ list_contents = read_formula_list exception_file
+
+ next if list_contents.blank?
+
+ list[list_name] = list_contents
+ end
+
+ list
+ end
end
# A specialized {Tap} class for the core formulae.
@@ -739,6 +760,13 @@ class CoreTap < Tap
end
end
+ def pypi_formula_mappings
+ @pypi_formula_mappings ||= begin
+ self.class.ensure_installed!
+ super
+ end
+ end
+
# @private
def formula_file_to_name(file)
file.basename(".rb").to_s
diff --git a/Library/Homebrew/tap_auditor.rb b/Library/Homebrew/tap_auditor.rb
index d8294815f2..5936980919 100644
--- a/Library/Homebrew/tap_auditor.rb
+++ b/Library/Homebrew/tap_auditor.rb
@@ -8,20 +8,21 @@ module Homebrew
class TapAuditor
extend T::Sig
- attr_reader :name, :path, :tap_audit_exceptions, :problems
+ attr_reader :name, :path, :tap_audit_exceptions, :tap_pypi_formula_mappings, :problems
sig { params(tap: Tap, strict: T.nilable(T::Boolean)).void }
def initialize(tap, strict:)
- @name = tap.name
- @path = tap.path
- @tap_audit_exceptions = tap.audit_exceptions
- @problems = []
+ @name = tap.name
+ @path = tap.path
+ @tap_audit_exceptions = tap.audit_exceptions
+ @tap_pypi_formula_mappings = tap.pypi_formula_mappings
+ @problems = []
end
sig { void }
def audit
audit_json_files
- audit_tap_audit_exceptions
+ audit_tap_formula_lists
end
sig { void }
@@ -35,38 +36,49 @@ module Homebrew
end
sig { void }
- def audit_tap_audit_exceptions
- @tap_audit_exceptions.each do |list_name, formula_names|
- unless [Hash, Array].include? formula_names.class
- problem <<~EOS
- audit_exceptions/#{list_name}.json should contain a JSON array
- of formula names or a JSON object mapping formula names to values
- EOS
- next
- end
-
- formula_names = formula_names.keys if formula_names.is_a? Hash
-
- invalid_formulae = []
- formula_names.each do |name|
- invalid_formulae << name if Formula[name].tap != @name
- rescue FormulaUnavailableError
- invalid_formulae << name
- end
-
- next if invalid_formulae.empty?
-
- problem <<~EOS
- audit_exceptions/#{list_name}.json references
- formulae that are not found in the #{@name} tap.
- Invalid formulae: #{invalid_formulae.join(", ")}
- EOS
- end
+ def audit_tap_formula_lists
+ check_formula_list_directory "audit_exceptions", @tap_audit_exceptions
+ check_formula_list "pypi_formula_mappings", @tap_pypi_formula_mappings
end
sig { params(message: String).void }
def problem(message)
@problems << ({ message: message, location: nil })
end
+
+ private
+
+ sig { params(list_file: String, list: T.untyped).void }
+ def check_formula_list(list_file, list)
+ unless [Hash, Array].include? list.class
+ problem <<~EOS
+ #{list_file}.json should contain a JSON array
+ of formula names or a JSON object mapping formula names to values
+ EOS
+ return
+ end
+
+ invalid_formulae = []
+ list.each do |name, _|
+ invalid_formulae << name if Formula[name].tap != @name
+ rescue FormulaUnavailableError
+ invalid_formulae << name
+ end
+
+ return if invalid_formulae.empty?
+
+ problem <<~EOS
+ #{list_file}.json references
+ formulae that are not found in the #{@name} tap.
+ Invalid formulae: #{invalid_formulae.join(", ")}
+ EOS
+ end
+
+ sig { params(directory_name: String, lists: Hash).void }
+ def check_formula_list_directory(directory_name, lists)
+ lists.each do |list_name, list|
+ check_formula_list "#{directory_name}/#{list_name}", list
+ end
+ end
end
end
diff --git a/Library/Homebrew/test/cask/artifact/shared_examples/uninstall_zap.rb b/Library/Homebrew/test/cask/artifact/shared_examples/uninstall_zap.rb
index fc91356cfb..3d97672cc4 100644
--- a/Library/Homebrew/test/cask/artifact/shared_examples/uninstall_zap.rb
+++ b/Library/Homebrew/test/cask/artifact/shared_examples/uninstall_zap.rb
@@ -8,7 +8,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
let(:artifact_dsl_key) { described_class.dsl_key }
let(:artifact) { cask.artifacts.find { |a| a.is_a?(described_class) } }
- let(:fake_system_command) { FakeSystemCommand }
+ let(:fake_system_command) { class_double(SystemCommand) }
context "using :launchctl" do
let(:cask) { Cask::CaskLoader.load(cask_path("with-#{artifact_dsl_key}-launchctl")) }
@@ -31,41 +31,37 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
it "works when job is owned by user" do
- FakeSystemCommand.stubs_command(
- launchctl_list_cmd,
- service_info,
- )
+ allow(fake_system_command).to receive(:run)
+ .with("/bin/launchctl", args: ["list", "my.fancy.package.service"], print_stderr: false, sudo: false)
+ .and_return(instance_double(SystemCommand::Result, stdout: service_info))
+ allow(fake_system_command).to receive(:run)
+ .with("/bin/launchctl", args: ["list", "my.fancy.package.service"], print_stderr: false, sudo: true)
+ .and_return(instance_double(SystemCommand::Result, stdout: unknown_response))
- FakeSystemCommand.stubs_command(
- sudo(launchctl_list_cmd),
- unknown_response,
- )
-
- FakeSystemCommand.expects_command(launchctl_remove_cmd)
+ expect(fake_system_command).to receive(:run!)
+ .with("/bin/launchctl", args: ["remove", "my.fancy.package.service"], sudo: false)
+ .and_return(instance_double(SystemCommand::Result))
subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command)
end
it "works when job is owned by system" do
- FakeSystemCommand.stubs_command(
- launchctl_list_cmd,
- unknown_response,
- )
+ allow(fake_system_command).to receive(:run)
+ .with("/bin/launchctl", args: ["list", "my.fancy.package.service"], print_stderr: false, sudo: false)
+ .and_return(instance_double(SystemCommand::Result, stdout: unknown_response))
+ allow(fake_system_command).to receive(:run)
+ .with("/bin/launchctl", args: ["list", "my.fancy.package.service"], print_stderr: false, sudo: true)
+ .and_return(instance_double(SystemCommand::Result, stdout: service_info))
- FakeSystemCommand.stubs_command(
- sudo(launchctl_list_cmd),
- service_info,
- )
-
- FakeSystemCommand.expects_command(sudo(launchctl_remove_cmd))
+ expect(fake_system_command).to receive(:run!)
+ .with("/bin/launchctl", args: ["remove", "my.fancy.package.service"], sudo: true)
+ .and_return(instance_double(SystemCommand::Result))
subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command)
end
end
context "using :pkgutil" do
- let(:fake_system_command) { class_double(SystemCommand) }
-
let(:cask) { Cask::CaskLoader.load(cask_path("with-#{artifact_dsl_key}-pkgutil")) }
let(:main_pkg_id) { "my.fancy.package.main" }
diff --git a/Library/Homebrew/test/cask/dsl/postflight_spec.rb b/Library/Homebrew/test/cask/dsl/postflight_spec.rb
index 259921fceb..bc36ff4367 100644
--- a/Library/Homebrew/test/cask/dsl/postflight_spec.rb
+++ b/Library/Homebrew/test/cask/dsl/postflight_spec.rb
@@ -6,7 +6,8 @@ require "test/cask/dsl/shared_examples/staged"
describe Cask::DSL::Postflight, :cask do
let(:cask) { Cask::CaskLoader.load(cask_path("basic-cask")) }
- let(:dsl) { described_class.new(cask, FakeSystemCommand) }
+ let(:fake_system_command) { class_double(SystemCommand) }
+ let(:dsl) { described_class.new(cask, fake_system_command) }
it_behaves_like Cask::DSL::Base
diff --git a/Library/Homebrew/test/cask/dsl/preflight_spec.rb b/Library/Homebrew/test/cask/dsl/preflight_spec.rb
index 93f1a60174..12cbf50b17 100644
--- a/Library/Homebrew/test/cask/dsl/preflight_spec.rb
+++ b/Library/Homebrew/test/cask/dsl/preflight_spec.rb
@@ -6,7 +6,8 @@ require "test/cask/dsl/shared_examples/staged"
describe Cask::DSL::Preflight, :cask do
let(:cask) { Cask::CaskLoader.load(cask_path("basic-cask")) }
- let(:dsl) { described_class.new(cask, FakeSystemCommand) }
+ let(:fake_system_command) { class_double(SystemCommand) }
+ let(:dsl) { described_class.new(cask, fake_system_command) }
it_behaves_like Cask::DSL::Base
diff --git a/Library/Homebrew/test/cask/dsl/shared_examples/staged.rb b/Library/Homebrew/test/cask/dsl/shared_examples/staged.rb
index b6490e825d..0036751501 100644
--- a/Library/Homebrew/test/cask/dsl/shared_examples/staged.rb
+++ b/Library/Homebrew/test/cask/dsl/shared_examples/staged.rb
@@ -4,8 +4,8 @@
require "cask/staged"
shared_examples Cask::Staged do
- let(:existing_path) { Pathname.new("/path/to/file/that/exists") }
- let(:non_existent_path) { Pathname.new("/path/to/file/that/does/not/exist") }
+ let(:existing_path) { Pathname("/path/to/file/that/exists") }
+ let(:non_existent_path) { Pathname("/path/to/file/that/does/not/exist") }
before do
allow(existing_path).to receive(:exist?).and_return(true)
@@ -17,9 +17,8 @@ shared_examples Cask::Staged do
end
it "can run system commands with list-form arguments" do
- FakeSystemCommand.expects_command(
- ["echo", "homebrew-cask", "rocks!"],
- )
+ expect(fake_system_command).to receive(:run!)
+ .with("echo", args: ["homebrew-cask", "rocks!"])
staged.system_command("echo", args: ["homebrew-cask", "rocks!"])
end
@@ -28,9 +27,8 @@ shared_examples Cask::Staged do
fake_pathname = existing_path
allow(staged).to receive(:Pathname).and_return(fake_pathname)
- FakeSystemCommand.expects_command(
- ["/bin/chmod", "-R", "--", "777", fake_pathname],
- )
+ expect(fake_system_command).to receive(:run!)
+ .with("/bin/chmod", args: ["-R", "--", "777", fake_pathname], sudo: false)
staged.set_permissions(fake_pathname.to_s, "777")
end
@@ -39,9 +37,8 @@ shared_examples Cask::Staged do
fake_pathname = existing_path
allow(staged).to receive(:Pathname).and_return(fake_pathname)
- FakeSystemCommand.expects_command(
- ["/bin/chmod", "-R", "--", "777", fake_pathname, fake_pathname],
- )
+ expect(fake_system_command).to receive(:run!)
+ .with("/bin/chmod", args: ["-R", "--", "777", fake_pathname, fake_pathname], sudo: false)
staged.set_permissions([fake_pathname.to_s, fake_pathname.to_s], "777")
end
@@ -58,9 +55,8 @@ shared_examples Cask::Staged do
allow(User).to receive(:current).and_return(User.new("fake_user"))
allow(staged).to receive(:Pathname).and_return(fake_pathname)
- FakeSystemCommand.expects_command(
- sudo("/usr/sbin/chown", "-R", "--", "fake_user:staff", fake_pathname),
- )
+ expect(fake_system_command).to receive(:run!)
+ .with("/usr/sbin/chown", args: ["-R", "--", "fake_user:staff", fake_pathname], sudo: true)
staged.set_ownership(fake_pathname.to_s)
end
@@ -71,9 +67,8 @@ shared_examples Cask::Staged do
allow(User).to receive(:current).and_return(User.new("fake_user"))
allow(staged).to receive(:Pathname).and_return(fake_pathname)
- FakeSystemCommand.expects_command(
- sudo("/usr/sbin/chown", "-R", "--", "fake_user:staff", fake_pathname, fake_pathname),
- )
+ expect(fake_system_command).to receive(:run!)
+ .with("/usr/sbin/chown", args: ["-R", "--", "fake_user:staff", fake_pathname, fake_pathname], sudo: true)
staged.set_ownership([fake_pathname.to_s, fake_pathname.to_s])
end
@@ -83,9 +78,8 @@ shared_examples Cask::Staged do
allow(staged).to receive(:Pathname).and_return(fake_pathname)
- FakeSystemCommand.expects_command(
- sudo("/usr/sbin/chown", "-R", "--", "other_user:other_group", fake_pathname),
- )
+ expect(fake_system_command).to receive(:run!)
+ .with("/usr/sbin/chown", args: ["-R", "--", "other_user:other_group", fake_pathname], sudo: true)
staged.set_ownership(fake_pathname.to_s, user: "other_user", group: "other_group")
end
diff --git a/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb b/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb
index 48c7653d5f..c188142015 100644
--- a/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb
+++ b/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb
@@ -5,7 +5,7 @@ require "test/cask/dsl/shared_examples/base"
describe Cask::DSL::UninstallPostflight, :cask do
let(:cask) { Cask::CaskLoader.load(cask_path("basic-cask")) }
- let(:dsl) { described_class.new(cask, FakeSystemCommand) }
+ let(:dsl) { described_class.new(cask, class_double(SystemCommand)) }
it_behaves_like Cask::DSL::Base
end
diff --git a/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb b/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb
index 635c35c030..e8d7d5c4ff 100644
--- a/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb
+++ b/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb
@@ -6,7 +6,8 @@ require "test/cask/dsl/shared_examples/staged"
describe Cask::DSL::UninstallPreflight, :cask do
let(:cask) { Cask::CaskLoader.load(cask_path("basic-cask")) }
- let(:dsl) { described_class.new(cask, FakeSystemCommand) }
+ let(:fake_system_command) { class_double(SystemCommand) }
+ let(:dsl) { described_class.new(cask, fake_system_command) }
it_behaves_like Cask::DSL::Base
diff --git a/Library/Homebrew/test/cask/pkg_spec.rb b/Library/Homebrew/test/cask/pkg_spec.rb
index e98face38a..cd45d57cf7 100644
--- a/Library/Homebrew/test/cask/pkg_spec.rb
+++ b/Library/Homebrew/test/cask/pkg_spec.rb
@@ -153,8 +153,12 @@ describe Cask::Pkg, :cask do
"/usr/sbin/pkgutil",
args: ["--pkg-info-plist", pkg_id],
).and_return(
- SystemCommand::Result.new(nil, [[:stdout, pkg_info_plist]], instance_double(Process::Status, exitstatus: 0),
- secrets: []),
+ SystemCommand::Result.new(
+ ["/usr/sbin/pkgutil", "--pkg-info-plist", pkg_id],
+ [[:stdout, pkg_info_plist]],
+ instance_double(Process::Status, exitstatus: 0),
+ secrets: [],
+ ),
)
info = pkg.info
diff --git a/Library/Homebrew/test/cmd/switch_spec.rb b/Library/Homebrew/test/cmd/switch_spec.rb
index b568e53000..8ad0ceb4c7 100644
--- a/Library/Homebrew/test/cmd/switch_spec.rb
+++ b/Library/Homebrew/test/cmd/switch_spec.rb
@@ -6,17 +6,3 @@ require "cmd/shared_examples/args_parse"
describe "Homebrew.switch_args" do
it_behaves_like "parseable arguments"
end
-
-describe "brew switch", :integration_test do
- it "allows switching between Formula versions" do
- install_test_formula "testball"
-
- testball_rack = HOMEBREW_CELLAR/"testball"
- FileUtils.cp_r testball_rack/"0.1", testball_rack/"0.2"
-
- expect { brew "switch", "testball", "0.2" }
- .to output(/links created/).to_stdout
- .and not_to_output.to_stderr
- .and be_a_success
- end
-end
diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb
index c91b27d04f..e09790157b 100644
--- a/Library/Homebrew/test/formula_spec.rb
+++ b/Library/Homebrew/test/formula_spec.rb
@@ -794,21 +794,19 @@ describe Formula do
f1 = formula "f1" do
url "f1-1"
- depends_on :java
depends_on x11: :recommended
depends_on xcode: ["1.0", :optional]
end
stub_formula_loader(f1)
- java = JavaRequirement.new
x11 = X11Requirement.new([:recommended])
xcode = XcodeRequirement.new(["1.0", :optional])
- expect(Set.new(f1.recursive_requirements)).to eq(Set[java, x11])
+ expect(Set.new(f1.recursive_requirements)).to eq(Set[x11])
f1.build = BuildOptions.new(["--with-xcode", "--without-x11"], f1.options)
- expect(Set.new(f1.recursive_requirements)).to eq(Set[java, xcode])
+ expect(Set.new(f1.recursive_requirements)).to eq(Set[xcode])
f1.build = f1.stable.build
f2 = formula "f2" do
@@ -817,14 +815,14 @@ describe Formula do
depends_on "f1"
end
- expect(Set.new(f2.recursive_requirements)).to eq(Set[java, x11])
- expect(Set.new(f2.recursive_requirements {})).to eq(Set[java, x11, xcode])
+ expect(Set.new(f2.recursive_requirements)).to eq(Set[x11])
+ expect(Set.new(f2.recursive_requirements {})).to eq(Set[x11, xcode])
requirements = f2.recursive_requirements do |_dependent, requirement|
- Requirement.prune if requirement.is_a?(JavaRequirement)
+ Requirement.prune if requirement.is_a?(X11Requirement)
end
- expect(Set.new(requirements)).to eq(Set[x11, xcode])
+ expect(Set.new(requirements)).to eq(Set[xcode])
end
specify "#to_hash" do
diff --git a/Library/Homebrew/test/language/java_spec.rb b/Library/Homebrew/test/language/java_spec.rb
index 52613697e0..ccabd4a0f4 100644
--- a/Library/Homebrew/test/language/java_spec.rb
+++ b/Library/Homebrew/test/language/java_spec.rb
@@ -6,13 +6,13 @@ require "language/java"
describe Language::Java do
describe "::java_home" do
if !OS.mac? || MacOS.version < :big_sur
- it "returns valid JAVA_HOME if version is specified", :needs_java do
+ it "returns valid JAVA_HOME if version is specified", :needs_macos do
java_home = described_class.java_home("1.6+")
expect(java_home/"bin/java").to be_an_executable
end
end
- it "returns valid JAVA_HOME if version is not specified", :needs_java do
+ it "returns valid JAVA_HOME if version is not specified", :needs_macos do
java_home = described_class.java_home
expect(java_home/"bin/java").to be_an_executable
end
@@ -24,7 +24,7 @@ describe Language::Java do
expect(java_home[:JAVA_HOME]).to include("--version blah")
end
- it "returns java_home path without version if version is not specified", :needs_java do
+ it "returns java_home path without version if version is not specified", :needs_macos do
java_home = described_class.java_home_env
expect(java_home[:JAVA_HOME]).not_to include("--version")
end
@@ -36,7 +36,7 @@ describe Language::Java do
expect(java_home[:JAVA_HOME]).to include("--version blah")
end
- it "returns java_home path without version if version is not specified", :needs_java do
+ it "returns java_home path without version if version is not specified", :needs_macos do
java_home = described_class.overridable_java_home_env
expect(java_home[:JAVA_HOME]).not_to include("--version")
end
diff --git a/Library/Homebrew/test/os/mac/java_requirement_spec.rb b/Library/Homebrew/test/os/mac/java_requirement_spec.rb
deleted file mode 100644
index 20ea5687b6..0000000000
--- a/Library/Homebrew/test/os/mac/java_requirement_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# typed: false
-# frozen_string_literal: true
-
-require "requirements/java_requirement"
-require "fileutils"
-
-describe JavaRequirement do
- subject { described_class.new(%w[1.8]) }
-
- let(:java_home) { mktmpdir }
-
- before do
- FileUtils.mkdir java_home/"bin"
- FileUtils.touch java_home/"bin/java"
- allow(subject).to receive(:preferred_java).and_return(java_home/"bin/java")
- end
-
- specify "Apple Java environment" do
- expect(subject).to be_satisfied
-
- expect(ENV).to receive(:prepend_path)
- expect(ENV).to receive(:append_to_cflags)
-
- subject.modify_build_environment
- expect(ENV["JAVA_HOME"]).to eq(java_home.to_s)
- end
-
- specify "Oracle Java environment" do
- expect(subject).to be_satisfied
-
- FileUtils.mkdir java_home/"include"
- expect(ENV).to receive(:prepend_path)
- expect(ENV).to receive(:append_to_cflags).twice
-
- subject.modify_build_environment
- expect(ENV["JAVA_HOME"]).to eq(java_home.to_s)
- end
-end
diff --git a/Library/Homebrew/test/requirements/java_requirement_spec.rb b/Library/Homebrew/test/requirements/java_requirement_spec.rb
deleted file mode 100644
index 95835ce2f7..0000000000
--- a/Library/Homebrew/test/requirements/java_requirement_spec.rb
+++ /dev/null
@@ -1,159 +0,0 @@
-# typed: false
-# frozen_string_literal: true
-
-require "requirements/java_requirement"
-
-describe JavaRequirement do
- subject { described_class.new([]) }
-
- before do
- ENV["JAVA_HOME"] = nil
- end
-
- describe "#initialize" do
- it "parses '1.8' tag correctly" do
- req = described_class.new(["1.8"])
- expect(req.display_s).to eq("Java = 1.8")
- end
-
- it "parses '9' tag correctly" do
- req = described_class.new(["9"])
- expect(req.display_s).to eq("Java = 9")
- end
-
- it "parses '9+' tag correctly" do
- req = described_class.new(["9+"])
- expect(req.display_s).to eq("Java >= 9")
- end
-
- it "parses '11' tag correctly" do
- req = described_class.new(["11"])
- expect(req.display_s).to eq("Java = 11")
- end
-
- it "parses bogus tag correctly" do
- req = described_class.new(["bogus1.8"])
- expect(req.display_s).to eq("Java")
- end
- end
-
- describe "#message" do
- its(:message) { is_expected.to match(/Java is required for this software./) }
- end
-
- describe "#inspect" do
- subject { described_class.new(%w[1.7+]) }
-
- its(:inspect) { is_expected.to eq('#') }
- end
-
- describe "#display_s" do
- context "without specific version" do
- its(:display_s) { is_expected.to eq("Java") }
- end
-
- context "with version 1.8" do
- subject { described_class.new(%w[1.8]) }
-
- its(:display_s) { is_expected.to eq("Java = 1.8") }
- end
-
- context "with version 1.8+" do
- subject { described_class.new(%w[1.8+]) }
-
- its(:display_s) { is_expected.to eq("Java >= 1.8") }
- end
- end
-
- describe "#satisfied?" do
- subject(:requirement) { described_class.new(%w[1.8]) }
-
- if !OS.mac? || MacOS.version < :big_sur
- it "returns false if no `java` executable can be found" do
- allow(File).to receive(:executable?).and_return(false)
- expect(requirement).not_to be_satisfied
- end
- end
-
- it "returns true if #preferred_java returns a path" do
- allow(requirement).to receive(:preferred_java).and_return(Pathname.new("/usr/bin/java"))
- expect(requirement).to be_satisfied
- end
-
- context "when #possible_javas contains paths" do
- let(:path) { mktmpdir }
- let(:java) { path/"java" }
-
- def setup_java_with_version(version)
- IO.write java, <<~SH
- #!/bin/sh
- echo 'java version "#{version}"' 1>&2
- SH
- FileUtils.chmod "+x", java
- end
-
- before do
- allow(requirement).to receive(:possible_javas).and_return([java])
- end
-
- context "and 1.7 is required" do
- subject(:requirement) { described_class.new(%w[1.7]) }
-
- it "returns false if all are lower" do
- setup_java_with_version "1.6.0_5"
- expect(requirement).not_to be_satisfied
- end
-
- it "returns true if one is equal" do
- setup_java_with_version "1.7.0_5"
- expect(requirement).to be_satisfied
- end
-
- it "returns false if all are higher" do
- setup_java_with_version "1.8.0_5"
- expect(requirement).not_to be_satisfied
- end
- end
-
- context "and 1.7+ is required" do
- subject(:requirement) { described_class.new(%w[1.7+]) }
-
- it "returns false if all are lower" do
- setup_java_with_version "1.6.0_5"
- expect(requirement).not_to be_satisfied
- end
-
- it "returns true if one is equal" do
- setup_java_with_version "1.7.0_5"
- expect(requirement).to be_satisfied
- end
-
- it "returns true if one is higher" do
- setup_java_with_version "1.8.0_5"
- expect(requirement).to be_satisfied
- end
- end
- end
- end
-
- describe "#suggestion" do
- context "without specific version" do
- its(:suggestion) { is_expected.to match(/brew install --cask adoptopenjdk/) }
- its(:cask) { is_expected.to eq("adoptopenjdk") }
- end
-
- context "with version 1.8" do
- subject { described_class.new(%w[1.8]) }
-
- its(:suggestion) { is_expected.to match(%r{brew install --cask homebrew/cask-versions/adoptopenjdk8}) }
- its(:cask) { is_expected.to eq("homebrew/cask-versions/adoptopenjdk8") }
- end
-
- context "with version 1.8+" do
- subject { described_class.new(%w[1.8+]) }
-
- its(:suggestion) { is_expected.to match(/brew install --cask adoptopenjdk/) }
- its(:cask) { is_expected.to eq("adoptopenjdk") }
- end
- end
-end
diff --git a/Library/Homebrew/test/rubocops/components_order_spec.rb b/Library/Homebrew/test/rubocops/components_order_spec.rb
index 8aa6bfc867..0a925d52ca 100644
--- a/Library/Homebrew/test/rubocops/components_order_spec.rb
+++ b/Library/Homebrew/test/rubocops/components_order_spec.rb
@@ -324,6 +324,7 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
homepage "https://brew.sh"
on_macos do
+ disable! because: :does_not_build
depends_on "readline"
end
@@ -341,6 +342,7 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
homepage "https://brew.sh"
on_linux do
+ deprecate! because: "it's deprecated"
depends_on "readline"
end
diff --git a/Library/Homebrew/test/rubocops/text_spec.rb b/Library/Homebrew/test/rubocops/text_spec.rb
index c308451b19..63c49df4f8 100644
--- a/Library/Homebrew/test/rubocops/text_spec.rb
+++ b/Library/Homebrew/test/rubocops/text_spec.rb
@@ -250,61 +250,6 @@ describe RuboCop::Cop::FormulaAudit::Text do
RUBY
end
- it "When using JAVA_HOME without a java dependency" do
- expect_offense(<<~RUBY)
- class Foo < Formula
- def install
- ohai "JAVA_HOME"
- ^^^^^^^^^^^ Use `depends_on :java` to set JAVA_HOME
- end
- end
- RUBY
- end
-
- it "When using JAVA_HOME with an openjdk dependency" do
- expect_no_offenses(<<~RUBY)
- class Foo < Formula
- depends_on "openjdk"
- def install
- ohai "JAVA_HOME"
- end
- end
- RUBY
- end
-
- it "When using JAVA_HOME with an openjdk build dependency" do
- expect_no_offenses(<<~RUBY)
- class Foo < Formula
- depends_on "openjdk" => :build
- def install
- ohai "JAVA_HOME"
- end
- end
- RUBY
- end
-
- it "When using JAVA_HOME with a java dependency" do
- expect_no_offenses(<<~RUBY)
- class Foo < Formula
- depends_on :java
- def install
- ohai "JAVA_HOME"
- end
- end
- RUBY
- end
-
- it "When using JAVA_HOME with a java build dependency" do
- expect_no_offenses(<<~RUBY)
- class Foo < Formula
- depends_on :java => :build
- def install
- ohai "JAVA_HOME"
- end
- end
- RUBY
- end
-
it "When using `prefix + \"bin\"` instead of `bin`" do
expect_offense(<<~RUBY)
class Foo < Formula
diff --git a/Library/Homebrew/test/support/helper/cask/fake_system_command.rb b/Library/Homebrew/test/support/helper/cask/fake_system_command.rb
deleted file mode 100644
index 2587e7bc52..0000000000
--- a/Library/Homebrew/test/support/helper/cask/fake_system_command.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# typed: true
-# frozen_string_literal: true
-
-def sudo(*args)
- ["/usr/bin/sudo", "-E", "--"] + args.flatten
-end
-
-class FakeSystemCommand
- def self.responses
- @responses ||= {}
- end
-
- def self.expectations
- @expectations ||= {}
- end
-
- def self.system_calls
- @system_calls ||= Hash.new(0)
- end
-
- def self.clear
- @responses = nil
- @expectations = nil
- @system_calls = nil
- end
-
- def self.stubs_command(command, response = "")
- command = command.map(&:to_s)
- responses[command] = response
- end
-
- def self.expects_command(command, response = "", times = 1)
- command = command.map(&:to_s)
- stubs_command(command, response)
- expectations[command] = times
- end
-
- def self.verify_expectations!
- expectations.each do |command, times|
- unless system_calls[command] == times
- raise("expected #{command.inspect} to be run #{times} times, but got #{system_calls[command]}")
- end
- end
- end
-
- def self.run(command_string, options = {})
- command = SystemCommand.new(command_string, options).command
- puts command
- unless responses.key?(command)
- raise("no response faked for #{command.inspect}, faked responses are: #{responses.inspect}")
- end
-
- system_calls[command] += 1
-
- response = responses[command]
- if response.respond_to?(:call)
- response.call(command_string, options)
- else
- SystemCommand::Result.new(command, [[:stdout, response]], OpenStruct.new(exitstatus: 0), secrets: [])
- end
- end
-
- def self.run!(command, options = {})
- run(command, options.merge(must_succeed: true))
- end
-end
-
-RSpec.configure do |config|
- config.after do
- FakeSystemCommand.verify_expectations!
- ensure
- FakeSystemCommand.clear
- end
-end
diff --git a/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb b/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb
index 760bd80147..1682091b97 100644
--- a/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb
+++ b/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb
@@ -4,7 +4,6 @@
require "cask/config"
require "cask/cache"
-require "test/support/helper/cask/fake_system_command"
require "test/support/helper/cask/install_helper"
require "test/support/helper/cask/never_sudo_system_command"
diff --git a/Library/Homebrew/test/utils/github_spec.rb b/Library/Homebrew/test/utils/github_spec.rb
index 1949123d28..8704b8f6a5 100644
--- a/Library/Homebrew/test/utils/github_spec.rb
+++ b/Library/Homebrew/test/utils/github_spec.rb
@@ -61,18 +61,24 @@ describe GitHub do
describe "::get_artifact_url", :needs_network do
it "fails to find a nonexistant workflow" do
expect {
- subject.get_artifact_url("Homebrew", "homebrew-core", 1)
+ subject.get_artifact_url(
+ subject.get_workflow_run("Homebrew", "homebrew-core", 1),
+ )
}.to raise_error(/No matching workflow run found/)
end
it "fails to find artifacts that don't exist" do
expect {
- subject.get_artifact_url("Homebrew", "homebrew-core", 51971, artifact_name: "false_bottles")
+ subject.get_artifact_url(
+ subject.get_workflow_run("Homebrew", "homebrew-core", 51971, artifact_name: "false_bottles"),
+ )
}.to raise_error(/No artifact .+ was found/)
end
it "gets an artifact link" do
- url = subject.get_artifact_url("Homebrew", "homebrew-core", 51971, artifact_name: "bottles")
+ url = subject.get_artifact_url(
+ subject.get_workflow_run("Homebrew", "homebrew-core", 51971, artifact_name: "bottles"),
+ )
expect(url).to eq("https://api.github.com/repos/Homebrew/homebrew-core/actions/artifacts/3557392/zip")
end
end
diff --git a/Library/Homebrew/test/utils/pypi_spec.rb b/Library/Homebrew/test/utils/pypi_spec.rb
new file mode 100644
index 0000000000..021a2215c8
--- /dev/null
+++ b/Library/Homebrew/test/utils/pypi_spec.rb
@@ -0,0 +1,171 @@
+# typed: false
+# frozen_string_literal: true
+
+require "utils/pypi"
+
+describe PyPI do
+ let(:package_url) do
+ "https://files.pythonhosted.org/packages/b0/3f/2e1dad67eb172b6443b5eb37eb885a054a55cfd733393071499514140282/"\
+ "snakemake-5.29.0.tar.gz"
+ end
+ let(:old_package_url) do
+ "https://files.pythonhosted.org/packages/6f/c4/da52bfdd6168ea46a0fe2b7c983b6c34c377a8733ec177cc00b197a96a9f/"\
+ "snakemake-5.28.0.tar.gz"
+ end
+
+ describe PyPI::Package do
+ let(:package_checksum) { "47417307d08ecb0707b3b29effc933bd63d8c8e3ab15509c62b685b7614c6568" }
+ let(:old_package_checksum) { "2367ce91baf7f8fa7738d33aff9670ffdf5410bbac49aeb209f73b45a3425046" }
+
+ let(:package) { described_class.new("snakemake") }
+ let(:package_with_version) { described_class.new("snakemake==5.28.0") }
+ let(:package_with_different_version) { described_class.new("snakemake==5.29.0") }
+ let(:package_with_extra) { described_class.new("snakemake[foo]") }
+ let(:package_with_extra_and_version) { described_class.new("snakemake[foo]==5.28.0") }
+ let(:package_from_url) { described_class.new(package_url, is_url: true) }
+ let(:other_package) { described_class.new("virtualenv==20.2.0") }
+
+ describe "initialize" do
+ it "initializes name" do
+ expect(described_class.new("foo").name).to eq "foo"
+ end
+
+ it "initializes name with extra" do
+ expect(described_class.new("foo[bar]").name).to eq "foo"
+ end
+
+ it "initializes extra" do
+ expect(described_class.new("foo[bar]").extras).to eq ["bar"]
+ end
+
+ it "initializes multiple extras" do
+ expect(described_class.new("foo[bar,baz]").extras).to eq ["bar", "baz"]
+ end
+
+ it "initializes name with version" do
+ expect(described_class.new("foo==1.2.3").name).to eq "foo"
+ end
+
+ it "initializes version" do
+ expect(described_class.new("foo==1.2.3").version).to eq "1.2.3"
+ end
+
+ it "initializes extra with version" do
+ expect(described_class.new("foo[bar]==1.2.3").extras).to eq ["bar"]
+ end
+
+ it "initializes multiple extras with version" do
+ expect(described_class.new("foo[bar,baz]==1.2.3").extras).to eq ["bar", "baz"]
+ end
+
+ it "initializes version with extra" do
+ expect(described_class.new("foo[bar]==1.2.3").version).to eq "1.2.3"
+ end
+
+ it "initializes version with multiple extras" do
+ expect(described_class.new("foo[bar,baz]==1.2.3").version).to eq "1.2.3"
+ end
+
+ it "initializes name from url" do
+ expect(described_class.new(package_url, is_url: true).name).to eq "snakemake"
+ end
+
+ it "initializes version from url" do
+ expect(described_class.new(package_url, is_url: true).version).to eq "5.29.0"
+ end
+ end
+
+ describe ".pypi_info", :needs_network do
+ it "gets pypi info from a package name" do
+ expect(package.pypi_info.first).to eq "snakemake"
+ end
+
+ it "gets pypi info from a package name and specified version" do
+ expect(package.pypi_info(version: "5.29.0")).to eq ["snakemake", package_url, package_checksum, "5.29.0"]
+ end
+
+ it "gets pypi info from a package name with extra" do
+ expect(package_with_extra.pypi_info.first).to eq "snakemake"
+ end
+
+ it "gets pypi info from a package name and version" do
+ expect(package_with_version.pypi_info).to eq ["snakemake", old_package_url, old_package_checksum, "5.28.0"]
+ end
+
+ it "gets pypi info from a package name with overriden version" do
+ expected_result = ["snakemake", package_url, package_checksum, "5.29.0"]
+ expect(package_with_version.pypi_info(version: "5.29.0")).to eq expected_result
+ end
+
+ it "gets pypi info from a package name, extras, and version" do
+ expected_result = ["snakemake", old_package_url, old_package_checksum, "5.28.0"]
+ expect(package_with_extra_and_version.pypi_info).to eq expected_result
+ end
+
+ it "gets pypi info from a url" do
+ expect(package_from_url.pypi_info).to eq ["snakemake", package_url, package_checksum, "5.29.0"]
+ end
+
+ it "gets pypi info from a url with overriden version" do
+ expected_result = ["snakemake", old_package_url, old_package_checksum, "5.28.0"]
+ expect(package_from_url.pypi_info(version: "5.28.0")).to eq expected_result
+ end
+ end
+
+ describe ".to_s" do
+ it "returns string representation of package name" do
+ expect(package.to_s).to eq "snakemake"
+ end
+
+ it "returns string representation of package with version" do
+ expect(package_with_version.to_s).to eq "snakemake==5.28.0"
+ end
+
+ it "returns string representation of package with extra" do
+ expect(package_with_extra.to_s).to eq "snakemake[foo]"
+ end
+
+ it "returns string representation of package with extra and version" do
+ expect(package_with_extra_and_version.to_s).to eq "snakemake[foo]==5.28.0"
+ end
+
+ it "returns string representation of package from url" do
+ expect(package_from_url.to_s).to eq "snakemake==5.29.0"
+ end
+ end
+
+ describe ".same_package?" do
+ it "returns false for different packages" do
+ expect(package.same_package?(other_package)).to eq false
+ end
+
+ it "returns true for the same package" do
+ expect(package.same_package?(package_with_version)).to eq true
+ end
+
+ it "returns true for the same package with different versions" do
+ expect(package_with_version.same_package?(package_with_different_version)).to eq true
+ end
+ end
+
+ describe "<=>" do
+ it "returns -1" do
+ expect(package <=> other_package).to eq((-1))
+ end
+
+ it "returns 0" do
+ expect(package <=> package_with_version).to eq 0
+ end
+
+ it "returns 1" do
+ expect(other_package <=> package_with_extra_and_version).to eq 1
+ end
+ end
+ end
+
+ describe "update_pypi_url", :needs_network do
+ it "updates url to new version" do
+ expect(described_class.update_pypi_url(old_package_url, "5.29.0")).to eq package_url
+ end
+ end
+end
diff --git a/Library/Homebrew/unpack_strategy/dmg.rb b/Library/Homebrew/unpack_strategy/dmg.rb
index db6f3285d5..b8395ddef5 100644
--- a/Library/Homebrew/unpack_strategy/dmg.rb
+++ b/Library/Homebrew/unpack_strategy/dmg.rb
@@ -91,8 +91,10 @@ module UnpackStrategy
Tempfile.open(["", ".bom"]) do |bomfile|
bomfile.close
+ bom = path.bom
+
Tempfile.open(["", ".list"]) do |filelist|
- filelist.puts(path.bom)
+ filelist.puts(bom)
filelist.close
system_command! "mkbom",
@@ -100,9 +102,23 @@ module UnpackStrategy
verbose: verbose
end
- system_command! "ditto",
- args: ["--bom", bomfile.path, "--", path, unpack_dir],
- verbose: verbose
+ result = system_command! "ditto",
+ args: ["--bom", bomfile.path, "--", path, unpack_dir],
+ verbose: verbose
+
+ if result.stderr.include?("contains no files, nothing copied")
+ all_paths_find = system_command("find", args: [".", "-print0"], chdir: path, print_stderr: false)
+ .stdout
+ .split("\0")
+
+ all_paths_ruby = Pathname.glob(path/"**/*", File::FNM_DOTMATCH)
+ .map { |p| p.relative_path_from(path).to_s }
+
+ odebug "BOM contents:", bom
+ odebug "BOM contents (retry):", path.bom
+ odebug "Directory contents (find):", all_paths_find.join("\n")
+ odebug "Directory contents (Ruby):", all_paths_ruby.join("\n")
+ end
FileUtils.chmod "u+w", Pathname.glob(unpack_dir/"**/*", File::FNM_DOTMATCH).reject(&:symlink?)
end
diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb
index a235b77d74..dfd585a567 100644
--- a/Library/Homebrew/utils/github.rb
+++ b/Library/Homebrew/utils/github.rb
@@ -96,9 +96,7 @@ module GitHub
return unless Homebrew::EnvConfig.github_api_username
return unless Homebrew::EnvConfig.github_api_password
- odeprecated "the GitHub API with HOMEBREW_GITHUB_API_PASSWORD", "HOMEBREW_GITHUB_API_TOKEN"
-
- [Homebrew::EnvConfig.github_api_password, Homebrew::EnvConfig.github_api_username]
+ odisabled "the GitHub API with HOMEBREW_GITHUB_API_PASSWORD", "HOMEBREW_GITHUB_API_TOKEN"
end
def keychain_username_password
@@ -510,7 +508,7 @@ module GitHub
open_api(url, data_binary_path: local_file, request_method: :POST, scopes: CREATE_ISSUE_FORK_OR_PR_SCOPES)
end
- def get_artifact_url(user, repo, pr, workflow_id: "tests.yml", artifact_name: "bottles")
+ def get_workflow_run(user, repo, pr, workflow_id: "tests.yml", artifact_name: "bottles")
scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES
base_url = "#{API_URL}/repos/#{user}/#{repo}"
pr_payload = open_api("#{base_url}/pulls/#{pr}", scopes: scopes)
@@ -523,6 +521,11 @@ module GitHub
run["head_sha"] == pr_sha
end
+ [workflow_run, pr_sha, pr_branch, pr, workflow_id, scopes, artifact_name]
+ end
+
+ def get_artifact_url(workflow_array)
+ workflow_run, pr_sha, pr_branch, pr, workflow_id, scopes, artifact_name = *workflow_array
if workflow_run.empty?
raise Error, <<~EOS
No matching workflow run found for these criteria!
diff --git a/Library/Homebrew/utils/inreplace.rb b/Library/Homebrew/utils/inreplace.rb
index b414647aea..951b55148c 100644
--- a/Library/Homebrew/utils/inreplace.rb
+++ b/Library/Homebrew/utils/inreplace.rb
@@ -34,7 +34,7 @@ module Utils
# @api public
sig do
params(
- paths: T.any(T::Array[T.untyped], String),
+ paths: T.any(T::Array[T.untyped], String, Pathname),
before: T.nilable(T.any(Regexp, String)),
after: T.nilable(T.any(String, Symbol)),
audit_result: T::Boolean,
diff --git a/Library/Homebrew/utils/pypi.rb b/Library/Homebrew/utils/pypi.rb
index 6f91f31b57..d1cffdfd36 100644
--- a/Library/Homebrew/utils/pypi.rb
+++ b/Library/Homebrew/utils/pypi.rb
@@ -5,70 +5,161 @@
#
# @api private
module PyPI
+ extend T::Sig
+
module_function
PYTHONHOSTED_URL_PREFIX = "https://files.pythonhosted.org/packages/"
private_constant :PYTHONHOSTED_URL_PREFIX
- AUTOMATIC_RESOURCE_UPDATE_BLOCKLIST = %w[
- ansible
- ansible@2.8
- cloudformation-cli
- diffoscope
- dxpy
- ipython
- molecule
- salt
- ].freeze
- private_constant :AUTOMATIC_RESOURCE_UPDATE_BLOCKLIST
-
@pipgrip_installed = nil
- def url_to_pypi_package_name(url)
- return unless url.start_with? PYTHONHOSTED_URL_PREFIX
+ # PyPI Package
+ #
+ # @api private
+ class Package
+ extend T::Sig
- File.basename(url).match(/^(.+)-[a-z\d.]+$/)[1]
+ attr_accessor :name
+ attr_accessor :extras
+ attr_accessor :version
+
+ sig { params(package_string: String, is_url: T::Boolean).void }
+ def initialize(package_string, is_url: false)
+ @pypi_info = nil
+
+ if is_url
+ unless package_string.start_with?(PYTHONHOSTED_URL_PREFIX) &&
+ match = File.basename(package_string).match(/^(.+)-([a-z\d.]+?)(?:.tar.gz|.zip)$/)
+ raise ArgumentError, "package should be a valid PyPI url"
+ end
+
+ @name = match[1]
+ @version = match[2]
+ return
+ end
+
+ @name = package_string
+ @name, @version = @name.split("==") if @name.include? "=="
+
+ return unless match = @name.match(/^(.*?)\[(.+)\]$/)
+
+ @name = match[1]
+ @extras = match[2].split ","
+ end
+
+ # Get name, URL, SHA-256 checksum, and latest version for a given PyPI package.
+ sig { params(version: T.nilable(T.any(String, Version))).returns(T.nilable(T::Array[String])) }
+ def pypi_info(version: nil)
+ return @pypi_info if @pypi_info.present? && version.blank?
+
+ version ||= @version
+ metadata_url = if version.present?
+ "https://pypi.org/pypi/#{@name}/#{version}/json"
+ else
+ "https://pypi.org/pypi/#{@name}/json"
+ end
+ out, _, status = curl_output metadata_url, "--location"
+
+ return unless status.success?
+
+ begin
+ json = JSON.parse out
+ rescue JSON::ParserError
+ return
+ end
+
+ sdist = json["urls"].find { |url| url["packagetype"] == "sdist" }
+ return json["info"]["name"] if sdist.nil?
+
+ @pypi_info = [json["info"]["name"], sdist["url"], sdist["digests"]["sha256"], json["info"]["version"]]
+ end
+
+ sig { returns(T::Boolean) }
+ def valid_pypi_package?
+ info = pypi_info
+ info.present? && info.is_a?(Array)
+ end
+
+ sig { returns(String) }
+ def to_s
+ out = @name
+ out += "[#{@extras.join(",")}]" if @extras.present?
+ out += "==#{@version}" if @version.present?
+ out
+ end
+
+ sig { params(other: Package).returns(T::Boolean) }
+ def same_package?(other)
+ @name.tr("_", "-") == other.name.tr("_", "-")
+ end
+
+ # Compare only names so we can use .include? on a Package array
+ sig { params(other: Package).returns(T::Boolean) }
+ def ==(other)
+ same_package?(other)
+ end
+
+ sig { params(other: Package).returns(T.nilable(Integer)) }
+ def <=>(other)
+ @name <=> other.name
+ end
end
+ sig { params(url: String, version: T.any(String, Version)).returns(T.nilable(String)) }
def update_pypi_url(url, version)
- package = url_to_pypi_package_name url
- return if package.nil?
+ package = Package.new url, is_url: true
- _, url = get_pypi_info(package, version)
+ _, url = package.pypi_info(version: version)
url
end
- # Get name, URL and SHA-256 checksum for a given PyPI package.
- def get_pypi_info(package, version)
- metadata_url = "https://pypi.org/pypi/#{package}/#{version}/json"
- out, _, status = curl_output metadata_url, "--location"
-
- return unless status.success?
-
- begin
- json = JSON.parse out
- rescue JSON::ParserError
- return
- end
-
- sdist = json["urls"].find { |url| url["packagetype"] == "sdist" }
- return json["info"]["name"] if sdist.nil?
-
- [json["info"]["name"], sdist["url"], sdist["digests"]["sha256"]]
- end
-
# Return true if resources were checked (even if no change).
- def update_python_resources!(formula, version = nil, print_only: false, silent: false,
- ignore_non_pypi_packages: false)
+ sig do
+ params(
+ formula: Formula,
+ version: T.nilable(String),
+ package_name: T.nilable(String),
+ extra_packages: T.nilable(T::Array[String]),
+ exclude_packages: T.nilable(T::Array[String]),
+ print_only: T::Boolean,
+ silent: T::Boolean,
+ ignore_non_pypi_packages: T::Boolean,
+ ).returns(T.nilable(T::Boolean))
+ end
+ def update_python_resources!(formula, version: nil, package_name: nil, extra_packages: nil, exclude_packages: nil,
+ print_only: false, silent: false, ignore_non_pypi_packages: false)
- if !print_only && AUTOMATIC_RESOURCE_UPDATE_BLOCKLIST.include?(formula.full_name)
- odie "The resources for \"#{formula.name}\" need special attention. Please update them manually."
- return
+ auto_update_list = formula.tap&.pypi_formula_mappings
+ if auto_update_list.present? && auto_update_list.key?(formula.full_name) &&
+ package_name.blank? && extra_packages.blank? && exclude_packages.blank?
+
+ list_entry = auto_update_list[formula.full_name]
+ case list_entry
+ when false
+ unless print_only
+ odie "The resources for \"#{formula.name}\" need special attention. Please update them manually."
+ end
+ when String
+ package_name = list_entry
+ when Hash
+ package_name = list_entry["package_name"]
+ extra_packages = list_entry["extra_packages"]
+ exclude_packages = list_entry["exclude_packages"]
+ end
end
- pypi_name = url_to_pypi_package_name formula.stable.url
+ main_package = if package_name.present?
+ Package.new(package_name)
+ else
+ begin
+ Package.new(formula.stable.url, is_url: true)
+ rescue ArgumentError
+ nil
+ end
+ end
- if pypi_name.nil?
+ if main_package.blank?
return if ignore_non_pypi_packages
odie <<~EOS
@@ -77,47 +168,81 @@ module PyPI
EOS
end
- version ||= formula.version
+ unless main_package.valid_pypi_package?
+ return if ignore_non_pypi_packages
- if get_pypi_info(pypi_name, version).blank?
- odie "\"#{pypi_name}\" at version #{version} is not available on PyPI." unless ignore_non_pypi_packages
- return
+ odie "\"#{main_package}\" is not available on PyPI."
end
- non_pypi_resources = formula.resources.reject do |resource|
- resource.url.start_with? PYTHONHOSTED_URL_PREFIX
+ main_package.version = version if version.present?
+
+ extra_packages = (extra_packages || []).map { |p| Package.new p }
+ exclude_packages = (exclude_packages || []).map { |p| Package.new p }
+
+ input_packages = [main_package]
+ extra_packages.each do |extra_package|
+ if !extra_package.valid_pypi_package? && !ignore_non_pypi_packages
+ odie "\"#{extra_package}\" is not available on PyPI."
+ end
+
+ input_packages.each do |existing_package|
+ if existing_package.same_package?(extra_package) && existing_package.version != extra_package.version
+ odie "Conflicting versions specified for the `#{extra_package.name}` package: "\
+ "#{existing_package.version}, #{extra_package.version}"
+ end
+ end
+
+ input_packages << extra_package unless input_packages.include? extra_package
end
- if non_pypi_resources.present? && !print_only
- odie "\"#{formula.name}\" contains non-PyPI resources. Please update the resources manually."
+ formula.resources.each do |resource|
+ if !print_only && !resource.url.start_with?(PYTHONHOSTED_URL_PREFIX)
+ odie "\"#{formula.name}\" contains non-PyPI resources. Please update the resources manually."
+ end
end
@pipgrip_installed ||= Formula["pipgrip"].any_version_installed?
odie '"pipgrip" must be installed (`brew install pipgrip`)' unless @pipgrip_installed
- ohai "Retrieving PyPI dependencies for \"#{pypi_name}==#{version}\"..." if !print_only && !silent
- pipgrip_output = Utils.popen_read Formula["pipgrip"].bin/"pipgrip", "--json", "--no-cache-dir",
- "#{pypi_name}==#{version}"
- unless $CHILD_STATUS.success?
- odie <<~EOS
- Unable to determine dependencies for \"#{pypi_name}\" because of a failure when running
- `pipgrip --json --no-cache-dir #{pypi_name}==#{version}`.
- Please update the resources for \"#{formula.name}\" manually.
- EOS
- end
+ found_packages = []
+ input_packages.each do |package|
+ ohai "Retrieving PyPI dependencies for \"#{package}\"..." if !print_only && !silent
+ pipgrip_output = Utils.popen_read Formula["pipgrip"].bin/"pipgrip", "--json", "--no-cache-dir", package.to_s
+ unless $CHILD_STATUS.success?
+ odie <<~EOS
+ Unable to determine dependencies for \"#{package}\" because of a failure when running
+ `pipgrip --json --no-cache-dir #{package}`.
+ Please update the resources for \"#{formula.name}\" manually.
+ EOS
+ end
- packages = JSON.parse(pipgrip_output).sort.to_h
+ JSON.parse(pipgrip_output).to_h.each do |new_name, new_version|
+ new_package = Package.new("#{new_name}==#{new_version}")
+
+ found_packages.each do |existing_package|
+ if existing_package.same_package?(new_package) && existing_package.version != new_package.version
+ odie "Conflicting versions found for the `#{new_package.name}` resource: "\
+ "#{existing_package.version}, #{new_package.version}"
+ end
+ end
+
+ found_packages << new_package unless found_packages.include? new_package
+ end
+ end
# Remove extra packages that may be included in pipgrip output
- exclude_list = %W[#{pypi_name.downcase} argparse pip setuptools wheel wsgiref]
- packages.delete_if do |package|
- exclude_list.include? package
- end
+ exclude_list = %W[#{main_package.name} argparse pip setuptools wheel wsgiref].map { |p| Package.new p }
+ found_packages.delete_if { |package| exclude_list.include? package }
new_resource_blocks = ""
- packages.each do |package, package_version|
- ohai "Getting PyPI info for \"#{package}==#{package_version}\"" if !print_only && !silent
- name, url, checksum = get_pypi_info package, package_version
+ found_packages.sort.each do |package|
+ if exclude_packages.include? package
+ ohai "Excluding \"#{package}\"" if !print_only && !silent
+ next
+ end
+
+ ohai "Getting PyPI info for \"#{package}\"" if !print_only && !silent
+ name, url, checksum = package.pypi_info
# Fail if unable to find name, url or checksum for any resource
if name.blank?
odie "Unable to resolve some dependencies. Please update the resources for \"#{formula.name}\" manually."
diff --git a/Library/Homebrew/utils/shared_audits.rb b/Library/Homebrew/utils/shared_audits.rb
index b8fdb8c0f6..6587672c8e 100644
--- a/Library/Homebrew/utils/shared_audits.rb
+++ b/Library/Homebrew/utils/shared_audits.rb
@@ -32,7 +32,6 @@ module SharedAudits
end
GITHUB_PRERELEASE_ALLOWLIST = {
- "amd-power-gadget" => :all,
"elm-format" => "0.8.3",
"extraterm" => :all,
"freetube" => :all,
diff --git a/Library/Homebrew/vendor/bundle/bundler/setup.rb b/Library/Homebrew/vendor/bundle/bundler/setup.rb
index fbfbedd4b5..ba4a5500af 100644
--- a/Library/Homebrew/vendor/bundle/bundler/setup.rb
+++ b/Library/Homebrew/vendor/bundle/bundler/setup.rb
@@ -47,11 +47,11 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/webrobots-0.1.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mechanize-2.7.6/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/method_source-1.0.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mustache-1.1.1/lib"
-$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.20.0/lib"
-$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.3.0/lib"
+$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.20.1/lib"
+$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.4.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.2.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib"
-$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.6100/lib"
+$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.6101/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parlour-4.0.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/patchelf-1.3.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib"
@@ -68,8 +68,8 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-mocks-3.10.0/li
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-3.10.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-its-1.3.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-retry-0.6.2/lib"
-$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.6100-universal-darwin-19/lib"
-$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.6100/lib"
+$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.6101-universal-darwin-19/lib"
+$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.6101/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-sorbet-1.7.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-wait-0.0.9/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-1.1.1/lib"
diff --git a/completions/internal_commands_list.txt b/completions/internal_commands_list.txt
index 9c91e9f1f3..13cf54e93a 100644
--- a/completions/internal_commands_list.txt
+++ b/completions/internal_commands_list.txt
@@ -68,7 +68,6 @@ pr-publish
pr-pull
pr-upload
prof
-pull
readall
reinstall
release-notes
diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock
index 584884075e..69694766ee 100644
--- a/docs/Gemfile.lock
+++ b/docs/Gemfile.lock
@@ -84,7 +84,7 @@ GEM
html-pipeline (2.14.0)
activesupport (>= 2)
nokogiri (>= 1.4)
- html-proofer (3.17.0)
+ html-proofer (3.17.1)
addressable (~> 2.3)
mercenary (~> 0.3)
nokogumbo (~> 2.0)
@@ -219,12 +219,12 @@ GEM
multipart-post (2.1.1)
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
- nokogumbo (2.0.2)
+ nokogumbo (2.0.3)
nokogiri (~> 1.8, >= 1.8.4)
octokit (4.18.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
- parallel (1.20.0)
+ parallel (1.20.1)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (3.1.1)
diff --git a/docs/Installation.md b/docs/Installation.md
index f9ebcad45b..6bc84a6563 100644
--- a/docs/Installation.md
+++ b/docs/Installation.md
@@ -11,7 +11,7 @@ it does it too. You have to confirm everything it will do before it starts.
## macOS Requirements
* A 64-bit Intel CPU [1](#1)
-* macOS High Sierra (10.13) (or higher) [2](#2)
+* macOS Mojave (10.14) (or higher) [2](#2)
* Command Line Tools (CLT) for Xcode: `xcode-select --install`,
[developer.apple.com/downloads](https://developer.apple.com/downloads) or
[Xcode](https://itunes.apple.com/us/app/xcode/id497799835) [3](#3)
@@ -52,7 +52,7 @@ Uninstallation is documented in the [FAQ](FAQ.md).
1 For 32-bit or PPC support see
[Tigerbrew](https://github.com/mistydemeo/tigerbrew).
-2 10.13 or higher is recommended. 10.9–10.12 are
+2 10.14 or higher is recommended. 10.9–10.13 are
supported on a best-effort basis. For 10.4-10.6 see
[Tigerbrew](https://github.com/mistydemeo/tigerbrew).
diff --git a/docs/Manpage.md b/docs/Manpage.md
index 280e07ca95..8c2c809f51 100644
--- a/docs/Manpage.md
+++ b/docs/Manpage.md
@@ -905,14 +905,16 @@ Display the path to the file being used when invoking `brew` *`cmd`*.
### `create` [*`options`*] *`URL`*
-Generate a formula for the downloadable file at *`URL`* and open it in the editor.
-Homebrew will attempt to automatically derive the formula name and version, but
-if it fails, you'll have to make your own template. The `wget` formula serves as
-a simple example. For the complete API, see:
+Generate a formula or, with `--cask`, a cask for the downloadable file at *`URL`*
+and open it in the editor. Homebrew will attempt to automatically derive the
+formula name and version, but if it fails, you'll have to make your own template.
+The `wget` formula serves as a simple example. For the complete API, see:
* `--autotools`:
Create a basic template for an Autotools-style build.
+* `--cask`:
+ Create a basic template for a cask.
* `--cmake`:
Create a basic template for a CMake-style build.
* `--crystal`:
@@ -936,9 +938,9 @@ a simple example. For the complete API, see:
* `--HEAD`:
Indicate that *`URL`* points to the package's repository rather than a file.
* `--set-name`:
- Explicitly set the *`name`* of the new formula.
+ Explicitly set the *`name`* of the new formula or cask.
* `--set-version`:
- Explicitly set the *`version`* of the new formula.
+ Explicitly set the *`version`* of the new formula or cask.
* `--set-license`:
Explicitly set the *`license`* of the new formula.
* `--tap`:
@@ -961,17 +963,6 @@ Build bottles for these formulae with GitHub Actions.
* `--upload`:
Upload built bottles to Bintray.
-### `diy` [*`options`*]
-
-Automatically determine the installation prefix for non-Homebrew software.
-Using the output from this command, you can install your own software into
-the Cellar and then link it into Homebrew's prefix with `brew link`.
-
-* `--name`:
- Explicitly set the *`name`* of the package being installed.
-* `--version`:
- Explicitly set the *`version`* of the package being installed.
-
### `edit` [*`formula`*|*`cask`*]
Open a *`formula`* or *`cask`* in the editor set by `EDITOR` or `HOMEBREW_EDITOR`,
@@ -1055,6 +1046,17 @@ Generate Homebrew's manpages.
* `--link`:
This is now done automatically by `brew update`.
+### `mirror` *`formula`*
+
+Reupload the stable URL of a formula to Bintray for use as a mirror.
+
+* `--bintray-org`:
+ Upload to the specified Bintray organisation (default: `homebrew`).
+* `--bintray-repo`:
+ Upload to the specified Bintray repository (default: `mirror`).
+* `--no-publish`:
+ Upload to Bintray, but don't publish.
+
### `pr-automerge` [*`options`*]
Find pull requests that can be automatically merged using `brew pr-publish`.
@@ -1115,7 +1117,7 @@ Requires write access to the repository.
* `--message`:
Message to include when autosquashing revision bumps, deletions, and rebuilds.
* `--workflow`:
- Retrieve artifacts from the specified workflow (default: `tests.yml`).
+ Retrieve artifacts from the specified workflow (default: `tests.yml`). Legacy: use --workflows instead
* `--artifact`:
Download artifacts with the specified name (default: `bottles`).
* `--bintray-org`:
@@ -1126,6 +1128,10 @@ Requires write access to the repository.
Use the specified *`URL`* as the root of the bottle's URL instead of Homebrew's default.
* `--bintray-mirror`:
Use the specified Bintray repository to automatically mirror stable URLs defined in the formulae (default: `mirror`).
+* `--workflows`:
+ Retrieve artifacts from the specified workflow (default: `tests.yml`) Comma-separated list to include multiple workflows.
+* `--ignore-missing-artifacts`:
+ Comma-separated list of workflows which can be ignored if they have not been run.
### `pr-upload` [*`options`*]
@@ -1305,6 +1311,12 @@ Update versions for PyPI resource blocks in *`formula`*.
Don't fail if *`formula`* is not a PyPI package.
* `--version`:
Use the specified *`version`* when finding resources for *`formula`*. If no version is specified, the current version for *`formula`* will be used.
+* `--package-name`:
+ Use the specified *`package-name`* when finding resources for *`formula`*. If no package name is specified, it will be inferred from the formula's stable URL.
+* `--extra-packages`:
+ Include these additional packages when finding resources.
+* `--exclude-packages`:
+ Exclude these packages when finding resources.
### `update-test` [*`options`*]
diff --git a/manpages/brew.1 b/manpages/brew.1
index e7287d93ed..0d2eeaf63b 100644
--- a/manpages/brew.1
+++ b/manpages/brew.1
@@ -1241,13 +1241,17 @@ Treat all named arguments as casks\.
Display the path to the file being used when invoking \fBbrew\fR \fIcmd\fR\.
.
.SS "\fBcreate\fR [\fIoptions\fR] \fIURL\fR"
-Generate a formula for the downloadable file at \fIURL\fR and open it in the editor\. Homebrew will attempt to automatically derive the formula name and version, but if it fails, you\'ll have to make your own template\. The \fBwget\fR formula serves as a simple example\. For the complete API, see: \fIhttps://rubydoc\.brew\.sh/Formula\fR
+Generate a formula or, with \fB\-\-cask\fR, a cask for the downloadable file at \fIURL\fR and open it in the editor\. Homebrew will attempt to automatically derive the formula name and version, but if it fails, you\'ll have to make your own template\. The \fBwget\fR formula serves as a simple example\. For the complete API, see: \fIhttps://rubydoc\.brew\.sh/Formula\fR
.
.TP
\fB\-\-autotools\fR
Create a basic template for an Autotools\-style build\.
.
.TP
+\fB\-\-cask\fR
+Create a basic template for a cask\.
+.
+.TP
\fB\-\-cmake\fR
Create a basic template for a CMake\-style build\.
.
@@ -1293,11 +1297,11 @@ Indicate that \fIURL\fR points to the package\'s repository rather than a file\.
.
.TP
\fB\-\-set\-name\fR
-Explicitly set the \fIname\fR of the new formula\.
+Explicitly set the \fIname\fR of the new formula or cask\.
.
.TP
\fB\-\-set\-version\fR
-Explicitly set the \fIversion\fR of the new formula\.
+Explicitly set the \fIversion\fR of the new formula or cask\.
.
.TP
\fB\-\-set\-license\fR
@@ -1334,17 +1338,6 @@ Dispatch specified workflow (default: \fBdispatch\-build\-bottle\.yml\fR)\.
\fB\-\-upload\fR
Upload built bottles to Bintray\.
.
-.SS "\fBdiy\fR [\fIoptions\fR]"
-Automatically determine the installation prefix for non\-Homebrew software\. Using the output from this command, you can install your own software into the Cellar and then link it into Homebrew\'s prefix with \fBbrew link\fR\.
-.
-.TP
-\fB\-\-name\fR
-Explicitly set the \fIname\fR of the package being installed\.
-.
-.TP
-\fB\-\-version\fR
-Explicitly set the \fIversion\fR of the package being installed\.
-.
.SS "\fBedit\fR [\fIformula\fR|\fIcask\fR]"
Open a \fIformula\fR or \fIcask\fR in the editor set by \fBEDITOR\fR or \fBHOMEBREW_EDITOR\fR, or open the Homebrew repository for editing if no formula is provided\.
.
@@ -1444,6 +1437,21 @@ Return a failing status code if changes are detected in the manpage outputs\. Th
\fB\-\-link\fR
This is now done automatically by \fBbrew update\fR\.
.
+.SS "\fBmirror\fR \fIformula\fR"
+Reupload the stable URL of a formula to Bintray for use as a mirror\.
+.
+.TP
+\fB\-\-bintray\-org\fR
+Upload to the specified Bintray organisation (default: \fBhomebrew\fR)\.
+.
+.TP
+\fB\-\-bintray\-repo\fR
+Upload to the specified Bintray repository (default: \fBmirror\fR)\.
+.
+.TP
+\fB\-\-no\-publish\fR
+Upload to Bintray, but don\'t publish\.
+.
.SS "\fBpr\-automerge\fR [\fIoptions\fR]"
Find pull requests that can be automatically merged using \fBbrew pr\-publish\fR\.
.
@@ -1539,7 +1547,7 @@ Message to include when autosquashing revision bumps, deletions, and rebuilds\.
.
.TP
\fB\-\-workflow\fR
-Retrieve artifacts from the specified workflow (default: \fBtests\.yml\fR)\.
+Retrieve artifacts from the specified workflow (default: \fBtests\.yml\fR)\. Legacy: use \-\-workflows instead
.
.TP
\fB\-\-artifact\fR
@@ -1561,6 +1569,14 @@ Use the specified \fIURL\fR as the root of the bottle\'s URL instead of Homebrew
\fB\-\-bintray\-mirror\fR
Use the specified Bintray repository to automatically mirror stable URLs defined in the formulae (default: \fBmirror\fR)\.
.
+.TP
+\fB\-\-workflows\fR
+Retrieve artifacts from the specified workflow (default: \fBtests\.yml\fR) Comma\-separated list to include multiple workflows\.
+.
+.TP
+\fB\-\-ignore\-missing\-artifacts\fR
+Comma\-separated list of workflows which can be ignored if they have not been run\.
+.
.SS "\fBpr\-upload\fR [\fIoptions\fR]"
Apply the bottle commit and publish bottles to Bintray or GitHub Releases\.
.
@@ -1797,6 +1813,18 @@ Don\'t fail if \fIformula\fR is not a PyPI package\.
\fB\-\-version\fR
Use the specified \fIversion\fR when finding resources for \fIformula\fR\. If no version is specified, the current version for \fIformula\fR will be used\.
.
+.TP
+\fB\-\-package\-name\fR
+Use the specified \fIpackage\-name\fR when finding resources for \fIformula\fR\. If no package name is specified, it will be inferred from the formula\'s stable URL\.
+.
+.TP
+\fB\-\-extra\-packages\fR
+Include these additional packages when finding resources\.
+.
+.TP
+\fB\-\-exclude\-packages\fR
+Exclude these packages when finding resources\.
+.
.SS "\fBupdate\-test\fR [\fIoptions\fR]"
Run a test of \fBbrew update\fR with a new repository clone\. If no options are passed, use \fBorigin/master\fR as the start commit\.
.