Merge pull request #19355 from Homebrew/strategy-interface

feat: Add interface for livecheck strategies
This commit is contained in:
Mike McQuaid 2025-02-27 08:26:15 +00:00 committed by GitHub
commit 9dc1e61443
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 183 additions and 101 deletions

View File

@ -255,6 +255,11 @@ RSpec/Focus:
RSpec/MessageSpies:
EnforcedStyle: receive
# These are legacy violations that we should try to fix.
Sorbet/AllowIncompatibleOverride:
Exclude:
- "Homebrew/livecheck/strategy/*.rb"
# Try getting rid of these.
Sorbet/ConstantsFromStrings:
Enabled: false

View File

@ -28,15 +28,15 @@ module Homebrew
].freeze, T::Array[String])
private_constant :UNSTABLE_VERSION_KEYWORDS
sig { params(strategy_class: T::Class[T.anything]).returns(String) }
sig { params(strategy_class: T::Class[Strategic]).returns(String) }
private_class_method def self.livecheck_strategy_names(strategy_class)
@livecheck_strategy_names ||= T.let({}, T.nilable(T::Hash[T::Class[T.anything], String]))
@livecheck_strategy_names ||= T.let({}, T.nilable(T::Hash[T::Class[Strategic], String]))
@livecheck_strategy_names[strategy_class] ||= Utils.demodulize(strategy_class.name)
end
sig { params(strategy_class: T::Class[T.anything]).returns(T::Array[Symbol]) }
sig { params(strategy_class: T::Class[Strategic]).returns(T::Array[Symbol]) }
private_class_method def self.livecheck_find_versions_parameters(strategy_class)
@livecheck_find_versions_parameters ||= T.let({}, T.nilable(T::Hash[T::Class[T.anything], T::Array[Symbol]]))
@livecheck_find_versions_parameters ||= T.let({}, T.nilable(T::Hash[T::Class[Strategic], T::Array[Symbol]]))
@livecheck_find_versions_parameters[strategy_class] ||=
T::Utils.signature_for_method(strategy_class.method(:find_versions)).parameters.map(&:second)
end

View File

@ -0,0 +1,40 @@
# typed: strong
# frozen_string_literal: true
module Homebrew
module Livecheck
# The interface for livecheck strategies. Because third-party strategies
# are not required to extend this module, we do not provide any default
# method implementations here.
module Strategic
extend T::Helpers
interface!
# Whether the strategy can be applied to the provided URL.
#
# @param url [String] the URL to match against
sig { abstract.params(url: String).returns(T::Boolean) }
def match?(url); end
# Checks the content at the URL for new versions. Implementations may not
# support all options.
#
# @param url the URL of the content to check
# @param regex a regex for matching versions in content
# @param provided_content content to check instead of
# fetching
# @param options options to modify behavior
# @param block a block to match the content
sig {
abstract.params(
url: String,
regex: T.nilable(Regexp),
provided_content: T.nilable(String),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.anything])
}
def find_versions(url:, regex: nil, provided_content: nil, options: Options.new, &block); end
end
end
end

View File

@ -300,6 +300,7 @@ module Homebrew
end
end
require_relative "strategic"
require_relative "strategy/apache"
require_relative "strategy/bitbucket"
require_relative "strategy/cpan"

View File

