Attempt to deal with more cases of gems with native components.

This commit adds a rudimentary check for 'unbuilt' gems, so that we can abort
the application load if there are any gems that have native components that
have not yet been built.

The rake task gems:build has now only builds 'unbuilt' gems as a result.

The rake task gems:build:force has been added to deal with cases of incomplete
builds, or any case where you need to force the build of all of your gems.

Changes the gems:build task to get its gem list by parsing directory entries
in vendor/gems, which sidesteps the chicken/egg issues involved with having a
gem unpacked into vendor/gems without before its native bits are compiled.

[#2266 state:committed]

Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
This commit is contained in:
David Dollar 2009-04-29 01:22:54 -04:00 committed by Jeremy Kemper
parent acd5db300b
commit 599f2cfb4a
9 changed files with 159 additions and 6 deletions

@ -156,6 +156,8 @@ def process
add_support_load_paths
check_for_unbuilt_gems
load_gems
load_plugins
@ -308,6 +310,25 @@ def load_gems
end
end
def check_for_unbuilt_gems
unbuilt_gems = @configuration.gems.select(&:frozen?).reject(&:built?)
if unbuilt_gems.size > 0
# don't print if the gems:build rake tasks are being run
unless $gems_build_rake_task
abort <<-end_error
The following gems have native components that need to be built
#{unbuilt_gems.map { |gem| "#{gem.name} #{gem.requirement}" } * "\n "}
You're running:
ruby #{Gem.ruby_version} at #{Gem.ruby}
rubygems #{Gem::RubyGemsVersion} at #{Gem.path * ', '}
Run `rake gems:build` to build the unbuilt gems.
end_error
end
end
end
def check_gem_dependencies
unloaded_gems = @configuration.gems.reject { |g| g.loaded? }
if unloaded_gems.size > 0

@ -29,6 +29,15 @@ def self.add_frozen_gem_path
end
end
def self.from_directory_name(directory_name)
directory_name_parts = File.basename(directory_name).split('-')
name = directory_name_parts[0..-2].join('-')
version = directory_name_parts.last
self.new(name, :version => version)
rescue ArgumentError => e
raise "Unable to determine gem name and version from '#{directory_name}'"
end
def initialize(name, options = {})
require 'rubygems' unless Object.const_defined?(:Gem)
@ -101,8 +110,12 @@ def requirement
end
def built?
# TODO: If Rubygems ever gives us a way to detect this, we should use it
false
return false unless frozen?
specification.extensions.each do |ext|
makefile = File.join(unpacked_gem_directory, File.dirname(ext), 'Makefile')
return false unless File.exists?(makefile)
end
true
end
def framework_gem?
@ -155,9 +168,9 @@ def vendor_gem?
specification && File.exists?(unpacked_gem_directory)
end
def build
def build(options={})
require 'rails/gem_builder'
unless built?
if options[:force] || !built?
return unless File.exists?(unpacked_specification_filename)
spec = YAML::load_file(unpacked_specification_filename)
Rails::GemBuilder.new(spec, unpacked_gem_directory).build_extensions

@ -20,8 +20,16 @@ namespace :gems do
desc "Build any native extensions for unpacked gems"
task :build do
$gems_build_rake_task = true
Rake::Task['gems:unpack'].invoke
current_gems.each &:build
frozen_gems.each &:build
end
namespace :build do
desc "Force the build of all gems"
task :force do
$gems_build_rake_task = true
Rake::Task['gems:unpack'].invoke
current_gems.each { |gem| gem.build(:force => true) }
end
end
desc "Installs all required gems."
@ -53,6 +61,12 @@ def current_gems
gems
end
def frozen_gems
Dir[File.join(RAILS_ROOT, 'vendor', 'gems', '*-*')].map do |gem_dir|
Rails::GemDependency.from_directory_name(gem_dir)
end
end
def print_gem_status(gem, indent=1)
code = case
when gem.framework_gem? then 'R'

@ -145,4 +145,25 @@ def test_gem_handle_missing_dependencies
end
end
def test_gem_from_directory_name
dummy_gem = Rails::GemDependency.from_directory_name('dummy-gem-1.1')
assert_equal 'dummy-gem', dummy_gem.name
assert_equal '= 1.1', dummy_gem.version_requirements.to_s
end
def test_gem_from_invalid_directory_name
assert_raises RuntimeError do
dummy_gem = Rails::GemDependency.from_directory_name('dummy-gem')
end
assert_raises RuntimeError do
dummy_gem = Rails::GemDependency.from_directory_name('dummy')
end
end
def test_gem_determines_build_status
assert_equal true, Rails::GemDependency.new("dummy-gem-a").built?
assert_equal true, Rails::GemDependency.new("dummy-gem-i").built?
assert_equal false, Rails::GemDependency.new("dummy-gem-j").built?
end
end

@ -0,0 +1,41 @@
--- !ruby/object:Gem::Specification
name: dummy-gem-i
version: !ruby/object:Gem::Version
version: 1.3.0
platform: ruby
authors:
- "Nobody"
date: 2008-10-03 00:00:00 -04:00
dependencies:
- !ruby/object:Gem::Dependency
name: dummy-gem-i
type: :runtime
version_requirement:
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 1.0.0
version:
extensions:
- ext/dummy-gem-i/extconf.rb
files:
- lib
- lib/dummy-gem-i.rb
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: "0"
version:
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: "0"
version:
requirements: []
specification_version: 2
summary: Dummy Gem G

@ -0,0 +1 @@
DUMMY_GEM_I_VERSION="1.0.0"

@ -0,0 +1,41 @@
--- !ruby/object:Gem::Specification
name: dummy-gem-j
version: !ruby/object:Gem::Version
version: 1.3.0
platform: ruby
authors:
- "Nobody"
date: 2008-10-03 00:00:00 -04:00
dependencies:
- !ruby/object:Gem::Dependency
name: dummy-gem-j
type: :runtime
version_requirement:
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 1.0.0
version:
extensions:
- ext/dummy-gem-j/extconf.rb
files:
- lib
- lib/dummy-gem-j.rb
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: "0"
version:
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: "0"
version:
requirements: []
specification_version: 2
summary: Dummy Gem G

@ -0,0 +1 @@
DUMMY_GEM_J_VERSION="1.0.0"