diff --git a/ChangeLog b/ChangeLog index 4194ff2a56..1a54a045e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Sun Nov 25 12:12:03 2007 Eric Hodel + + * gem_prelude.rb: Import fast-loading gem_prelude.rb from RubyGems. + + * lib/rubygems*: Import RubyGems r1516. + Fri Nov 23 17:34:24 2007 Koichi Sasada * io.c: add rb_read_internal() as blocking function. diff --git a/gem_prelude.rb b/gem_prelude.rb index 7340efcaaf..997dae4699 100644 --- a/gem_prelude.rb +++ b/gem_prelude.rb @@ -1,10 +1,182 @@ # empty gem_prelude.rb # # p Gem::Enable -# p RbConfig::CONFIG["arch"] -# p RbConfig::CONFIG["bindir"] -# p RbConfig::CONFIG["datadir"] -# p RbConfig::CONFIG["sitedir"] -# p RbConfig::CONFIG["sitelibdir"] -# p RbConfig::CONFIG["EXEEXT"] -# p RbConfig::CONFIG["RUBY_SO_NAME"] + +if defined?(Gem::Enable) && Gem::Enable +#t = Time.now + +module Kernel + + def gem(gem_name, *version_requirements) + Gem.push_gem_version_on_load_path(gem_name, *version_requirements) + end + +end + +module Gem + + ConfigMap = { + :sitedir => RbConfig::CONFIG["sitedir"], + :ruby_version => RbConfig::CONFIG["ruby_version"], + :libdir => RbConfig::CONFIG["libdir"], + :sitelibdir => RbConfig::CONFIG["sitelibdir"], + :arch => RbConfig::CONFIG["arch"], + :bindir => RbConfig::CONFIG["bindir"], + :EXEEXT => RbConfig::CONFIG["EXEEXT"], + :RUBY_SO_NAME => RbConfig::CONFIG["RUBY_SO_NAME"], + :ruby_install_name => RbConfig::CONFIG["ruby_install_name"] + } + + class << self + + def default_dir + if defined? RUBY_FRAMEWORK_VERSION + return File.join(File.dirname(ConfigMap[:sitedir]), "Gems") + else + File.join(ConfigMap[:libdir], 'ruby', 'gems', ConfigMap[:ruby_version]) + end + end + + def dir + @gem_home ||= nil + set_home(ENV['GEM_HOME'] || default_dir) unless @gem_home + @gem_home + end + + def path + @gem_path ||= nil + unless @gem_path + paths = [ENV['GEM_PATH']] + paths << APPLE_GEM_HOME if defined? APPLE_GEM_HOME + set_paths(paths.compact.join(File::PATH_SEPARATOR)) + end + @gem_path + end + + # Set the Gem home directory (as reported by +dir+). + def set_home(home) + @gem_home = home + ensure_gem_subdirectories(@gem_home) + end + + def set_paths(gpaths) + if gpaths + @gem_path = gpaths.split(File::PATH_SEPARATOR) + @gem_path << Gem.dir + else + @gem_path = [Gem.dir] + end + @gem_path.uniq! + @gem_path.each do |gp| ensure_gem_subdirectories(gp) end + end + + def ensure_gem_subdirectories(path) + end + + end + + module QuickLoader + + class << self + def load_full_rubygems_library + QuickLoader.instance_methods.each {|method_name| QuickLoader.send(:undef_method, method_name)} + load "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) + raise LoadError.new("Could not find RubyGem #{gem_name} (>= 0)\n") + end + # highest version gems already active + return false + else + if version_requirements.length > 1 + QuickLoader.load_full_rubygems_library + return gem(gem_name, *version_requirements) + end + requirement, version = version_requirements[0].split + requirement.strip! + if requirement == ">" || requirement == ">=" + if (GemVersions[gem_name] <=> Gem.calculate_integers_for_gem_version(version)) >= 0 + return false + end + elsif requirement == "~>" + loaded_version = GemVersions[gem_name] + required_version = Gem.calculate_integers_for_gem_version(version) + if loaded_version && (loaded_version[0] == required_version[0]) + return false + end + end + QuickLoader.load_full_rubygems_library + gem(gem_name, *version_requirements) + end + end + + def calculate_integers_for_gem_version(gem_version) + numbers = gem_version.split(".").collect {|n| n.to_i} + numbers.pop while numbers.last == 0 + numbers << 0 if numbers.empty? + numbers + end + + 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) + Dir.entries(gems_directory).each do |gem_directory_name| + next if gem_directory_name == "." || gem_directory_name == ".." + dash = gem_directory_name.rindex("-") + gem_name = gem_directory_name[0...dash] + current_version = GemVersions[gem_name] + new_version = calculate_integers_for_gem_version(gem_directory_name[dash+1..-1]) + if current_version + if (current_version <=> new_version) == -1 + GemVersions[gem_name] = new_version + GemPaths[gem_name] = File.join(gems_directory, gem_directory_name) + end + else + GemVersions[gem_name] = new_version + GemPaths[gem_name] = File.join(gems_directory, gem_directory_name) + end + end + end + end + require_paths = [] + GemPaths.values.each do |path| + if File.exist?(File.join(path, ".require_paths")) + require_paths.concat(File.read(File.join(path, ".require_paths")).split.map {|require_path| File.join(path, require_path)}) + else + require_paths << File.join(path, "lib") if File.exist?(File.join(path, "lib")) + require_paths << File.join(path, "bin") if File.exist?(File.join(path, "bin")) + end + end + + # gem directories must come after -I and ENV['RUBYLIB'] + $:[$:.index(ConfigMap[:sitelibdir]),0] = require_paths + end + + def const_missing(constant) + QuickLoader.load_full_rubygems_library + Gem.const_get(constant) + end + + def method_missing(method, *args, &block) + QuickLoader.load_full_rubygems_library + Gem.send(method, *args, &block) + end + end + + extend QuickLoader + +end + +Gem.push_all_highest_version_gems_on_load_path +$".unshift File.join(Gem::ConfigMap[:libdir], "ruby", Gem::ConfigMap[:ruby_version], "rubygems.rb") + +#puts "Gem load in #{Time.now - t} seconds" +end # Gem::Enable \ No newline at end of file diff --git a/lib/rubygems.rb b/lib/rubygems.rb index 184461b4d0..f233b520f1 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -5,7 +5,6 @@ # See LICENSE.txt for permissions. #++ -require 'rbconfig' require 'rubygems/rubygems_version' require 'thread' @@ -82,11 +81,25 @@ end # module Gem + ConfigMap = {} unless defined?(ConfigMap) + require 'rbconfig' + ConfigMap.merge!( + :sitedir => RbConfig::CONFIG["sitedir"], + :ruby_version => RbConfig::CONFIG["ruby_version"], + :libdir => RbConfig::CONFIG["libdir"], + :sitelibdir => RbConfig::CONFIG["sitelibdir"], + :arch => RbConfig::CONFIG["arch"], + :bindir => RbConfig::CONFIG["bindir"], + :EXEEXT => RbConfig::CONFIG["EXEEXT"], + :RUBY_SO_NAME => RbConfig::CONFIG["RUBY_SO_NAME"], + :ruby_install_name => RbConfig::CONFIG["ruby_install_name"] + ) + MUTEX = Mutex.new RubyGemsPackageVersion = RubyGemsVersion - DIRECTORIES = %w[cache doc gems specifications] + DIRECTORIES = %w[cache doc gems specifications] unless defined?(DIRECTORIES) @@source_index = nil @@win_platform = nil @@ -120,7 +133,7 @@ module Gem def self.prefix prefix = File.dirname File.expand_path(__FILE__) - if prefix == Config::CONFIG['sitelibdir'] then + if prefix == ConfigMap[:sitelibdir] then nil else File.dirname prefix @@ -221,7 +234,7 @@ module Gem if defined? RUBY_FRAMEWORK_VERSION then # mac framework support '/usr/bin' else # generic install - Config::CONFIG['bindir'] + ConfigMap[:bindir] end end @@ -280,9 +293,9 @@ module Gem # Return the Ruby command to use to execute the Ruby interpreter. def ruby if @ruby.nil? then - @ruby = File.join(Config::CONFIG['bindir'], - Config::CONFIG['ruby_install_name']) - @ruby << Config::CONFIG['EXEEXT'] + @ruby = File.join(ConfigMap[:bindir], + ConfigMap[:ruby_install_name]) + @ruby << ConfigMap[:EXEEXT] end @ruby @@ -342,7 +355,7 @@ module Gem File.join spec.full_gem_path, path end - sitelibdir = Config::CONFIG['sitelibdir'] + sitelibdir = ConfigMap[:sitelibdir] # gem directories must come after -I and ENV['RUBYLIB'] $:.insert($:.index(sitelibdir), *require_paths) @@ -529,9 +542,9 @@ module Gem # not specified in the environment. def default_dir if defined? RUBY_FRAMEWORK_VERSION - return File.join(File.dirname(Config::CONFIG["sitedir"]), "Gems", Config::CONFIG['ruby_version']) + return File.join(File.dirname(ConfigMap[:sitedir]), "Gems", ConfigMap[:ruby_version]) else - File.join(Config::CONFIG['libdir'], 'ruby', 'gems', Config::CONFIG['ruby_version']) + File.join(ConfigMap[:libdir], 'ruby', 'gems', ConfigMap[:ruby_version]) end end @@ -549,7 +562,7 @@ module Config # :nodoc: # Return the path to the data directory associated with the named # package. If the package is loaded as a gem, return the gem # specific data directory. Otherwise return a path to the share - # area as define by "#{Config::CONFIG['datadir']}/#{package_name}". + # area as define by "#{ConfigMap[:datadir]}/#{package_name}". def datadir(package_name) Gem.datadir(package_name) || Config.gem_original_datadir(package_name) end diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index 03f7c92828..46d0144a88 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -10,6 +10,7 @@ require 'rbconfig' require 'rubygems/format' require 'rubygems/ext' +require 'rubygems/require_paths_builder' ## # The installer class processes RubyGem .gem files and installs the @@ -27,6 +28,8 @@ class Gem::Installer class ExtensionBuildError < Gem::InstallError; end include Gem::UserInteraction + + include Gem::RequirePathsBuilder ## # Constructs an Installer instance that will install the gem located at @@ -111,6 +114,8 @@ class Gem::Installer generate_bin build_extensions write_spec + + write_require_paths_file_if_needed # HACK remove? Isn't this done in multiple places? cached_gem = File.join @gem_home, "cache", @gem.split(/\//).pop @@ -235,8 +240,8 @@ class Gem::Installer # the symlink if the gem being installed has a newer version. # def generate_bin_symlink(filename, bindir) - if Config::CONFIG["arch"] =~ /dos|win32/i then - alert_warning "Unable to use symlinks on win32, installing wrapper" + if Gem.win_platform? then + alert_warning "Unable to use symlinks on Windows, installing wrapper" generate_bin_script filename, bindir return end diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb index 24081d4fec..496c4b1fb8 100644 --- a/lib/rubygems/platform.rb +++ b/lib/rubygems/platform.rb @@ -13,7 +13,7 @@ class Gem::Platform attr_accessor :version def self.local - arch = Config::CONFIG['arch'] + arch = Gem::ConfigMap[:arch] arch = "#{arch}_60" if arch =~ /mswin32$/ @local ||= new(arch) end @@ -27,6 +27,8 @@ class Gem::Platform def self.new(arch) # :nodoc: case arch + when Gem::Platform::CURRENT then + Gem::Platform.local when Gem::Platform::RUBY, nil, '' then Gem::Platform::RUBY else @@ -71,7 +73,10 @@ class Gem::Platform when /^java([\d.]*)/ then [ 'java', $1 ] when /linux/ then [ 'linux', $1 ] when /mingw32/ then [ 'mingw32', nil ] - when /(mswin\d+)(\_(\d+))?/ then [ $1, $3 ] + when /(mswin\d+)(\_(\d+))?/ then + os, version = $1, $3 + @cpu = 'x86' if @cpu.nil? and os =~ /32$/ + [os, version] when /netbsdelf/ then [ 'netbsdelf', nil ] when /openbsd(\d+\.\d+)/ then [ 'openbsd', $1 ] when /solaris(\d+\.\d+)/ then [ 'solaris', $1 ] diff --git a/lib/rubygems/require_paths_builder.rb b/lib/rubygems/require_paths_builder.rb new file mode 100644 index 0000000000..fe4f593bf4 --- /dev/null +++ b/lib/rubygems/require_paths_builder.rb @@ -0,0 +1,15 @@ +module Gem + module RequirePathsBuilder + def write_require_paths_file_if_needed(spec = @spec, gem_home = @gem_home) + return if spec.require_paths == ["lib"] && (spec.bindir.nil? || spec.bindir == "bin") + file_name = File.join(gem_home, 'gems', "#{@spec.full_name}", ".require_paths") + file_name.untaint + File.open(file_name, "w") do |file| + spec.require_paths.each do |path| + file.puts path + end + file.puts spec.bindir if spec.bindir + end + end + end +end \ No newline at end of file diff --git a/test/rubygems/gemutilities.rb b/test/rubygems/gemutilities.rb index 0d5ab0297a..bb54ff6362 100644 --- a/test/rubygems/gemutilities.rb +++ b/test/rubygems/gemutilities.rb @@ -8,7 +8,7 @@ at_exit { $SAFE = 1 } require 'fileutils' -require 'test/unit/testcase' +require 'test/unit' require 'tmpdir' require 'uri' require 'rubygems/gem_open_uri' @@ -20,6 +20,10 @@ module Gem def self.source_index=(si) @@source_index = si end + + def self.win_platform=(val) + @@win_platform = val + end end class FakeFetcher @@ -58,7 +62,8 @@ class RubyGemTestCase < Test::Unit::TestCase include Gem::DefaultUserInteraction - undef_method :default_test + undef_method :default_test if instance_methods.include? 'default_test' or + instance_methods.include? :default_test def setup super @@ -84,7 +89,7 @@ class RubyGemTestCase < Test::Unit::TestCase @gem_repo = "http://gems.example.com" Gem.sources.replace [@gem_repo] - @orig_arch = Config::CONFIG['arch'] + @orig_arch = Gem::ConfigMap[:arch] if win_platform? util_set_arch 'i386-mswin32' @@ -96,7 +101,7 @@ class RubyGemTestCase < Test::Unit::TestCase end def teardown - Config::CONFIG['arch'] = @orig_arch + Gem::ConfigMap[:arch] = @orig_arch if defined? Gem::RemoteFetcher then Gem::RemoteFetcher.instance_variable_set :@fetcher, nil @@ -228,7 +233,7 @@ class RubyGemTestCase < Test::Unit::TestCase # Set the platform to +cpu+ and +os+ def util_set_arch(arch) - Config::CONFIG['arch'] = arch + Gem::ConfigMap[:arch] = arch platform = Gem::Platform.new arch Gem.instance_variable_set :@platforms, nil diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb index 05e38f67f8..9a091a291e 100644 --- a/test/rubygems/test_gem_installer.rb +++ b/test/rubygems/test_gem_installer.rb @@ -417,8 +417,8 @@ load 'my_exec' end def test_generate_bin_symlinks_win32 - old_arch = Config::CONFIG["arch"] - Config::CONFIG["arch"] = "win32" + old_win_platform = Gem.win_platform? + Gem.win_platform = true @installer.wrappers = false util_make_exec @installer.gem_dir = util_gem_dir @@ -431,16 +431,13 @@ load 'my_exec' installed_exec = File.join(util_inst_bindir, "my_exec") assert_equal true, File.exist?(installed_exec) - assert_match(/Unable to use symlinks on win32, installing wrapper/i, + assert_match(/Unable to use symlinks on Windows, installing wrapper/i, @ui.error) - - expected_mode = win_platform? ? 0100644 : 0100755 - assert_equal expected_mode, File.stat(installed_exec).mode wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) ensure - Config::CONFIG["arch"] = old_arch + Gem.win_platform = old_win_platform end def test_generate_bin_uses_default_shebang diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb index 4a1651bc0e..a1462d4dcd 100644 --- a/test/rubygems/test_gem_platform.rb +++ b/test/rubygems/test_gem_platform.rb @@ -19,6 +19,7 @@ class TestGemPlatform < RubyGemTestCase end def test_self_new + assert_equal Gem::Platform.local, Gem::Platform.new(Gem::Platform::CURRENT) assert_equal Gem::Platform::RUBY, Gem::Platform.new(Gem::Platform::RUBY) assert_equal Gem::Platform::RUBY, Gem::Platform.new(nil) assert_equal Gem::Platform::RUBY, Gem::Platform.new('') @@ -63,6 +64,7 @@ class TestGemPlatform < RubyGemTestCase 'i386-openbsd4.0' => ['x86', 'openbsd', '4.0'], 'i386-solaris2.10' => ['x86', 'solaris', '2.10'], 'i386-solaris2.8' => ['x86', 'solaris', '2.8'], + 'mswin32' => ['x86', 'mswin32', nil], 'x86_64-linux' => ['x86_64', 'linux', nil], 'x86_64-openbsd3.9' => ['x86_64', 'openbsd', '3.9'], 'x86_64-openbsd4.0' => ['x86_64', 'openbsd', '4.0'],