From 3700f1f2de0c4ab7930ca2feec04aecebf021eea Mon Sep 17 00:00:00 2001 From: Ronald Tse Date: Thu, 5 Nov 2026 01:46:04 +0800 Subject: [PATCH 1/3] fix: locate the maps registry yaml under rubygems 4 rubygems 4 removed StubSpecification#files, which Gem.find_latest_files relies on - on rubygems-4 installs every Interscript.transliterate call raised from map_gems before any map could load. The fast path is kept for rubygems 3 and wrapped: when it raises (or comes back empty), the fallback globs the interscript-maps gems directly (one or two gems, cheap). Verified on a rubygems-4.0.23 install where the gem index is in stub-only state: map resolution and transliteration work without any workaround; rubygems-3 behavior unchanged (fast path intact). --- lib/interscript.rb | 22 +++++++++++++++++- spec/interscript/map_gems_spec.rb | 37 +++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 spec/interscript/map_gems_spec.rb diff --git a/lib/interscript.rb b/lib/interscript.rb index d5483bf8..fd2135bd 100644 --- a/lib/interscript.rb +++ b/lib/interscript.rb @@ -82,8 +82,28 @@ def detect(source, destination, **kwargs) detector.call(source, destination) end + # Locate the interscript-maps registry yaml(s) across installed gems. + # + # rubygems 4 removed StubSpecification#files, which + # Gem.find_latest_files relies on, so the fast path can raise there; + # the fallback globs the interscript-maps gems directly (there are + # only ever one or two of them, so this stays cheap). + def locate_map_gems_yaml + found = begin + Gem.find_latest_files("interscript-maps.yaml") + rescue StandardError, NameError + nil + end + return found if found.is_a?(Array) && found.any? + + Gem::Specification.latest_specs + .select { |spec| spec.name == "interscript-maps" } + .flat_map { |spec| Dir.glob(File.join(spec.full_gem_path, "**", "interscript-maps.yaml")) } + .uniq + end + def map_gems - @map_gems ||= Gem.find_latest_files("interscript-maps.yaml").map do |i| + @map_gems ||= locate_map_gems_yaml.map do |i| [i, YAML.load_file(i)] end.to_h end diff --git a/spec/interscript/map_gems_spec.rb b/spec/interscript/map_gems_spec.rb new file mode 100644 index 00000000..c4f1a90a --- /dev/null +++ b/spec/interscript/map_gems_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require "interscript" +require "tmpdir" +require "fileutils" +require "yaml" + +RSpec.describe Interscript do + describe ".locate_map_gems_yaml" do + it "finds the registry yaml via Gem.find_latest_files when available" do + Dir.mktmpdir do |dir| + gem_dir = File.join(dir, "gems", "interscript-maps-9.9.9") + FileUtils.mkdir_p(gem_dir) + yaml_path = File.join(gem_dir, "interscript-maps.yaml") + File.write(yaml_path, { "paths" => ["maps"] }.to_yaml) + spec = Struct.new(:name, :full_gem_path).new("interscript-maps", gem_dir) + allow(Gem::Specification).to receive(:latest_specs).and_return([spec]) + allow(Gem).to receive(:find_latest_files).with("interscript-maps.yaml").and_return([yaml_path]) + expect(Interscript.locate_map_gems_yaml).to include(yaml_path) + end + end + + it "falls back to a direct gem-dir glob when Gem.find_latest_files is unavailable (rubygems 4)" do + Dir.mktmpdir do |dir| + gem_dir = File.join(dir, "gems", "interscript-maps-9.9.9") + FileUtils.mkdir_p(File.join(gem_dir, "maps")) + yaml_path = File.join(gem_dir, "interscript-maps.yaml") + File.write(yaml_path, { "paths" => ["maps"] }.to_yaml) + spec = Struct.new(:name, :full_gem_path).new("interscript-maps", gem_dir) + allow(Gem::Specification).to receive(:latest_specs).and_return([spec]) + allow(Gem).to receive(:find_latest_files).with("interscript-maps.yaml") + .and_raise(RuntimeError, "undefined method 'files' for Gem::StubSpecification") + expect(Interscript.locate_map_gems_yaml).to include(yaml_path) + end + end + end +end From b2a6fac6bd1fadc46adcd1cb1ee8e674afe90fbd Mon Sep 17 00:00:00 2001 From: Ronald Tse Date: Thu, 5 Nov 2026 02:46:25 +0800 Subject: [PATCH 2/3] style: standardrb - unshadow the rescue, brace spacing in spec --- lib/interscript.rb | 2 +- spec/interscript/map_gems_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/interscript.rb b/lib/interscript.rb index fd2135bd..ef772e5f 100644 --- a/lib/interscript.rb +++ b/lib/interscript.rb @@ -91,7 +91,7 @@ def detect(source, destination, **kwargs) def locate_map_gems_yaml found = begin Gem.find_latest_files("interscript-maps.yaml") - rescue StandardError, NameError + rescue StandardError nil end return found if found.is_a?(Array) && found.any? diff --git a/spec/interscript/map_gems_spec.rb b/spec/interscript/map_gems_spec.rb index c4f1a90a..0afd3f2f 100644 --- a/spec/interscript/map_gems_spec.rb +++ b/spec/interscript/map_gems_spec.rb @@ -12,7 +12,7 @@ gem_dir = File.join(dir, "gems", "interscript-maps-9.9.9") FileUtils.mkdir_p(gem_dir) yaml_path = File.join(gem_dir, "interscript-maps.yaml") - File.write(yaml_path, { "paths" => ["maps"] }.to_yaml) + File.write(yaml_path, {"paths" => ["maps"]}.to_yaml) spec = Struct.new(:name, :full_gem_path).new("interscript-maps", gem_dir) allow(Gem::Specification).to receive(:latest_specs).and_return([spec]) allow(Gem).to receive(:find_latest_files).with("interscript-maps.yaml").and_return([yaml_path]) @@ -25,7 +25,7 @@ gem_dir = File.join(dir, "gems", "interscript-maps-9.9.9") FileUtils.mkdir_p(File.join(gem_dir, "maps")) yaml_path = File.join(gem_dir, "interscript-maps.yaml") - File.write(yaml_path, { "paths" => ["maps"] }.to_yaml) + File.write(yaml_path, {"paths" => ["maps"]}.to_yaml) spec = Struct.new(:name, :full_gem_path).new("interscript-maps", gem_dir) allow(Gem::Specification).to receive(:latest_specs).and_return([spec]) allow(Gem).to receive(:find_latest_files).with("interscript-maps.yaml") From ba603e18aa9bfecd36fa5a188927ccd03a8a8c07 Mon Sep 17 00:00:00 2001 From: Ronald Tse Date: Thu, 5 Nov 2026 02:59:42 +0800 Subject: [PATCH 3/3] style: bare rescue per Style/RescueStandardError --- lib/interscript.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/interscript.rb b/lib/interscript.rb index ef772e5f..b7d4e757 100644 --- a/lib/interscript.rb +++ b/lib/interscript.rb @@ -91,7 +91,7 @@ def detect(source, destination, **kwargs) def locate_map_gems_yaml found = begin Gem.find_latest_files("interscript-maps.yaml") - rescue StandardError + rescue nil end return found if found.is_a?(Array) && found.any?