cachable: Move registry to test directory

Now we only include the cachable registry when running tests.
We basically just load it first and add a bunch of methods to
it before loading the rest of the formula files when we require
global.rb. I added a check to make sure this require order is
preserved.

I also made a bunch of methods private, stop excluding classes
that inherit from casks since it's unnecessary and add more docs.
This commit is contained in:
apainintheneck 2024-02-26 20:26:06 -08:00
parent 536ae08a44
commit 5cc1c85a5f
3 changed files with 56 additions and 40 deletions

View File

@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true
module Cachable
@ -11,43 +11,4 @@ module Cachable
def clear_cache
cache.clear
end
# Collect all classes that mix in Cachable so that those caches can be cleared in-between tests.
if ENV["HOMEBREW_TESTS"]
def self.included(klass)
raise ArgumentError, "Don't use Cachable with singleton classes" if klass.singleton_class?
super if defined?(super)
end
# Ignore classes that get inherited from a lot and that have
# caches that we don't need to clear on the class level.
IGNORE_INHERITED_CLASSES = %w[Formula Cask].freeze
private_constant :IGNORE_INHERITED_CLASSES
def self.extended(klass)
Registry.list << klass
klass.extend(Inherited) unless IGNORE_INHERITED_CLASSES.include?(klass.name)
super if defined?(super)
end
module Inherited
def inherited(klass)
# A class might inherit Cachable at the instance level
# and in that case we just want to skip registering it.
Registry.list << klass if klass.respond_to?(:clear_cache)
super if defined?(super)
end
end
module Registry
def self.list
@list ||= []
end
def self.clear_all_caches
list.each(&:clear_cache)
end
end
end
end

View File

@ -35,6 +35,8 @@ require "timeout"
$LOAD_PATH.unshift(File.expand_path("#{ENV.fetch("HOMEBREW_LIBRARY")}/Homebrew/test/support/lib"))
require_relative "support/extend/cachable"
require_relative "../global"
require "test/support/quiet_progress_formatter"

View File

@ -0,0 +1,53 @@
# frozen_string_literal: true
raise "This needs to be required before Cachable gets loaded normally." if defined?(Cachable)
# Collect all classes that mix in Cachable so that those caches can be cleared in-between tests.
module Cachable
private_class_method def self.included(klass)
# It's difficult to backtrack from a singleton class to find the original class
# and you can always just extend this module instead for equivalent behavior.
raise ArgumentError, "Don't use Cachable with singleton classes" if klass.singleton_class?
super if defined?(super)
end
private_class_method def self.extended(klass)
Registry.class_list << klass
# Ignore the `Formula` class that gets inherited from a lot and
# that has caches that we don't need to clear on the class level.
klass.extend(Inherited) if klass.name != "Formula"
super if defined?(super)
end
module Inherited
private
def inherited(klass)
# A class might inherit Cachable at the instance level
# and in that case we just want to skip registering it.
Registry.class_list << klass if klass.respond_to?(:clear_cache)
super if defined?(super)
end
end
module Registry
# A list of all classes that have been loaded into memory that mixin or
# inherit `Cachable` at the class or module level.
#
# Note: Classes that inherit from `Formula` are excluded since it's not
# necessary to track and clear individual formula caches.
def self.class_list
@class_list ||= []
end
# Clear the cache of every class or module that mixes in or inherits
# `Cachable` at the class or module level.
#
# Note: Classes that inherit from `Formula` are excluded since it's not
# necessary to track and clear individual formula caches.
def self.clear_all_caches
class_list.each(&:clear_cache)
end
end
end