diff --git a/.gitignore b/.gitignore
index 459a668d06ee0..58bd229b00650 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,25 +53,6 @@
!**/vendor/bundle/ruby/*/gems/*/lib
!**/vendor/bundle/ruby/*/gems/addressable-*/data
!**/vendor/bundle/ruby/*/gems/public_suffix-*/data
-!**/vendor/bundle/ruby/*/gems/rubocop-performance-*/config
-!**/vendor/bundle/ruby/*/gems/rubocop-rails-*/config
-!**/vendor/bundle/ruby/*/gems/rubocop-rspec-*/config
-!**/vendor/bundle/ruby/*/gems/rubocop-sorbet-*/config
-
-# Ignore activesupport, except the ones we need.
-**/vendor/bundle/ruby/*/gems/activesupport-*/lib/**/*
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/*/
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/array/access.rb
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/enumerable.rb
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/file/atomic.rb
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/hash/deep_merge.rb
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/hash/deep_transform_values.rb
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/hash/keys.rb
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/object/deep_dup.rb
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/object/duplicable.rb
-!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/string/exclude.rb
# Ignore partially included gems where we don't need all files
**/vendor/gems/mechanize-*/.*
@@ -89,6 +70,7 @@
**/vendor/gems/mechanize-*/test/
# Ignore dependencies we don't wish to vendor
+**/vendor/bundle/ruby/*/gems/activesupport-*/
**/vendor/bundle/ruby/*/gems/ast-*/
**/vendor/bundle/ruby/*/gems/bootsnap-*/
**/vendor/bundle/ruby/*/gems/bundler-*/
diff --git a/Library/Homebrew/cask/artifact/abstract_artifact.rb b/Library/Homebrew/cask/artifact/abstract_artifact.rb
index 7e86cf4ac58a7..dcfddaca46223 100644
--- a/Library/Homebrew/cask/artifact/abstract_artifact.rb
+++ b/Library/Homebrew/cask/artifact/abstract_artifact.rb
@@ -2,7 +2,7 @@
# frozen_string_literal: true
require "attrable"
-require "active_support/core_ext/object/deep_dup"
+require "extend/object/deep_dup"
module Cask
module Artifact
diff --git a/Library/Homebrew/cask/artifact/abstract_uninstall.rb b/Library/Homebrew/cask/artifact/abstract_uninstall.rb
index db0dbe3551937..a08431eb93409 100644
--- a/Library/Homebrew/cask/artifact/abstract_uninstall.rb
+++ b/Library/Homebrew/cask/artifact/abstract_uninstall.rb
@@ -6,6 +6,7 @@
require "utils/user"
require "cask/artifact/abstract_artifact"
require "cask/pkg"
+require "extend/hash/keys"
module Cask
module Artifact
diff --git a/Library/Homebrew/cask/artifact/installer.rb b/Library/Homebrew/cask/artifact/installer.rb
index 69de947bea375..810a48b9f784d 100644
--- a/Library/Homebrew/cask/artifact/installer.rb
+++ b/Library/Homebrew/cask/artifact/installer.rb
@@ -2,6 +2,7 @@
# frozen_string_literal: true
require "cask/artifact/abstract_artifact"
+require "extend/hash/keys"
module Cask
module Artifact
diff --git a/Library/Homebrew/cask/artifact/pkg.rb b/Library/Homebrew/cask/artifact/pkg.rb
index 0d2610f29f620..5bf94b6ee6525 100644
--- a/Library/Homebrew/cask/artifact/pkg.rb
+++ b/Library/Homebrew/cask/artifact/pkg.rb
@@ -5,6 +5,7 @@
require "utils/user"
require "cask/artifact/abstract_artifact"
+require "extend/hash/keys"
module Cask
module Artifact
diff --git a/Library/Homebrew/cask/artifact/relocated.rb b/Library/Homebrew/cask/artifact/relocated.rb
index ecb6ba3242b1e..345699031dcdd 100644
--- a/Library/Homebrew/cask/artifact/relocated.rb
+++ b/Library/Homebrew/cask/artifact/relocated.rb
@@ -2,6 +2,7 @@
# frozen_string_literal: true
require "cask/artifact/abstract_artifact"
+require "extend/hash/keys"
module Cask
module Artifact
diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb
index 9adcb5ad8c58c..9516792de8ebc 100644
--- a/Library/Homebrew/cask/cask_loader.rb
+++ b/Library/Homebrew/cask/cask_loader.rb
@@ -5,6 +5,7 @@
require "cask/cask"
require "uri"
require "utils/curl"
+require "extend/hash/keys"
module Cask
# Loads a cask from various sources.
diff --git a/Library/Homebrew/cask/config.rb b/Library/Homebrew/cask/config.rb
index b546a44f48102..ac11934b7a756 100644
--- a/Library/Homebrew/cask/config.rb
+++ b/Library/Homebrew/cask/config.rb
@@ -5,6 +5,7 @@
require "lazy_object"
require "locale"
+require "extend/hash/keys"
module Cask
# Configuration for installing casks.
diff --git a/Library/Homebrew/cask/dsl/conflicts_with.rb b/Library/Homebrew/cask/dsl/conflicts_with.rb
index 40b19f60568bd..1b177198fd378 100644
--- a/Library/Homebrew/cask/dsl/conflicts_with.rb
+++ b/Library/Homebrew/cask/dsl/conflicts_with.rb
@@ -2,6 +2,7 @@
# frozen_string_literal: true
require "delegate"
+require "extend/hash/keys"
module Cask
class DSL
diff --git a/Library/Homebrew/cli/parser.rb b/Library/Homebrew/cli/parser.rb
index 4bb9aec91cdb7..1f2f4cdc186e7 100644
--- a/Library/Homebrew/cli/parser.rb
+++ b/Library/Homebrew/cli/parser.rb
@@ -126,9 +126,9 @@ def initialize(&block)
# Filter out Sorbet runtime type checking method calls.
cmd_location = T.must(caller_locations).select do |location|
T.must(location.path).exclude?("/gems/sorbet-runtime-")
- end.second
- @command_name = cmd_location.label.chomp("_args").tr("_", "-")
- @is_dev_cmd = cmd_location.absolute_path.start_with?(Commands::HOMEBREW_DEV_CMD_PATH)
+ end.fetch(1)
+ @command_name = T.must(cmd_location.label).chomp("_args").tr("_", "-")
+ @is_dev_cmd = T.must(cmd_location.absolute_path).start_with?(Commands::HOMEBREW_DEV_CMD_PATH)
@constraints = []
@conflicts = []
diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb
index 524674708d60e..7ebc235b33236 100644
--- a/Library/Homebrew/dev-cmd/bottle.rb
+++ b/Library/Homebrew/dev-cmd/bottle.rb
@@ -11,6 +11,7 @@
require "erb"
require "utils/gzip"
require "api"
+require "extend/hash/deep_merge"
BOTTLE_ERB = <<-EOS.freeze
bottle do
diff --git a/Library/Homebrew/dev-cmd/pr-upload.rb b/Library/Homebrew/dev-cmd/pr-upload.rb
index 971a191e72fb9..5f6fa25633dd1 100644
--- a/Library/Homebrew/dev-cmd/pr-upload.rb
+++ b/Library/Homebrew/dev-cmd/pr-upload.rb
@@ -5,6 +5,7 @@
require "formula"
require "github_packages"
require "github_releases"
+require "extend/hash/deep_merge"
module Homebrew
module_function
diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb
index 4f9becfad999a..af8931b6fe60f 100644
--- a/Library/Homebrew/download_strategy.rb
+++ b/Library/Homebrew/download_strategy.rb
@@ -360,7 +360,7 @@ def parse_basename(url, search_query: true)
end
if search_query && (uri_query = uri.query.presence)
- components[:query] = URI.decode_www_form(uri_query).map(&:second)
+ components[:query] = URI.decode_www_form(uri_query).map { _2 }
end
else
components[:path] = [url]
diff --git a/Library/Homebrew/extend/array.rb b/Library/Homebrew/extend/array.rb
index 2755ee92bf5a6..152033304bae3 100644
--- a/Library/Homebrew/extend/array.rb
+++ b/Library/Homebrew/extend/array.rb
@@ -1,7 +1,27 @@
-# typed: true
+# typed: strict
# frozen_string_literal: true
class Array
+ # Equal to self[1].
+ #
+ # %w( a b c d e ).second # => "b"
+ def second = self[1]
+
+ # Equal to self[2].
+ #
+ # %w( a b c d e ).third # => "c"
+ def third = self[2]
+
+ # Equal to self[3].
+ #
+ # %w( a b c d e ).fourth # => "d"
+ def fourth = self[3]
+
+ # Equal to self[4].
+ #
+ # %w( a b c d e ).fifth # => "e"
+ def fifth = self[4]
+
# Converts the array to a comma-separated sentence where the last element is
# joined by the connector word.
#
@@ -48,6 +68,7 @@ class Array
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ sig { params(words_connector: String, two_words_connector: String, last_word_connector: String).returns(String) }
def to_sentence(words_connector: ", ", two_words_connector: " and ", last_word_connector: " and ")
case length
when 0
diff --git a/Library/Homebrew/extend/array.rbi b/Library/Homebrew/extend/array.rbi
new file mode 100644
index 0000000000000..3d9e293bd459b
--- /dev/null
+++ b/Library/Homebrew/extend/array.rbi
@@ -0,0 +1,15 @@
+# typed: strict
+
+class Array
+ sig { returns(T.nilable(Elem)) }
+ def second; end
+
+ sig { returns(T.nilable(Elem)) }
+ def third; end
+
+ sig { returns(T.nilable(Elem)) }
+ def fourth; end
+
+ sig { returns(T.nilable(Elem)) }
+ def fifth; end
+end
diff --git a/Library/Homebrew/extend/enumerable.rb b/Library/Homebrew/extend/enumerable.rb
new file mode 100644
index 0000000000000..77b499b2ddc79
--- /dev/null
+++ b/Library/Homebrew/extend/enumerable.rb
@@ -0,0 +1,30 @@
+# typed: strict
+# frozen_string_literal: true
+
+module Enumerable
+ # The negative of the Enumerable#include?. Returns +true+ if the
+ # collection does not include the object.
+ sig { params(object: T.untyped).returns(T::Boolean) }
+ def exclude?(object) = !include?(object)
+
+ # Returns a new +Array+ without the blank items.
+ # Uses Object#blank? for determining if an item is blank.
+ #
+ # [1, "", nil, 2, " ", [], {}, false, true].compact_blank
+ # # => [1, 2, true]
+ #
+ # Set.new([nil, "", 1, false]).compact_blank
+ # # => [1]
+ #
+ # When called on a +Hash+, returns a new +Hash+ without the blank values.
+ #
+ # { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
+ # # => { b: 1, f: true }
+ sig { returns(T.self_type) }
+ def compact_blank = T.unsafe(self).reject(&:blank?)
+end
+
+class Hash
+ # Hash#reject has its own definition, so this needs one too.
+ def compact_blank = reject { |_k, v| T.unsafe(v).blank? }
+end
diff --git a/Library/Homebrew/extend/enumerable.rbi b/Library/Homebrew/extend/enumerable.rbi
new file mode 100644
index 0000000000000..207de60eb603d
--- /dev/null
+++ b/Library/Homebrew/extend/enumerable.rbi
@@ -0,0 +1,6 @@
+# typed: strict
+
+class Hash
+ sig { returns(T::Hash[Hash::K, Hash::V]) }
+ def compact_blank; end
+end
diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/file/atomic.rb b/Library/Homebrew/extend/file/atomic.rb
similarity index 75%
rename from Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/file/atomic.rb
rename to Library/Homebrew/extend/file/atomic.rb
index 9deceb1bb44d5..b57c9cc8504c9 100644
--- a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/file/atomic.rb
+++ b/Library/Homebrew/extend/file/atomic.rb
@@ -1,3 +1,4 @@
+# typed: strict
# frozen_string_literal: true
require "fileutils"
@@ -18,7 +19,14 @@ class File
# File.atomic_write('/data/something.important', '/data/tmp') do |file|
# file.write('hello')
# end
- def self.atomic_write(file_name, temp_dir = dirname(file_name))
+ sig {
+ type_parameters(:out).params(
+ file_name: T.any(Pathname, String),
+ temp_dir: String,
+ _block: T.proc.params(arg0: Tempfile).returns(T.type_parameter(:out)),
+ ).returns(T.type_parameter(:out))
+ }
+ def self.atomic_write(file_name, temp_dir = dirname(file_name), &_block)
require "tempfile" unless defined?(Tempfile)
Tempfile.open(".#{basename(file_name)}", temp_dir) do |temp_file|
@@ -38,32 +46,35 @@ def self.atomic_write(file_name, temp_dir = dirname(file_name))
if old_stat
# Set correct permissions on new file
begin
- chown(old_stat.uid, old_stat.gid, temp_file.path)
+ chown(old_stat.uid, old_stat.gid, T.must(temp_file.path))
# This operation will affect filesystem ACL's
- chmod(old_stat.mode, temp_file.path)
+ chmod(old_stat.mode, T.must(temp_file.path))
rescue Errno::EPERM, Errno::EACCES
# Changing file ownership failed, moving on.
end
end
# Overwrite original file with temp file
- rename(temp_file.path, file_name)
+ rename(T.must(temp_file.path), file_name)
return_val
end
end
# Private utility method.
- def self.probe_stat_in(dir) #:nodoc:
+ sig { params(dir: String).returns(T.nilable(File::Stat)) }
+ private_class_method def self.probe_stat_in(dir) # :nodoc:
basename = [
".permissions_check",
Thread.current.object_id,
Process.pid,
- rand(1000000)
+ rand(1_000_000),
].join(".")
file_name = join(dir, basename)
FileUtils.touch(file_name)
stat(file_name)
+ rescue Errno::ENOENT
+ file_name = nil
ensure
FileUtils.rm_f(file_name) if file_name
end
diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_merge.rb b/Library/Homebrew/extend/hash/deep_merge.rb
similarity index 81%
rename from Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_merge.rb
rename to Library/Homebrew/extend/hash/deep_merge.rb
index 9bc50b7bc63bf..01ecbe926044c 100644
--- a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_merge.rb
+++ b/Library/Homebrew/extend/hash/deep_merge.rb
@@ -1,3 +1,4 @@
+# typed: strict
# frozen_string_literal: true
class Hash
@@ -22,10 +23,10 @@ def deep_merge(other_hash, &block)
# Same as +deep_merge+, but modifies +self+.
def deep_merge!(other_hash, &block)
merge!(other_hash) do |key, this_val, other_val|
- if this_val.is_a?(Hash) && other_val.is_a?(Hash)
- this_val.deep_merge(other_val, &block)
- elsif block_given?
- block.call(key, this_val, other_val)
+ if T.unsafe(this_val).is_a?(Hash) && other_val.is_a?(Hash)
+ T.unsafe(this_val).deep_merge(other_val, &block)
+ elsif block
+ yield(key, this_val, other_val)
else
other_val
end
diff --git a/Library/Homebrew/extend/hash/deep_merge.rbi b/Library/Homebrew/extend/hash/deep_merge.rbi
new file mode 100644
index 0000000000000..ed5f3a9b6ce8e
--- /dev/null
+++ b/Library/Homebrew/extend/hash/deep_merge.rbi
@@ -0,0 +1,20 @@
+# typed: strict
+# frozen_string_literal: true
+
+class Hash
+ sig do
+ type_parameters(:k2).params(
+ other_hash: T::Hash[T.type_parameter(:k2), T.untyped],
+ block: T.nilable(T.proc.params(k: T.untyped, v1: T.untyped, v2: T.untyped).returns(T.untyped))
+ ).returns(T::Hash[T.any(Hash::K, T.type_parameter(:k2)), T.untyped])
+ end
+ def deep_merge(other_hash, &block); end
+
+ sig do
+ type_parameters(:k2).params(
+ other_hash: T::Hash[T.type_parameter(:k2), T.untyped],
+ block: T.nilable(T.proc.params(k: T.untyped, v1: T.untyped, v2: T.untyped).returns(T.untyped))
+ ).returns(T::Hash[T.any(Hash::K, T.type_parameter(:k2)), T.untyped])
+ end
+ def deep_merge!(other_hash, &block); end
+end
diff --git a/Library/Homebrew/extend/hash/deep_transform_values.rb b/Library/Homebrew/extend/hash/deep_transform_values.rb
new file mode 100644
index 0000000000000..608e3c73a87f4
--- /dev/null
+++ b/Library/Homebrew/extend/hash/deep_transform_values.rb
@@ -0,0 +1,46 @@
+# typed: strict
+# frozen_string_literal: true
+
+class Hash
+ # Returns a new hash with all values converted by the block operation.
+ # This includes the values from the root hash and from all
+ # nested hashes and arrays.
+ #
+ # hash = { person: { name: 'Rob', age: '28' } }
+ #
+ # hash.deep_transform_values{ |value| value.to_s.upcase }
+ # # => {person: {name: "ROB", age: "28"}}
+ def deep_transform_values(&block) = _deep_transform_values_in_object(self, &block)
+
+ # Destructively converts all values by using the block operation.
+ # This includes the values from the root hash and from all
+ # nested hashes and arrays.
+ def deep_transform_values!(&block) = _deep_transform_values_in_object!(self, &block)
+
+ private
+
+ # Support methods for deep transforming nested hashes and arrays.
+ sig { params(object: T.anything, block: T.proc.params(v: T.untyped).returns(T.untyped)).returns(T.untyped) }
+ def _deep_transform_values_in_object(object, &block)
+ case object
+ when Hash
+ object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
+ when Array
+ object.map { |e| _deep_transform_values_in_object(e, &block) }
+ else
+ yield(object)
+ end
+ end
+
+ sig { params(object: T.anything, block: T.proc.params(v: T.untyped).returns(T.untyped)).returns(T.untyped) }
+ def _deep_transform_values_in_object!(object, &block)
+ case object
+ when Hash
+ object.transform_values! { |value| _deep_transform_values_in_object!(value, &block) }
+ when Array
+ object.map! { |e| _deep_transform_values_in_object!(e, &block) }
+ else
+ yield(object)
+ end
+ end
+end
diff --git a/Library/Homebrew/extend/hash/deep_transform_values.rbi b/Library/Homebrew/extend/hash/deep_transform_values.rbi
new file mode 100644
index 0000000000000..29c8d273e2935
--- /dev/null
+++ b/Library/Homebrew/extend/hash/deep_transform_values.rbi
@@ -0,0 +1,17 @@
+# typed: strict
+
+class Hash
+ sig {
+ type_parameters(:out).params(
+ block: T.proc.params(o: Hash::V).returns(T.type_parameter(:out))
+ ).returns(T::Hash[Hash::K, T.type_parameter(:out)])
+ }
+ def deep_transform_values(&block); end
+
+ sig {
+ type_parameters(:out).params(
+ block: T.proc.params(o: Hash::V).returns(T.type_parameter(:out))
+ ).returns(T::Hash[Hash::K, T.type_parameter(:out)])
+ }
+ def deep_transform_values!(&block); end
+end
diff --git a/Library/Homebrew/extend/hash/keys.rb b/Library/Homebrew/extend/hash/keys.rb
new file mode 100644
index 0000000000000..caa742d3b2e03
--- /dev/null
+++ b/Library/Homebrew/extend/hash/keys.rb
@@ -0,0 +1,117 @@
+# typed: strict
+# frozen_string_literal: true
+
+class Hash
+ # Validates all keys in a hash match *valid_keys, raising
+ # +ArgumentError+ on a mismatch.
+ #
+ # Note that keys are treated differently than HashWithIndifferentAccess,
+ # meaning that string and symbol keys will not match.
+ #
+ # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age)
+ # # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
+ # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age')
+ # # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
+ # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
+ sig { params(valid_keys: T.untyped).void }
+ def assert_valid_keys(*valid_keys)
+ valid_keys.flatten!
+ each_key do |k|
+ next if valid_keys.include?(k)
+
+ raise ArgumentError,
+ "Unknown key: #{T.unsafe(k).inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(", ")}"
+ end
+ end
+
+ # Returns a new hash with all keys converted by the block operation.
+ # This includes the keys from the root hash and from all
+ # nested hashes and arrays.
+ #
+ # hash = { person: { name: 'Rob', age: '28' } }
+ #
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
+ # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
+ def deep_transform_keys(&block) = _deep_transform_keys_in_object(self, &block)
+
+ # Destructively converts all keys by using the block operation.
+ # This includes the keys from the root hash and from all
+ # nested hashes and arrays.
+ def deep_transform_keys!(&block) = _deep_transform_keys_in_object!(self, &block)
+
+ # Returns a new hash with all keys converted to strings.
+ # This includes the keys from the root hash and from all
+ # nested hashes and arrays.
+ #
+ # hash = { person: { name: 'Rob', age: '28' } }
+ #
+ # hash.deep_stringify_keys
+ # # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
+ def deep_stringify_keys = T.unsafe(self).deep_transform_keys(&:to_s)
+
+ # Destructively converts all keys to strings.
+ # This includes the keys from the root hash and from all
+ # nested hashes and arrays.
+ def deep_stringify_keys! = T.unsafe(self).deep_transform_keys!(&:to_s)
+
+ # Returns a new hash with all keys converted to symbols, as long as
+ # they respond to +to_sym+. This includes the keys from the root hash
+ # and from all nested hashes and arrays.
+ #
+ # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
+ #
+ # hash.deep_symbolize_keys
+ # # => {:person=>{:name=>"Rob", :age=>"28"}}
+ def deep_symbolize_keys
+ deep_transform_keys do |key|
+ T.unsafe(key).to_sym
+ rescue
+ key
+ end
+ end
+
+ # Destructively converts all keys to symbols, as long as they respond
+ # to +to_sym+. This includes the keys from the root hash and from all
+ # nested hashes and arrays.
+ def deep_symbolize_keys!
+ deep_transform_keys! do |key|
+ T.unsafe(key).to_sym
+ rescue
+ key
+ end
+ end
+
+ private
+
+ # Support methods for deep transforming nested hashes and arrays.
+ sig { params(object: T.anything, block: T.proc.params(k: T.untyped).returns(T.untyped)).returns(T.untyped) }
+ def _deep_transform_keys_in_object(object, &block)
+ case object
+ when Hash
+ object.each_with_object({}) do |(key, value), result|
+ result[yield(key)] = _deep_transform_keys_in_object(value, &block)
+ end
+ when Array
+ object.map { |e| _deep_transform_keys_in_object(e, &block) }
+ else
+ object
+ end
+ end
+
+ sig { params(object: T.anything, block: T.proc.params(k: T.untyped).returns(T.untyped)).returns(T.untyped) }
+ def _deep_transform_keys_in_object!(object, &block)
+ case object
+ when Hash
+ # We can't use `each_key` here because we're updating the hash in-place
+ object.keys.each do |key| # rubocop:disable Style/HashEachMethods
+ value = object.delete(key)
+ object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
+ end
+ object
+ when Array
+ object.map! { |e| _deep_transform_keys_in_object!(e, &block) }
+ else
+ object
+ end
+ end
+end
diff --git a/Library/Homebrew/extend/hash/keys.rbi b/Library/Homebrew/extend/hash/keys.rbi
new file mode 100644
index 0000000000000..581c876f7fa8d
--- /dev/null
+++ b/Library/Homebrew/extend/hash/keys.rbi
@@ -0,0 +1,30 @@
+# typed: strict
+# frozen_string_literal: true
+
+class Hash
+ sig {
+ type_parameters(:out).params(
+ block: T.proc.params(o: K).returns(T.type_parameter(:out))
+ ).returns(T::Hash[T.type_parameter(:out), V])
+ }
+ def deep_transform_keys(&block); end
+
+ sig {
+ type_parameters(:out).params(
+ block: T.proc.params(o: K).returns(T.type_parameter(:out))
+ ).returns(T::Hash[T.type_parameter(:out), V])
+ }
+ def deep_transform_keys!(&block); end
+
+ sig { returns(T::Hash[String, V]) }
+ def deep_stringify_keys; end
+
+ sig { returns(T::Hash[String, V]) }
+ def deep_stringify_keys!; end
+
+ sig { returns(T::Hash[Symbol, V]) }
+ def deep_symbolize_keys; end
+
+ sig { returns(T::Hash[Symbol, V]) }
+ def deep_symbolize_keys!; end
+end
diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/deep_dup.rb b/Library/Homebrew/extend/object/deep_dup.rb
similarity index 58%
rename from Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/deep_dup.rb
rename to Library/Homebrew/extend/object/deep_dup.rb
index 5c903917f5f06..24262d1a5a155 100644
--- a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/deep_dup.rb
+++ b/Library/Homebrew/extend/object/deep_dup.rb
@@ -1,6 +1,7 @@
+# typed: strict
# frozen_string_literal: true
-require "active_support/core_ext/object/duplicable"
+require "extend/object/duplicable"
class Object
# Returns a deep copy of object if it's duplicable. If it's
@@ -12,6 +13,7 @@ class Object
#
# object.instance_variable_defined?(:@a) # => false
# dup.instance_variable_defined?(:@a) # => true
+ sig { returns(T.self_type) }
def deep_dup
duplicable? ? dup : self
end
@@ -26,8 +28,9 @@ class Array
#
# array[1][2] # => nil
# dup[1][2] # => 4
+ sig { returns(T.self_type) }
def deep_dup
- map(&:deep_dup)
+ T.unsafe(self).map(&:deep_dup)
end
end
@@ -40,16 +43,35 @@ class Hash
#
# hash[:a][:c] # => nil
# dup[:a][:c] # => "c"
+ sig { returns(T.self_type) }
def deep_dup
hash = dup
each_pair do |key, value|
- if (::String === key && key.frozen?) || ::Symbol === key
- hash[key] = value.deep_dup
+ case key
+ when ::String, ::Symbol
+ hash[key] = T.unsafe(value).deep_dup
else
hash.delete(key)
- hash[key.deep_dup] = value.deep_dup
+ hash[T.unsafe(key).deep_dup] = T.unsafe(value).deep_dup
end
end
hash
end
end
+
+class Module
+ # Returns a copy of module or class if it's anonymous. If it's
+ # named, returns +self+.
+ #
+ # Object.deep_dup == Object # => true
+ # klass = Class.new
+ # klass.deep_dup == klass # => false
+ sig { returns(T.self_type) }
+ def deep_dup
+ if name.nil?
+ super
+ else
+ self
+ end
+ end
+end
diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/duplicable.rb b/Library/Homebrew/extend/object/duplicable.rb
similarity index 58%
rename from Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/duplicable.rb
rename to Library/Homebrew/extend/object/duplicable.rb
index 3ebcdca02b73c..d5f566cb52e64 100644
--- a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/duplicable.rb
+++ b/Library/Homebrew/extend/object/duplicable.rb
@@ -1,3 +1,4 @@
+# typed: strict
# frozen_string_literal: true
#--
@@ -23,27 +24,34 @@ class Object
#
# False for method objects;
# true otherwise.
- def duplicable?
- true
- end
+ sig { returns(T::Boolean) }
+ def duplicable? = true
end
class Method
# Methods are not duplicable:
#
- # method(:puts).duplicable? # => false
- # method(:puts).dup # => TypeError: allocator undefined for Method
- def duplicable?
- false
- end
+ # method(:puts).duplicable? # => false
+ # method(:puts).dup # => TypeError: allocator undefined for Method
+ sig { returns(FalseClass) }
+ def duplicable? = false
end
class UnboundMethod
# Unbound methods are not duplicable:
#
- # method(:puts).unbind.duplicable? # => false
- # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
- def duplicable?
- false
- end
+ # method(:puts).unbind.duplicable? # => false
+ # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
+ sig { returns(FalseClass) }
+ def duplicable? = false
+end
+
+require "singleton"
+
+module Singleton
+ # Singleton instances are not duplicable:
+ #
+ # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
+ sig { returns(FalseClass) }
+ def duplicable? = false
end
diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb
index c2b5a8a933296..82fdd38fcba1f 100644
--- a/Library/Homebrew/extend/pathname.rb
+++ b/Library/Homebrew/extend/pathname.rb
@@ -4,6 +4,7 @@
require "context"
require "resource"
require "metafiles"
+require "extend/file/atomic"
module DiskUsageExtension
sig { returns(Integer) }
diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/exclude.rb b/Library/Homebrew/extend/string.rb
similarity index 71%
rename from Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/exclude.rb
rename to Library/Homebrew/extend/string.rb
index 8e462689f1cc2..6beadc7272f67 100644
--- a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/exclude.rb
+++ b/Library/Homebrew/extend/string.rb
@@ -1,3 +1,4 @@
+# typed: strict
# frozen_string_literal: true
class String
@@ -7,7 +8,6 @@ class String
# "hello".exclude? "lo" # => false
# "hello".exclude? "ol" # => true
# "hello".exclude? ?h # => false
- def exclude?(string)
- !include?(string)
- end
+ sig { params(string: String).returns(T::Boolean) }
+ def exclude?(string) = !include?(string)
end
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index d99a518595fd9..4d7a21cf960bd 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -566,7 +566,7 @@ def expand_requirements
unsatisfied_reqs = Hash.new { |h, k| h[k] = [] }
formulae = [formula]
formula_deps_map = formula.recursive_dependencies
- .index_by(&:name)
+ .each_with_object({}) { |dep, h| h[dep.name] = dep }
while (f = formulae.pop)
runtime_requirements = runtime_requirements(f)
@@ -1208,7 +1208,7 @@ def fetch_bottle_tab
formula.fetch_bottle_tab
@bottle_tab_runtime_dependencies = formula.bottle_tab_attributes
.fetch("runtime_dependencies", [])
- .index_by { |dep| dep["full_name"] }
+ .each_with_object({}) { |dep, h| h[dep["full_name"]] = dep }
.freeze
true
rescue DownloadError, ArgumentError
diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb
index f473dcb08a5e9..5063333823207 100644
--- a/Library/Homebrew/formulary.rb
+++ b/Library/Homebrew/formulary.rb
@@ -8,8 +8,8 @@
require "service"
require "utils/curl"
require "deprecate_disable"
-
-require "active_support/core_ext/hash/deep_transform_values"
+require "extend/hash/deep_transform_values"
+require "extend/hash/keys"
# The {Formulary} is responsible for creating instances of {Formula}.
# It is not meant to be used directly from formulae.
diff --git a/Library/Homebrew/github_packages.rb b/Library/Homebrew/github_packages.rb
index 9d3fc79bcb845..1bcd1ccb59131 100644
--- a/Library/Homebrew/github_packages.rb
+++ b/Library/Homebrew/github_packages.rb
@@ -4,6 +4,7 @@
require "utils/curl"
require "json"
require "zlib"
+require "extend/hash/keys"
# GitHub Packages client.
#
diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb
index d747954e2bdae..0a04c785cde9a 100644
--- a/Library/Homebrew/global.rb
+++ b/Library/Homebrew/global.rb
@@ -10,14 +10,10 @@
require "forwardable"
require "set"
-# Only require "core_ext" here to ensure we're only requiring the minimum of
-# what we need.
-require "active_support/core_ext/array/access"
-require "active_support/core_ext/enumerable"
-require "active_support/core_ext/file/atomic"
-require "active_support/core_ext/hash/deep_merge"
-require "active_support/core_ext/hash/keys"
-require "active_support/core_ext/string/exclude"
+require "extend/array"
+require "extend/blank"
+require "extend/enumerable"
+require "extend/string"
HOMEBREW_API_DEFAULT_DOMAIN = ENV.fetch("HOMEBREW_API_DEFAULT_DOMAIN").freeze
HOMEBREW_BOTTLE_DEFAULT_DOMAIN = ENV.fetch("HOMEBREW_BOTTLE_DEFAULT_DOMAIN").freeze
@@ -70,8 +66,6 @@
%r[https://github\.com/([\w-]+)/([\w-]+)?/(?:pull/(\d+)|commit/[0-9a-fA-F]{4,40})]
HOMEBREW_BOTTLES_EXTNAME_REGEX = /\.([a-z0-9_]+)\.bottle\.(?:(\d+)\.)?tar\.gz$/
-require "extend/module"
-require "extend/blank"
require "env_config"
require "macos_version"
require "os"
@@ -130,7 +124,6 @@ def auto_update_command?
end
require "context"
-require "extend/array"
require "git_repository"
require "extend/pathname"
require "cli/args"
diff --git a/Library/Homebrew/livecheck/strategy/gnu.rb b/Library/Homebrew/livecheck/strategy/gnu.rb
index 90c39af566d40..090d8d0be1725 100644
--- a/Library/Homebrew/livecheck/strategy/gnu.rb
+++ b/Library/Homebrew/livecheck/strategy/gnu.rb
@@ -1,4 +1,4 @@
-# typed: true
+# typed: strict
# frozen_string_literal: true
module Homebrew
@@ -32,11 +32,11 @@ class Gnu
NICE_NAME = "GNU"
# The `Regexp` used to determine if the strategy applies to the URL.
- URL_MATCH_REGEX = %r{
+ URL_MATCH_REGEX = T.let(%r{
^https?://
(?:(?:[^/]+?\.)*gnu\.org/(?:gnu|software)/(?[^/]+)/
|(?[^/]+)\.gnu\.org/?$)
- }ix
+ }ix, Regexp)
# Whether the strategy can be applied to the provided URL.
#
diff --git a/Library/Homebrew/rubocops.rb b/Library/Homebrew/rubocops.rb
index 187b69236835e..3e5daa64c331e 100644
--- a/Library/Homebrew/rubocops.rb
+++ b/Library/Homebrew/rubocops.rb
@@ -2,6 +2,5 @@
# frozen_string_literal: true
require_relative "standalone"
-require_relative "extend/module"
require "rubocops/all"
diff --git a/Library/Homebrew/rubocops/shell_commands.rb b/Library/Homebrew/rubocops/shell_commands.rb
index 2a431fd19227d..1672b414e5e03 100644
--- a/Library/Homebrew/rubocops/shell_commands.rb
+++ b/Library/Homebrew/rubocops/shell_commands.rb
@@ -1,7 +1,7 @@
# typed: true
# frozen_string_literal: true
-require "active_support/core_ext/array/access"
+require "extend/array"
require "rubocops/shared/helper_functions"
require "shellwords"
diff --git a/Library/Homebrew/standalone/sorbet.rb b/Library/Homebrew/standalone/sorbet.rb
index 4aaa7e965ac29..d15116a8f1e4b 100644
--- a/Library/Homebrew/standalone/sorbet.rb
+++ b/Library/Homebrew/standalone/sorbet.rb
@@ -2,6 +2,7 @@
# frozen_string_literal: true
require "sorbet-runtime"
+require "extend/module"
# Disable runtime checking unless enabled.
# In the future we should consider not doing this monkey patch,
diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb
index d38503bde7da5..44225a085bc4e 100644
--- a/Library/Homebrew/tab.rb
+++ b/Library/Homebrew/tab.rb
@@ -92,7 +92,7 @@ def self.from_file_content(content, path)
end
if attributes["source"]["spec"].nil?
- version = PkgVersion.parse path.to_s.split("/").second_to_last
+ version = PkgVersion.parse(File.basename(File.dirname(path)))
attributes["source"]["spec"] = if version.head?
"head"
else
diff --git a/Library/Homebrew/utils/gems.rb b/Library/Homebrew/utils/gems.rb
index c6762c4985651..5479d3f419f7d 100644
--- a/Library/Homebrew/utils/gems.rb
+++ b/Library/Homebrew/utils/gems.rb
@@ -12,9 +12,9 @@ module Homebrew
# After updating this, run `brew vendor-gems --update=--bundler`.
HOMEBREW_BUNDLER_VERSION = "2.4.18"
- # Bump this whenever a committed vendored gem is later added to gitignore.
+ # Bump this whenever a committed vendored gem is later added to or exclusion removed from gitignore.
# This will trigger it to reinstall properly if `brew install-bundler-gems` needs it.
- VENDOR_VERSION = 4
+ VENDOR_VERSION = 5
private_constant :VENDOR_VERSION
RUBY_BUNDLE_VENDOR_DIRECTORY = (HOMEBREW_LIBRARY_PATH/"vendor/bundle/ruby").freeze
diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/MIT-LICENSE b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/MIT-LICENSE
deleted file mode 100644
index 0a0ce3889a0c1..0000000000000
--- a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/MIT-LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2005-2022 David Heinemeier Hansson
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/array/access.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/array/access.rb
deleted file mode 100644
index ea01e5891c397..0000000000000
--- a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/array/access.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: true
-
-class Array
- # Returns the tail of the array from +position+.
- #
- # %w( a b c d ).from(0) # => ["a", "b", "c", "d"]
- # %w( a b c d ).from(2) # => ["c", "d"]
- # %w( a b c d ).from(10) # => []
- # %w().from(0) # => []
- # %w( a b c d ).from(-2) # => ["c", "d"]
- # %w( a b c ).from(-10) # => []
- def from(position)
- self[position, length] || []
- end
-
- # Returns the beginning of the array up to +position+.
- #
- # %w( a b c d ).to(0) # => ["a"]
- # %w( a b c d ).to(2) # => ["a", "b", "c"]
- # %w( a b c d ).to(10) # => ["a", "b", "c", "d"]
- # %w().to(0) # => []
- # %w( a b c d ).to(-2) # => ["a", "b", "c"]
- # %w( a b c ).to(-10) # => []
- def to(position)
- if position >= 0
- take position + 1
- else
- self[0..position]
- end
- end
-
- # Returns a new array that includes the passed elements.
- #
- # [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
- # [ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ]
- def including(*elements)
- self + elements.flatten(1)
- end
-
- # Returns a copy of the Array excluding the specified elements.
- #
- # ["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]
- # [ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ]) # => [ [ 0, 1 ] ]
- #
- # Note: This is an optimization of Enumerable#excluding that uses Array#-
- # instead of Array#reject for performance reasons.
- def excluding(*elements)
- self - elements.flatten(1)
- end
-
- # Alias for #excluding.
- def without(*elements)
- excluding(*elements)
- end
-
- # Equal to self[1].
- #
- # %w( a b c d e ).second # => "b"
- def second
- self[1]
- end
-
- # Equal to self[2].
- #
- # %w( a b c d e ).third # => "c"
- def third
- self[2]
- end
-
- # Equal to self[3].
- #
- # %w( a b c d e ).fourth # => "d"
- def fourth
- self[3]
- end
-
- # Equal to self[4].
- #
- # %w( a b c d e ).fifth # => "e"
- def fifth
- self[4]
- end
-
- # Equal to self[41]. Also known as accessing "the reddit".
- #
- # (1..42).to_a.forty_two # => 42
- def forty_two
- self[41]
- end
-
- # Equal to self[-3].
- #
- # %w( a b c d e ).third_to_last # => "c"
- def third_to_last
- self[-3]
- end
-
- # Equal to self[-2].
- #
- # %w( a b c d e ).second_to_last # => "d"
- def second_to_last
- self[-2]
- end
-end
diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/enumerable.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/enumerable.rb
deleted file mode 100644
index 97c918a71f89e..0000000000000
--- a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/enumerable.rb
+++ /dev/null
@@ -1,260 +0,0 @@
-# frozen_string_literal: true
-
-module Enumerable
- INDEX_WITH_DEFAULT = Object.new
- private_constant :INDEX_WITH_DEFAULT
-
- # Enumerable#sum was added in Ruby 2.4, but it only works with Numeric elements
- # when we omit an identity.
-
- # :stopdoc:
-
- # We can't use Refinements here because Refinements with Module which will be prepended
- # doesn't work well https://bugs.ruby-lang.org/issues/13446
- alias :_original_sum_with_required_identity :sum
- private :_original_sum_with_required_identity
-
- # :startdoc:
-
- # Calculates a sum from the elements.
- #
- # payments.sum { |p| p.price * p.tax_rate }
- # payments.sum(&:price)
- #
- # The latter is a shortcut for:
- #
- # payments.inject(0) { |sum, p| sum + p.price }
- #
- # It can also calculate the sum without the use of a block.
- #
- # [5, 15, 10].sum # => 30
- # ['foo', 'bar'].sum # => "foobar"
- # [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5]
- #
- # The default sum of an empty list is zero. You can override this default:
- #
- # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
- def sum(identity = nil, &block)
- if identity
- _original_sum_with_required_identity(identity, &block)
- elsif block_given?
- map(&block).sum(identity)
- else
- inject(:+) || 0
- end
- end
-
- # Convert an enumerable to a hash, using the block result as the key and the
- # element as the value.
- #
- # people.index_by(&:login)
- # # => { "nextangle" => , "chade-" => , ...}
- #
- # people.index_by { |person| "#{person.first_name} #{person.last_name}" }
- # # => { "Chade- Fowlersburg-e" => , "David Heinemeier Hansson" => , ...}
- def index_by
- if block_given?
- result = {}
- each { |elem| result[yield(elem)] = elem }
- result
- else
- to_enum(:index_by) { size if respond_to?(:size) }
- end
- end
-
- # Convert an enumerable to a hash, using the element as the key and the block
- # result as the value.
- #
- # post = Post.new(title: "hey there", body: "what's up?")
- #
- # %i( title body ).index_with { |attr_name| post.public_send(attr_name) }
- # # => { title: "hey there", body: "what's up?" }
- #
- # If an argument is passed instead of a block, it will be used as the value
- # for all elements:
- #
- # %i( created_at updated_at ).index_with(Time.now)
- # # => { created_at: 2020-03-09 22:31:47, updated_at: 2020-03-09 22:31:47 }
- def index_with(default = INDEX_WITH_DEFAULT)
- if block_given?
- result = {}
- each { |elem| result[elem] = yield(elem) }
- result
- elsif default != INDEX_WITH_DEFAULT
- result = {}
- each { |elem| result[elem] = default }
- result
- else
- to_enum(:index_with) { size if respond_to?(:size) }
- end
- end
-
- # Returns +true+ if the enumerable has more than 1 element. Functionally
- # equivalent to enum.to_a.size > 1. Can be called with a block too,
- # much like any?, so people.many? { |p| p.age > 26 } returns +true+
- # if more than one person is over 26.
- def many?
- cnt = 0
- if block_given?
- any? do |element|
- cnt += 1 if yield element
- cnt > 1
- end
- else
- any? { (cnt += 1) > 1 }
- end
- end
-
- # Returns a new array that includes the passed elements.
- #
- # [ 1, 2, 3 ].including(4, 5)
- # # => [ 1, 2, 3, 4, 5 ]
- #
- # ["David", "Rafael"].including %w[ Aaron Todd ]
- # # => ["David", "Rafael", "Aaron", "Todd"]
- def including(*elements)
- to_a.including(*elements)
- end
-
- # The negative of the Enumerable#include?. Returns +true+ if the
- # collection does not include the object.
- def exclude?(object)
- !include?(object)
- end
-
- # Returns a copy of the enumerable excluding the specified elements.
- #
- # ["David", "Rafael", "Aaron", "Todd"].excluding "Aaron", "Todd"
- # # => ["David", "Rafael"]
- #
- # ["David", "Rafael", "Aaron", "Todd"].excluding %w[ Aaron Todd ]
- # # => ["David", "Rafael"]
- #
- # {foo: 1, bar: 2, baz: 3}.excluding :bar
- # # => {foo: 1, baz: 3}
- def excluding(*elements)
- elements.flatten!(1)
- reject { |element| elements.include?(element) }
- end
-
- # Alias for #excluding.
- def without(*elements)
- excluding(*elements)
- end
-
- # Extract the given key from each element in the enumerable.
- #
- # [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
- # # => ["David", "Rafael", "Aaron"]
- #
- # [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name)
- # # => [[1, "David"], [2, "Rafael"]]
- def pluck(*keys)
- if keys.many?
- map { |element| keys.map { |key| element[key] } }
- else
- key = keys.first
- map { |element| element[key] }
- end
- end
-
- # Extract the given key from the first element in the enumerable.
- #
- # [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pick(:name)
- # # => "David"
- #
- # [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pick(:id, :name)
- # # => [1, "David"]
- def pick(*keys)
- return if none?
-
- if keys.many?
- keys.map { |key| first[key] }
- else
- first[keys.first]
- end
- end
-
- # Returns a new +Array+ without the blank items.
- # Uses Object#blank? for determining if an item is blank.
- #
- # [1, "", nil, 2, " ", [], {}, false, true].compact_blank
- # # => [1, 2, true]
- #
- # Set.new([nil, "", 1, 2])
- # # => [2, 1] (or [1, 2])
- #
- # When called on a +Hash+, returns a new +Hash+ without the blank values.
- #
- # { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
- # #=> { b: 1, f: true }
- def compact_blank
- reject(&:blank?)
- end
-end
-
-class Hash
- # Hash#reject has its own definition, so this needs one too.
- def compact_blank #:nodoc:
- reject { |_k, v| v.blank? }
- end
-
- # Removes all blank values from the +Hash+ in place and returns self.
- # Uses Object#blank? for determining if a value is blank.
- #
- # h = { a: "", b: 1, c: nil, d: [], e: false, f: true }
- # h.compact_blank!
- # # => { b: 1, f: true }
- def compact_blank!
- # use delete_if rather than reject! because it always returns self even if nothing changed
- delete_if { |_k, v| v.blank? }
- end
-end
-
-class Range #:nodoc:
- # Optimize range sum to use arithmetic progression if a block is not given and
- # we have a range of numeric values.
- def sum(identity = nil)
- if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
- super
- else
- actual_last = exclude_end? ? (last - 1) : last
- if actual_last >= first
- sum = identity || 0
- sum + (actual_last - first + 1) * (actual_last + first) / 2
- else
- identity || 0
- end
- end
- end
-end
-
-# Using Refinements here in order not to expose our internal method
-using Module.new {
- refine Array do
- alias :orig_sum :sum
- end
-}
-
-class Array #:nodoc:
- # Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
- def sum(init = nil, &block)
- if init.is_a?(Numeric) || first.is_a?(Numeric)
- init ||= 0
- orig_sum(init, &block)
- else
- super
- end
- end
-
- # Removes all blank elements from the +Array+ in place and returns self.
- # Uses Object#blank? for determining if an item is blank.
- #
- # a = [1, "", nil, 2, " ", [], {}, false, true]
- # a.compact_blank!
- # # => [1, 2, true]
- def compact_blank!
- # use delete_if rather than reject! because it always returns self even if nothing changed
- delete_if(&:blank?)
- end
-end
diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_transform_values.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_transform_values.rb
deleted file mode 100644
index 8ad85c0a6d8eb..0000000000000
--- a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_transform_values.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-class Hash
- # Returns a new hash with all values converted by the block operation.
- # This includes the values from the root hash and from all
- # nested hashes and arrays.
- #
- # hash = { person: { name: 'Rob', age: '28' } }
- #
- # hash.deep_transform_values{ |value| value.to_s.upcase }
- # # => {person: {name: "ROB", age: "28"}}
- def deep_transform_values(&block)
- _deep_transform_values_in_object(self, &block)
- end
-
- # Destructively converts all values by using the block operation.
- # This includes the values from the root hash and from all
- # nested hashes and arrays.
- def deep_transform_values!(&block)
- _deep_transform_values_in_object!(self, &block)
- end
-
- private
- # Support methods for deep transforming nested hashes and arrays.
- def _deep_transform_values_in_object(object, &block)
- case object
- when Hash
- object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
- when Array
- object.map { |e| _deep_transform_values_in_object(e, &block) }
- else
- yield(object)
- end
- end
-
- def _deep_transform_values_in_object!(object, &block)
- case object
- when Hash
- object.transform_values! { |value| _deep_transform_values_in_object!(value, &block) }
- when Array
- object.map! { |e| _deep_transform_values_in_object!(e, &block) }
- else
- yield(object)
- end
- end
-end
diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/keys.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/keys.rb
deleted file mode 100644
index f2db61f386e63..0000000000000
--- a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/keys.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-# frozen_string_literal: true
-
-class Hash
- # Returns a new hash with all keys converted to strings.
- #
- # hash = { name: 'Rob', age: '28' }
- #
- # hash.stringify_keys
- # # => {"name"=>"Rob", "age"=>"28"}
- def stringify_keys
- transform_keys(&:to_s)
- end
-
- # Destructively converts all keys to strings. Same as
- # +stringify_keys+, but modifies +self+.
- def stringify_keys!
- transform_keys!(&:to_s)
- end
-
- # Returns a new hash with all keys converted to symbols, as long as
- # they respond to +to_sym+.
- #
- # hash = { 'name' => 'Rob', 'age' => '28' }
- #
- # hash.symbolize_keys
- # # => {:name=>"Rob", :age=>"28"}
- def symbolize_keys
- transform_keys { |key| key.to_sym rescue key }
- end
- alias_method :to_options, :symbolize_keys
-
- # Destructively converts all keys to symbols, as long as they respond
- # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
- def symbolize_keys!
- transform_keys! { |key| key.to_sym rescue key }
- end
- alias_method :to_options!, :symbolize_keys!
-
- # Validates all keys in a hash match *valid_keys, raising
- # +ArgumentError+ on a mismatch.
- #
- # Note that keys are treated differently than HashWithIndifferentAccess,
- # meaning that string and symbol keys will not match.
- #
- # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
- # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
- # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
- def assert_valid_keys(*valid_keys)
- valid_keys.flatten!
- each_key do |k|
- unless valid_keys.include?(k)
- raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
- end
- end
- end
-
- # Returns a new hash with all keys converted by the block operation.
- # This includes the keys from the root hash and from all
- # nested hashes and arrays.
- #
- # hash = { person: { name: 'Rob', age: '28' } }
- #
- # hash.deep_transform_keys{ |key| key.to_s.upcase }
- # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
- def deep_transform_keys(&block)
- _deep_transform_keys_in_object(self, &block)
- end
-
- # Destructively converts all keys by using the block operation.
- # This includes the keys from the root hash and from all
- # nested hashes and arrays.
- def deep_transform_keys!(&block)
- _deep_transform_keys_in_object!(self, &block)
- end
-
- # Returns a new hash with all keys converted to strings.
- # This includes the keys from the root hash and from all
- # nested hashes and arrays.
- #
- # hash = { person: { name: 'Rob', age: '28' } }
- #
- # hash.deep_stringify_keys
- # # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
- def deep_stringify_keys
- deep_transform_keys(&:to_s)
- end
-
- # Destructively converts all keys to strings.
- # This includes the keys from the root hash and from all
- # nested hashes and arrays.
- def deep_stringify_keys!
- deep_transform_keys!(&:to_s)
- end
-
- # Returns a new hash with all keys converted to symbols, as long as
- # they respond to +to_sym+. This includes the keys from the root hash
- # and from all nested hashes and arrays.
- #
- # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
- #
- # hash.deep_symbolize_keys
- # # => {:person=>{:name=>"Rob", :age=>"28"}}
- def deep_symbolize_keys
- deep_transform_keys { |key| key.to_sym rescue key }
- end
-
- # Destructively converts all keys to symbols, as long as they respond
- # to +to_sym+. This includes the keys from the root hash and from all
- # nested hashes and arrays.
- def deep_symbolize_keys!
- deep_transform_keys! { |key| key.to_sym rescue key }
- end
-
- private
- # Support methods for deep transforming nested hashes and arrays.
- def _deep_transform_keys_in_object(object, &block)
- case object
- when Hash
- object.each_with_object({}) do |(key, value), result|
- result[yield(key)] = _deep_transform_keys_in_object(value, &block)
- end
- when Array
- object.map { |e| _deep_transform_keys_in_object(e, &block) }
- else
- object
- end
- end
-
- def _deep_transform_keys_in_object!(object, &block)
- case object
- when Hash
- object.keys.each do |key|
- value = object.delete(key)
- object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
- end
- object
- when Array
- object.map! { |e| _deep_transform_keys_in_object!(e, &block) }
- else
- object
- end
- end
-end