Author: assaf
Date: Mon Mar 17 23:10:42 2008
New Revision: 638226

URL: http://svn.apache.org/viewvc?rev=638226&view=rev
Log:
Test cases for addon ... now we know it works

Modified:
    incubator/buildr/trunk/lib/core/addon.rb
    incubator/buildr/trunk/spec/addon_spec.rb

Modified: incubator/buildr/trunk/lib/core/addon.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/core/addon.rb?rev=638226&r1=638225&r2=638226&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/core/addon.rb (original)
+++ incubator/buildr/trunk/lib/core/addon.rb Mon Mar 17 23:10:42 2008
@@ -26,33 +26,38 @@
 module Buildr
 
   # :call-seq:
-  #   addon(id, options?)
-  #   addon(task, options?)
+  #   addon(name, version?)
+  #   addon(task)
   #
-  # Use this to download and install an addon.  The first form takes the addon 
identifier,
-  # a string that contains the qualified name, colon and version number.  For 
example:
-  #   addon 'buildr-openjpa', '1.0'
-  # Some addon accept options passed as a hash argument.
+  # Use the specified addon, downloading and install it, if necessary.
   #
-  # The second form takes a file task that points to the directory containing 
the addon.
+  # Addons are essentially Ruby gems, but installed and loaded differently:
+  # * The addon method downloads and installs the gem, if necessary.
+  # * It requires a Ruby file with the same name as the gem, if it finds one.
+  # * It imports all .rake files found in the Gem's tasks directory.
+  #
+  # The first form takes the gem's name and optional version requirement.  The 
default
+  # version requirement is '>= 0' (see RubyGem's gem method for more 
information).
+  # For example:
+  #   addon 'buildr-java', '~> 1.0'
+  #
+  # The second form takes a file task that points to the Gem file.
   def addon(name_or_path, version = nil)
     case name_or_path
     when Rake::FileTask
       path = name_or_path.to_s
       spec = Gem::Format.from_file_by_path(path).spec
-      name, version = spec.name, spec.version
     when String
-      name = name_or_path
-      spec = Gem::SourceIndex.from_installed_gems.search(name, version).first 
|| Gem::SourceInfoCache.search(name, version).first
-      fail "Could not find #{name} locally or in remote repository." unless 
spec
-      version ||= '> 0'
+      dep = Gem::Dependency.new(name_or_path, version)
+      spec = Gem::SourceIndex.from_installed_gems.search(dep).last || 
Gem::SourceInfoCache.search(dep).last
+      fail Gem::LoadError, "Could not find #{name_or_path} locally or in 
remote repository." unless spec
     else fail "First argument must be Gem name or File task."
     end
 
-    if Gem::SourceIndex.from_installed_gems.search(name, version).empty?
-      say "Installing #{spec.full_name} ... "
-      cmd = File.join(Config::CONFIG['bindir'], 
Config::CONFIG['ruby_install_name']), '-S', 'gem', 'install', name_or_path.to_s
-      cmd << '-v' << version.to_s if version
+    if Gem::SourceIndex.from_installed_gems.search(spec.name, 
spec.version).empty?
+      say "Installing #{spec.full_name} ... " if verbose
+      cmd = Config::CONFIG['ruby_install_name'], '-S', 'gem', 'install', 
name_or_path.to_s
+      cmd << '-v' << spec.version.to_s
       cmd.unshift 'sudo' unless Gem.win_platform? || RUBY_PLATFORM =~ /java/
       sh *cmd.push(:verbose=>false)
       Gem.source_index.load_gems_in Gem::SourceIndex.installed_spec_directories
@@ -74,12 +79,11 @@
 =end
     end
     
-    Gem.activate(name, true, version).tap do
-      spec = Gem.loaded_specs[name]
+    Gem.activate(spec.name, true, spec.version).tap do
       FileList[spec.require_paths.map { |path| 
File.expand_path("#{path}/*.rb", spec.full_gem_path) }].
         map { |path| File.basename(path) }.each { |file| require file }
       FileList[File.expand_path('tasks/*.rake', spec.full_gem_path)].each do 
|file| 
-        Rake.application.add_import
+        Rake.application.add_import file
       end
     end
   end
@@ -143,10 +147,9 @@
 
     def package_as_gem(file_name) #:nodoc:
       PackageGemTask.define_task(file_name).tap do |gem|
-        { 'lib' =>_(:source, :main, :ruby),
-          'test'=>_(:source, :test, :ruby),
-          'doc' =>_(:source, :doc) }.
-          each { |target, source| gem.include :from=>source, :path=>target if 
File.directory?(source) }
+        %{ lib test doc }.each do |dir|
+          gem.include :from=>_(dir), :path=>dir if File.directory?(_(dir))
+        end
         gem.spec do |spec|
           spec.name = id
           spec.version = version

Modified: incubator/buildr/trunk/spec/addon_spec.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/spec/addon_spec.rb?rev=638226&r1=638225&r2=638226&view=diff
==============================================================================
--- incubator/buildr/trunk/spec/addon_spec.rb (original)
+++ incubator/buildr/trunk/spec/addon_spec.rb Mon Mar 17 23:10:42 2008
@@ -17,156 +17,103 @@
 require File.join(File.dirname(__FILE__), 'spec_helpers')
 
 
