diff --git a/Library/Homebrew/cask/artifact/stage_only.rb b/Library/Homebrew/cask/artifact/stage_only.rb index 3c5f10b639..e1c22e050a 100644 --- a/Library/Homebrew/cask/artifact/stage_only.rb +++ b/Library/Homebrew/cask/artifact/stage_only.rb @@ -11,8 +11,10 @@ module Cask class StageOnly < AbstractArtifact extend T::Sig - def self.from_args(cask, *args) - raise CaskInvalidError.new(cask.token, "'stage_only' takes only a single argument: true") if args != [true] + def self.from_args(cask, *args, **kwargs) + if args != [true] || kwargs.present? + raise CaskInvalidError.new(cask.token, "'stage_only' takes only a single argument: true") + end new(cask, true) end diff --git a/Library/Homebrew/cask/artifact_set.rb b/Library/Homebrew/cask/artifact_set.rb new file mode 100644 index 0000000000..de4817fddd --- /dev/null +++ b/Library/Homebrew/cask/artifact_set.rb @@ -0,0 +1,22 @@ +# typed: false +# frozen_string_literal: true + +require "set" + +module Cask + # Sorted set containing all cask artifacts. + # + # @api private + class ArtifactSet < ::Set + def each(&block) + return enum_for(__method__) { size } unless block + + to_a.each(&block) + self + end + + def to_a + super.sort + end + end +end diff --git a/Library/Homebrew/cask/cmd/abstract_command.rb b/Library/Homebrew/cask/cmd/abstract_command.rb index 6c93a9e49f..6690ae55a3 100644 --- a/Library/Homebrew/cask/cmd/abstract_command.rb +++ b/Library/Homebrew/cask/cmd/abstract_command.rb @@ -33,8 +33,9 @@ module Cask Cmd.parser do instance_eval(&block) if block - OPTIONS.each do |option| - send(*option) + OPTIONS.map(&:dup).each do |option| + kwargs = option.pop + send(*option, **kwargs) end end end diff --git a/Library/Homebrew/cask/cmd/install.rb b/Library/Homebrew/cask/cmd/install.rb index 8b088de6b3..a52b412391 100644 --- a/Library/Homebrew/cask/cmd/install.rb +++ b/Library/Homebrew/cask/cmd/install.rb @@ -24,8 +24,9 @@ module Cask switch "--force", description: "Force overwriting existing files." - OPTIONS.each do |option| - send(*option) + OPTIONS.map(&:dup).each do |option| + kwargs = option.pop + send(*option, **kwargs) end instance_eval(&block) if block diff --git a/Library/Homebrew/cask/dsl.rb b/Library/Homebrew/cask/dsl.rb index fc01a79f90..88556e2624 100644 --- a/Library/Homebrew/cask/dsl.rb +++ b/Library/Homebrew/cask/dsl.rb @@ -6,6 +6,7 @@ require "lazy_object" require "livecheck" require "cask/artifact" +require "cask/artifact_set" require "cask/caskroom" require "cask/exceptions" @@ -207,14 +208,14 @@ module Cask end # @api public - def appcast(*args) - set_unique_stanza(:appcast, args.empty?) { DSL::Appcast.new(*args) } + def appcast(*args, **kwargs) + set_unique_stanza(:appcast, args.empty? && kwargs.empty?) { DSL::Appcast.new(*args, **kwargs) } end # @api public - def container(*args) - set_unique_stanza(:container, args.empty?) do - DSL::Container.new(*args) + def container(**kwargs) + set_unique_stanza(:container, kwargs.empty?) do + DSL::Container.new(**kwargs) end end @@ -261,12 +262,12 @@ module Cask # `depends_on` uses a load method so that multiple stanzas can be merged. # @api public - def depends_on(*args) + def depends_on(**kwargs) @depends_on ||= DSL::DependsOn.new - return @depends_on if args.empty? + return @depends_on if kwargs.empty? begin - @depends_on.load(*args) + @depends_on.load(**kwargs) rescue RuntimeError => e raise CaskInvalidError.new(cask, e) end @@ -274,13 +275,13 @@ module Cask end # @api public - def conflicts_with(*args) + def conflicts_with(**kwargs) # TODO: remove this constraint, and instead merge multiple conflicts_with stanzas - set_unique_stanza(:conflicts_with, args.empty?) { DSL::ConflictsWith.new(*args) } + set_unique_stanza(:conflicts_with, kwargs.empty?) { DSL::ConflictsWith.new(**kwargs) } end def artifacts - @artifacts ||= SortedSet.new + @artifacts ||= ArtifactSet.new end def caskroom_path @@ -337,13 +338,13 @@ module Cask end ORDINARY_ARTIFACT_CLASSES.each do |klass| - define_method(klass.dsl_key) do |*args| + define_method(klass.dsl_key) do |*args, **kwargs| if [*artifacts.map(&:class), klass].include?(Artifact::StageOnly) && (artifacts.map(&:class) & ACTIVATABLE_ARTIFACT_CLASSES).any? raise CaskInvalidError.new(cask, "'stage_only' must be the only activatable artifact.") end - artifacts.add(klass.from_args(cask, *args)) + artifacts.add(klass.from_args(cask, *args, **kwargs)) rescue CaskInvalidError raise rescue => e diff --git a/Library/Homebrew/cask/dsl/container.rb b/Library/Homebrew/cask/dsl/container.rb index a386adab8d..4d0d63213a 100644 --- a/Library/Homebrew/cask/dsl/container.rb +++ b/Library/Homebrew/cask/dsl/container.rb @@ -16,7 +16,7 @@ module Cask attr_accessor(*VALID_KEYS, :pairs) - def initialize(pairs = {}) + def initialize(**pairs) @pairs = pairs pairs.each do |key, value| raise "invalid container key: #{key.inspect}" unless VALID_KEYS.include?(key) diff --git a/Library/Homebrew/cask/dsl/version.rb b/Library/Homebrew/cask/dsl/version.rb index 6a643217fc..bb02439dbf 100644 --- a/Library/Homebrew/cask/dsl/version.rb +++ b/Library/Homebrew/cask/dsl/version.rb @@ -156,6 +156,12 @@ module Cask version { gsub(DIVIDER_REGEX, "") } end + # @api public + sig { params(separator: T.nilable(String)).returns(T.self_type) } + def chomp(separator = nil) + version { to_s.chomp(T.unsafe(separator)) } + end + private sig { returns(T.self_type) } diff --git a/Library/Homebrew/cli/parser.rb b/Library/Homebrew/cli/parser.rb index a507451f25..68e3f1e24f 100644 --- a/Library/Homebrew/cli/parser.rb +++ b/Library/Homebrew/cli/parser.rb @@ -367,8 +367,9 @@ module Homebrew end def cask_options - self.class.global_cask_options.each do |method, *args, **options| - send(method, *args, **options) + self.class.global_cask_options.each do |args| + options = args.pop + send(*args, **options) conflicts "--formula", args.last end @cask_options = true diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 60f2733cd1..f9eeb6a0b0 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -121,16 +121,18 @@ module Homebrew [:switch, "--overwrite", { description: "Delete files that already exist in the prefix while linking.", }], - ].each do |*args, **options| + ].each do |args| + options = args.pop send(*args, **options) conflicts "--cask", args.last end formula_options [ [:switch, "--cask", "--casks", { description: "Treat all named arguments as casks." }], - *Cask::Cmd::AbstractCommand::OPTIONS, - *Cask::Cmd::Install::OPTIONS, - ].each do |*args, **options| + *Cask::Cmd::AbstractCommand::OPTIONS.map(&:dup), + *Cask::Cmd::Install::OPTIONS.map(&:dup), + ].each do |args| + options = args.pop send(*args, **options) conflicts "--formula", args.last end diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index 62f4777e0d..863f8162db 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -68,18 +68,20 @@ module Homebrew [:switch, "-g", "--git", { description: "Create a Git repository, useful for creating patches to the software.", }], - ].each do |options| - send(*options) - conflicts "--cask", options[-2] + ].each do |args| + options = args.pop + send(*args, **options) + conflicts "--cask", args.last end formula_options [ [:switch, "--cask", "--casks", { description: "Treat all named arguments as casks." }], - *Cask::Cmd::AbstractCommand::OPTIONS, - *Cask::Cmd::Install::OPTIONS, - ].each do |options| - send(*options) - conflicts "--formula", options[-2] + *Cask::Cmd::AbstractCommand::OPTIONS.map(&:dup), + *Cask::Cmd::Install::OPTIONS.map(&:dup), + ].each do |args| + options = args.pop + send(*args, **options) + conflicts "--formula", args.last end cask_options diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index f176a26a5b..e33b3cab0b 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -76,9 +76,10 @@ module Homebrew env: :display_install_times, description: "Print install times for each package at the end of the run.", }], - ].each do |options| - send(*options) - conflicts "--cask", options[-2] + ].each do |args| + options = args.pop + send(*args, **options) + conflicts "--cask", args.last end formula_options [ @@ -86,11 +87,12 @@ module Homebrew description: "Treat all named arguments as casks. If no named arguments " \ "are specified, upgrade only outdated casks.", }], - *Cask::Cmd::AbstractCommand::OPTIONS, - *Cask::Cmd::Upgrade::OPTIONS, - ].each do |options| - send(*options) - conflicts "--formula", options[-2] + *Cask::Cmd::AbstractCommand::OPTIONS.map(&:dup), + *Cask::Cmd::Upgrade::OPTIONS.map(&:dup), + ].each do |args| + options = args.pop + send(*args, **options) + conflicts "--formula", args.last end cask_options diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 44815e7cd1..2c35aa08c4 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -594,7 +594,7 @@ class CurlGitHubPackagesDownloadStrategy < CurlDownloadStrategy # GitHub Packages authorization header. # HOMEBREW_GITHUB_PACKAGES_AUTH set in brew.sh meta[:headers] << "Authorization: #{HOMEBREW_GITHUB_PACKAGES_AUTH}" - super(url, name, version, meta) + super(url, name, version, **meta) end private diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index 29d1abfc54..df7353df8b 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -107,7 +107,7 @@ class SoftwareSpec def url(val = nil, specs = {}) return @resource.url if val.nil? - @resource.url(val, specs) + @resource.url(val, **specs) dependency_collector.add(@resource) end @@ -467,10 +467,11 @@ class Bottle image_name = GitHubPackages.image_formula_name(@name) image_tag = GitHubPackages.image_version_rebuild(version_rebuild) - resource.url("#{root_url}/#{image_name}/manifests/#{image_tag}", { + resource.url( + "#{root_url}/#{image_name}/manifests/#{image_tag}", using: CurlGitHubPackagesDownloadStrategy, headers: ["Accept: application/vnd.oci.image.index.v1+json"], - }) + ) resource.downloader.resolved_basename = "#{name}-#{version_rebuild}.bottle_manifest.json" resource end @@ -501,7 +502,7 @@ class Bottle filename = Filename.create(resource.owner, @tag, @spec.rebuild) path, resolved_basename = Utils::Bottles.path_resolved_basename(val, name, resource.checksum, filename) - @resource.url("#{val}/#{path}", select_download_strategy(specs)) + @resource.url("#{val}/#{path}", **select_download_strategy(specs)) @resource.downloader.resolved_basename = resolved_basename if resolved_basename.present? end end diff --git a/Library/Homebrew/system_command.rb b/Library/Homebrew/system_command.rb index 17ff585d10..2dca869746 100644 --- a/Library/Homebrew/system_command.rb +++ b/Library/Homebrew/system_command.rb @@ -24,12 +24,12 @@ class SystemCommand module Mixin extend T::Sig - def system_command(*args) - T.unsafe(SystemCommand).run(*args) + def system_command(executable, **options) + SystemCommand.run(executable, **options) end - def system_command!(*args) - T.unsafe(SystemCommand).run!(*args) + def system_command!(command, **options) + SystemCommand.run!(command, **options) end end @@ -37,11 +37,11 @@ class SystemCommand extend Predicable def self.run(executable, **options) - T.unsafe(self).new(executable, **options).run! + new(executable, **options).run! end def self.run!(command, **options) - T.unsafe(self).run(command, **options, must_succeed: true) + run(command, **options, must_succeed: true) end sig { returns(SystemCommand::Result) } diff --git a/Library/Homebrew/test/utils/user_spec.rb b/Library/Homebrew/test/utils/user_spec.rb index b223b30ec6..610d6b4c8b 100644 --- a/Library/Homebrew/test/utils/user_spec.rb +++ b/Library/Homebrew/test/utils/user_spec.rb @@ -10,7 +10,7 @@ describe User do describe "#gui?" do before do - allow(SystemCommand).to receive(:run).with("who") + allow(SystemCommand).to receive(:run).with("who", {}) .and_return([who_output, "", instance_double(Process::Status, success?: true)]) end diff --git a/Library/Homebrew/utils/gems.rb b/Library/Homebrew/utils/gems.rb index 24b7c5bd90..7db328ef4a 100644 --- a/Library/Homebrew/utils/gems.rb +++ b/Library/Homebrew/utils/gems.rb @@ -119,6 +119,10 @@ module Homebrew end def install_bundler! + if Gem.ruby_version >= Gem::Version.new("2.7") + raise "Installing and using Bundler is currently only supported on Ruby 2.6." + end + setup_gem_environment!(gem_home: gem_user_dir, gem_bindir: gem_user_bindir) install_gem_setup_path!( "bundler",