mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
livecheck: move url/regex generation into methods
This commit is contained in:
parent
f026dd21c1
commit
26821301e7
@ -75,6 +75,9 @@ module Homebrew
|
||||
# In rare cases, this can also be a double newline (`\n\n`).
|
||||
HTTP_HEAD_BODY_SEPARATOR = "\r\n\r\n"
|
||||
|
||||
# A regex used to identify a tarball extension at the end of a string.
|
||||
TARBALL_EXTENSION_REGEX = /\.t(?:ar\..+|[a-z0-9]+)$/i.freeze
|
||||
|
||||
# An error message to use when a `strategy` block returns a value of
|
||||
# an inappropriate type.
|
||||
INVALID_BLOCK_RETURN_VALUE_MSG = "Return value of a strategy block must be a string or array of strings."
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -42,6 +42,38 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
# Example URL: `https://archive.apache.org/dist/example/`
|
||||
values[:url] = "https://archive.apache.org/dist/#{match[:path]}/"
|
||||
|
||||
regex_prefix = Regexp.escape(match[:prefix] || "").gsub("\\-", "-")
|
||||
|
||||
# Use `\.t` instead of specific tarball extensions (e.g. .tar.gz)
|
||||
suffix = match[:suffix]&.sub(Strategy::TARBALL_EXTENSION_REGEX, "\.t")
|
||||
regex_suffix = Regexp.escape(suffix || "").gsub("\\-", "-")
|
||||
|
||||
# Example directory regex: `%r{href=["']?v?(\d+(?:\.\d+)+)/}i`
|
||||
# Example file regexes:
|
||||
# * `/href=["']?example-v?(\d+(?:\.\d+)+)\.t/i`
|
||||
# * `/href=["']?example-v?(\d+(?:\.\d+)+)-bin\.zip/i`
|
||||
values[:regex] = /href=["']?#{regex_prefix}v?(\d+(?:\.\d+)+)#{regex_suffix}/i
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -59,21 +91,9 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
# Use `\.t` instead of specific tarball extensions (e.g. .tar.gz)
|
||||
suffix = match[:suffix].sub(/\.t(?:ar\..+|[a-z0-9]+)$/i, "\.t")
|
||||
|
||||
# Example URL: `https://archive.apache.org/dist/example/`
|
||||
page_url = "https://archive.apache.org/dist/#{match[:path]}/"
|
||||
|
||||
# Example directory regex: `%r{href=["']?v?(\d+(?:\.\d+)+)/}i`
|
||||
# Example file regexes:
|
||||
# * `/href=["']?example-v?(\d+(?:\.\d+)+)\.t/i`
|
||||
# * `/href=["']?example-v?(\d+(?:\.\d+)+)-bin\.zip/i`
|
||||
regex ||= /href=["']?#{Regexp.escape(match[:prefix])}v?(\d+(?:\.\d+)+)#{Regexp.escape(suffix)}/i
|
||||
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
T.unsafe(PageMatch).find_versions(url: generated[:url], regex: regex || generated[:regex], **unused, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -49,6 +49,42 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
# `/get/` archives are Git tag snapshots, so we need to check that tab
|
||||
# instead of the main `/downloads/` page
|
||||
values[:url] = if match[:dl_type] == "get"
|
||||
"https://bitbucket.org/#{match[:path]}/downloads/?tab=tags"
|
||||
else
|
||||
"https://bitbucket.org/#{match[:path]}/downloads/"
|
||||
end
|
||||
|
||||
regex_prefix = Regexp.escape(T.must(match[:prefix])).gsub("\\-", "-")
|
||||
|
||||
# Use `\.t` instead of specific tarball extensions (e.g. .tar.gz)
|
||||
suffix = T.must(match[:suffix]).sub(Strategy::TARBALL_EXTENSION_REGEX, "\.t")
|
||||
regex_suffix = Regexp.escape(suffix).gsub("\\-", "-")
|
||||
|
||||
# Example regexes:
|
||||
# * `/href=.*?v?(\d+(?:\.\d+)+)\.t/i`
|
||||
# * `/href=.*?example-v?(\d+(?:\.\d+)+)\.t/i`
|
||||
values[:regex] = /href=.*?#{regex_prefix}v?(\d+(?:\.\d+)+)#{regex_suffix}/i
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -66,25 +102,9 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
# Use `\.t` instead of specific tarball extensions (e.g. .tar.gz)
|
||||
suffix = match[:suffix].sub(/\.t(?:ar\..+|[a-z0-9]+)$/i, "\.t")
|
||||
|
||||
# `/get/` archives are Git tag snapshots, so we need to check that tab
|
||||
# instead of the main `/downloads/` page
|
||||
page_url = if match[:dl_type] == "get"
|
||||
"https://bitbucket.org/#{match[:path]}/downloads/?tab=tags"
|
||||
else
|
||||
"https://bitbucket.org/#{match[:path]}/downloads/"
|
||||
end
|
||||
|
||||
# Example regexes:
|
||||
# * `/href=.*?v?(\d+(?:\.\d+)+)\.t/i`
|
||||
# * `/href=.*?example-v?(\d+(?:\.\d+)+)\.t/i`
|
||||
regex ||= /href=.*?#{Regexp.escape(match[:prefix])}v?(\d+(?:\.\d+)+)#{Regexp.escape(suffix)}/i
|
||||
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
T.unsafe(PageMatch).find_versions(url: generated[:url], regex: regex || generated[:regex], **unused, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -40,6 +40,35 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
# The directory listing page where the archive files are found
|
||||
values[:url] = "https://cpan.metacpan.org#{match[:path]}"
|
||||
|
||||
regex_prefix = Regexp.escape(T.must(match[:prefix])).gsub("\\-", "-")
|
||||
|
||||
# Use `\.t` instead of specific tarball extensions (e.g. .tar.gz)
|
||||
suffix = T.must(match[:suffix]).sub(Strategy::TARBALL_EXTENSION_REGEX, "\.t")
|
||||
regex_suffix = Regexp.escape(suffix).gsub("\\-", "-")
|
||||
|
||||
# Example regex: `/href=.*?Brew[._-]v?(\d+(?:\.\d+)*)\.t/i`
|
||||
values[:regex] = /href=.*?#{regex_prefix}[._-]v?(\d+(?:\.\d+)*)#{regex_suffix}/i
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -57,18 +86,9 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
# Use `\.t` instead of specific tarball extensions (e.g. .tar.gz)
|
||||
suffix = match[:suffix].sub(/\.t(?:ar\..+|[a-z0-9]+)$/i, "\.t")
|
||||
|
||||
# The directory listing page where the archive files are found
|
||||
page_url = "https://cpan.metacpan.org#{match[:path]}"
|
||||
|
||||
# Example regex: `/href=.*?Brew[._-]v?(\d+(?:\.\d+)*)\.t/i`
|
||||
regex ||= /href=.*?#{match[:prefix]}[._-]v?(\d+(?:\.\d+)*)#{Regexp.escape(suffix)}/i
|
||||
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
T.unsafe(PageMatch).find_versions(url: generated[:url], regex: regex || generated[:regex], **unused, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -30,8 +30,8 @@ module Homebrew
|
||||
# lowest to highest).
|
||||
PRIORITY = 8
|
||||
|
||||
# The default regex used to naively identify numeric versions from tags
|
||||
# when a regex isn't provided.
|
||||
# The default regex used to naively identify versions from tags when a
|
||||
# regex isn't provided.
|
||||
DEFAULT_REGEX = /\D*(.+)/.freeze
|
||||
|
||||
# Whether the strategy can be applied to the provided URL.
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -48,6 +48,10 @@ module Homebrew
|
||||
/(?<repository>[^/]+) # The GitHub repository name
|
||||
}ix.freeze
|
||||
|
||||
# The default regex used to identify a version from a tag when a regex
|
||||
# isn't provided.
|
||||
DEFAULT_REGEX = %r{href=.*?/tag/v?(\d+(?:\.\d+)+)["' >]}i.freeze
|
||||
|
||||
# Whether the strategy can be applied to the provided URL.
|
||||
#
|
||||
# @param url [String] the URL to match against
|
||||
@ -57,6 +61,26 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = url.sub(/\.git$/i, "").match(URL_MATCH_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
# Example URL: `https://github.com/example/example/releases/latest`
|
||||
values[:url] = "https://github.com/#{match[:username]}/#{match[:repository]}/releases/latest"
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -74,15 +98,9 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = url.sub(/\.git$/i, "").match(URL_MATCH_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
# Example URL: `https://github.com/example/example/releases/latest`
|
||||
page_url = "https://github.com/#{match[:username]}/#{match[:repository]}/releases/latest"
|
||||
|
||||
# The default regex is the same for all URLs using this strategy
|
||||
regex ||= %r{href=.*?/tag/v?(\d+(?:\.\d+)+)["' >]}i
|
||||
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
T.unsafe(PageMatch).find_versions(url: generated[:url], regex: regex || DEFAULT_REGEX, **unused, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -45,6 +45,32 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
values[:url] = "https://download.gnome.org/sources/#{match[:package_name]}/cache.json"
|
||||
|
||||
regex_name = Regexp.escape(T.must(match[:package_name])).gsub("\\-", "-")
|
||||
|
||||
# GNOME archive files seem to use a standard filename format, so we
|
||||
# count on the delimiter between the package name and numeric
|
||||
# version being a hyphen and the file being a tarball.
|
||||
values[:regex] = /#{regex_name}-(\d+(?:\.\d+)+)\.t/i
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -62,27 +88,24 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
page_url = "https://download.gnome.org/sources/#{match[:package_name]}/cache.json"
|
||||
version_data = T.unsafe(PageMatch).find_versions(
|
||||
url: generated[:url],
|
||||
regex: regex || generated[:regex],
|
||||
**unused,
|
||||
&block
|
||||
)
|
||||
|
||||
if regex.blank?
|
||||
# GNOME archive files seem to use a standard filename format, so we
|
||||
# count on the delimiter between the package name and numeric
|
||||
# version being a hyphen and the file being a tarball.
|
||||
regex = /#{Regexp.escape(match[:package_name])}-(\d+(?:\.\d+)+)\.t/i
|
||||
version_data = PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
|
||||
# Filter out unstable versions using the old version scheme where
|
||||
# the major version is below 40.
|
||||
version_data[:matches].reject! do |_, version|
|
||||
version.major < 40 && (version.minor >= 90 || version.minor.to_i.odd?)
|
||||
end
|
||||
end
|
||||
|
||||
version_data
|
||||
else
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -49,6 +49,38 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url) && url.exclude?("savannah.")
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
# The directory listing page for the project's files
|
||||
values[:url] = "http://ftp.gnu.org/gnu/#{match[:project_name]}/"
|
||||
|
||||
regex_name = Regexp.escape(T.must(match[:project_name])).gsub("\\-", "-")
|
||||
|
||||
# The default regex consists of the following parts:
|
||||
# * `href=.*?`: restricts matching to URLs in `href` attributes
|
||||
# * The project name
|
||||
# * `[._-]`: the generic delimiter between project name and version
|
||||
# * `v?(\d+(?:\.\d+)*)`: the numeric version
|
||||
# * `(?:\.[a-z]+|/)`: the file extension (a trailing delimiter)
|
||||
#
|
||||
# Example regex: `%r{href=.*?example[._-]v?(\d+(?:\.\d+)*)(?:\.[a-z]+|/)}i`
|
||||
values[:regex] = %r{href=.*?#{regex_name}[._-]v?(\d+(?:\.\d+)*)(?:\.[a-z]+|/)}i
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -66,22 +98,9 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
# The directory listing page for the project's files
|
||||
page_url = "http://ftp.gnu.org/gnu/#{match[:project_name]}/?C=M&O=D"
|
||||
|
||||
# The default regex consists of the following parts:
|
||||
# * `href=.*?`: restricts matching to URLs in `href` attributes
|
||||
# * The project name
|
||||
# * `[._-]`: the generic delimiter between project name and version
|
||||
# * `v?(\d+(?:\.\d+)*)`: the numeric version
|
||||
# * `(?:\.[a-z]+|/)`: the file extension (a trailing delimiter)
|
||||
#
|
||||
# Example regex: `%r{href=.*?example[._-]v?(\d+(?:\.\d+)*)(?:\.[a-z]+|/)}i`
|
||||
regex ||= %r{href=.*?#{match[:project_name]}[._-]v?(\d+(?:\.\d+)*)(?:\.[a-z]+|/)}i
|
||||
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
T.unsafe(PageMatch).find_versions(url: generated[:url], regex: regex || generated[:regex], **unused, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -42,6 +42,31 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = File.basename(url).match(FILENAME_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
# A page containing a directory listing of the latest source tarball
|
||||
values[:url] = "https://hackage.haskell.org/package/#{match[:package_name]}/src/"
|
||||
|
||||
regex_name = Regexp.escape(T.must(match[:package_name])).gsub("\\-", "-")
|
||||
|
||||
# Example regex: `%r{<h3>example-(.*?)/?</h3>}i`
|
||||
values[:regex] = %r{<h3>#{regex_name}-(.*?)/?</h3>}i
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -59,15 +84,9 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = File.basename(url).match(FILENAME_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
# A page containing a directory listing of the latest source tarball
|
||||
page_url = "https://hackage.haskell.org/package/#{match[:package_name]}/src/"
|
||||
|
||||
# Example regex: `%r{<h3>example-(.*?)/?</h3>}i`
|
||||
regex ||= %r{<h3>#{Regexp.escape(match[:package_name])}-(.*?)/?</h3>}i
|
||||
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
T.unsafe(PageMatch).find_versions(url: generated[:url], regex: regex || generated[:regex], **unused, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -31,6 +31,10 @@ module Homebrew
|
||||
/(?<project_name>[^/]+) # The Launchpad project name
|
||||
}ix.freeze
|
||||
|
||||
# The default regex used to identify the latest version when a regex
|
||||
# isn't provided.
|
||||
DEFAULT_REGEX = %r{class="[^"]*version[^"]*"[^>]*>\s*Latest version is (.+)\s*</}.freeze
|
||||
|
||||
# Whether the strategy can be applied to the provided URL.
|
||||
#
|
||||
# @param url [String] the URL to match against
|
||||
@ -40,6 +44,26 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
# The main page for the project on Launchpad
|
||||
values[:url] = "https://launchpad.net/#{match[:project_name]}/"
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -57,15 +81,9 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
# The main page for the project on Launchpad
|
||||
page_url = "https://launchpad.net/#{match[:project_name]}"
|
||||
|
||||
# The default regex is the same for all URLs using this strategy
|
||||
regex ||= %r{class="[^"]*version[^"]*"[^>]*>\s*Latest version is (.+)\s*</}
|
||||
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
T.unsafe(PageMatch).find_versions(url: generated[:url], regex: regex || DEFAULT_REGEX, **unused, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -36,6 +36,32 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
values[:url] = "https://www.npmjs.com/package/#{match[:package_name]}?activeTab=versions"
|
||||
|
||||
regex_name = Regexp.escape(T.must(match[:package_name])).gsub("\\-", "-")
|
||||
|
||||
# Example regexes:
|
||||
# * `%r{href=.*?/package/example/v/(\d+(?:\.\d+)+)"}i`
|
||||
# * `%r{href=.*?/package/@example/example/v/(\d+(?:\.\d+)+)"}i`
|
||||
values[:regex] = %r{href=.*?/package/#{regex_name}/v/(\d+(?:\.\d+)+)"}i
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -53,16 +79,9 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
page_url = "https://www.npmjs.com/package/#{match[:package_name]}?activeTab=versions"
|
||||
|
||||
# Example regexes:
|
||||
# * `%r{href=.*?/package/example/v/(\d+(?:\.\d+)+)"}i`
|
||||
# * `%r{href=.*?/package/@example/example/v/(\d+(?:\.\d+)+)"}i`
|
||||
regex ||= %r{href=.*?/package/#{Regexp.escape(match[:package_name])}/v/(\d+(?:\.\d+)+)"}i
|
||||
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
T.unsafe(PageMatch).find_versions(url: generated[:url], regex: regex || generated[:regex], **unused, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -90,6 +90,7 @@ module Homebrew
|
||||
}
|
||||
def self.find_versions(url:, regex:, provided_content: nil, **_unused, &block)
|
||||
match_data = { matches: {}, regex: regex, url: url }
|
||||
return match_data if url.blank? || regex.blank?
|
||||
|
||||
content = if provided_content.is_a?(String)
|
||||
match_data[:cached] = true
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -46,6 +46,36 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = File.basename(url).match(FILENAME_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
# It's not technically necessary to have the `#files` fragment at the
|
||||
# end of the URL but it makes the debug output a bit more useful.
|
||||
values[:url] = "https://pypi.org/project/#{T.must(match[:package_name]).gsub(/%20|_/, "-")}/#files"
|
||||
|
||||
# Use `\.t` instead of specific tarball extensions (e.g. .tar.gz)
|
||||
suffix = T.must(match[:suffix]).sub(Strategy::TARBALL_EXTENSION_REGEX, "\.t")
|
||||
regex_suffix = Regexp.escape(suffix).gsub("\\-", "-")
|
||||
|
||||
# Example regex: `%r{href=.*?/packages.*?/example[._-]v?(\d+(?:\.\d+)*(?:[._-]post\d+)?)\.t}i`
|
||||
regex_name = Regexp.escape(T.must(match[:package_name])).gsub("\\-", "-")
|
||||
values[:regex] =
|
||||
%r{href=.*?/packages.*?/#{regex_name}[._-]v?(\d+(?:\.\d+)*(?:[._-]post\d+)?)#{regex_suffix}}i
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -63,21 +93,9 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = File.basename(url).match(FILENAME_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
# Use `\.t` instead of specific tarball extensions (e.g. .tar.gz)
|
||||
suffix = match[:suffix].sub(/\.t(?:ar\..+|[a-z0-9]+)$/i, "\.t")
|
||||
|
||||
# It's not technically necessary to have the `#files` fragment at the
|
||||
# end of the URL but it makes the debug output a bit more useful.
|
||||
page_url = "https://pypi.org/project/#{match[:package_name].gsub(/%20|_/, "-")}/#files"
|
||||
|
||||
# Example regex: `%r{href=.*?/packages.*?/example[._-]v?(\d+(?:\.\d+)*(?:[._-]post\d+)?)\.t}i`
|
||||
re_package_name = Regexp.escape(match[:package_name])
|
||||
re_suffix = Regexp.escape(suffix)
|
||||
regex ||= %r{href=.*?/packages.*?/#{re_package_name}[._-]v?(\d+(?:\.\d+)*(?:[._-]post\d+)?)#{re_suffix}}i
|
||||
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
T.unsafe(PageMatch).find_versions(url: generated[:url], regex: regex || generated[:regex], **unused, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -52,6 +52,35 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
# Don't generate a URL if the URL already points to the RSS feed
|
||||
unless url.match?(%r{/rss(?:/?$|\?)})
|
||||
values[:url] = "https://sourceforge.net/projects/#{match[:project_name]}/rss"
|
||||
end
|
||||
|
||||
regex_name = Regexp.escape(T.must(match[:project_name])).gsub("\\-", "-")
|
||||
|
||||
# It may be possible to improve the generated regex but there's quite
|
||||
# a bit of variation between projects and it can be challenging to
|
||||
# create something that works for most URLs.
|
||||
values[:regex] = %r{url=.*?/#{regex_name}/files/.*?[-_/](\d+(?:[-.]\d+)+)[-_/%.]}i
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and passes them
|
||||
# to {PageMatch.find_versions} to identify versions in the content.
|
||||
#
|
||||
@ -69,20 +98,14 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
match = url.match(URL_MATCH_REGEX)
|
||||
generated = generate_input_values(url)
|
||||
|
||||
page_url = if url.match?(%r{/rss(?:/?$|\?)})
|
||||
url
|
||||
else
|
||||
"https://sourceforge.net/projects/#{match[:project_name]}/rss"
|
||||
end
|
||||
|
||||
# It may be possible to improve the default regex but there's quite a
|
||||
# bit of variation between projects and it can be challenging to
|
||||
# create something that works for most URLs.
|
||||
regex ||= %r{url=.*?/#{Regexp.escape(match[:project_name])}/files/.*?[-_/](\d+(?:[-.]\d+)+)[-_/%.]}i
|
||||
|
||||
PageMatch.find_versions(url: page_url, regex: regex, **unused, &block)
|
||||
T.unsafe(PageMatch).find_versions(
|
||||
url: generated[:url] || url,
|
||||
regex: regex || generated[:regex],
|
||||
**unused,
|
||||
&block
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
@ -69,6 +69,34 @@ module Homebrew
|
||||
URL_MATCH_REGEX.match?(url)
|
||||
end
|
||||
|
||||
# Extracts information from a provided URL and uses it to generate
|
||||
# various input values used by the strategy to check for new versions.
|
||||
# Some of these values act as defaults and can be overridden in a
|
||||
# `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 = {}
|
||||
|
||||
file_name = File.basename(url)
|
||||
match = file_name.match(FILENAME_REGEX)
|
||||
return values if match.blank?
|
||||
|
||||
# /pub/ URLs redirect to the same URL with /archive/, so we replace
|
||||
# it to avoid the redirection. Removing the filename from the end of
|
||||
# the URL gives us the relevant directory listing page.
|
||||
values[:url] = url.sub("x.org/pub/", "x.org/archive/").delete_suffix(file_name)
|
||||
|
||||
regex_name = Regexp.escape(T.must(match[:module_name])).gsub("\\-", "-")
|
||||
|
||||
# Example regex: `/href=.*?example[._-]v?(\d+(?:\.\d+)+)\.t/i`
|
||||
values[:regex] = /href=.*?#{regex_name}[._-]v?(\d+(?:\.\d+)+)\.t/i
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
# Generates a URL and regex (if one isn't provided) and checks the
|
||||
# content at the URL for new versions (using the regex for matching).
|
||||
#
|
||||
@ -92,29 +120,21 @@ module Homebrew
|
||||
).returns(T::Hash[Symbol, T.untyped])
|
||||
}
|
||||
def self.find_versions(url:, regex: nil, **unused, &block)
|
||||
file_name = File.basename(url)
|
||||
match = file_name.match(FILENAME_REGEX)
|
||||
|
||||
# /pub/ URLs redirect to the same URL with /archive/, so we replace
|
||||
# it to avoid the redirection. Removing the filename from the end of
|
||||
# the URL gives us the relevant directory listing page.
|
||||
page_url = url.sub("x.org/pub/", "x.org/archive/").delete_suffix(file_name)
|
||||
|
||||
# Example regex: `/href=.*?example[._-]v?(\d+(?:\.\d+)+)\.t/i`
|
||||
regex ||= /href=.*?#{Regexp.escape(match[:module_name])}[._-]v?(\d+(?:\.\d+)+)\.t/i
|
||||
generated = generate_input_values(url)
|
||||
generated_url = generated[:url]
|
||||
|
||||
# Use the cached page content to avoid duplicate fetches
|
||||
cached_content = @page_data[page_url]
|
||||
match_data = PageMatch.find_versions(
|
||||
url: page_url,
|
||||
regex: regex,
|
||||
cached_content = @page_data[generated_url]
|
||||
match_data = T.unsafe(PageMatch).find_versions(
|
||||
url: generated_url,
|
||||
regex: regex || generated[:regex],
|
||||
provided_content: cached_content,
|
||||
**unused,
|
||||
&block
|
||||
)
|
||||
|
||||
# Cache any new page content
|
||||
@page_data[page_url] = match_data[:content] if match_data[:content].present?
|
||||
@page_data[generated_url] = match_data[:content] if match_data[:content].present?
|
||||
|
||||
match_data
|
||||
end
|
||||
|
@ -1,21 +1,58 @@
|
||||
# typed: false
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "livecheck/strategy/apache"
|
||||
require "livecheck/strategy"
|
||||
|
||||
describe Homebrew::Livecheck::Strategy::Apache do
|
||||
subject(:apache) { described_class }
|
||||
|
||||
let(:apache_url) { "https://www.apache.org/dyn/closer.lua?path=abc/1.2.3/def-1.2.3.tar.gz" }
|
||||
let(:apache_urls) {
|
||||
{
|
||||
version_dir: "https://www.apache.org/dyn/closer.lua?path=abc/1.2.3/def-1.2.3.tar.gz",
|
||||
name_and_version_dir: "https://www.apache.org/dyn/closer.lua?path=abc/def-1.2.3/ghi-1.2.3.tar.gz",
|
||||
name_dir_bin: "https://www.apache.org/dyn/closer.lua?path=abc/def/ghi-1.2.3-bin.tar.gz",
|
||||
}
|
||||
}
|
||||
let(:non_apache_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
version_dir: {
|
||||
url: "https://archive.apache.org/dist/abc/",
|
||||
regex: %r{href=["']?v?(\d+(?:\.\d+)+)/}i,
|
||||
},
|
||||
name_and_version_dir: {
|
||||
url: "https://archive.apache.org/dist/abc/",
|
||||
regex: %r{href=["']?def-v?(\d+(?:\.\d+)+)/}i,
|
||||
},
|
||||
name_dir_bin: {
|
||||
url: "https://archive.apache.org/dist/abc/def/",
|
||||
regex: /href=["']?ghi-v?(\d+(?:\.\d+)+)-bin\.t/i,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for an Apache URL" do
|
||||
expect(apache.match?(apache_url)).to be true
|
||||
expect(apache.match?(apache_urls[:version_dir])).to be true
|
||||
expect(apache.match?(apache_urls[:name_and_version_dir])).to be true
|
||||
expect(apache.match?(apache_urls[:name_dir_bin])).to be true
|
||||
end
|
||||
|
||||
it "returns false for a non-Apache URL" do
|
||||
expect(apache.match?(non_apache_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for an Apache URL" do
|
||||
expect(apache.generate_input_values(apache_urls[:version_dir])).to eq(generated[:version_dir])
|
||||
expect(apache.generate_input_values(apache_urls[:name_and_version_dir])).to eq(generated[:name_and_version_dir])
|
||||
expect(apache.generate_input_values(apache_urls[:name_dir_bin])).to eq(generated[:name_dir_bin])
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-Apache URL" do
|
||||
expect(apache.generate_input_values(non_apache_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,21 +1,51 @@
|
||||
# typed: false
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "livecheck/strategy/bitbucket"
|
||||
require "livecheck/strategy"
|
||||
|
||||
describe Homebrew::Livecheck::Strategy::Bitbucket do
|
||||
subject(:bitbucket) { described_class }
|
||||
|
||||
let(:bitbucket_url) { "https://bitbucket.org/abc/def/get/1.2.3.tar.gz" }
|
||||
let(:bitbucket_urls) {
|
||||
{
|
||||
get: "https://bitbucket.org/abc/def/get/1.2.3.tar.gz",
|
||||
downloads: "https://bitbucket.org/abc/def/downloads/ghi-1.2.3.tar.gz",
|
||||
}
|
||||
}
|
||||
let(:non_bitbucket_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
get: {
|
||||
url: "https://bitbucket.org/abc/def/downloads/?tab=tags",
|
||||
regex: /href=.*?v?(\d+(?:\.\d+)+)\.t/i,
|
||||
},
|
||||
downloads: {
|
||||
url: "https://bitbucket.org/abc/def/downloads/",
|
||||
regex: /href=.*?ghi-v?(\d+(?:\.\d+)+)\.t/i,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for a Bitbucket URL" do
|
||||
expect(bitbucket.match?(bitbucket_url)).to be true
|
||||
expect(bitbucket.match?(bitbucket_urls[:get])).to be true
|
||||
expect(bitbucket.match?(bitbucket_urls[:downloads])).to be true
|
||||
end
|
||||
|
||||
it "returns false for a non-Bitbucket URL" do
|
||||
expect(bitbucket.match?(non_bitbucket_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for a Bitbucket URL" do
|
||||
expect(bitbucket.generate_input_values(bitbucket_urls[:get])).to eq(generated[:get])
|
||||
expect(bitbucket.generate_input_values(bitbucket_urls[:downloads])).to eq(generated[:downloads])
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-Bitbucket URL" do
|
||||
expect(bitbucket.generate_input_values(non_bitbucket_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,23 +1,51 @@
|
||||
# typed: false
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "livecheck/strategy/cpan"
|
||||
require "livecheck/strategy"
|
||||
|
||||
describe Homebrew::Livecheck::Strategy::Cpan do
|
||||
subject(:cpan) { described_class }
|
||||
|
||||
let(:cpan_url_no_subdirectory) { "https://cpan.metacpan.org/authors/id/H/HO/HOMEBREW/Brew-v1.2.3.tar.gz" }
|
||||
let(:cpan_url_with_subdirectory) { "https://cpan.metacpan.org/authors/id/H/HO/HOMEBREW/brew/brew-v1.2.3.tar.gz" }
|
||||
let(:cpan_urls) {
|
||||
{
|
||||
no_subdirectory: "https://cpan.metacpan.org/authors/id/H/HO/HOMEBREW/Brew-v1.2.3.tar.gz",
|
||||
with_subdirectory: "https://cpan.metacpan.org/authors/id/H/HO/HOMEBREW/brew/brew-v1.2.3.tar.gz",
|
||||
}
|
||||
}
|
||||
let(:non_cpan_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
no_subdirectory: {
|
||||
url: "https://cpan.metacpan.org/authors/id/H/HO/HOMEBREW/",
|
||||
regex: /href=.*?Brew[._-]v?(\d+(?:\.\d+)*)\.t/i,
|
||||
},
|
||||
with_subdirectory: {
|
||||
url: "https://cpan.metacpan.org/authors/id/H/HO/HOMEBREW/brew/",
|
||||
regex: /href=.*?brew[._-]v?(\d+(?:\.\d+)*)\.t/i,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for a CPAN URL" do
|
||||
expect(cpan.match?(cpan_url_no_subdirectory)).to be true
|
||||
expect(cpan.match?(cpan_url_with_subdirectory)).to be true
|
||||
expect(cpan.match?(cpan_urls[:no_subdirectory])).to be true
|
||||
expect(cpan.match?(cpan_urls[:with_subdirectory])).to be true
|
||||
end
|
||||
|
||||
it "returns false for a non-CPAN URL" do
|
||||
expect(cpan.match?(non_cpan_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for a CPAN URL" do
|
||||
expect(cpan.generate_input_values(cpan_urls[:no_subdirectory])).to eq(generated[:no_subdirectory])
|
||||
expect(cpan.generate_input_values(cpan_urls[:with_subdirectory])).to eq(generated[:with_subdirectory])
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-CPAN URL" do
|
||||
expect(cpan.generate_input_values(non_cpan_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,28 +6,54 @@ require "livecheck/strategy/github_latest"
|
||||
describe Homebrew::Livecheck::Strategy::GithubLatest do
|
||||
subject(:github_latest) { described_class }
|
||||
|
||||
let(:github_release_artifact_url) {
|
||||
"https://github.com/example/example/releases/download/1.2.3/example-1.2.3.tar.gz"
|
||||
let(:github_urls) {
|
||||
{
|
||||
release_artifact: "https://github.com/abc/def/releases/download/1.2.3/ghi-1.2.3.tar.gz",
|
||||
tag_archive: "https://github.com/abc/def/archive/v1.2.3.tar.gz",
|
||||
repository_upload: "https://github.com/downloads/abc/def/ghi-1.2.3.tar.gz",
|
||||
}
|
||||
}
|
||||
let(:github_tag_archive_url) { "https://github.com/example/example/archive/v1.2.3.tar.gz" }
|
||||
let(:github_repository_upload_url) { "https://github.com/downloads/example/example/example-1.2.3.tar.gz" }
|
||||
let(:non_github_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
url: "https://github.com/abc/def/releases/latest",
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for a GitHub release artifact URL" do
|
||||
expect(github_latest.match?(github_release_artifact_url)).to be true
|
||||
expect(github_latest.match?(github_urls[:release_artifact])).to be true
|
||||
end
|
||||
|
||||
it "returns true for a GitHub tag archive URL" do
|
||||
expect(github_latest.match?(github_tag_archive_url)).to be true
|
||||
expect(github_latest.match?(github_urls[:tag_archive])).to be true
|
||||
end
|
||||
|
||||
it "returns true for a GitHub repository upload URL" do
|
||||
expect(github_latest.match?(github_repository_upload_url)).to be true
|
||||
expect(github_latest.match?(github_urls[:repository_upload])).to be true
|
||||
end
|
||||
|
||||
it "returns false for a non-GitHub URL" do
|
||||
expect(github_latest.match?(non_github_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing a url and regex for a GitHub release artifact URL" do
|
||||
expect(github_latest.generate_input_values(github_urls[:release_artifact])).to eq(generated)
|
||||
end
|
||||
|
||||
it "returns a hash containing a url and regex for a GitHub tag archive URL" do
|
||||
expect(github_latest.generate_input_values(github_urls[:tag_archive])).to eq(generated)
|
||||
end
|
||||
|
||||
it "returns a hash containing a url and regex for a GitHub repository upload URL" do
|
||||
expect(github_latest.generate_input_values(github_urls[:repository_upload])).to eq(generated)
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-Github URL" do
|
||||
expect(github_latest.generate_input_values(non_github_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,9 +6,16 @@ require "livecheck/strategy/gnome"
|
||||
describe Homebrew::Livecheck::Strategy::Gnome do
|
||||
subject(:gnome) { described_class }
|
||||
|
||||
let(:gnome_url) { "https://download.gnome.org/sources/abc/1.2/def-1.2.3.tar.xz" }
|
||||
let(:gnome_url) { "https://download.gnome.org/sources/abc/1.2/abc-1.2.3.tar.xz" }
|
||||
let(:non_gnome_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
url: "https://download.gnome.org/sources/abc/cache.json",
|
||||
regex: /abc-(\d+(?:\.\d+)+)\.t/i,
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for a GNOME URL" do
|
||||
expect(gnome.match?(gnome_url)).to be true
|
||||
@ -18,4 +25,14 @@ describe Homebrew::Livecheck::Strategy::Gnome do
|
||||
expect(gnome.match?(non_gnome_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for a GNOME URL" do
|
||||
expect(gnome.generate_input_values(gnome_url)).to eq(generated)
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-GNOME URL" do
|
||||
expect(gnome.generate_input_values(non_gnome_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,21 +6,63 @@ require "livecheck/strategy/gnu"
|
||||
describe Homebrew::Livecheck::Strategy::Gnu do
|
||||
subject(:gnu) { described_class }
|
||||
|
||||
let(:gnu_url) { "https://ftp.gnu.org/gnu/abc/def-1.2.3.tar.gz" }
|
||||
let(:savannah_gnu_url) { "https://download.savannah.gnu.org/releases/abc/def-1.2.3.tar.gz" }
|
||||
let(:gnu_urls) {
|
||||
{
|
||||
no_version_dir: "https://ftp.gnu.org/gnu/abc/abc-1.2.3.tar.gz",
|
||||
software_page: "https://www.gnu.org/software/abc/",
|
||||
subdomain: "https://abc.gnu.org",
|
||||
savannah: "https://download.savannah.gnu.org/releases/abc/abc-1.2.3.tar.gz",
|
||||
}
|
||||
}
|
||||
let(:non_gnu_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
no_version_dir: {
|
||||
url: "http://ftp.gnu.org/gnu/abc/",
|
||||
regex: %r{href=.*?abc[._-]v?(\d+(?:\.\d+)*)(?:\.[a-z]+|/)}i,
|
||||
},
|
||||
software_page: {
|
||||
url: "http://ftp.gnu.org/gnu/abc/",
|
||||
regex: %r{href=.*?abc[._-]v?(\d+(?:\.\d+)*)(?:\.[a-z]+|/)}i,
|
||||
},
|
||||
subdomain: {
|
||||
url: "http://ftp.gnu.org/gnu/abc/",
|
||||
regex: %r{href=.*?abc[._-]v?(\d+(?:\.\d+)*)(?:\.[a-z]+|/)}i,
|
||||
},
|
||||
savannah: {},
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for a [non-Savannah] GNU URL" do
|
||||
expect(gnu.match?(gnu_url)).to be true
|
||||
expect(gnu.match?(gnu_urls[:no_version_dir])).to be true
|
||||
expect(gnu.match?(gnu_urls[:software_page])).to be true
|
||||
expect(gnu.match?(gnu_urls[:subdomain])).to be true
|
||||
end
|
||||
|
||||
it "returns false for a Savannah GNU URL" do
|
||||
expect(gnu.match?(savannah_gnu_url)).to be false
|
||||
expect(gnu.match?(gnu_urls[:savannah])).to be false
|
||||
end
|
||||
|
||||
it "returns false for a non-GNU URL (not nongnu.org)" do
|
||||
expect(gnu.match?(non_gnu_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for a [non-Savannah] GNU URL" do
|
||||
expect(gnu.generate_input_values(gnu_urls[:no_version_dir])).to eq(generated[:no_version_dir])
|
||||
expect(gnu.generate_input_values(gnu_urls[:software_page])).to eq(generated[:software_page])
|
||||
expect(gnu.generate_input_values(gnu_urls[:subdomain])).to eq(generated[:subdomain])
|
||||
end
|
||||
|
||||
it "returns an empty hash for a Savannah GNU URL" do
|
||||
expect(gnu.generate_input_values(gnu_urls[:savannah])).to eq(generated[:savannah])
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-GNU URL (not nongnu.org)" do
|
||||
expect(gnu.generate_input_values(non_gnu_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,18 +6,40 @@ require "livecheck/strategy/hackage"
|
||||
describe Homebrew::Livecheck::Strategy::Hackage do
|
||||
subject(:hackage) { described_class }
|
||||
|
||||
let(:hackage_url) { "https://hackage.haskell.org/package/abc-1.2.3/def-1.2.3.tar.gz" }
|
||||
let(:hackage_downloads_url) { "https://downloads.haskell.org/~abc/1.2.3/def-1.2.3-src.tar.xz" }
|
||||
let(:hackage_urls) {
|
||||
{
|
||||
package: "https://hackage.haskell.org/package/abc-1.2.3/abc-1.2.3.tar.gz",
|
||||
downloads: "https://downloads.haskell.org/~abc/1.2.3/abc-1.2.3-src.tar.xz",
|
||||
}
|
||||
}
|
||||
let(:non_hackage_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
url: "https://hackage.haskell.org/package/abc/src/",
|
||||
regex: %r{<h3>abc-(.*?)/?</h3>}i,
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for a Hackage URL" do
|
||||
expect(hackage.match?(hackage_url)).to be true
|
||||
expect(hackage.match?(hackage_downloads_url)).to be true
|
||||
expect(hackage.match?(hackage_urls[:package])).to be true
|
||||
expect(hackage.match?(hackage_urls[:downloads])).to be true
|
||||
end
|
||||
|
||||
it "returns false for a non-Hackage URL" do
|
||||
expect(hackage.match?(non_hackage_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for a Hackage URL" do
|
||||
expect(hackage.generate_input_values(hackage_urls[:package])).to eq(generated)
|
||||
expect(hackage.generate_input_values(hackage_urls[:downloads])).to eq(generated)
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-Hackage URL" do
|
||||
expect(hackage.generate_input_values(non_hackage_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,16 +6,42 @@ require "livecheck/strategy/launchpad"
|
||||
describe Homebrew::Livecheck::Strategy::Launchpad do
|
||||
subject(:launchpad) { described_class }
|
||||
|
||||
let(:launchpad_url) { "https://launchpad.net/abc/1.2/1.2.3/+download/def-1.2.3.tar.gz" }
|
||||
let(:launchpad_urls) {
|
||||
{
|
||||
version_dir: "https://launchpad.net/abc/1.2/1.2.3/+download/abc-1.2.3.tar.gz",
|
||||
trunk: "https://launchpad.net/abc/trunk/1.2.3/+download/abc-1.2.3.tar.gz",
|
||||
code_subdomain: "https://code.launchpad.net/abc/1.2/1.2.3/+download/abc-1.2.3.tar.gz",
|
||||
}
|
||||
}
|
||||
let(:non_launchpad_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
url: "https://launchpad.net/abc/",
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for a Launchpad URL" do
|
||||
expect(launchpad.match?(launchpad_url)).to be true
|
||||
expect(launchpad.match?(launchpad_urls[:version_dir])).to be true
|
||||
expect(launchpad.match?(launchpad_urls[:trunk])).to be true
|
||||
expect(launchpad.match?(launchpad_urls[:code_subdomain])).to be true
|
||||
end
|
||||
|
||||
it "returns false for a non-Launchpad URL" do
|
||||
expect(launchpad.match?(non_launchpad_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for an Launchpad URL" do
|
||||
expect(launchpad.generate_input_values(launchpad_urls[:version_dir])).to eq(generated)
|
||||
expect(launchpad.generate_input_values(launchpad_urls[:trunk])).to eq(generated)
|
||||
expect(launchpad.generate_input_values(launchpad_urls[:code_subdomain])).to eq(generated)
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-Launchpad URL" do
|
||||
expect(launchpad.generate_input_values(non_launchpad_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,18 +6,46 @@ require "livecheck/strategy/npm"
|
||||
describe Homebrew::Livecheck::Strategy::Npm do
|
||||
subject(:npm) { described_class }
|
||||
|
||||
let(:npm_url) { "https://registry.npmjs.org/abc/-/def-1.2.3.tgz" }
|
||||
let(:npm_scoped_url) { "https://registry.npmjs.org/@example/abc/-/def-1.2.3.tgz" }
|
||||
let(:npm_urls) {
|
||||
{
|
||||
typical: "https://registry.npmjs.org/abc/-/def-1.2.3.tgz",
|
||||
org_scoped: "https://registry.npmjs.org/@example/abc/-/def-1.2.3.tgz",
|
||||
}
|
||||
}
|
||||
let(:non_npm_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
typical: {
|
||||
url: "https://www.npmjs.com/package/abc?activeTab=versions",
|
||||
regex: %r{href=.*?/package/abc/v/(\d+(?:\.\d+)+)"}i,
|
||||
},
|
||||
org_scoped: {
|
||||
url: "https://www.npmjs.com/package/@example/abc?activeTab=versions",
|
||||
regex: %r{href=.*?/package/@example/abc/v/(\d+(?:\.\d+)+)"}i,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for an npm URL" do
|
||||
expect(npm.match?(npm_url)).to be true
|
||||
expect(npm.match?(npm_scoped_url)).to be true
|
||||
expect(npm.match?(npm_urls[:typical])).to be true
|
||||
expect(npm.match?(npm_urls[:org_scoped])).to be true
|
||||
end
|
||||
|
||||
it "returns false for a non-npm URL" do
|
||||
expect(npm.match?(non_npm_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for an npm URL" do
|
||||
expect(npm.generate_input_values(npm_urls[:typical])).to eq(generated[:typical])
|
||||
expect(npm.generate_input_values(npm_urls[:org_scoped])).to eq(generated[:org_scoped])
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-npm URL" do
|
||||
expect(npm.generate_input_values(non_npm_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,14 +1,21 @@
|
||||
# typed: false
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "livecheck/strategy/pypi"
|
||||
require "livecheck/strategy"
|
||||
|
||||
describe Homebrew::Livecheck::Strategy::Pypi do
|
||||
subject(:pypi) { described_class }
|
||||
|
||||
let(:pypi_url) { "https://files.pythonhosted.org/packages/ab/cd/efg/hij-1.2.3.tar.gz" }
|
||||
let(:pypi_url) { "https://files.pythonhosted.org/packages/ab/cd/efg/example-1.2.3.tar.gz" }
|
||||
let(:non_pypi_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
url: "https://pypi.org/project/example/#files",
|
||||
regex: %r{href=.*?/packages.*?/example[._-]v?(\d+(?:\.\d+)*(?:[._-]post\d+)?)\.t}i,
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for a PyPI URL" do
|
||||
expect(pypi.match?(pypi_url)).to be true
|
||||
@ -18,4 +25,14 @@ describe Homebrew::Livecheck::Strategy::Pypi do
|
||||
expect(pypi.match?(non_pypi_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for an PyPI URL" do
|
||||
expect(pypi.generate_input_values(pypi_url)).to eq(generated)
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-PyPI URL" do
|
||||
expect(pypi.generate_input_values(non_pypi_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,16 +6,48 @@ require "livecheck/strategy/sourceforge"
|
||||
describe Homebrew::Livecheck::Strategy::Sourceforge do
|
||||
subject(:sourceforge) { described_class }
|
||||
|
||||
let(:sourceforge_url) { "https://downloads.sourceforge.net/project/abc/def-1.2.3.tar.gz" }
|
||||
let(:sourceforge_urls) {
|
||||
{
|
||||
typical: "https://downloads.sourceforge.net/project/abc/def-1.2.3.tar.gz",
|
||||
rss: "https://sourceforge.net/projects/abc/rss",
|
||||
rss_with_path: "https://sourceforge.net/projects/abc/rss?path=/def",
|
||||
}
|
||||
}
|
||||
let(:non_sourceforge_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
typical: {
|
||||
url: "https://sourceforge.net/projects/abc/rss",
|
||||
regex: %r{url=.*?/abc/files/.*?[-_/](\d+(?:[-.]\d+)+)[-_/%.]}i,
|
||||
},
|
||||
rss: {
|
||||
regex: %r{url=.*?/abc/files/.*?[-_/](\d+(?:[-.]\d+)+)[-_/%.]}i,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for a SourceForge URL" do
|
||||
expect(sourceforge.match?(sourceforge_url)).to be true
|
||||
expect(sourceforge.match?(sourceforge_urls[:typical])).to be true
|
||||
expect(sourceforge.match?(sourceforge_urls[:rss])).to be true
|
||||
expect(sourceforge.match?(sourceforge_urls[:rss_with_path])).to be true
|
||||
end
|
||||
|
||||
it "returns false for a non-SourceForge URL" do
|
||||
expect(sourceforge.match?(non_sourceforge_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for an Apache URL" do
|
||||
expect(sourceforge.generate_input_values(sourceforge_urls[:typical])).to eq(generated[:typical])
|
||||
expect(sourceforge.generate_input_values(sourceforge_urls[:rss])).to eq(generated[:rss])
|
||||
expect(sourceforge.generate_input_values(sourceforge_urls[:rss_with_path])).to eq(generated[:rss])
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-Apache URL" do
|
||||
expect(sourceforge.generate_input_values(non_sourceforge_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,16 +6,67 @@ require "livecheck/strategy/xorg"
|
||||
describe Homebrew::Livecheck::Strategy::Xorg do
|
||||
subject(:xorg) { described_class }
|
||||
|
||||
let(:xorg_url) { "https://www.x.org/archive/individual/app/abc-1.2.3.tar.bz2" }
|
||||
let(:xorg_urls) {
|
||||
{
|
||||
app: "https://www.x.org/archive/individual/app/abc-1.2.3.tar.bz2",
|
||||
font: "https://www.x.org/archive/individual/font/abc-1.2.3.tar.bz2",
|
||||
lib: "https://www.x.org/archive/individual/lib/libabc-1.2.3.tar.bz2",
|
||||
ftp_lib: "https://ftp.x.org/archive/individual/lib/libabc-1.2.3.tar.bz2",
|
||||
pub_doc: "https://www.x.org/pub/individual/doc/abc-1.2.3.tar.bz2",
|
||||
}
|
||||
}
|
||||
let(:non_xorg_url) { "https://brew.sh/test" }
|
||||
|
||||
let(:generated) {
|
||||
{
|
||||
app: {
|
||||
url: "https://www.x.org/archive/individual/app/",
|
||||
regex: /href=.*?abc[._-]v?(\d+(?:\.\d+)+)\.t/i,
|
||||
},
|
||||
font: {
|
||||
url: "https://www.x.org/archive/individual/font/",
|
||||
regex: /href=.*?abc[._-]v?(\d+(?:\.\d+)+)\.t/i,
|
||||
},
|
||||
lib: {
|
||||
url: "https://www.x.org/archive/individual/lib/",
|
||||
regex: /href=.*?libabc[._-]v?(\d+(?:\.\d+)+)\.t/i,
|
||||
},
|
||||
ftp_lib: {
|
||||
url: "https://ftp.x.org/archive/individual/lib/",
|
||||
regex: /href=.*?libabc[._-]v?(\d+(?:\.\d+)+)\.t/i,
|
||||
},
|
||||
pub_doc: {
|
||||
url: "https://www.x.org/archive/individual/doc/",
|
||||
regex: /href=.*?abc[._-]v?(\d+(?:\.\d+)+)\.t/i,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe "::match?" do
|
||||
it "returns true for an X.Org URL" do
|
||||
expect(xorg.match?(xorg_url)).to be true
|
||||
expect(xorg.match?(xorg_urls[:app])).to be true
|
||||
expect(xorg.match?(xorg_urls[:font])).to be true
|
||||
expect(xorg.match?(xorg_urls[:lib])).to be true
|
||||
expect(xorg.match?(xorg_urls[:ftp_lib])).to be true
|
||||
expect(xorg.match?(xorg_urls[:pub_doc])).to be true
|
||||
end
|
||||
|
||||
it "returns false for a non-X.Org URL" do
|
||||
expect(xorg.match?(non_xorg_url)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "::generate_input_values" do
|
||||
it "returns a hash containing url and regex for an X.org URL" do
|
||||
expect(xorg.generate_input_values(xorg_urls[:app])).to eq(generated[:app])
|
||||
expect(xorg.generate_input_values(xorg_urls[:font])).to eq(generated[:font])
|
||||
expect(xorg.generate_input_values(xorg_urls[:lib])).to eq(generated[:lib])
|
||||
expect(xorg.generate_input_values(xorg_urls[:ftp_lib])).to eq(generated[:ftp_lib])
|
||||
expect(xorg.generate_input_values(xorg_urls[:pub_doc])).to eq(generated[:pub_doc])
|
||||
end
|
||||
|
||||
it "returns an empty hash for a non-X.org URL" do
|
||||
expect(xorg.generate_input_values(non_xorg_url)).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user