@ -26,6 +26,8 @@ module Homebrew
#
# @api public
class Apache
extend Strategic
# The `Regexp` used to determine if the strategy applies to the URL.
URL_MATCH_REGEX = %r{
^https?://
@ -42,8 +44,7 @@ module Homebrew
# Whether the strategy can be applied to the provided URL.
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -54,7 +55,6 @@ module Homebrew
# `livecheck` block.
#
# @param url [String] the URL used to generate values
# @return [Hash]
sig { params(url: String).returns(T::Hash[Symbol, T.untyped]) }
def self.generate_input_values(url)
values = {}
@ -88,12 +88,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
generated = generate_input_values(url)

View File

@ -28,6 +28,8 @@ module Homebrew
#
# @api public
class Bitbucket
extend Strategic
# The `Regexp` used to determine if the strategy applies to the URL.
URL_MATCH_REGEX = %r{
^https?://bitbucket\.org
@ -41,8 +43,7 @@ module Homebrew
# Whether the strategy can be applied to the provided URL.
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -53,7 +54,6 @@ module Homebrew
# `livecheck` block.
#
# @param url [String] the URL used to generate values
# @return [Hash]
sig { params(url: String).returns(T::Hash[Symbol, T.untyped]) }
def self.generate_input_values(url)
values = {}
@ -96,12 +96,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
generated = generate_input_values(url)

View File

@ -18,6 +18,8 @@ module Homebrew
#
# @api public
class Cpan
extend Strategic
NICE_NAME = "CPAN"
# The `Regexp` used to determine if the strategy applies to the URL.
@ -32,8 +34,7 @@ module Homebrew
# Whether the strategy can be applied to the provided URL.
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -44,7 +45,6 @@ module Homebrew
# `livecheck` block.
#
# @param url [String] the URL used to generate values
# @return [Hash]
sig { params(url: String).returns(T::Hash[Symbol, T.untyped]) }
def self.generate_input_values(url)
values = {}
@ -75,12 +75,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
generated = generate_input_values(url)

View File

@ -17,6 +17,8 @@ module Homebrew
#
# @api public
class Crate
extend Strategic
# The default regex used to identify versions when a regex isn't
# provided.
DEFAULT_REGEX = /^v?(\d+(?:\.\d+)+)$/i
@ -31,7 +33,7 @@ module Homebrew
match[1]
end
end.freeze, T.proc.params(
arg0: T::Hash[String, T.untyped],
arg0: T::Hash[String, T.anything],
arg1: Regexp,
).returns(T.any(String, T::Array[String])))
@ -45,8 +47,7 @@ module Homebrew
# Whether the strategy can be applied to the provided URL.
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -55,7 +56,6 @@ module Homebrew
# various input values used by the strategy to check for new versions.
#
# @param url [String] the URL used to generate values
# @return [Hash]
sig { params(url: String).returns(T::Hash[Symbol, T.untyped]) }
def self.generate_input_values(url)
values = {}
@ -67,7 +67,7 @@ module Homebrew
end
# Generates a URL and checks the content at the URL for new versions
# using {Json#versions_from_content}.
# using {Json.versions_from_content}.
#
# @param url [String] the URL of the content to check
# @param regex [Regexp, nil] a regex for matching versions in content
@ -76,13 +76,13 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override.params(
url: String,
regex: T.nilable(Regexp),
provided_content: T.nilable(String),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, provided_content: nil, options: Options.new, &block)
match_data = { matches: {}, regex:, url: }

View File

@ -10,6 +10,8 @@ module Homebrew
# This strategy is not applied automatically and it's necessary to use
# `strategy :electron_builder` in a `livecheck` block to apply it.
class ElectronBuilder
extend Strategic
NICE_NAME = "electron-builder"
# A priority of zero causes livecheck to skip the strategy. We do this
@ -22,8 +24,7 @@ module Homebrew
# Whether the strategy can be applied to the provided URL.
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -37,16 +38,16 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override.params(
url: String,
regex: T.nilable(Regexp),
provided_content: T.nilable(String),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, provided_content: nil, options: Options.new, &block)
if regex.present? && block.blank?
if regex.present? && !block_given?
raise ArgumentError,
"#{Utils.demodulize(name)} only supports a regex when using a `strategy` block"
end

View File

@ -17,6 +17,8 @@ module Homebrew
# This strategy is not applied automatically and it's necessary to use
# `strategy :extract_plist` in a `livecheck` block to apply it.
class ExtractPlist
extend Strategic
# A priority of zero causes livecheck to skip the strategy. We do this
# for {ExtractPlist} so we can selectively apply it when appropriate.
PRIORITY = 0
@ -28,7 +30,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -82,16 +84,16 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
cask: Cask::Cask,
url: T.nilable(String),
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(cask:, url: nil, regex: nil, options: Options.new, &block)
if regex.present? && block.blank?
if regex.present? && !block_given?
raise ArgumentError,
"#{Utils.demodulize(name)} only supports a regex when using a `strategy` block"
end

View File

@ -25,6 +25,7 @@ module Homebrew
#
# @api public
class Git
extend Strategic
extend SystemCommand::Mixin
# Used to cache processed URLs, to avoid duplicating effort.
@ -104,7 +105,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
url = preprocess_url(url)
(DownloadStrategyDetector.detect(url) <= GitDownloadStrategy) == true
@ -189,12 +190,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
match_data = { matches: {}, regex:, url: }

View File

@ -28,6 +28,8 @@ module Homebrew
#
# @api public
class GithubLatest
extend Strategic
NICE_NAME = "GitHub - Latest"
# A priority of zero causes livecheck to skip the strategy. We do this
@ -39,7 +41,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
GithubReleases.match?(url)
end
@ -73,12 +75,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: Regexp,
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: GithubReleases::DEFAULT_REGEX, options: Options.new, &block)
match_data = { matches: {}, regex:, url: }

