diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 81dcf445fc..a2deeed57f 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -1225,7 +1225,8 @@ class DownloadStrategyDetector when %r{^https?://github\.com/[^/]+/[^/]+\.git$} GitHubGitDownloadStrategy when %r{^https?://.+\.git$}, - %r{^git://} + %r{^git://}, + %r{^https?://git\.sr\.ht/[^/]+/[^/]+$} GitDownloadStrategy when %r{^https?://www\.apache\.org/dyn/closer\.cgi}, %r{^https?://www\.apache\.org/dyn/closer\.lua} diff --git a/Library/Homebrew/livecheck/livecheck.rb b/Library/Homebrew/livecheck/livecheck.rb index fae6e91804..1c4d6d3699 100644 --- a/Library/Homebrew/livecheck/livecheck.rb +++ b/Library/Homebrew/livecheck/livecheck.rb @@ -3,6 +3,7 @@ require "livecheck/strategy" require "ruby-progressbar" +require "uri" module Homebrew # The {Livecheck} module consists of methods used by the `brew livecheck` @@ -13,18 +14,15 @@ module Homebrew module Livecheck module_function - GITHUB_SPECIAL_CASES = %w[ - api.github.com - /latest - mednafen - camlp5 - kotlin - osrm-backend - prometheus - pyenv-virtualenv - sysdig - shairport-sync - yuicompressor + GITEA_INSTANCES = %w[ + codeberg.org + gitea.com + opendev.org + tildegit.org + ].freeze + + GOGS_INSTANCES = %w[ + lolg.it ].freeze UNSTABLE_VERSION_KEYWORDS = %w[ @@ -316,26 +314,35 @@ module Homebrew # Preprocesses and returns the URL used by livecheck. # @return [String] def preprocess_url(url) - # Check for GitHub repos on github.com, not AWS - url = url.sub("github.s3.amazonaws.com", "github.com") if url.include?("github") + begin + uri = URI.parse url + rescue URI::InvalidURIError + return url + end - # Use repo from GitHub or GitLab inferred from download URL - if url.include?("github.com") && GITHUB_SPECIAL_CASES.none? { |sc| url.include? sc } - if url.include? "archive" - url = url.sub(%r{/archive/.*}, ".git") if url.include? "github" - elsif url.include? "releases" - url = url.sub(%r{/releases/.*}, ".git") - elsif url.include? "downloads" - url = "#{Pathname.new(url.sub(%r{/downloads(.*)}, "\\1")).dirname}.git" - elsif !url.end_with?(".git") - # Truncate the URL at the user/repo part, if possible - %r{(?(?:[a-z]+://)?github.com/[^/]+/[^/#]+)} =~ url - url = github_repo_url if github_repo_url.present? + host = uri.host == "github.s3.amazonaws.com" ? "github.com" : uri.host + path = uri.path.delete_prefix("/").delete_suffix(".git") + scheme = uri.scheme - url.delete_suffix!("/") if url.end_with?("/") - url += ".git" - end - elsif url.include?("/-/archive/") + if host.end_with?("github.com") + return url if path.match? %r{/releases/latest/?$} + + owner, repo = path.delete_prefix("downloads/").split("/") + url = "#{scheme}://#{host}/#{owner}/#{repo}.git" + elsif host.end_with?(*GITEA_INSTANCES) + return url if path.match? %r{/releases/latest/?$} + + owner, repo = path.split("/") + url = "#{scheme}://#{host}/#{owner}/#{repo}.git" + elsif host.end_with?(*GOGS_INSTANCES) + owner, repo = path.split("/") + url = "#{scheme}://#{host}/#{owner}/#{repo}.git" + # sourcehut + elsif host.end_with?("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 diff --git a/Library/Homebrew/test/livecheck/livecheck_spec.rb b/Library/Homebrew/test/livecheck/livecheck_spec.rb index edf2d27216..261896abd9 100644 --- a/Library/Homebrew/test/livecheck/livecheck_spec.rb +++ b/Library/Homebrew/test/livecheck/livecheck_spec.rb @@ -156,6 +156,12 @@ describe Homebrew::Livecheck do describe "::preprocess_url" do let(:github_git_url_with_extension) { "https://github.com/Homebrew/brew.git" } + it "returns the unmodified URL for an unparseable 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) @@ -200,5 +206,35 @@ describe Homebrew::Livecheck 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