From 26821301e74b3b4a559877c97ce8af1b8da8f545 Mon Sep 17 00:00:00 2001 From: Sam Ford <1584702+samford@users.noreply.github.com> Date: Wed, 28 Jul 2021 13:20:12 -0400 Subject: [PATCH] livecheck: move url/regex generation into methods --- Library/Homebrew/livecheck/strategy.rb | 3 + Library/Homebrew/livecheck/strategy/apache.rb | 50 +++++++++++----- .../Homebrew/livecheck/strategy/bitbucket.rb | 58 +++++++++++++------ Library/Homebrew/livecheck/strategy/cpan.rb | 44 ++++++++++---- Library/Homebrew/livecheck/strategy/git.rb | 4 +- .../livecheck/strategy/github_latest.rb | 36 +++++++++--- Library/Homebrew/livecheck/strategy/gnome.rb | 49 +++++++++++----- Library/Homebrew/livecheck/strategy/gnu.rb | 51 +++++++++++----- .../Homebrew/livecheck/strategy/hackage.rb | 37 +++++++++--- .../Homebrew/livecheck/strategy/launchpad.rb | 36 +++++++++--- Library/Homebrew/livecheck/strategy/npm.rb | 39 +++++++++---- .../Homebrew/livecheck/strategy/page_match.rb | 1 + Library/Homebrew/livecheck/strategy/pypi.rb | 48 ++++++++++----- .../livecheck/strategy/sourceforge.rb | 51 +++++++++++----- Library/Homebrew/livecheck/strategy/xorg.rb | 52 ++++++++++++----- .../test/livecheck/strategy/apache_spec.rb | 43 +++++++++++++- .../test/livecheck/strategy/bitbucket_spec.rb | 36 +++++++++++- .../test/livecheck/strategy/cpan_spec.rb | 38 ++++++++++-- .../livecheck/strategy/github_latest_spec.rb | 40 ++++++++++--- .../test/livecheck/strategy/gnome_spec.rb | 19 +++++- .../test/livecheck/strategy/gnu_spec.rb | 50 ++++++++++++++-- .../test/livecheck/strategy/hackage_spec.rb | 30 ++++++++-- .../test/livecheck/strategy/launchpad_spec.rb | 30 +++++++++- .../test/livecheck/strategy/npm_spec.rb | 36 ++++++++++-- .../test/livecheck/strategy/pypi_spec.rb | 21 ++++++- .../livecheck/strategy/sourceforge_spec.rb | 36 +++++++++++- .../test/livecheck/strategy/xorg_spec.rb | 55 +++++++++++++++++- 27 files changed, 795 insertions(+), 198 deletions(-) diff --git a/Library/Homebrew/livecheck/strategy.rb b/Library/Homebrew/livecheck/strategy.rb index 515cdb80a1..056af4ee00 100644 --- a/Library/Homebrew/livecheck/strategy.rb +++ b/Library/Homebrew/livecheck/strategy.rb @@ -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." diff --git a/Library/Homebrew/livecheck/strategy/apache.rb b/Library/Homebrew/livecheck/strategy/apache.rb index 45b7f0213c..37ce2ce3c7 100644 --- a/Library/Homebrew/livecheck/strategy/apache.rb +++ b/Library/Homebrew/livecheck/strategy/apache.rb @@ -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 diff --git a/Library/Homebrew/livecheck/strategy/bitbucket.rb b/Library/Homebrew/livecheck/strategy/bitbucket.rb index 26e997588c..f2679f421f 100644 --- a/Library/Homebrew/livecheck/strategy/bitbucket.rb +++ b/Library/Homebrew/livecheck/strategy/bitbucket.rb @@ -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 diff --git a/Library/Homebrew/livecheck/strategy/cpan.rb b/Library/Homebrew/livecheck/strategy/cpan.rb index 6ffc99a023..2478f9d0d0 100644 --- a/Library/Homebrew/livecheck/strategy/cpan.rb +++ b/Library/Homebrew/livecheck/strategy/cpan.rb @@ -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 diff --git a/Library/Homebrew/livecheck/strategy/git.rb b/Library/Homebrew/livecheck/strategy/git.rb index 96b47df4f3..d7078b7cd1 100644 --- a/Library/Homebrew/livecheck/strategy/git.rb +++ b/Library/Homebrew/livecheck/strategy/git.rb @@ -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. diff --git a/Library/Homebrew/livecheck/strategy/github_latest.rb b/Library/Homebrew/livecheck/strategy/github_latest.rb index 8dadcdd4ce..9b2fdff359 100644 --- a/Library/Homebrew/livecheck/strategy/github_latest.rb +++ b/Library/Homebrew/livecheck/strategy/github_latest.rb @@ -1,4 +1,4 @@ -# typed: false +# typed: true # frozen_string_literal: true module Homebrew @@ -48,6 +48,10 @@ module Homebrew /(?[^/]+) # 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 diff --git a/Library/Homebrew/livecheck/strategy/gnome.rb b/Library/Homebrew/livecheck/strategy/gnome.rb index 34ebc83319..88700eb968 100644 --- a/Library/Homebrew/livecheck/strategy/gnome.rb +++ b/Library/Homebrew/livecheck/strategy/gnome.rb @@ -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 - - version_data - else - PageMatch.find_versions(url: page_url, regex: regex, **unused, &block) end + + version_data end end end diff --git a/Library/Homebrew/livecheck/strategy/gnu.rb b/Library/Homebrew/livecheck/strategy/gnu.rb index 90c12da5e3..86e4eeb143 100644 --- a/Library/Homebrew/livecheck/strategy/gnu.rb +++ b/Library/Homebrew/livecheck/strategy/gnu.rb @@ -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 diff --git a/Library/Homebrew/livecheck/strategy/hackage.rb b/Library/Homebrew/livecheck/strategy/hackage.rb index d21c9efd49..42587c82d4 100644 --- a/Library/Homebrew/livecheck/strategy/hackage.rb +++ b/Library/Homebrew/livecheck/strategy/hackage.rb @@ -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{