View File

@ -29,6 +29,8 @@ module Homebrew
#
# @api public
class GithubReleases
extend Strategic
NICE_NAME = "GitHub - Releases"
# A priority of zero causes livecheck to skip the strategy. We do this
@ -56,7 +58,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -108,7 +110,7 @@ module Homebrew
content.compact_blank.filter_map do |release|
next if release["draft"] || release["prerelease"]
value = T.let(nil, T.untyped)
value = T.let(nil, T.nilable(String))
VERSION_KEYS.find do |key|
match = release[key]&.match(regex)
next if match.blank?
@ -127,12 +129,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: Regexp,
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: DEFAULT_REGEX, options: Options.new, &block)
match_data = { matches: {}, regex:, url: }

View File

@ -25,6 +25,8 @@ module Homebrew
#
# @api public
class Gnome
extend Strategic
NICE_NAME = "GNOME"
# The `Regexp` used to determine if the strategy applies to the URL.
@ -38,7 +40,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -77,12 +79,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
generated = generate_input_values(url)

View File

@ -29,6 +29,8 @@ module Homebrew
#
# @api public
class Gnu
extend Strategic
NICE_NAME = "GNU"
# The `Regexp` used to determine if the strategy applies to the URL.
@ -42,7 +44,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url) && url.exclude?("savannah.")
end
@ -87,12 +89,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
generated = generate_input_values(url)

View File

@ -17,6 +17,8 @@ module Homebrew
#
# @api public
class Hackage
extend Strategic
# A `Regexp` used in determining if the strategy applies to the URL and
# also as part of extracting the package name from the URL basename.
PACKAGE_NAME_REGEX = /(?<package_name>.+?)-\d+/i
@ -35,7 +37,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -73,12 +75,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
generated = generate_input_values(url)

View File

@ -10,6 +10,8 @@ module Homebrew
# This strategy is not applied automatically and it's necessary to use
# `strategy :header_match` in a `livecheck` block to apply it.
class HeaderMatch
extend Strategic
NICE_NAME = "Header match"
# A priority of zero causes livecheck to skip the strategy. We do this
@ -26,7 +28,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -70,12 +72,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
match_data = { matches: {}, regex:, url: }

View File

