[#29270] Proposal: Module#thunk_method — Charles Oliver Nutter <headius@...>

Many people use define_method solely so they can define a new method

13 messages 2010/04/06

[#29293] URI.(un)escape deprecated? — Marc-Andre Lafortune <ruby-core-mailing-list@...>

Hi.

16 messages 2010/04/07
[#29366] Re: URI.(un)escape deprecated? — Tanaka Akira <akr@...> 2010/04/08

2010/4/7 Marc-Andre Lafortune <ruby-core-mailing-list@marc-andre.ca>:

[#29313] [Bug #3112] require "yaml" doesn't use psych as default — Usaku NAKAMURA <redmine@...>

Bug #3112: require "yaml" doesn't use psych as default

28 messages 2010/04/08
[#29315] [Bug #3112] require "yaml" doesn't use psych as default — Yui NARUSE <redmine@...> 2010/04/08

Issue #3112 has been updated by Yui NARUSE.

[#29336] Re: [Bug #3112] require "yaml" doesn't use psych as default — Aaron Patterson <aaron@...> 2010/04/08

On Thu, Apr 08, 2010 at 02:06:55PM +0900, Yui NARUSE wrote:

[#29395] [Bug #3119] [Patch] "IOError (closed stream)" error with tempfile unlink then close usage — Simon Nicholls <redmine@...>

Bug #3119: [Patch] "IOError (closed stream)" error with tempfile unlink then close usage

9 messages 2010/04/09

[#29427] [Bug #3124] SocketError on SnowLeopard (during make test-all) — Aaron Patterson <redmine@...>

Bug #3124: SocketError on SnowLeopard (during make test-all)

10 messages 2010/04/11

[#29462] [Feature #3131] add Kernel#Hash() method like Kernel#Array() — Suraj Kurapati <redmine@...>

Feature #3131: add Kernel#Hash() method like Kernel#Array()

10 messages 2010/04/11

[#29464] [Bug #3132] …/nokogiri-1.4.1/ext/nokogiri/nokogiri.bundle: [BUG] Bus Error — Ashley Williams <redmine@...>

Bug #3132: …/nokogiri-1.4.1/ext/nokogiri/nokogiri.bundle: [BUG] Bus Error

8 messages 2010/04/12

[#29486] [Bug #3140] gem activation has changed between 1.8 and 1.9 — Aaron Patterson <redmine@...>

Bug #3140: gem activation has changed between 1.8 and 1.9

102 messages 2010/04/13
[#31002] [Bug #3140] gem activation has changed between 1.8 and 1.9 — Aaron Patterson <redmine@...> 2010/07/02

Issue #3140 has been updated by Aaron Patterson.

[#31003] Re: [Bug #3140] gem activation has changed between 1.8 and 1.9 — Yusuke ENDOH <mame@...> 2010/07/02

Hi,

[#31005] Re: [Bug #3140] gem activation has changed between 1.8 and 1.9 — Yehuda Katz <wycats@...> 2010/07/02

We are about to ship a version of Ruby with a built in package manager with

[#29489] Re: [Bug #3140] gem activation has changed between 1.8 and 1.9 — Evan Phoenix <evan@...> 2010/04/13

After a brief discussion with Eric Hodel about this, there are a few questions before we can figure out how to solve this:

[#29513] Re: [Bug #3140] gem activation has changed between 1.8 and 1.9 — Evan Phoenix <evan@...> 2010/04/14

Is there any comment on this? This is a big bug in 1.9.2 that we'd like to get fixed as soon as we can, but I need some input on it.

[#29526] Re: [Bug #3140] gem activation has changed between 1.8 and 1.9 — Rich Kilmer <rich.kilmer@...> 2010/04/15

I wrote this original code in gem_prelude.

[#31104] [Bug #3140] gem activation has changed between 1.8 and 1.9 — Yusuke Endoh <redmine@...> 2010/07/07

Issue #3140 has been updated by Yusuke Endoh.

[#31108] Re: [Bug #3140] gem activation has changed between 1.8 and 1.9 — Roger Pack <rogerdpack2@...> 2010/07/07

> I've commited the patch to trunk.

[#31193] Re: [Bug #3140] gem activation has changed between 1.8 and 1.9 — Yusuke ENDOH <mame@...> 2010/07/11

Hi,

[#31223] Re: [Bug #3140] gem activation has changed between 1.8 and 1.9 — Roger Pack <rogerdpack2@...> 2010/07/12

> Roger, could you re-try to build from scratch? ould you apply

[#31215] [Bug #3140] gem activation has changed between 1.8 and 1.9 — Yehuda Katz <redmine@...> 2010/07/12

Issue #3140 has been updated by Yehuda Katz.

[#31218] Re: [Bug #3140] gem activation has changed between 1.8 and 1.9 — Yukihiro Matsumoto <matz@...> 2010/07/12

Hi,

[#29528] [Bug #3150] net/https peer verification doesn't do anything — Hongli Lai <redmine@...>

Bug #3150: net/https peer verification doesn't do anything

11 messages 2010/04/15

[#29578] [Bug #3163] SyntaxError when using variable which is also a method in current scope with a Symbol argument — Benoit Daloze <redmine@...>

Bug #3163: SyntaxError when using variable which is also a method in current scope with a Symbol argument

17 messages 2010/04/17
[#29583] [Bug #3163] SyntaxError when using variable which is also a method in current scope with a Symbol argument — caleb clausen <redmine@...> 2010/04/18

Issue #3163 has been updated by caleb clausen.

[#29641] [Feature #3176] Thread#priority= should actually do something — caleb clausen <redmine@...>

Feature #3176: Thread#priority= should actually do something

28 messages 2010/04/19

[#29710] [Bug #3185] File.expand_path repeats forward slashes at the beginning of the path — Brian Ford <redmine@...>

Bug #3185: File.expand_path repeats forward slashes at the beginning of the path

10 messages 2010/04/21

[#29835] [Bug #3212] ConditionVariable may become inconsistent for interrupted threads — Sylvain Joyeux <redmine@...>

Bug #3212: ConditionVariable may become inconsistent for interrupted threads

24 messages 2010/04/28

[#29868] [Bug:trunk] assert now passes non-boolean result — Nobuyoshi Nakada <nobu@...>

Hi,

15 messages 2010/04/29

[ruby-core:29537] Re: [Bug #3140] gem activation has changed between 1.8 and 1.9

From: Evan Phoenix <evan@...>
Date: 2010-04-15 18:08:27 UTC
List: ruby-core #29537
On Apr 14, 2010, at 8:36 PM, Rich Kilmer wrote:

> I wrote this original code in gem_prelude.
> 
> The intent of this was threefold:
> 
> 1) Make RubyGems packaged files accessible with require/load in 1.9
> without having to require 'rubygems'
> 2) Minimize startup time (don't load the full rubygems library if its
> not going to be used)
> 3) Load rubygems proper if need be.
> 
<snip>

> I would prefer C.  I know we don't have a lot of time before 1.9.2 but
> if we get our ducks in a row we can make this work...it does need to
> be fixed.

I've gone ahead and implemented an option D, which is very similar to the original suggestion made for RubyGems back in 2007 (blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/12792).

This moves the RubyGem custom require into the prelude and triggers the full loading of RubyGems itself if the normal require raises a LoadError. It fixes the problem because the highest version gems are no longer pushed on $LOAD_PATH, allowing RubyGems to activate gems and the proper dependencies.

This isn't as nice as Rich's suggestions, but it's possible to do easily without changes load.c.

I've attached the patch for comment.

Thanks!

 - Evan

Attachments (1)

gems-load.diff (9.42 KB, text/x-diff)
Index: gem_prelude.rb
===================================================================
--- gem_prelude.rb	(revision 27351)
+++ gem_prelude.rb	(working copy)
@@ -1,23 +1,15 @@
-# depends on: array.rb dir.rb env.rb file.rb hash.rb module.rb regexp.rb
 # vim: filetype=ruby
+# WARN
 
 # NOTICE: Ruby is during initialization here.
 # * Encoding.default_external does not reflects -E.
 # * Should not expect Encoding.default_internal.
 # * Locale encoding is available.
 
+# The implementation must define the Gem module before loading this prelude
+# to indicate that it wants the prelude to introduce rubygems functionality.
 if defined?(Gem) then
 
-  # :stopdoc:
-
-  module Kernel
-
-    def gem(gem_name, *version_requirements)
-      Gem.push_gem_version_on_load_path(gem_name, *version_requirements)
-    end
-    private :gem
-  end
-
   module Gem
 
     ConfigMap = {
@@ -66,8 +58,8 @@
     end
 
     def self.set_home(home)
-      home = home.dup.force_encoding(Encoding.find('filesystem'))
-      home.gsub!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
+      home = home.dup.force_encoding Encoding.find('filesystem')
+      home.gsub! File::ALT_SEPARATOR, File::SEPARATOR if File::ALT_SEPARATOR
       @gem_home = home
     end
 
@@ -88,11 +80,12 @@
       end
 
       @gem_path.uniq!
-      @gem_path.map!{|x|x.force_encoding(Encoding.find('filesystem'))}
+      @gem_path.map! { |dir| dir.force_encoding Encoding.find('filesystem') }
     end
 
     def self.user_home
-      @user_home ||= File.expand_path("~").force_encoding(Encoding.find('filesystem'))
+      @user_home ||= File.expand_path("~").force_encoding \
+        Encoding.find('filesystem')
     rescue
       if File::ALT_SEPARATOR then
         "C:/"
@@ -106,7 +99,6 @@
     require 'lib/rubygems/defaults.rb'
     # end rubygems/defaults
 
-
     ##
     # Methods before this line will be removed when QuickLoader is replaced
     # with the real RubyGems
@@ -135,6 +127,7 @@
     module QuickLoader
 
       @loaded_full_rubygems_library = false
+      @loading_full_rubygems = false
 
       def self.load_full_rubygems_library
         return if @loaded_full_rubygems_library
@@ -154,120 +147,52 @@
         end
 
         $".delete path_to_full_rubygems_library
+
         $".each do |path|
-          if /#{Regexp.escape File::SEPARATOR}rubygems\.rb\z/ =~ path
+          if /#{Regexp.escape File::SEPARATOR}rubygems\.rb\z/ =~ path then
             raise LoadError, "another rubygems is already loaded from #{path}"
           end
         end
+
+        @loading_full_rubygems = true
         require 'rubygems'
+        @loading_full_rubygems = false
       end
 
       def self.fake_rubygems_as_loaded
         path = path_to_full_rubygems_library
-        $" << path unless $".include?(path)
+        $" << path unless $".include? path
       end
 
       def self.path_to_full_rubygems_library
-        installed_path = File.join(Gem::ConfigMap[:rubylibprefix], Gem::ConfigMap[:ruby_version])
-        if $:.include?(installed_path)
-          return File.join(installed_path, 'rubygems.rb')
+        installed_path = File.join(Gem::ConfigMap[:rubylibprefix],
+                                   Gem::ConfigMap[:ruby_version])
+
+        if $:.include? installed_path then
+          File.join installed_path, 'rubygems.rb'
         else # e.g., on test-all
           $:.each do |dir|
-            if File.exist?( path = File.join(dir, 'rubygems.rb') )
-              return path
-            end
+            path = File.join(dir, 'rubygems.rb')
+            return path if File.exist?(path)
           end
+
           raise LoadError, 'rubygems.rb'
         end
       end
 
-      GemPaths = {}
-      GemVersions = {}
-
       def push_gem_version_on_load_path(gem_name, *version_requirements)
-        if version_requirements.empty?
-          unless GemPaths.has_key?(gem_name) then
-            raise Gem::LoadError, "Could not find RubyGem #{gem_name} (>= 0)\n"
-          end
+        QuickLoader.load_full_rubygems_library
+        gem gem_name, *version_requirements
+      end
 
-          # highest version gems already active
-          return false
-        else
-          if version_requirements.length > 1 then
-            QuickLoader.load_full_rubygems_library
-            return gem(gem_name, *version_requirements)
-          end
-
-          requirement, version = version_requirements[0].split
-          requirement.strip!
-
-          if loaded_version = GemVersions[gem_name] then
-            case requirement
-            when ">", ">=" then
-              return false if
-                (loaded_version <=> Gem.integers_for(version)) >= 0
-            when "~>" then
-              required_version = Gem.integers_for version
-
-              return false if loaded_version.first == required_version.first
-            end
-          end
-
+      def self.try_require(path)
+        unless @loaded_full_rubygems_library
           QuickLoader.load_full_rubygems_library
-          gem gem_name, *version_requirements
         end
-      end
 
-      def integers_for(gem_version)
-        numbers = gem_version.split(".").collect {|n| n.to_i}
-        numbers.pop while numbers.last == 0
-        numbers << 0 if numbers.empty?
-        numbers
-      end
+        return false if @loading_full_rubygems
 
-      def push_all_highest_version_gems_on_load_path
-        Gem.path.each do |path|
-          gems_directory = File.join(path, "gems")
-
-          if File.exist?(gems_directory) then
-            Dir.entries(gems_directory).each do |gem_directory_name|
-              next if gem_directory_name == "." || gem_directory_name == ".."
-
-              next unless gem_name = gem_directory_name[/(.*)-(.*)/, 1]
-              new_version = integers_for($2)
-              current_version = GemVersions[gem_name]
-
-              if !current_version or (current_version <=> new_version) < 0 then
-                GemVersions[gem_name] = new_version
-                GemPaths[gem_name] = File.join(gems_directory, gem_directory_name)
-              end
-            end
-          end
-        end
-
-        require_paths = []
-
-        GemPaths.each_value do |path|
-          if File.exist?(file = File.join(path, ".require_paths")) then
-            paths = File.read(file).split.map do |require_path|
-              File.join path, require_path
-            end
-
-            require_paths.concat paths
-          else
-            require_paths << file if File.exist?(file = File.join(path, "bin"))
-            require_paths << file if File.exist?(file = File.join(path, "lib"))
-          end
-        end
-
-        # "tag" the first require_path inserted into the $LOAD_PATH to enable
-        # indexing correctly with rubygems proper when it inserts an explicitly
-        # gem version
-        unless require_paths.empty? then
-          require_paths.first.instance_variable_set(:@gem_prelude_index, true)
-        end
-        # gem directories must come after -I and ENV['RUBYLIB']
-        $:[$:.index{|e|e.instance_variable_defined?(:@gem_prelude_index)}||-1,0] = require_paths
+        Gem.try_require(path)
       end
 
       def const_missing(constant)
@@ -291,8 +216,53 @@
 
   end
 
+  # :stopdoc:
+
+  module Kernel
+
+    def gem(gem_name, *version_requirements)
+      Gem.push_gem_version_on_load_path(gem_name, *version_requirements)
+    end
+
+    private :gem
+
+    ##
+    # The Kernel#require from before RubyGems was loaded.
+
+    alias gem_original_require require
+
+    ##
+    # When RubyGems is required, Kernel#require is replaced with our own which
+    # is capable of loading gems on demand.
+    #
+    # When you call <tt>require 'x'</tt>, this is what happens:
+    # * If the file can be loaded from the existing Ruby loadpath, it
+    #   is.
+    # * Otherwise, installed gems are searched for a file that matches.
+    #   If it's found in gem 'y', that gem is activated (added to the
+    #   loadpath).
+    #
+    # The normal <tt>require</tt> functionality of returning false if
+    # that file has already been loaded is preserved.
+
+    def require(path) # :doc:
+      gem_original_require path
+    rescue LoadError => load_error
+      if load_error.message =~ /#{Regexp.escape path}\z/ then
+        unless Gem::QuickLoader.try_require(path)
+          raise load_error
+        end
+      end
+
+      raise load_error
+    end
+
+    private :require
+    private :gem_original_require
+
+  end
+
   begin
-    Gem.push_all_highest_version_gems_on_load_path
     Gem::QuickLoader.fake_rubygems_as_loaded
   rescue Exception => e
     puts "Error loading gem paths on load path in gem_prelude"
Index: lib/rubygems/custom_require.rb
===================================================================
--- lib/rubygems/custom_require.rb	(revision 27351)
+++ lib/rubygems/custom_require.rb	(working copy)
@@ -6,6 +6,27 @@
 
 require 'rubygems'
 
+if defined? Gem::QuickLoader
+
+module Gem
+
+  ##
+  #
+  # Called from the gem_prelude to attempt to activate +path+
+
+  def self.try_require(path) # :doc:
+    spec = Gem.searcher.find(path)
+    return false unless spec
+
+    Gem.activate(spec.name, "= #{spec.version}")
+    gem_original_require path
+
+    return true
+  end
+end
+
+else
+
 module Kernel
 
   ##
@@ -44,3 +65,4 @@
 
 end
 
+end
Index: lib/rubygems.rb
===================================================================
--- lib/rubygems.rb	(revision 27351)
+++ lib/rubygems.rb	(working copy)
@@ -1063,6 +1063,7 @@
 end
 
 require 'rubygems/config_file'
+require 'rubygems/custom_require'
 
 Gem.clear_paths
 

In This Thread