diff options
author | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-09-13 19:58:57 +0000 |
---|---|---|
committer | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-09-13 19:58:57 +0000 |
commit | 1daa0b113d853bfa57b776cc569939b61ca14292 (patch) | |
tree | f8c4acb08a551820299dff2b13966d6ac38d31e4 /lib/rubygems/installer.rb | |
parent | 85995e88d49c442b5b113c2676456133e79f5c02 (diff) | |
download | ruby-1daa0b113d853bfa57b776cc569939b61ca14292.tar.gz |
* lib/rubygems: Update to RubyGems 2.1.3
Fixed installing platform gems
Restored concurrent requires
Fixed installing gems with extensions with --install-dir
Fixed `gem fetch -v` to install the latest version
Fixed installing gems with "./" in their files entries
* test/rubygems/test_gem_package.rb: Tests for the above.
* NEWS: Updated for RubyGems 2.1.3
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42938 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rubygems/installer.rb')
-rw-r--r-- | lib/rubygems/installer.rb | 148 |
1 files changed, 88 insertions, 60 deletions
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index 261af890c8..0ccf7ad52f 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -9,6 +9,7 @@ require 'rubygems/package' require 'rubygems/ext' require 'rubygems/user_interaction' require 'fileutils' +require 'thread' ## # The installer installs the files contained in the .gem into the Gem.home. @@ -32,6 +33,14 @@ class Gem::Installer ENV_PATHS = %w[/usr/bin/env /bin/env] ## + # The builder shells-out to run various commands after changing the + # directory. This means multiple installations cannot be allowed to build + # extensions in parallel as they may change each other's directories leading + # to broken extensions or failed installations. + + CHDIR_MUTEX = Mutex.new # :nodoc: + + ## # Raised when there is an error while building extensions. # class ExtensionBuildError < Gem::InstallError; end @@ -84,8 +93,8 @@ class Gem::Installer # :env_shebang:: Use /usr/bin/env in bin wrappers. # :force:: Overrides all version checks and security policy checks, except # for a signed-gems-only policy. - # :format_executable:: Format the executable the same as the Ruby executable. - # If your Ruby is ruby18, foo_exec will be installed as + # :format_executable:: Format the executable the same as the ruby executable. + # If your ruby is ruby18, foo_exec will be installed as # foo_exec18. # :ignore_dependencies:: Don't raise if a dependency is missing. # :install_dir:: The directory to install the gem into. @@ -144,7 +153,7 @@ class Gem::Installer io.gets # blankline # TODO detect a specially formatted comment instead of trying - # to run a regexp against Ruby code. + # to run a regexp against ruby code. next unless io.gets =~ /This file was generated by RubyGems/ ruby_executable = true @@ -213,25 +222,20 @@ class Gem::Installer FileUtils.mkdir_p gem_dir - spec.loaded_from = spec_file - - if @options[:install_as_default] - extract_bin - write_default_spec - else - extract_files + extract_files - build_extensions - write_build_info_file - run_post_build_hooks + build_extensions + write_build_info_file + run_post_build_hooks - generate_bin - write_spec - write_cache_file - end + generate_bin + write_spec + write_cache_file say spec.post_install_message unless spec.post_install_message.nil? + spec.loaded_from = spec_file + Gem::Specification.add_spec spec unless Gem::Specification.include? spec run_post_install_hooks @@ -332,14 +336,6 @@ class Gem::Installer end ## - # The location of of the default spec file for default gems. - # - - def default_spec_file - File.join gem_home, "specifications/default", "#{spec.full_name}.gemspec" - end - - ## # Writes the .gemspec specification (in Ruby) to the gem home's # specifications directory. @@ -351,16 +347,6 @@ class Gem::Installer end ## - # Writes the full .gemspec specification (in Ruby) to the gem home's - # specifications/default directory. - - def write_default_spec - File.open(default_spec_file, "w") do |file| - file.puts spec.to_ruby - end - end - - ## # Creates windows .bat files for easy running of commands def generate_windows_script(filename, bindir) @@ -561,13 +547,13 @@ class Gem::Installer :bin_dir => nil, :env_shebang => false, :force => false, + :install_dir => Gem.dir, :only_install_dir => false }.merge options @env_shebang = options[:env_shebang] @force = options[:force] - @install_dir = options[:install_dir] - @gem_home = options[:install_dir] || Gem.dir + @gem_home = options[:install_dir] @ignore_dependencies = options[:ignore_dependencies] @format_executable = options[:format_executable] @security_policy = options[:security_policy] @@ -642,7 +628,7 @@ TEXT end ## - # return the stub script text used to launch the true Ruby script + # return the stub script text used to launch the true ruby script def windows_stub_script(bindir, bin_file_name) ruby = File.basename(Gem.ruby).chomp('"') @@ -661,20 +647,75 @@ TEXT # configure scripts and rakefiles or mkrf_conf files. def build_extensions - builder = Gem::Ext::Builder.new spec, @build_args + return if spec.extensions.empty? - builder.build_extensions + if @build_args.empty? + say "Building native extensions. This could take a while..." + else + say "Building native extensions with: '#{@build_args.join(' ')}'" + say "This could take a while..." + end + + dest_path = File.join gem_dir, spec.require_paths.first + ran_rake = false # only run rake once + + spec.extensions.each do |extension| + break if ran_rake + results = [] + + extension ||= "" + extension_dir = File.join gem_dir, File.dirname(extension) + + builder = case extension + when /extconf/ then + Gem::Ext::ExtConfBuilder + when /configure/ then + Gem::Ext::ConfigureBuilder + when /rakefile/i, /mkrf_conf/i then + ran_rake = true + Gem::Ext::RakeBuilder + when /CMakeLists.txt/ then + Gem::Ext::CmakeBuilder + else + message = "No builder for extension '#{extension}'" + extension_build_error extension_dir, message + end + + begin + FileUtils.mkdir_p dest_path + + CHDIR_MUTEX.synchronize do + Dir.chdir extension_dir do + results = builder.build(extension, gem_dir, dest_path, + results, @build_args) + + say results.join("\n") if Gem.configuration.really_verbose + end + end + rescue + extension_build_error(extension_dir, results.join("\n"), $@) + end + end end ## # Logs the build +output+ in +build_dir+, then raises ExtensionBuildError. - # - # TODO: Delete this for RubyGems 3. It remains for API compatibility - def extension_build_error(build_dir, output, backtrace = nil) # :nodoc: - builder = Gem::Ext::Builder.new spec, @build_args + def extension_build_error(build_dir, output, backtrace = nil) + gem_make_out = File.join build_dir, 'gem_make.out' + + open gem_make_out, 'wb' do |io| io.puts output end - builder.build_error build_dir, output, backtrace + message = <<-EOF +ERROR: Failed to build gem native extension. + + #{output} + +Gem files will remain installed in #{gem_dir} for inspection. +Results logged to #{gem_make_out} +EOF + + raise ExtensionBuildError, message, backtrace end ## @@ -687,15 +728,6 @@ TEXT end ## - # Extracts only the bin/ files from the gem into the gem directory. - # This is used by default gems to allow a gem-aware stub to function - # without the full gem installed. - - def extract_bin - @package.extract_files gem_dir, "bin/*" - end - - ## # Prefix and suffix the program filename the same as ruby. def formatted_program_filename(filename) @@ -718,7 +750,7 @@ TEXT ## # Performs various checks before installing the gem such as the install - # repository is writable and its directories exist, required Ruby and + # repository is writable and its directories exist, required ruby and # rubygems versions are met and that dependencies are installed. # # Version and dependency checks are skipped if this install is forced. @@ -735,11 +767,7 @@ TEXT ensure_loadable_spec - if options[:install_as_default] - Gem.ensure_default_gem_subdirectories gem_home - else - Gem.ensure_gem_subdirectories gem_home - end + Gem.ensure_gem_subdirectories gem_home return true if @force |