Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

livecheck: move #preprocess_url into strategies #18455

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 11 additions & 77 deletions Library/Homebrew/livecheck/livecheck.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,6 @@
# command. These methods print the requested livecheck information
# for formulae.
module Livecheck
GITEA_INSTANCES = T.let(%w[
codeberg.org
gitea.com
opendev.org
tildegit.org
].freeze, T::Array[String])
private_constant :GITEA_INSTANCES

GOGS_INSTANCES = T.let(%w[
lolg.it
].freeze, T::Array[String])
private_constant :GOGS_INSTANCES

STRATEGY_SYMBOLS_TO_SKIP_PREPROCESS_URL = T.let([
:extract_plist,
:github_latest,
:header_match,
:json,
:page_match,
:sparkle,
:xml,
:yaml,
].freeze, T::Array[Symbol])
private_constant :STRATEGY_SYMBOLS_TO_SKIP_PREPROCESS_URL

UNSTABLE_VERSION_KEYWORDS = T.let(%w[
alpha
beta
Expand Down Expand Up @@ -573,48 +548,6 @@
urls.compact.uniq
end

# Preprocesses and returns the URL used by livecheck.
sig { params(url: String).returns(String) }
def self.preprocess_url(url)
begin
uri = Addressable::URI.parse url
rescue Addressable::URI::InvalidURIError
return url
end

host = uri.host
path = uri.path
return url if host.nil? || path.nil?

host = "github.com" if host == "github.s3.amazonaws.com"
path = path.delete_prefix("/").delete_suffix(".git")
scheme = uri.scheme

if host == "github.com"
return url if path.match? %r{/releases/latest/?$}

owner, repo = path.delete_prefix("downloads/").split("/")
url = "#{scheme}://#{host}/#{owner}/#{repo}.git"
elsif GITEA_INSTANCES.include?(host)
return url if path.match? %r{/releases/latest/?$}

owner, repo = path.split("/")
url = "#{scheme}://#{host}/#{owner}/#{repo}.git"
elsif GOGS_INSTANCES.include?(host)
owner, repo = path.split("/")
url = "#{scheme}://#{host}/#{owner}/#{repo}.git"
# sourcehut
elsif host == "git.sr.ht"
owner, repo = path.split("/")
url = "#{scheme}://#{host}/#{owner}/#{repo}"
# GitLab (gitlab.com or self-hosted)
elsif path.include?("/-/archive/")
url = url.sub(%r{/-/archive/.*$}i, ".git")
end

url
end

# livecheck should fetch a URL using brewed curl if the formula/cask
# contains a `stable`/`url` or `head` URL `using: :homebrew_curl` that
# shares the same root domain.
Expand Down Expand Up @@ -705,12 +638,7 @@

checked_urls = []
urls.each_with_index do |original_url, i|
# Only preprocess the URL when it's appropriate
url = if STRATEGY_SYMBOLS_TO_SKIP_PREPROCESS_URL.include?(livecheck_strategy)
original_url
else
preprocess_url(original_url)
end
url = original_url

Check warning on line 641 in Library/Homebrew/livecheck/livecheck.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/livecheck/livecheck.rb#L641

Added line #L641 was not covered by tests
next if checked_urls.include?(url)

strategies = Strategy.from_url(
Expand All @@ -722,6 +650,11 @@
strategy = Strategy.from_symbol(livecheck_strategy) || strategies.first
strategy_name = livecheck_strategy_names[strategy]

if strategy.respond_to?(:preprocess_url)
url = strategy.preprocess_url(url)
next if checked_urls.include?(url)
end

if debug
puts
if livecheck_url.is_a?(Symbol)
Expand Down Expand Up @@ -921,10 +854,6 @@
checked_urls = []
urls.each_with_index do |original_url, i|
url = original_url.gsub(Constants::LATEST_VERSION, formula_latest)

# Only preprocess the URL when it's appropriate
url = preprocess_url(url) unless STRATEGY_SYMBOLS_TO_SKIP_PREPROCESS_URL.include?(livecheck_strategy)

next if checked_urls.include?(url)

strategies = Strategy.from_url(
Expand All @@ -936,6 +865,11 @@
strategy = Strategy.from_symbol(livecheck_strategy) || strategies.first
strategy_name = livecheck_strategy_names[strategy]

if strategy.respond_to?(:preprocess_url)
url = strategy.preprocess_url(url)
next if checked_urls.include?(url)
end

if debug
puts
if livecheck_url.is_a?(Symbol)
Expand Down
67 changes: 67 additions & 0 deletions Library/Homebrew/livecheck/strategy/git.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# typed: strict
# frozen_string_literal: true

require "addressable"
require "system_command"

module Homebrew
Expand All @@ -26,6 +27,9 @@ module Strategy
class Git
extend SystemCommand::Mixin

# Used to cache processed URLs, to avoid duplicating effort.
@processed_urls = T.let({}, T::Hash[String, String])

# The priority of the strategy on an informal scale of 1 to 10 (from
# lowest to highest).
PRIORITY = 8
Expand All @@ -34,12 +38,75 @@ class Git
# regex isn't provided.
DEFAULT_REGEX = /\D*(.+)/

GITEA_INSTANCES = T.let(%w[
codeberg.org
gitea.com
opendev.org
tildegit.org
].freeze, T::Array[String])
private_constant :GITEA_INSTANCES

GOGS_INSTANCES = T.let(%w[
lolg.it
].freeze, T::Array[String])
private_constant :GOGS_INSTANCES

# Processes and returns the URL used by livecheck.
sig { params(url: String).returns(String) }
def self.preprocess_url(url)
processed_url = @processed_urls[url]
return processed_url if processed_url

begin
uri = Addressable::URI.parse url
rescue Addressable::URI::InvalidURIError
return url
end

host = uri.host
path = uri.path
return url if host.nil? || path.nil?

host = "github.com" if host == "github.s3.amazonaws.com"
path = path.delete_prefix("/").delete_suffix(".git")
scheme = uri.scheme

if host == "github.com"
return url if path.match? %r{/releases/latest/?$}

owner, repo = path.delete_prefix("downloads/").split("/")
processed_url = "#{scheme}://#{host}/#{owner}/#{repo}.git"
elsif GITEA_INSTANCES.include?(host)
return url if path.match? %r{/releases/latest/?$}

owner, repo = path.split("/")
processed_url = "#{scheme}://#{host}/#{owner}/#{repo}.git"
elsif GOGS_INSTANCES.include?(host)
owner, repo = path.split("/")
processed_url = "#{scheme}://#{host}/#{owner}/#{repo}.git"
# sourcehut
elsif host == "git.sr.ht"
owner, repo = path.split("/")
processed_url = "#{scheme}://#{host}/#{owner}/#{repo}"
# GitLab (gitlab.com or self-hosted)
elsif path.include?("/-/archive/")
processed_url = url.sub(%r{/-/archive/.*$}i, ".git")
end

if processed_url && (processed_url != url)
@processed_urls[url] = processed_url
else
url
end
end

# 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) }
def self.match?(url)
url = preprocess_url(url)
(DownloadStrategyDetector.detect(url) <= GitDownloadStrategy) == true
end

Expand Down
85 changes: 0 additions & 85 deletions Library/Homebrew/test/livecheck/livecheck_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -256,89 +256,4 @@
expect(livecheck.use_homebrew_curl?(f_homebrew_curl, "test")).to be(false)
end
end

describe "::preprocess_url" do
let(:github_git_url_with_extension) { "https://github.com/Homebrew/brew.git" }

it "returns the unmodified URL for an unparsable URL" do
# Modeled after the `head` URL in the `ncp` formula
expect(livecheck.preprocess_url(":something:cvs:@cvs.brew.sh:/cvs"))
.to eq(":something:cvs:@cvs.brew.sh:/cvs")
end

it "returns the unmodified URL for a GitHub URL ending in .git" do
expect(livecheck.preprocess_url(github_git_url_with_extension))
.to eq(github_git_url_with_extension)
end

it "returns the Git repository URL for a GitHub URL not ending in .git" do
expect(livecheck.preprocess_url("https://github.com/Homebrew/brew"))
.to eq(github_git_url_with_extension)
end

it "returns the unmodified URL for a GitHub /releases/latest URL" do
expect(livecheck.preprocess_url("https://github.com/Homebrew/brew/releases/latest"))
.to eq("https://github.com/Homebrew/brew/releases/latest")
end

it "returns the Git repository URL for a GitHub AWS URL" do
expect(livecheck.preprocess_url("https://github.s3.amazonaws.com/downloads/Homebrew/brew/1.0.0.tar.gz"))
.to eq(github_git_url_with_extension)
end

it "returns the Git repository URL for a github.com/downloads/... URL" do
expect(livecheck.preprocess_url("https://github.com/downloads/Homebrew/brew/1.0.0.tar.gz"))
.to eq(github_git_url_with_extension)
end

it "returns the Git repository URL for a GitHub tag archive URL" do
expect(livecheck.preprocess_url("https://github.com/Homebrew/brew/archive/1.0.0.tar.gz"))
.to eq(github_git_url_with_extension)
end

it "returns the Git repository URL for a GitHub release archive URL" do
expect(livecheck.preprocess_url("https://github.com/Homebrew/brew/releases/download/1.0.0/brew-1.0.0.tar.gz"))
.to eq(github_git_url_with_extension)
end

it "returns the Git repository URL for a gitlab.com archive URL" do
expect(livecheck.preprocess_url("https://gitlab.com/Homebrew/brew/-/archive/1.0.0/brew-1.0.0.tar.gz"))
.to eq("https://gitlab.com/Homebrew/brew.git")
end

it "returns the Git repository URL for a self-hosted GitLab archive URL" do
expect(livecheck.preprocess_url("https://brew.sh/Homebrew/brew/-/archive/1.0.0/brew-1.0.0.tar.gz"))
.to eq("https://brew.sh/Homebrew/brew.git")
end

it "returns the Git repository URL for a Codeberg archive URL" do
expect(livecheck.preprocess_url("https://codeberg.org/Homebrew/brew/archive/brew-1.0.0.tar.gz"))
.to eq("https://codeberg.org/Homebrew/brew.git")
end

it "returns the Git repository URL for a Gitea archive URL" do
expect(livecheck.preprocess_url("https://gitea.com/Homebrew/brew/archive/brew-1.0.0.tar.gz"))
.to eq("https://gitea.com/Homebrew/brew.git")
end

it "returns the Git repository URL for an Opendev archive URL" do
expect(livecheck.preprocess_url("https://opendev.org/Homebrew/brew/archive/brew-1.0.0.tar.gz"))
.to eq("https://opendev.org/Homebrew/brew.git")
end

it "returns the Git repository URL for a tildegit archive URL" do
expect(livecheck.preprocess_url("https://tildegit.org/Homebrew/brew/archive/brew-1.0.0.tar.gz"))
.to eq("https://tildegit.org/Homebrew/brew.git")
end

it "returns the Git repository URL for a LOL Git archive URL" do
expect(livecheck.preprocess_url("https://lolg.it/Homebrew/brew/archive/brew-1.0.0.tar.gz"))
.to eq("https://lolg.it/Homebrew/brew.git")
end

it "returns the Git repository URL for a sourcehut archive URL" do
expect(livecheck.preprocess_url("https://git.sr.ht/~Homebrew/brew/archive/1.0.0.tar.gz"))
.to eq("https://git.sr.ht/~Homebrew/brew")
end
end
end
Loading