From a1d718f7fb4c1a6fafbdba571bfdc2aa91ab1461 Mon Sep 17 00:00:00 2001 From: Max Downey Twiss Date: Wed, 26 Nov 2025 18:01:22 +1100 Subject: [PATCH] Refactor name mapping in tools/version.rb (#13637) * Add get_clean_name function to PackageUtils * Use PackageUtils.get_clean_name in tools/version.rb and refactor name mapping --- lib/const.rb | 8 ++------ lib/package_utils.rb | 19 ++++++++++++++++++- tests/lib/package_utils.rb | 22 ++++++++++++++++++++++ tests/tools/version.rb | 25 +++++++++++++++++++++++++ tools/version.rb | 18 +++++++++++------- 5 files changed, 78 insertions(+), 14 deletions(-) diff --git a/lib/const.rb b/lib/const.rb index bb532ee20..fe7bb8fc5 100644 --- a/lib/const.rb +++ b/lib/const.rb @@ -4,7 +4,7 @@ require 'etc' require 'open3' OLD_CREW_VERSION = defined?(CREW_VERSION) ? CREW_VERSION : '1.0' -CREW_VERSION = '1.68.2' unless defined?(CREW_VERSION) && CREW_VERSION == OLD_CREW_VERSION +CREW_VERSION = '1.68.3' unless defined?(CREW_VERSION) && CREW_VERSION == OLD_CREW_VERSION # Kernel architecture. KERN_ARCH = Etc.uname[:machine] @@ -397,9 +397,6 @@ CREW_ANITYA_PACKAGE_NAME_MAPPINGS = Set[ { pkg_name: 'docbook_xml51', anitya_pkg: 'docbook-xml', comments: '' }, { pkg_name: 'doxygen', anitya_pkg: 'doxygen', comments: '' }, { pkg_name: 'filecmd', anitya_pkg: 'file', comments: '' }, - { pkg_name: 'gcc_build', anitya_pkg: 'gcc', comments: '' }, - { pkg_name: 'gcc_dev', anitya_pkg: 'gcc', comments: '' }, - { pkg_name: 'gcc_lib', anitya_pkg: 'gcc', comments: '' }, { pkg_name: 'gcr_3', anitya_pkg: 'gcr~3', comments: '' }, { pkg_name: 'gcr_4', anitya_pkg: 'gcr', comments: '' }, { pkg_name: 'gemacs', anitya_pkg: 'emacs', comments: '' }, @@ -482,8 +479,7 @@ CREW_ANITYA_PACKAGE_NAME_MAPPINGS = Set[ { pkg_name: 'yad', anitya_pkg: 'yad', comments: 'Prefer to GitHub' }, { pkg_name: 'zig13', anitya_pkg: 'zig', comments: '' }, { pkg_name: 'zimg', anitya_pkg: 'zimg', comments: 'Prefer to GitHub' }, - { pkg_name: 'zoneinfo', anitya_pkg: 'tzdata', comments: '' }, - { pkg_name: 'zstd_static', anitya_pkg: 'zstd', comments: '' } + { pkg_name: 'zoneinfo', anitya_pkg: 'tzdata', comments: '' } ].to_h { |h| [h[:pkg_name], h[:anitya_pkg]] } CREW_LICENSE = <<~LICENSESTRING diff --git a/lib/package_utils.rb b/lib/package_utils.rb index 644c456cf..83c4c66f6 100644 --- a/lib/package_utils.rb +++ b/lib/package_utils.rb @@ -80,7 +80,7 @@ class PackageUtils pkg_version.gsub!(/-dfsg.*/, '') # Delete -gcc14, futureproofed until gcc 100 pkg_version.gsub!(/-gcc\d{2}/, '') - # Trim kde- suffixes in qt5 packages so nothing else gets confused. + # Trim kde- prefixes in qt5 packages so nothing else gets confused. pkg_version.delete_prefix!('kde-') # Delete -py3.12, futureproofed until Python 4 pkg_version.gsub!(/-py3\.\d{2}/, '') @@ -100,6 +100,23 @@ class PackageUtils return pkg_version end + # Remove our language-specific prefixes and any build splitting suffixes. + # This is mostly for use when querying Anitya in tools/version.rb, and is not suitable for Repology. + def self.get_clean_name(pkg_name) + # Delete language-specific prefixes. + pkg_name.delete_prefix!('perl_') + pkg_name.delete_prefix!('py3_') + pkg_name.delete_prefix!('ruby_') + # Delete suffixes for split packages. + pkg_name.delete_suffix!('_build') + pkg_name.delete_suffix!('_dev') + pkg_name.delete_suffix!('_lib') + # Delete the _static suffix for statically built packages. + pkg_name.delete_suffix!('_static') + + return pkg_name + end + def self.get_gitlab_pkginfo(pkg_name, pkg_version, pkg_arch, build = nil, verbose = nil) # This is largely rehashing self.get_binary_url(pkg) using the # curl and jq binaries for debugging purposes. diff --git a/tests/lib/package_utils.rb b/tests/lib/package_utils.rb index 23a89a455..46ac312cd 100644 --- a/tests/lib/package_utils.rb +++ b/tests/lib/package_utils.rb @@ -230,4 +230,26 @@ class PackageUtilsTest < Minitest::Test assert_equal('579-4', PackageUtils.get_clean_version('579-4-1628457')) assert_equal('2.1.5-20220429', PackageUtils.get_clean_version('2.1.5-20220429')) end + + def test_get_clean_perl_name + assert_equal('wakeonlan', PackageUtils.get_clean_name('perl_wakeonlan')) + end + + def test_get_clean_python_name + assert_equal('maturin', PackageUtils.get_clean_name('py3_maturin')) + end + + def test_get_clean_ruby_name + assert_equal('typeprof', PackageUtils.get_clean_name('ruby_typeprof')) + end + + def test_get_clean_split_name + assert_equal('gcc', PackageUtils.get_clean_name('gcc_build')) + assert_equal('gcc', PackageUtils.get_clean_name('gcc_dev')) + assert_equal('gcc', PackageUtils.get_clean_name('gcc_lib')) + end + + def test_get_clean_static_name + assert_equal('zstd', PackageUtils.get_clean_name('zstd_static')) + end end diff --git a/tests/tools/version.rb b/tests/tools/version.rb index 545a2a084..b4264171e 100644 --- a/tests/tools/version.rb +++ b/tests/tools/version.rb @@ -26,6 +26,31 @@ class VersionMonitorTest < Minitest::Test assert_nil(get_anitya_id('99_still_notreal', 'ftp://com.crystal', 'Package')) end + def test_get_prefixed_anitya_id + assert_equal(2636, get_anitya_id('perl_app_cpanminus', 'https://metacpan.org/pod/App::cpanminus', 'PERL')) + # We use the Anitya homepage for maturin here to simplify testing. + assert_equal(42653, get_anitya_id('py3_maturin', 'https://www.maturin.rs', 'Python')) + # Every ruby_ package has the RUBY buildsystem, so we lie here to test the behavior. + # Technically that means we don't need the behavior right now, but things may change. + assert_equal(139836, get_anitya_id('ruby_typeprof', 'https://github.com/ruby/typeprof', 'Package')) + end + + def test_get_split_anitya_id + assert_equal(6502, get_anitya_id('gcc_build', 'https://www.gnu.org/software/gcc/', 'Package')) + assert_equal(6502, get_anitya_id('gcc_dev', 'https://www.gnu.org/software/gcc/', 'Package')) + assert_equal(6502, get_anitya_id('gcc_lib', 'https://www.gnu.org/software/gcc/', 'Package')) + end + + def test_get_static_anitya_id + assert_equal(12083, get_anitya_id('zstd_static', 'https://facebook.github.io/zstd/', 'Package')) + end + + def test_get_mapped_anitya_id + assert_equal(1783, get_anitya_id('libxml2_autotools', 'http://xmlsoft.org/', 'Autotools')) + assert_equal(6502, get_anitya_id('libssp', 'https://gcc.gnu.org/', 'Autotools')) + assert_equal(4194, get_anitya_id('rest', 'https://wiki.gnome.org/Projects/Librest', 'Meson')) + end + def test_get_multi_ecosystem_anitya_id # This should eliminate all the other candidates due to their ecosystems, so the homepage isn't even checked. assert_equal(217, get_anitya_id('bridge_utils', 'https://wiki.linuxfoundation.org/networking/bridge', 'Package')) diff --git a/tools/version.rb b/tools/version.rb index efa94c7d2..9d75ab10d 100755 --- a/tools/version.rb +++ b/tools/version.rb @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# version.rb version 3.16 (for Chromebrew) +# version.rb version 3.17 (for Chromebrew) OPTIONS = %w[-h --help -j --json -u --update-package-files -v --verbose -vv] @@ -51,15 +51,11 @@ versions_updated = {} versions = [] def get_version(name, homepage, source, version) - anitya_name_mapping_idx = CREW_ANITYA_PACKAGE_NAME_MAPPINGS.keys.find_index { |i| i == name } - anitya_name = name.gsub(/\Apy\d_|\Aperl_|\Aruby_/, '') - anitya_name = CREW_ANITYA_PACKAGE_NAME_MAPPINGS.values[anitya_name_mapping_idx] unless anitya_name_mapping_idx.nil? - anitya_id = get_anitya_id(anitya_name, homepage, @pkg.superclass.to_s) - anitya_name = @new_anitya_name unless @new_anitya_name.nil? + anitya_id = get_anitya_id(name, homepage, @pkg.superclass.to_s) # If anitya_id cannot be determined, a Range can be returned, and # .nonzero? does not work with Ranges. anitya_id = nil if anitya_id.is_a? Range - puts "anitya_name: #{anitya_name} anitya_id: #{anitya_id}" if VERBOSE + puts "anitya_id: #{anitya_id}" if VERBOSE if anitya_id&.nonzero? # Get the latest stable version of the package from anitya. json = JSON.parse(Net::HTTP.get(URI("https://release-monitoring.org/api/v2/versions/?project_id=#{anitya_id}"))) @@ -197,6 +193,14 @@ def get_anitya_id(name, homepage, buildsystem) # Ignore python pip and ruby gem packages with the Pip and RUBY buildsystems. return if %w[Pip RUBY].include?(buildsystem) + # Change the name into something Anitya will prefer. + original_name = name.dup + # Remove any language-specific prefixes and build splitting suffixes. + name = PackageUtils.get_clean_name(name) + # If this package has a hardcoded mapping, use it. + name = CREW_ANITYA_PACKAGE_NAME_MAPPINGS[name] if CREW_ANITYA_PACKAGE_NAME_MAPPINGS.include?(name) + puts "anitya_name: #{name} #{"(instead of #{original_name})" if name != original_name}" if VERBOSE + # Find out how many packages Anitya has with the provided name. puts "url is https://release-monitoring.org/api/v2/projects/?name=#{CGI.escape(name)}" if VERY_VERBOSE json = JSON.parse(Net::HTTP.get(URI("https://release-monitoring.org/api/v2/projects/?name=#{CGI.escape(name)}")))