@ -23,6 +23,8 @@ module Homebrew
#
# @api public
class Json
extend Strategic
NICE_NAME = "JSON"
# A priority of zero causes livecheck to skip the strategy. We do this
@ -39,7 +41,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -74,7 +76,7 @@ module Homebrew
).returns(T::Array[String])
}
def self.versions_from_content(content, regex = nil, &block)
return [] if content.blank? || block.blank?
return [] if content.blank? || !block_given?
json = parse_json(content)
return [] if json.blank?
@ -97,19 +99,19 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override.params(
url: String,
regex: T.nilable(Regexp),
provided_content: T.nilable(String),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, provided_content: nil, options: Options.new, &block)
raise ArgumentError, "#{Utils.demodulize(name)} requires a `strategy` block" if block.blank?
raise ArgumentError, "#{Utils.demodulize(name)} requires a `strategy` block" unless block_given?
match_data = { matches: {}, regex:, url: }
return match_data if url.blank? || block.blank?
return match_data if url.blank?
content = if provided_content.is_a?(String)
match_data[:cached] = true

View File

@ -23,6 +23,8 @@ module Homebrew
#
# @api public
class Launchpad
extend Strategic
# The `Regexp` used to determine if the strategy applies to the URL.
URL_MATCH_REGEX = %r{
^https?://(?:[^/]+?\.)*launchpad\.net
@ -37,7 +39,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -70,12 +72,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: Regexp,
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: DEFAULT_REGEX, options: Options.new, &block)
generated = generate_input_values(url)

View File

@ -17,6 +17,8 @@ module Homebrew
#
# @api public
class Npm
extend Strategic
NICE_NAME = "npm"
# The `Regexp` used to determine if the strategy applies to the URL.
@ -29,7 +31,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -68,12 +70,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
generated = generate_input_values(url)

View File

@ -16,6 +16,8 @@ module Homebrew
#
# @api public
class PageMatch
extend Strategic
NICE_NAME = "Page match"
# A priority of zero causes livecheck to skip the strategy. We do this
@ -32,7 +34,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -80,7 +82,7 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override.params(
url: String,
regex: T.nilable(Regexp),
provided_content: T.nilable(String),
@ -89,12 +91,12 @@ module Homebrew
).returns(T::Hash[Symbol, T.untyped])
}
def self.find_versions(url:, regex: nil, provided_content: nil, options: Options.new, &block)
if regex.blank? && block.blank?
if regex.blank? && !block_given?
raise ArgumentError, "#{Utils.demodulize(name)} requires a regex or `strategy` block"
end
match_data = { matches: {}, regex:, url: }
return match_data if url.blank? || (regex.blank? && block.blank?)
return match_data if url.blank?
content = if provided_content.is_a?(String)
match_data[:cached] = true

View File

@ -16,6 +16,8 @@ module Homebrew
#
# @api public
class Pypi
extend Strategic
NICE_NAME = "PyPI"
# The default `strategy` block used to extract version information when
@ -26,7 +28,7 @@ module Homebrew
regex ? version[regex, 1] : version
end.freeze, T.proc.params(
json: T::Hash[String, T.untyped],
json: T::Hash[String, T.anything],
regex: T.nilable(Regexp),
).returns(T.nilable(String)))
@ -50,7 +52,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -82,13 +84,13 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override.params(
url: String,
regex: T.nilable(Regexp),
provided_content: T.nilable(String),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, provided_content: nil, options: Options.new, &block)
match_data = { matches: {}, regex:, url: }

View File

@ -31,6 +31,8 @@ module Homebrew
#
# @api public
class Sourceforge
extend Strategic
NICE_NAME = "SourceForge"
# The `Regexp` used to determine if the strategy applies to the URL.
@ -45,7 +47,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -87,12 +89,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
generated = generate_input_values(url)

View File

@ -12,6 +12,8 @@ module Homebrew
# This strategy is not applied automatically and it's necessary to use
# `strategy :sparkle` in a `livecheck` block to apply it.
class Sparkle
extend Strategic
# A priority of zero causes livecheck to skip the strategy. We do this
# for {Sparkle} so we can selectively apply it when appropriate.
PRIORITY = 0
@ -26,7 +28,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -217,15 +219,15 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
if regex.present? && block.blank?
if regex.present? && !block_given?
raise ArgumentError,
"#{Utils.demodulize(name)} only supports a regex when using a `strategy` block"
end

