Skip to content

Commit

Permalink
Support gem packaging for extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh French committed Dec 21, 2009
1 parent 729f0cd commit 046670d
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 9 deletions.
19 changes: 12 additions & 7 deletions lib/radiant/extension_loader.rb
Expand Up @@ -73,7 +73,7 @@ def load_extensions
@observer ||= DependenciesObserver.new(configuration).observe(::ActiveSupport::Dependencies)
self.extensions = load_extension_roots.map do |root|
begin
extension_file = "#{File.basename(root).sub(/^\d+_/,'')}_extension"
extension_file = "#{File.basename(root).sub(/^\d+_|-[\d.]+$/,'')}_extension"
extension = extension_file.camelize.constantize
extension.unloadable
extension.root = root
Expand Down Expand Up @@ -124,19 +124,17 @@ def load_extension_roots

def select_extension_roots
all_roots = all_extension_roots.dup

roots = configuration.extensions.map do |ext_name|
if :all === ext_name
:all
else
ext_path = all_roots.detect do |maybe_path|
File.basename(maybe_path).sub(/^\d+_/, '') == ext_name.to_s
File.basename(maybe_path).sub(/^\d+_|-[\d.]+$/, '') == ext_name.to_s
end
raise LoadError, "Cannot find the extension '#{ext_name}'!" if ext_path.nil?
all_roots.delete(ext_path)
end
end

if placeholder = roots.index(:all)
# replace the :all symbol with any remaining paths
roots[placeholder, 1] = all_roots
Expand All @@ -145,9 +143,16 @@ def select_extension_roots
end

def all_extension_roots
@all_extension_roots ||= configuration.extension_paths.map do |path|
Dir["#{path}/*"].map {|f| File.expand_path(f) if File.directory?(f) }.compact.sort
end.flatten
@all_extension_roots ||= begin
roots = configuration.extension_paths.map do |path|
Dir["#{path}/*"].map {|f| File.expand_path(f) if File.directory?(f) }.compact.sort
end
configuration.gems.inject(roots) do |paths,gem|
paths.tap { |p| p << gem.specification.full_gem_path if gem.specification and Dir[gem.specification.full_gem_path+'/*_extension.rb'].any? }
end
roots.flatten
end
end

end
end
11 changes: 9 additions & 2 deletions lib/radiant/initializer.rb
Expand Up @@ -35,9 +35,16 @@ def extensions
end

def all_available_extensions
extension_paths.map do |path|
# load vendorized extensions by inspecting load path(s)
all = extension_paths.map do |path|
Dir["#{path}/*"].select {|f| File.directory?(f) }
end.flatten.map {|f| File.basename(f).sub(/^\d+_/, '') }.sort.map {|e| e.to_sym }
end
# load any gem that looks like an extension. (too informal?)
gems.inject(all) do |available,gem|
available.tap { |a| a << gem.specification.full_gem_path if gem.specification and Dir[gem.specification.full_gem_path + '/*_extension.rb' ].any? }
end
# strip version info to glean proper extension names
all.flatten.map {|f| File.basename(f).sub(/^\d+_|-[\d\.]+$/, '') }.sort.map {|e| e.to_sym }
end

def admin
Expand Down
13 changes: 13 additions & 0 deletions spec/lib/radiant/extension_loader_spec.rb
Expand Up @@ -35,6 +35,13 @@
@instance.send(:select_extension_roots).should == [File.expand_path("#{RADIANT_ROOT}/test/fixtures/extensions/01_basic")]
end

it "should load extensions from gem paths" do
gem_path = File.join RADIANT_ROOT, %w(test fixtures gems gem_ext-0.0.0)
@configuration.should_receive(:extensions).at_least(:once).and_return([:gem_ext])
@instance.stub!(:all_extension_roots).and_return([File.expand_path gem_path])
@instance.send(:select_extension_roots).should == [gem_path]
end

it "should select extensions in an explicit order from the configuration" do
extensions = [:load_order_red, :load_order_blue, :load_order_green]
extension_roots = extensions.map {|ext| File.expand_path("#{RADIANT_ROOT}/test/fixtures/extensions/#{ext}") }
Expand All @@ -58,6 +65,12 @@
lambda { @instance.send(:select_extension_roots) }.should raise_error(LoadError)
end

it "should skip invalid gems" do
@configuration.stub!(:extension_paths).and_return([])
@configuration.stub!(:gems).and_return([Rails::GemDependency.new('bogus_gem')])
@instance.send(:all_extension_roots).should eql([])
end

it "should determine load paths from an extension path" do
@instance.send(:load_paths_for, "#{RADIANT_ROOT}/vendor/extensions/archive").should == %W{
#{RADIANT_ROOT}/vendor/extensions/archive/lib
Expand Down
23 changes: 23 additions & 0 deletions spec/lib/radiant/initializer_spec.rb
Expand Up @@ -70,6 +70,29 @@
@configuration.check_extension_dependencies
}.should raise_error(SystemExit)
end

describe "#all_available_extensions" do
before do
@spec = mock(Gem::Specification)
@gem = mock(Rails::GemDependency, :specification => @spec)
@configuration.gems = [@gem]
end

it "should include valid gems" do
@spec.stub!(:full_gem_path).and_return(File.join RADIANT_ROOT, %w(test fixtures gems gem_ext-0.0.0))
@configuration.all_available_extensions.should include(:gem_ext)
end

it "should not load gems that don't appear to be extensions" do
@spec.stub!(:full_gem_path).and_return(File.join RADIANT_ROOT, %w(test fixtures gems not_ext-0.0.0))
@configuration.all_available_extensions.should_not include(:not_ext)
end

it "should skip gems with invalid specifications" do
@configuration.gems = [Rails::GemDependency.new 'bogus_gem']
@configuration.all_available_extensions.should_not include(:bogus_gem)
end
end
end

describe Radiant::Initializer do
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/gems/gem_ext-0.0.0/gem_ext_extension.rb
@@ -0,0 +1,2 @@
class GemExtExtension
end

0 comments on commit 046670d

Please sign in to comment.