
At the moment, `#use_homebrew_curl?` can only be true for a `homepage` or `stable`/cask `url` with `using: :homebrew_curl`. If the checked URL differs from these URLs, livecheck won't use brewed curl. This limitation prevents livecheck from using brewed curl for a `livecheck` block URL that's a string literal (not a symbol for a `#checkable_url` like `:stable`, `:head`, `:url`). `libzip` was the original formula referenced in the related brew issue and it meets this criterion, so it doesn't appear to be handled by the existing `#use_homebrew_curl?` implementation. Additionally, the existing behavior can cause livecheck to unnecessarily use brewed curl for a completely different website (e.g., `cubelib`, `otf2`). For example, if the `stable` URL has `using: :homebrew_curl` and the `livecheck` block has `url :homepage`, livecheck will use brewed curl when checking the `homepage`. If these are completely different domains/servers, it's unlikely that we would need to use brewed curl when checking the `homepage`, so this particular behavior may not be beneficial. This commit reimplements `use_homebrew_curl?` to apply brewed curl when the checked URL's root domain is the same as the root domain of an aforementioned formula/cask URL with `using: :homebrew_curl`. For example, this looser approach would allow a `livecheck` block checking `https://www.example.com/downloads/` to use brewed curl if the `stable` URL was `https://downloads.example.com/example.zip` with `using: :homebrew_curl`. These could be different servers but, based on related formulae, this looseness is necessary for the moment. This approach aims to resolve both issues, allowing brewed curl to be applied to a slightly broader range of URLs (i.e., not limited to just the `#checkable_urls`) while also helping to avoid unnecessarily applying brewed curl when it's less likely to be useful (completely different domains). Neither approach is perfect but this one may be more useful in the interim time. Depending on how this looser approach works in practice, we may want to consider returning to a stricter approach once we have something like `using: :homebrew_curl` in `livecheck` blocks (this is forthcoming). Being explicit in a `livecheck` block is the most reliable approach (i.e., only use brewed curl when needed), so we could favor that and pare down the automated approach to only what's needed to support implicit checks (i.e., with no `livecheck` block). Of course, it's also possible to drop the automated approach entirely and simply require a `livecheck` block in this scenario but we can decide on how to handle this when the time comes.
310 lines
11 KiB
Ruby
310 lines
11 KiB
Ruby
# typed: false
|
|
# frozen_string_literal: true
|
|
|
|
require "livecheck/livecheck"
|
|
|
|
describe Homebrew::Livecheck do
|
|
subject(:livecheck) { described_class }
|
|
|
|
let(:cask_url) { "https://brew.sh/test-0.0.1.dmg" }
|
|
let(:head_url) { "https://github.com/Homebrew/brew.git" }
|
|
let(:homepage_url) { "https://brew.sh" }
|
|
let(:livecheck_url) { "https://formulae.brew.sh/api/formula/ruby.json" }
|
|
let(:stable_url) { "https://brew.sh/test-0.0.1.tgz" }
|
|
|
|
let(:f) do
|
|
formula("test") do
|
|
desc "Test formula"
|
|
homepage "https://brew.sh"
|
|
url "https://brew.sh/test-0.0.1.tgz"
|
|
head "https://github.com/Homebrew/brew.git"
|
|
|
|
livecheck do
|
|
url "https://formulae.brew.sh/api/formula/ruby.json"
|
|
regex(/"stable":"(\d+(?:\.\d+)+)"/i)
|
|
end
|
|
end
|
|
end
|
|
|
|
let(:c) do
|
|
Cask::CaskLoader.load(+<<-RUBY)
|
|
cask "test" do
|
|
version "0.0.1,2"
|
|
|
|
url "https://brew.sh/test-0.0.1.dmg"
|
|
name "Test"
|
|
desc "Test cask"
|
|
homepage "https://brew.sh"
|
|
|
|
livecheck do
|
|
url "https://formulae.brew.sh/api/formula/ruby.json"
|
|
regex(/"stable":"(\d+(?:\.\d+)+)"/i)
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
|
|
let(:f_duplicate_urls) do
|
|
formula("test_duplicate_urls") do
|
|
desc "Test formula with a duplicate URL"
|
|
homepage "https://github.com/Homebrew/brew.git"
|
|
url "https://brew.sh/test-0.0.1.tgz"
|
|
head "https://github.com/Homebrew/brew.git"
|
|
end
|
|
end
|
|
|
|
describe "::resolve_livecheck_reference" do
|
|
context "when a formula/cask has a livecheck block without formula/cask methods" do
|
|
it "returns [nil, []]" do
|
|
expect(livecheck.resolve_livecheck_reference(f)).to eq([nil, []])
|
|
expect(livecheck.resolve_livecheck_reference(c)).to eq([nil, []])
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "::formula_name" do
|
|
it "returns the name of the formula" do
|
|
expect(livecheck.formula_name(f)).to eq("test")
|
|
end
|
|
|
|
it "returns the full name" do
|
|
expect(livecheck.formula_name(f, full_name: true)).to eq("test")
|
|
end
|
|
end
|
|
|
|
describe "::cask_name" do
|
|
it "returns the token of the cask" do
|
|
expect(livecheck.cask_name(c)).to eq("test")
|
|
end
|
|
|
|
it "returns the full name of the cask" do
|
|
expect(livecheck.cask_name(c, full_name: true)).to eq("test")
|
|
end
|
|
end
|
|
|
|
describe "::status_hash" do
|
|
it "returns a hash containing the livecheck status" do
|
|
expect(livecheck.status_hash(f, "error", ["Unable to get versions"]))
|
|
.to eq({
|
|
formula: "test",
|
|
status: "error",
|
|
messages: ["Unable to get versions"],
|
|
meta: {
|
|
livecheckable: true,
|
|
},
|
|
})
|
|
end
|
|
end
|
|
|
|
describe "::livecheck_url_to_string" do
|
|
let(:f_livecheck_url) do
|
|
formula("test_livecheck_url") do
|
|
desc "Test Livecheck URL formula"
|
|
homepage "https://brew.sh"
|
|
url "https://brew.sh/test-0.0.1.tgz"
|
|
head "https://github.com/Homebrew/brew.git"
|
|
end
|
|
end
|
|
|
|
let(:c_livecheck_url) do
|
|
Cask::CaskLoader.load(+<<-RUBY)
|
|
cask "test_livecheck_url" do
|
|
version "0.0.1,2"
|
|
|
|
url "https://brew.sh/test-0.0.1.dmg"
|
|
name "Test"
|
|
desc "Test Livecheck URL cask"
|
|
homepage "https://brew.sh"
|
|
end
|
|
RUBY
|
|
end
|
|
|
|
it "returns a URL string when given a livecheck_url string" do
|
|
f_livecheck_url.livecheck.url(livecheck_url)
|
|
expect(livecheck.livecheck_url_to_string(livecheck_url, f_livecheck_url)).to eq(livecheck_url)
|
|
end
|
|
|
|
it "returns a URL symbol when given a valid livecheck_url symbol" do
|
|
f_livecheck_url.livecheck.url(:head)
|
|
expect(livecheck.livecheck_url_to_string(head_url, f_livecheck_url)).to eq(head_url)
|
|
|
|
f_livecheck_url.livecheck.url(:homepage)
|
|
expect(livecheck.livecheck_url_to_string(homepage_url, f_livecheck_url)).to eq(homepage_url)
|
|
|
|
c_livecheck_url.livecheck.url(:homepage)
|
|
expect(livecheck.livecheck_url_to_string(homepage_url, c_livecheck_url)).to eq(homepage_url)
|
|
|
|
f_livecheck_url.livecheck.url(:stable)
|
|
expect(livecheck.livecheck_url_to_string(stable_url, f_livecheck_url)).to eq(stable_url)
|
|
|
|
c_livecheck_url.livecheck.url(:url)
|
|
expect(livecheck.livecheck_url_to_string(cask_url, c_livecheck_url)).to eq(cask_url)
|
|
end
|
|
|
|
it "returns nil when not given a string or valid symbol" do
|
|
expect(livecheck.livecheck_url_to_string(nil, f_livecheck_url)).to be_nil
|
|
expect(livecheck.livecheck_url_to_string(nil, c_livecheck_url)).to be_nil
|
|
expect(livecheck.livecheck_url_to_string(:invalid_symbol, f_livecheck_url)).to be_nil
|
|
expect(livecheck.livecheck_url_to_string(:invalid_symbol, c_livecheck_url)).to be_nil
|
|
end
|
|
end
|
|
|
|
describe "::checkable_urls" do
|
|
it "returns the list of URLs to check" do
|
|
expect(livecheck.checkable_urls(f)).to eq([stable_url, head_url, homepage_url])
|
|
expect(livecheck.checkable_urls(c)).to eq([cask_url, homepage_url])
|
|
expect(livecheck.checkable_urls(f_duplicate_urls)).to eq([stable_url, head_url])
|
|
end
|
|
end
|
|
|
|
describe "::use_homebrew_curl?" do
|
|
let(:example_url) { "https://www.example.com/test-0.0.1.tgz" }
|
|
|
|
let(:f_homebrew_curl) do
|
|
formula("test") do
|
|
desc "Test formula"
|
|
homepage "https://brew.sh"
|
|
url "https://brew.sh/test-0.0.1.tgz", using: :homebrew_curl
|
|
# head is deliberably omitted to exercise more of the method
|
|
|
|
livecheck do
|
|
url "https://formulae.brew.sh/api/formula/ruby.json"
|
|
regex(/"stable":"(\d+(?:\.\d+)+)"/i)
|
|
end
|
|
end
|
|
end
|
|
|
|
let(:c_homebrew_curl) do
|
|
Cask::CaskLoader.load(+<<-RUBY)
|
|
cask "test" do
|
|
version "0.0.1,2"
|
|
|
|
url "https://brew.sh/test-0.0.1.dmg", using: :homebrew_curl
|
|
name "Test"
|
|
desc "Test cask"
|
|
homepage "https://brew.sh"
|
|
|
|
livecheck do
|
|
url "https://formulae.brew.sh/api/formula/ruby.json"
|
|
regex(/"stable":"(\d+(?:\.\d+)+)"/i)
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
|
|
it "returns `true` when URL matches a `using: :homebrew_curl` URL" do
|
|
expect(livecheck.use_homebrew_curl?(f_homebrew_curl, livecheck_url)).to be(true)
|
|
expect(livecheck.use_homebrew_curl?(f_homebrew_curl, homepage_url)).to be(true)
|
|
expect(livecheck.use_homebrew_curl?(f_homebrew_curl, stable_url)).to be(true)
|
|
expect(livecheck.use_homebrew_curl?(c_homebrew_curl, livecheck_url)).to be(true)
|
|
expect(livecheck.use_homebrew_curl?(c_homebrew_curl, homepage_url)).to be(true)
|
|
expect(livecheck.use_homebrew_curl?(c_homebrew_curl, cask_url)).to be(true)
|
|
end
|
|
|
|
it "returns `false` if URL root domain differs from `using: :homebrew_curl` URLs" do
|
|
expect(livecheck.use_homebrew_curl?(f_homebrew_curl, example_url)).to be(false)
|
|
expect(livecheck.use_homebrew_curl?(c_homebrew_curl, example_url)).to be(false)
|
|
end
|
|
|
|
it "returns `false` if a `using: homebrew_curl` URL is not present" do
|
|
expect(livecheck.use_homebrew_curl?(f, livecheck_url)).to be(false)
|
|
expect(livecheck.use_homebrew_curl?(f, homepage_url)).to be(false)
|
|
expect(livecheck.use_homebrew_curl?(f, stable_url)).to be(false)
|
|
expect(livecheck.use_homebrew_curl?(f, example_url)).to be(false)
|
|
expect(livecheck.use_homebrew_curl?(c, livecheck_url)).to be(false)
|
|
expect(livecheck.use_homebrew_curl?(c, homepage_url)).to be(false)
|
|
expect(livecheck.use_homebrew_curl?(c, cask_url)).to be(false)
|
|
expect(livecheck.use_homebrew_curl?(c, example_url)).to be(false)
|
|
end
|
|
|
|
it "returns `false` if URL string does not contain a domain" do
|
|
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 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)
|
|
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
|