[前][次][番号順一覧][スレッド一覧]

ruby-changes:61116

From: David <ko1@a...>
Date: Fri, 8 May 2020 14:14:37 +0900 (JST)
Subject: [ruby-changes:61116] 4a417b08ae (master): [rubygems/rubygems] Fix incorrect bundler version being required

https://git.ruby-lang.org/ruby.git/commit/?id=4a417b08ae

From 4a417b08aeaf296238059e6abdb465c324073e15 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20Rodr=C3=ADguez?= <deivid.rodriguez@r...>
Date: Sun, 29 Mar 2020 21:45:39 +0200
Subject: [rubygems/rubygems] Fix incorrect bundler version being required

In ruby 2.7.0, there's a slight change in bundler's default gemspec file
where the executable folder of the bundler gem is `libexec` instead of
`exe`. I made that change in https://github.com/ruby/ruby/pull/2380 to
try to simplify the integration of the `bundler` gem with upstream,
minimizing the number of changes that need to be made to the gemspec to
adapt to the structure of ruby-core.

That worked ok, expected for this issue. The new name of the folder
including the executable files uncovered a bug in rubygems, which is the
following:

* In order to be able to use newer versions of default gems, `rubygems`
ships with a customized `require` that has knowledge about which files
belong to which default gem. If one of these files is required,
`rubygems` will detect that and activate its gem mechanism to choose the
newest version of the corresponding default gem present in the system
(unless a different version has already been activated). It's this part
of the custom require:

https://github.com/rubygems/rubygems/blob/ea3e6f194df500b028b52b3b64decbd3df1d5ab0/lib/rubygems/core_ext/kernel_require.rb#L77-L85

* In order to do that, `rubygems` registers a map of default gems and
their files when it is first required:

https://github.com/rubygems/rubygems/blob/ea3e6f194df500b028b52b3b64decbd3df1d5ab0/lib/rubygems.rb#L1247-L1276

As explained in the method's header, two types of default gem
specifications are supported. One of the formats is the style used by
some ruby-core gemspec files, where paths inside the `spec.files` array
don't include the `spec.require_paths` part. So in this "old style", if
a gem ships with a `lib/bundler.rb` file, it will be registered in this
array as `spec.files = ["bundler.rb"]`, not as `spec.files =
["lib/bundler.rb"]`. The `Gem.register_default_spec` method "detects"
this style by making sure that none of the files in the `spec.files`
array start with any of the `spec.require_paths`.

* Since in ruby 2.7 the default specification file of the `bundler` gem
includes a `libexec/bundle` file, this check would no longer work
correctly, because even though the specification file is still "old
style", it has one registered file which starts with "lib", one of the
"require paths" of the gem.

* This means that the gem is incorrectly detected as "new style", but
since none of the paths start with "lib/", no files are actually
registered, so the gem is not being considered a default gem, and thus
the default version is always used with no possibility of being
"upgraded".

The fix of the problem is simple: check that no files start with `lib/`
(or any other require paths), instead of with "lib" which doesn't
exclude other potential "non requirable folder" starting with lib, like
in the `bundler` case.

https://github.com/rubygems/rubygems/commit/94df740c2b

diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 2703525..dbb32b2 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -1217,7 +1217,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} https://github.com/ruby/ruby/blob/trunk/lib/rubygems.rb#L1217
 
     def register_default_spec(spec)
       extended_require_paths = spec.require_paths.map {|f| f + "/"}
-      new_format = spec.require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } }
+      new_format = extended_require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } }
 
       if new_format
         prefix_group = extended_require_paths.join("|")
diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb
index d64a253..6b18bb9 100644
--- a/test/rubygems/test_gem.rb
+++ b/test/rubygems/test_gem.rb
@@ -1750,6 +1750,18 @@ class TestGem < Gem::TestCase https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem.rb#L1750
     assert_nil              Gem.find_unresolved_default_spec("README")
   end
 
+  def test_register_default_spec_old_style_with_folder_starting_with_lib
+    Gem.clear_default_specs
+
+    old_style = Gem::Specification.new do |spec|
+      spec.files = ["libexec/bundle", "foo.rb", "bar.rb"]
+    end
+
+    Gem.register_default_spec old_style
+
+    assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb")
+  end
+
   def test_use_gemdeps
     gem_deps_file = 'gem.deps.rb'.tap(&Gem::UNTAINT)
     spec = util_spec 'a', 1
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]