View File

@ -27,6 +27,8 @@ module Homebrew
#
# @api public
class Xml
extend Strategic
NICE_NAME = "XML"
# A priority of zero causes livecheck to skip the strategy. We do this
@ -43,7 +45,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -111,7 +113,7 @@ module Homebrew
).returns(T::Array[String])
}
def self.versions_from_content(content, regex = nil, &block)
return [] if content.blank? || block.blank?
return [] if content.blank? || !block_given?
require "rexml"
xml = parse_xml(content)
@ -137,19 +139,19 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override.params(
url: String,
regex: T.nilable(Regexp),
provided_content: T.nilable(String),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, provided_content: nil, options: Options.new, &block)
raise ArgumentError, "#{Utils.demodulize(name)} requires a `strategy` block" if block.blank?
raise ArgumentError, "#{Utils.demodulize(name)} requires a `strategy` block" unless block_given?
match_data = { matches: {}, regex:, url: }
return match_data if url.blank? || block.blank?
return match_data if url.blank?
content = if provided_content.is_a?(String)
match_data[:cached] = true

View File

@ -39,6 +39,8 @@ module Homebrew
#
# @api public
class Xorg
extend Strategic
NICE_NAME = "X.Org"
# A `Regexp` used in determining if the strategy applies to the URL and
@ -65,7 +67,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -112,12 +114,12 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override(allow_incompatible: true).params(
url: String,
regex: T.nilable(Regexp),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, options: Options.new, &block)
generated = generate_input_values(url)
@ -134,7 +136,7 @@ module Homebrew
)
# Cache any new page content
@page_data[generated_url] = match_data[:content] if match_data[:content].present?
@page_data[generated_url] = match_data[:content] unless match_data[:content].empty?
match_data
end

View File

@ -23,6 +23,8 @@ module Homebrew
#
# @api public
class Yaml
extend Strategic
NICE_NAME = "YAML"
# A priority of zero causes livecheck to skip the strategy. We do this
@ -39,7 +41,7 @@ module Homebrew
#
# @param url [String] the URL to match against
# @return [Boolean]
sig { params(url: String).returns(T::Boolean) }
sig { override.params(url: String).returns(T::Boolean) }
def self.match?(url)
URL_MATCH_REGEX.match?(url)
end
@ -72,7 +74,7 @@ module Homebrew
).returns(T::Array[String])
}
def self.versions_from_content(content, regex = nil, &block)
return [] if content.blank? || block.blank?
return [] if content.blank? || !block_given?
yaml = parse_yaml(content)
return [] if yaml.blank?
@ -97,19 +99,19 @@ module Homebrew
# @param options [Options] options to modify behavior
# @return [Hash]
sig {
params(
override.params(
url: String,
regex: T.nilable(Regexp),
provided_content: T.nilable(String),
options: Options,
block: T.nilable(Proc),
).returns(T::Hash[Symbol, T.untyped])
).returns(T::Hash[Symbol, T.anything])
}
def self.find_versions(url:, regex: nil, provided_content: nil, options: Options.new, &block)
raise ArgumentError, "#{Utils.demodulize(name)} requires a `strategy` block" if block.blank?
raise ArgumentError, "#{Utils.demodulize(name)} requires a `strategy` block" unless block_given?
match_data = { matches: {}, regex:, url: }
return match_data if url.blank? || block.blank?
return match_data if url.blank?
content = if provided_content.is_a?(String)
match_data[:cached] = true

View File

@ -74,7 +74,7 @@ class Resource
#
# @api public
def stage(target = nil, debug_symbols: false, &block)
raise ArgumentError, "Target directory or block is required" if !target && block.blank?
raise ArgumentError, "Target directory or block is required" if !target && !block_given?
prepare_patches
fetch_patches(skip_downloaded: true)