diff --git a/Library/Homebrew/test/utils/cpan_spec.rb b/Library/Homebrew/test/utils/cpan_spec.rb index 2270d686cf..eceacb07c4 100644 --- a/Library/Homebrew/test/utils/cpan_spec.rb +++ b/Library/Homebrew/test/utils/cpan_spec.rb @@ -6,12 +6,16 @@ RSpec.describe CPAN do let(:cpan_package_url) do "https://cpan.metacpan.org/authors/id/P/PE/PEVANS/Scalar-List-Utils-1.68.tar.gz" end + let(:cpan_tgz_url) do + "https://cpan.metacpan.org/authors/id/S/ST/STBEY/Example-Module-1.23.tgz" + end let(:non_cpan_package_url) do "https://github.com/example/package/archive/v1.0.0.tar.gz" end describe CPAN::Package do let(:package_from_cpan_url) { described_class.new("Scalar::Util", cpan_package_url) } + let(:package_from_tgz_url) { described_class.new("Example::Module", cpan_tgz_url) } let(:package_from_non_cpan_url) { described_class.new("SomePackage", non_cpan_package_url) } describe "initialize" do @@ -19,13 +23,13 @@ RSpec.describe CPAN do expect(package_from_cpan_url.name).to eq "Scalar::Util" end - it "extracts package name from CPAN url" do - expect(package_from_cpan_url.package_name).to eq "Scalar-List-Utils" - end - it "extracts version from CPAN url" do expect(package_from_cpan_url.current_version).to eq "1.68" end + + it "handles .tgz extensions" do + expect(package_from_tgz_url.current_version).to eq "1.23" + end end describe ".valid_cpan_package?" do diff --git a/Library/Homebrew/utils/cpan.rb b/Library/Homebrew/utils/cpan.rb index 89529123b4..aaaf3dcc7a 100644 --- a/Library/Homebrew/utils/cpan.rb +++ b/Library/Homebrew/utils/cpan.rb @@ -6,7 +6,8 @@ require "utils/inreplace" # Helper functions for updating CPAN resources. module CPAN METACPAN_URL_PREFIX = "https://cpan.metacpan.org/authors/id/" - private_constant :METACPAN_URL_PREFIX + CPAN_ARCHIVE_REGEX = /^(.+)-([0-9.v]+)\.(?:tar\.gz|tgz)$/ + private_constant :METACPAN_URL_PREFIX, :CPAN_ARCHIVE_REGEX # Represents a Perl package from an existing resource. class Package @@ -29,12 +30,6 @@ module CPAN @current_version end - sig { returns(T.nilable(String)) } - def package_name - extract_package_name_from_url if @package_name.blank? - @package_name - end - sig { returns(T::Boolean) } def valid_cpan_package? @is_cpan_url @@ -46,10 +41,7 @@ module CPAN return @cpan_info if @cpan_info.present? return unless valid_cpan_package? - pname = package_name - return unless pname - - metadata_url = "https://fastapi.metacpan.org/v1/release/#{pname}" + metadata_url = "https://fastapi.metacpan.org/v1/download_url/#{@resource_name}" result = Utils::Curl.curl_output(metadata_url, "--location", "--fail") return unless result.status.success? @@ -62,7 +54,7 @@ module CPAN download_url = json["download_url"] return unless download_url - checksum = get_checksum_from_cpan(download_url) + checksum = json["checksum_sha256"] return unless checksum @cpan_info = [@resource_name, download_url, checksum, json["version"]] @@ -79,44 +71,11 @@ module CPAN def extract_version_from_url return unless @is_cpan_url - match = File.basename(@resource_url).match(/^(.+)-([0-9.v]+)\.tar\.gz$/) + match = File.basename(@resource_url).match(CPAN_ARCHIVE_REGEX) return unless match @current_version = T.let(match[2], T.nilable(String)) end - - sig { returns(T.nilable(String)) } - def extract_package_name_from_url - return unless @is_cpan_url - - match = File.basename(@resource_url).match(/^(.+)-([0-9.v]+)\.tar\.gz$/) - return unless match - - @package_name = T.let(match[1], T.nilable(String)) - end - - # Get SHA256 checksum from CPAN CHECKSUMS file. - sig { params(download_url: String).returns(T.nilable(String)) } - def get_checksum_from_cpan(download_url) - filename = File.basename(download_url) - dir_url = File.dirname(download_url) - - checksums_url = "#{dir_url}/CHECKSUMS" - checksums_result = Utils::Curl.curl_output(checksums_url, "--location", "--fail") - - return unless checksums_result.status.success? - - checksums_content = checksums_result.stdout - file_block_pattern = /'#{Regexp.escape(filename)}'\s*=>\s*\{[^}]*'sha256'\s*=>\s*'([a-f0-9]{64})'/mi - sha256_match = checksums_content.match(file_block_pattern) - return sha256_match[1] if sha256_match - - alt_pattern = /#{Regexp.escape(filename)}.*?sha256.*?([a-f0-9]{64})/mi - alt_match = checksums_content.match(alt_pattern) - return alt_match[1] if alt_match - - nil - end end # Update CPAN resources in a formula. @@ -202,6 +161,7 @@ module CPAN else inreplace_regex = / \ \ ( + (\s*\#.*\s+)* (\#\ RESOURCE-ERROR:\ .*\s+)* resource\ .*\ do\s+ url\ .*\s+