-=begin
-describe Addon do
-  before { $loaded = false }
+describe Buildr, 'addon' do
 
-  it 'should list all loaded addons' do
-    write 'foobar/init.rb'
-    addon file('foobar')
-    Addon.list.each { |addon| addon.should be_kind_of(Addon) }.
-      map(&:name).should include('foobar')
-  end
-
-  it 'should return true when loading addon for first time' do
-    write 'foobar/init.rb'
-    addon(file('foobar')).should be(true)
-  end
-
-  it 'should allow loading same addon twice' do
-    write 'foobar/init.rb'
-    addon file('foobar')
-    lambda { addon file('foobar') }.should_not raise_error
-  end
-
-  it 'should return false when loading addon second time' do
-    write 'foobar/init.rb'
-    addon(file('foobar'))
-    addon(file('foobar')).should be(false)
-  end
-
-  it 'should instantiate addon once even if loaded twice' do
-    write 'foobar/init.rb', <<-RUBY
-      $loaded = !$loaded
-    RUBY
-    lambda { addon file('foobar') }.should change { $loaded }
-    lambda { addon file('foobar') }.should_not change { $loaded }
-  end
-end
-
-
-describe Addon, 'from directory' do
-  before { $loaded = false }
-
-  it 'should have no version number' do
-  end
-
-  it 'should add directory to LOAD_PATH' do
-    mkpath 'foobar'
-    lambda { addon file('foobar') }.should change { $LOAD_PATH.clone }
-    $LOAD_PATH.should include(File.expand_path('foobar'))
-  end
-
-  it 'should load init.rb file if found' do
-    write 'foobar/init.rb', '$loaded = true'
-    lambda { addon file('foobar') }.should change { $loaded }.to(true)
-  end
-
-  it 'should add init.rb to LOADED_FEATURES' do
-    write 'foobar/init.rb'
-    lambda { addon file('foobar') }.should change { $LOADED_FEATURES.clone }
-    $LOADED_FEATURES.should include(File.expand_path('foobar/init.rb'))
-  end
-
-  it 'should pass options to addon' do
-    write 'foobar/init.rb', '$loaded = $ADDON[:loaded]'
-    lambda { addon file('foobar'), :loaded=>5 }.should change { $loaded }.to(5)
-  end
-
-  it 'should import any tasks present in tasks sub-directory' do
-    write 'foobar/tasks/foo.rake', "$loaded = 'foo'"
-    addon file('foobar')
-    lambda { Rake.application.load_imports }.should change { $loaded 
}.to('foo')
-  end
-
-  it 'should fail if directory doesn\'t exist' do
-    lambda { addon file('missing') }.should raise_error(RuntimeError, /not a 
directory/i)
-  end
-
-  it 'should fail if path is not a directory' do
-    write 'wrong'
-    lambda { addon file('wrong') }.should raise_error(RuntimeError, /not a 
directory/i)
-  end
-end
-
-
-describe Addon, 'from artifact' do
-  before { $loaded = false }
-
-  def load_addon(options = nil)
-    write 'source/init.rb', "require 'extra'"
-    write 'source/extra.rb', '$loaded = $ADDON[:loaded] || true'
-    
zip('repository/org/apache/buildr/foobar/1.0/foobar-1.0.zip').include(:from=>'source').invoke
-    addon 'org.apache.buildr.foobar:1.0', options
-  end
-
-  it 'should figure out addon group from name:version' do
-    artifact('fizz.buzz:foobar:zip:1.0').should_receive(:execute)
-    addon 'fizz.buzz.foobar:1.0' rescue nil
-  end
-
-  it 'should pick name from prefix' do
-    load_addon
-    Addon.list.map(&:name).should include('org.apache.buildr.foobar')
-  end
-
-  it 'should pick version from suffix' do
-    load_addon
-    Addon.list.map(&:version).should include('1.0')
-  end
-
-  it 'should download artifact from remote repository' do
-    lambda { addon 'org.apache.buildr.foobar:1.0' }.should 
raise_error(Exception, /no remote repositories/i)
-  end
-
-  it 'should install artifact in local repository' do
-    load_addon
-    file('repository/org/apache/buildr/foobar/1.0/foobar-1.0.zip').should exist
-  end
-
-  it 'should expand ZIP addon into local repository' do
-    load_addon
-    file('repository/org/apache/buildr/foobar/1.0/foobar-1.0').should exist
-    file('repository/org/apache/buildr/foobar/1.0/foobar-1.0').should 
contain('init.rb', 'extra.rb')
-  end
-
-  it 'should add directory to LOAD_PATH' do
-    lambda { load_addon  }.should change { $LOAD_PATH.clone }
-    $LOAD_PATH.should 
include(File.expand_path('repository/org/apache/buildr/foobar/1.0/foobar-1.0'))
-  end
-
-  it 'should load init.rb file if found' do
-    lambda { load_addon }.should change { $loaded }.to(true)
-  end
-
-  it 'should add init.rb to LOADED_FEATURES' do
-    lambda { load_addon }.should change { $LOADED_FEATURES.clone }
-    $LOADED_FEATURES.should 
include(File.expand_path('repository/org/apache/buildr/foobar/1.0/foobar-1.0/init.rb'))
-  end
-
-  it 'should pass options to addon' do
-    lambda { load_addon :loaded=>5 }.should change { $loaded }.to(5)
-  end
-
-  it 'should fail if loading same addon with two different versions' do
-    load_addon
-    lambda { addon 'org.apache.buildr.foobar:2.0' }.should 
raise_error(RuntimeError, /two different version numbers/)
-  end
+  before do
+    Gem.source_index.load_gems_in Gem::SourceIndex.installed_spec_directories
+    @loaded_specs = Gem.loaded_specs.clone
+    @available ||= []
+    Gem::SourceInfoCache.should_receive(:search).any_number_of_times do |dep|
+      @available.select { |spec| spec.name == dep.name && 
dep.version_requirements.satisfied_by?(spec.version) }.sort_by(&:sort_obj)
+    end
+
+    should_receive(:sh).any_number_of_times do |*args|
+      unless Gem.win_platform? || RUBY_PLATFORM =~ /java/
+        fail 'Expecting sudo gem for this platform' unless args.shift == 'sudo'
+      end
+      args.shift =~ /ruby/ or fail 'Expecting ruby command'
+      args.shift == '-S' or fail 'Expecting -S command line argument'
+      args.shift == 'gem' or fail 'Expecting gem script'
+      args.shift == 'install' or fail 'Expecting install comamnd'
+      (name = args.shift) or fail 'Expecting gem name to come next'
+      args.shift == '-v' or fail 'Expecting -v option'
+      dep = Gem::Dependency.new(name, args.shift)
+      if spec = Gem::SourceInfoCache.search(dep).last
+        spec.loaded_from = File.join(Gem.dir, 'specifications', 
"#{spec.full_name}.gemspec")
+        Gem.source_index.add_spec(spec)
+        
Gem.source_index.should_receive(:load_gems_in).any_number_of_times.with(Gem::SourceIndex.installed_spec_directories)
+      else
+        fail 'Forget to check source info cache'
+      end
+    end
+  end
+
+  def available(name, version)
+    @available << Gem::Specification.new do |s|
+      s.platform = Gem::Platform::RUBY
+      s.name = name
+      s.version = version
+      s.author = 'A User'
+      s.email = '[EMAIL PROTECTED]'
+      s.homepage = 'http://example.com'
+      s.has_rdoc = true
+      s.summary = "this is a summary"
+      s.description = "This is a test description"
+      yield(s) if block_given?
+    end
+  end
+
+  it 'should install specified gem' do
+    available 'foobar', '1.0.0'
+    lambda { addon 'foobar' }.should change { spec = 
Gem.loaded_specs['foobar'] and spec.full_name }.to('foobar-1.0.0')
+  end
+
+  it 'should install version 0 or later' do
+    available 'foobar', '0.0.0'
+    lambda { addon 'foobar' }.should change { spec = 
Gem.loaded_specs['foobar'] and spec.full_name }.to('foobar-0.0.0')
+  end
+
+  it 'should install specified version number' do
+    ['1.0', '1.1', '1.2', '2.0'].each do |version|
+      available 'foobar', version
+    end
+    lambda { addon 'foobar', '1.1' }.should change { spec = 
Gem.loaded_specs['foobar'] and spec.full_name }.to('foobar-1.1')
+  end
+
+  it 'should install version matching requirement' do
+    ['1.0', '1.1', '1.2', '2.0'].each do |version|
+      available 'foobar', version
+    end
+    lambda { addon 'foobar', '~> 1' }.should change { spec = 
Gem.loaded_specs['foobar'] and spec.full_name }.to('foobar-1.2')
+  end
+
+  it 'should complain if no version matches requirement' do
+    available 'foobar', '1.0'
+    lambda { addon 'foobar', '2.0' }.should raise_error(Gem::LoadError, /could 
not find/i)
+  end
+
+  it 'should complain if installing conflicting versions' do
+    available 'foobar', '1.0'
+    available 'foobar', '2.0'
+    addon 'foobar', '1.0'
+    lambda { addon 'foobar', '2.0' }.should raise_error(Exception, /can't 
activate/)
+  end
+
+  it 'should complain if gem not in remote repository' do
+    lambda { addon 'foobar', '1.1' }.should raise_error(Gem::LoadError, /could 
not find foobar/i)
+  end
+
+  it 'should not install gem if already present' do
+    addon 'rake'
+  end
+
+  it 'should not install if gem already exists in local repository'
+
+  it 'should require files in gem require path (lib)'
+  it 'should not require files placed elsewhere in gem'
+  it 'should import all .rake files in tasks directory'
 
-  it 'should import any tasks present in tasks sub-directory' do
-    write 'source/tasks/foo.rake', "$loaded = 'foo'"
-    load_addon
-    lambda { Rake.application.load_imports }.should change { $loaded 
}.to('foo')
+  after do
+    Gem.loaded_specs.replace @loaded_specs
   end
 end
-=end


Reply via email to