example-(.*?)/?

}i` + values[:regex] = %r{

#{regex_name}-(.*?)/?

}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{

example-(.*?)/?

}i` - regex ||= %r{

#{Regexp.escape(match[:package_name])}-(.*?)/?

}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 diff --git a/Library/Homebrew/livecheck/strategy/launchpad.rb b/Library/Homebrew/livecheck/strategy/launchpad.rb index aa7116263e..b03125c357 100644 --- a/Library/Homebrew/livecheck/strategy/launchpad.rb +++ b/Library/Homebrew/livecheck/strategy/launchpad.rb @@ -1,4 +1,4 @@ -# typed: false +# typed: true # frozen_string_literal: true module Homebrew @@ -31,6 +31,10 @@ module Homebrew /(?[^/]+) # 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*]*>\s*Latest version is (.+)\s*abc-(.*?)/?}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 diff --git a/Library/Homebrew/test/livecheck/strategy/launchpad_spec.rb b/Library/Homebrew/test/livecheck/strategy/launchpad_spec.rb index c55a2144b6..1b00697907 100644 --- a/Library/Homebrew/test/livecheck/strategy/launchpad_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/launchpad_spec.rb @@ -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 diff --git a/Library/Homebrew/test/livecheck/strategy/npm_spec.rb b/Library/Homebrew/test/livecheck/strategy/npm_spec.rb index d07f28367d..24db5e4926 100644 --- a/Library/Homebrew/test/livecheck/strategy/npm_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/npm_spec.rb @@ -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 diff --git a/Library/Homebrew/test/livecheck/strategy/pypi_spec.rb b/Library/Homebrew/test/livecheck/strategy/pypi_spec.rb index 9f373829de..8623f172b9 100644 --- a/Library/Homebrew/test/livecheck/strategy/pypi_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/pypi_spec.rb @@ -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 diff --git a/Library/Homebrew/test/livecheck/strategy/sourceforge_spec.rb b/Library/Homebrew/test/livecheck/strategy/sourceforge_spec.rb index 94e4c0167b..15fc25a285 100644 --- a/Library/Homebrew/test/livecheck/strategy/sourceforge_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/sourceforge_spec.rb @@ -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 diff --git a/Library/Homebrew/test/livecheck/strategy/xorg_spec.rb b/Library/Homebrew/test/livecheck/strategy/xorg_spec.rb index 2eee435f49..a62e6b3f0b 100644 --- a/Library/Homebrew/test/livecheck/strategy/xorg_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/xorg_spec.rb @@ -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