Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove ActiveSupport from runtime #16463

Merged
merged 24 commits into from
Jan 22, 2024
Merged

Conversation

dduugg
Copy link
Member

@dduugg dduugg commented Jan 10, 2024

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew style with your changes locally?
  • Have you successfully run brew typecheck with your changes locally?
  • Have you successfully run brew tests with your changes locally?

Relates to #16190

Removes ActiveSupport from the brew runtime (it will still exist as a transitive dependency of rubocop-rails, for now).

I recommend to squash commits on merge (or I can force-push a squashed commit, not sure what the merge options are here).

I've used just the parts of the ActiveSupport files that we use, with some light modifications (including adding type signatures, and pulling in upstream changes, for which I've added comments). Another option could be to just vendor the existing dependencies, as we do with mechanize. However, ActiveSupport sometimes undergoes refactors and dependency changes, which might be a headache to keep up with (for instance, this refactor of Hash#deep_merge! to introduce another DeepMergeable module).

I haven't added new tests for this functionality, but don't want to dismiss their importance/value (rails uses a different framework, preventing this from being a simple c/p operation). Looks like there a just few spots without coverage though (including some error paths that may be hard to plausibly simulate). LMK if more are desirable.

@dduugg dduugg added the in progress Maintainers are working on this label Jan 10, 2024
@dduugg dduugg marked this pull request as draft January 10, 2024 20:36
@dduugg dduugg changed the title No active support Remove ActiveSupport from runtime Jan 10, 2024
@dduugg dduugg force-pushed the no-active-support branch 2 times, most recently from b76155c to 4267a7a Compare January 10, 2024 20:57
Library/Homebrew/tab.rb Outdated Show resolved Hide resolved
Library/Homebrew/download_strategy.rb Outdated Show resolved Hide resolved
Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good so far!

Library/Homebrew/utils/gems.rb Outdated Show resolved Hide resolved
@dduugg dduugg force-pushed the no-active-support branch 7 times, most recently from 3dfce75 to 07f98a9 Compare January 13, 2024 00:26
.gitignore Show resolved Hide resolved
@@ -6,6 +6,7 @@
require "utils/user"
require "cask/artifact/abstract_artifact"
require "cask/pkg"
require "extend/hash/keys"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I scoped these to the files that used them, rather than in global

@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)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor changes that are required when adding sigs to vendored methods

# typed: strict

class Array
sig { returns(T.nilable(Elem)) }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elem is an upstream RBI creation that isn't available at runtime, so these need to be in RBI files. (And similarly for Enumerable::Enum, Hash::K, Hash::V, etc. below…)

Library/Homebrew/extend/enumerable.rb Outdated Show resolved Hide resolved
end

class Hash
sig { returns(T::Hash[Hash::K, Hash::V]) }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to use a runtime sig with returns(T.self_type), but that's a bug: sorbet/sorbet#7586

end
end
hash
end
end

class Module
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sourced from the current upstream implementation


require "singleton"

module Singleton
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another upstream addition

^https?://
(?:(?:[^/]+?\.)*gnu\.org/(?:gnu|software)/(?<project_name>[^/]+)/
|(?<project_name>[^/]+)\.gnu\.org/?$)
}ix.freeze
}ix.freeze, Regexp)
Copy link
Member Author

@dduugg dduugg Jan 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strict typing and this change somehow resolve a spurious type error on line 42 ¯\(ツ)

@@ -2,6 +2,7 @@
# frozen_string_literal: true

require "sorbet-runtime"
require "extend/module"
Copy link
Member Author

@dduugg dduugg Jan 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mostly unrelated, but as of this change, the extension only extends Module to include T::Sig, so IMO it makes the most sense to live here rather than global.

components[:query] = URI.decode_www_form(uri_query).map(&:second)
components[:query] = URI.decode_www_form(uri_query).map { _2 }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't seen this pattern in the wild. Very cool!

@dduugg dduugg removed the in progress Maintainers are working on this label Jan 19, 2024
@dduugg dduugg marked this pull request as ready for review January 19, 2024 21:40
@dduugg
Copy link
Member Author

dduugg commented Jan 19, 2024

Ready for review

each { |elem| result[yield(elem)] = elem }
result
else
T.unsafe(self).to_enum(:index_by) { T.unsafe(self).size if respond_to?(:size) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really ugly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm honestly not entirely sure what's going on here. There's only two usages of index_by so if we're wanting to keep it then we don't really need to keep the nil-block case which has a behaviour that's undocumented anyway.

The whole thing can probably be simpified to each_with_object({}) { |elem, hash| hash[yield(elem)] = elem }, or replace the two usages with that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that index_by can probably be removed entirely and this code inlined given there's only two usages.

Library/Homebrew/extend/enumerable.rb Outdated Show resolved Hide resolved
@Bo98
Copy link
Member

Bo98 commented Jan 21, 2024

Looks ok, though some cleanup would be nice afterwards. deep_dup and friends can probably also go - duplicable? seems annoying to keep on top of and I'm not fully convinced its one current usage of deep_dup in Cask::Artifact::AbstractArtifact is really necessary anyway (or if so - it can probably be handled better). But given this PR is already quite large I'm ok deferring any further cleanup to a separate PR to reduce risk.

Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @dduugg! As this is a bit of a handful to review, I think it's probably worth merging soon (or as-is, will leave that up-to-you).

I think index_by and perhaps deep_dup could be dropped but that could be a follow-up PR if necessary.

each { |elem| result[yield(elem)] = elem }
result
else
T.unsafe(self).to_enum(:index_by) { T.unsafe(self).size if respond_to?(:size) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that index_by can probably be removed entirely and this code inlined given there's only two usages.

@@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @Bo98 mentioned: I think we can drop this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naïvely swapping out deep_dup for dup in abstract_artifact leads to test failures in test/cask/cask_spec.rb – could i trouble someone with more context to take a deeper (pun intended) look into this one?

@dduugg
Copy link
Member Author

dduugg commented Jan 22, 2024

I believe that I've addressed all the feedback except for deep_dup, PTAL

@dduugg dduugg force-pushed the no-active-support branch 2 times, most recently from ccb1c03 to 7036c9d Compare January 22, 2024 18:45
Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again @dduugg!

@MikeMcQuaid MikeMcQuaid merged commit 86e1c8a into Homebrew:master Jan 22, 2024
25 checks passed
@dduugg dduugg deleted the no-active-support branch January 22, 2024 19:31
@github-actions github-actions bot added the outdated PR was locked due to age label Mar 2, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated PR was locked due to age
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants