You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildr.apache.org by la...@apache.org on 2008/08/23 00:09:58 UTC

svn commit: r688204 - in /incubator/buildr/trunk: CHANGELOG lib/buildr/ide/eclipse.rb spec/eclipse_spec.rb

Author: lacton
Date: Fri Aug 22 15:09:57 2008
New Revision: 688204

URL: http://svn.apache.org/viewvc?rev=688204&view=rev
Log:
BUILDR-123: eclipse task now honors ResourceTask's target directory (+ heavy refactoring)

Modified:
    incubator/buildr/trunk/CHANGELOG
    incubator/buildr/trunk/lib/buildr/ide/eclipse.rb
    incubator/buildr/trunk/spec/eclipse_spec.rb

Modified: incubator/buildr/trunk/CHANGELOG
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/CHANGELOG?rev=688204&r1=688203&r2=688204&view=diff
==============================================================================
--- incubator/buildr/trunk/CHANGELOG (original)
+++ incubator/buildr/trunk/CHANGELOG Fri Aug 22 15:09:57 2008
@@ -26,6 +26,7 @@
 * Fixed:  BUILDR-119 Eclipse task does not accept test resource folders
           (Lacton)
 * Fixed:  BUILDR-122: eclipse task should not check for directory existence
+* Fixed:  BUILDR-123: eclipse task should honor ResourceTask's target directory
 * Fixed:  BUILDR-124 unzip(...).from_path does not work correctly without
           include (Rhett Sutphin).
 * Fixed:  BUILDR-126  Tests options are shared between unrelated projects when

Modified: incubator/buildr/trunk/lib/buildr/ide/eclipse.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/buildr/ide/eclipse.rb?rev=688204&r1=688203&r2=688204&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/buildr/ide/eclipse.rb (original)
+++ incubator/buildr/trunk/lib/buildr/ide/eclipse.rb Fri Aug 22 15:09:57 2008
@@ -59,20 +59,13 @@
         file(project.path_to(".classpath")=>sources) do |task|
           info "Writing #{task.name}"
 
-          # Find a path relative to the project's root directory.
-          relative = lambda do |path|
-            path or raise "Invalid path '#{path.inspect}'"
-            msg = [:to_path, :to_str, :to_s].find { |msg| path.respond_to? msg }
-            path = path.__send__(msg)
-            Util.relative_path(File.expand_path(path), project.path_to)
-          end
-
           m2repo = Buildr::Repositories.instance.local
-          excludes = [ '**/.svn/', '**/CVS/' ].join('|')
 
           File.open(task.name, "w") do |file|
             xml = Builder::XmlMarkup.new(:target=>file, :indent=>2)
             xml.classpath do
+              classpathentry = ClasspathEntryWriter.new project, xml
+
               # Note: Use the test classpath since Eclipse compiles both "main" and "test" classes using the same classpath
               cp = project.test.compile.dependencies.map(&:to_s) - [ project.compile.target.to_s, project.resources.target.to_s ]
               cp = cp.uniq
@@ -89,45 +82,23 @@
               # Generated: classpath elements in the project are assumed to be generated
               generated, libs = others.partition { |path| path.to_s.index(project.path_to.to_s) == 0 }
 
-              # Main resources implicitly copied into project.compile.target
-              srcs = (project.compile.sources + generated + project.resources.sources).map { |src| relative[src] }
-
-              srcs.sort.uniq.each do |path|
-                xml.classpathentry :kind=>'src', :path=>path, :excluding=>excludes
-              end
+              classpathentry.src project.compile.sources + generated
+              classpathentry.src project.resources
 
               if project.test.compile.target
-                # Test classes are generated in a separate output directory
-                test_sources = project.test.compile.sources.map { |src| relative[src] }
-                test_sources.each do |paths|
-                  paths.sort.uniq.each do |path|
-                    xml.classpathentry :kind=>'src', :path=>path, :output => relative[project.test.compile.target], :excluding=>excludes
-                  end
-                end
-
-                # Test resources go in separate output directory as well
-                test_resource_sources = project.test.resources.sources.map { |src| relative[src] }
-                test_resource_sources.each do |path|
-                  xml.classpathentry :kind=>'src', :path=>path, :output => relative[project.test.compile.target], :excluding=>excludes
-                end
+                classpathentry.src project.test.compile
+                classpathentry.src project.test.resources
               end
 
               # Classpath elements from other projects
-              project_libs.map(&:id).sort.uniq.each do |project_id|
-                xml.classpathentry :kind=>'src', :combineaccessrules=>"false", :path=>"/#{project_id}" 
-              end
+              classpathentry.src_projects project_libs
 
-              { :output => relative[project.compile.target],
-                :lib    => libs.map(&:to_s),
-                :var    => m2_libs.map { |path| path.to_s.sub(m2repo, 'M2_REPO') }
-              }.each do |kind, paths|
-                paths.sort.uniq.each do |path|
-                  xml.classpathentry :kind=>kind, :path=>path
-                end
-              end
+              classpathentry.output project.compile.target
+              classpathentry.lib libs
+              classpathentry.var m2_libs, 'M2_REPO', m2repo
 
-              xml.classpathentry :kind=>'con', :path=>'ch.epfl.lamp.sdt.launching.SCALA_CONTAINER' if scala
-              xml.classpathentry :kind=>'con', :path=>'org.eclipse.jdt.launching.JRE_CONTAINER'
+              classpathentry.con 'ch.epfl.lamp.sdt.launching.SCALA_CONTAINER' if scala
+              classpathentry.con 'org.eclipse.jdt.launching.JRE_CONTAINER'
             end
           end
         end
@@ -162,6 +133,83 @@
 
     end
 
+    # Writes 'classpathentry' tags in an xml file.
+    # It converts tasks to paths.
+    # It converts absolute paths to relative paths.
+    # It ignores duplicate directories.
+    class ClasspathEntryWriter
+      def initialize project, xml_builder
+        @project = project
+        @xml = xml_builder
+        @excludes = [ '**/.svn/', '**/CVS/' ].join('|')
+        @paths_written = []
+      end
+      
+      def con path
+        @xml.classpathentry :kind=>'con', :path=>path
+      end
+
+      def lib libs
+        libs.map(&:to_s).sort.uniq.each do |path|
+          @xml.classpathentry :kind=>'lib', :path=>path
+        end
+      end
+
+      # Write a classpathentry of kind 'src'.
+      # Accepts an array of absolute paths or a task.
+      def src arg
+        if [:sources, :target].all? { |message| arg.respond_to?(message) }
+          src_from_task arg
+        else
+          src_from_absolute_paths arg
+        end
+      end
+
+      # Write a classpathentry of kind 'src' for dependent projects.
+      # Accepts an array of projects.
+      def src_projects project_libs
+        project_libs.map(&:id).sort.uniq.each do |project_id|
+          @xml.classpathentry :kind=>'src', :combineaccessrules=>"false", :path=>"/#{project_id}"
+        end
+      end
+      
+      def output target
+        @xml.classpathentry :kind=>'output', :path=>relative(target)
+      end
+
+      def var libs, var_name, var_value
+        libs.map { |lib| lib.to_s.sub(var_value, var_name) }.sort.uniq.each do |path|
+          @xml.classpathentry :kind=>'var', :path=>path
+        end
+      end
+              
+      private
+
+      # Find a path relative to the project's root directory.
+      def relative path
+        path or raise "Invalid path '#{path.inspect}'"
+        msg = [:to_path, :to_str, :to_s].find { |msg| path.respond_to? msg }
+        path = path.__send__(msg)
+        Util.relative_path(File.expand_path(path), @project.path_to)
+      end
+
+      def src_from_task task
+        src_from_absolute_paths task.sources, task.target
+      end
+
+      def src_from_absolute_paths absolute_paths, output=nil
+        relative_paths = absolute_paths.map { |src| relative(src) }
+        relative_paths.sort.uniq.each do |path|
+          unless @paths_written.include?(path)
+            attributes = { :kind=>'src', :path=>path, :excluding=>@excludes }
+            attributes[:output] = relative(output) if output
+            @xml.classpathentry attributes
+            @paths_written << path
+          end
+        end
+      end
+    end
+
   end
 end # module Buildr
 

Modified: incubator/buildr/trunk/spec/eclipse_spec.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/spec/eclipse_spec.rb?rev=688204&r1=688203&r2=688204&view=diff
==============================================================================
--- incubator/buildr/trunk/spec/eclipse_spec.rb (original)
+++ incubator/buildr/trunk/spec/eclipse_spec.rb Fri Aug 22 15:09:57 2008
@@ -18,10 +18,20 @@
 
 
 module EclipseHelper
-  def classpath_sources attribute='path'
+  def classpath_xml_elements
     task('eclipse').invoke
-    REXML::Document.new(File.open('.classpath')).
-      root.elements.collect("classpathentry[@kind='src']") { |n| n.attributes[attribute] }
+    REXML::Document.new(File.open('.classpath')).root.elements
+  end
+
+  def classpath_sources attribute='path'
+    classpath_xml_elements.collect("classpathentry[@kind='src']") { |n| n.attributes[attribute] }
+  end
+
+  def classpath_output path
+    specific_output = classpath_xml_elements.collect("classpathentry[@path='#{path}']") { |n| n.attributes['output'] }
+    raise "expected: one output attribute for path '#{path}, got: #{specific_output} " if specific_output.length > 1
+    default_output = classpath_xml_elements.collect("classpathentry[@kind='output']") { |n| n.attributes['path'] }
+    specific_output[0] || default_output[0]
   end
 end
 
@@ -99,61 +109,128 @@
     describe 'source folders' do
        include EclipseHelper
       
-      def classpath_sources attribute='path'
-        task('eclipse').invoke
-        REXML::Document.new(File.open('.classpath')).
-          root.elements.collect("classpathentry[@kind='src']") { |n| n.attributes[attribute] }
-      end
-
       before do
         write 'buildfile'
         write 'src/main/java/Main.java'
         write 'src/test/java/Test.java'
       end
       
-      it 'should accept a default main source folder' do
+      describe 'source', :shared=>true do
+        it 'should ignore CVS and SVN files' do
+          define('foo')
+          classpath_sources('excluding').each do |excluding_attribute|
+            excluding = excluding_attribute.split('|')
+            excluding.should include('**/.svn/')
+            excluding.should include('**/CVS/')
+          end
+        end
+      end
+      
+      describe 'main code' do
+      it_should_behave_like 'source'
+        
+      it 'should accept to come from the default directory' do
         define('foo')
         classpath_sources.should include('src/main/java')
       end
-      
-      it 'should accept a user-defined main source folder' do
+        
+      it 'should accept to come from a user-defined directory' do
         define('foo') { compile path_to('src/java') }
-        write 'src/java/Foo.java'
         classpath_sources.should include('src/java')
       end
-      
+        
       it 'should accept a file task as a main source folder' do
         define('foo') { compile apt }
         classpath_sources.should include('target/generated/apt')
       end
+        
+      it 'should go to the default target directory' do
+        define('foo')
+        classpath_output('src/main/java').should == 'target/classes'
+      end
+      end
       
-      it 'should accept a default test source folder' do
+      describe 'test code' do
+      it_should_behave_like 'source'
+
+      it 'should accept to come from the default directory' do
         define('foo')
         classpath_sources.should include('src/test/java')
       end
-      
-      it 'should accept a user-defined test source folder' do
+
+      it 'should accept to come from a user-defined directory' do
         define('foo') { test.compile path_to('src/test') }
         classpath_sources.should include('src/test')
       end
+
+      it 'should go to the default target directory' do
+        define('foo')
+        classpath_output('src/test/java').should == 'target/test/classes'
+      end
+      end
       
-      it 'should accept a default main resource folder' do
+      describe 'main resources' do
+      it_should_behave_like 'source'
+
+      before do
         write 'src/main/resources/config.xml'
+      end
+
+      it 'should accept to come from the default directory' do
         define('foo')
         classpath_sources.should include('src/main/resources')
       end
-    
-      it 'should accept a default test resource folder' do
+
+      it 'should share a classpath entry if it comes from a directory with code' do
+        write 'src/main/java/config.properties'
+        define('foo') { resources.from('src/main/java').exclude('**/*.java') }
+        classpath_sources.select { |path| path == 'src/main/java'}.length.should == 1
+      end
+
+      it 'should go to the default target directory' do
+        define('foo')
+        classpath_output('src/main/resources').should == 'target/resources'
+      end
+      end
+      
+      describe 'test resources' do
+      it_should_behave_like 'source'
+
+      before do
         write 'src/test/resources/config-test.xml'
+      end
+
+      it 'should accept to come from the default directory' do
         define('foo')
         classpath_sources.should include('src/test/resources')
       end
-    
-      it 'should ignore CVS and SVN files' do
-        define('foo')
-        classpath_sources('excluding').uniq.should == ['**/.svn/|**/CVS/']
+
+      it 'should share a classpath entry if it comes from a directory with code' do
+        write 'src/test/java/config-test.properties'
+        define('foo') { test.resources.from('src/test/java').exclude('**/*.java') }
+        classpath_sources.select { |path| path == 'src/test/java'}.length.should == 1
+      end
+
+      it 'should go to the default target directory' do
+        define('foo')
+        classpath_output('src/test/resources').should == 'target/test/resources'
+      end
       end
       
+      describe 'project depending on another project' do
+        
+        it 'should have the underlying project in its classpath' do
+          mkdir 'bar'
+          define('myproject') {
+            project.version = '1.0'
+            define('foo') { package :jar }
+            define('bar') { compile.using(:javac).with project('foo'); }
+          }
+          task('eclipse').invoke
+          REXML::Document.new(File.open(File.join('bar', '.classpath'))).root.
+            elements.collect("classpathentry[@kind='src']") { |n| n.attributes['path'] }.should include('/myproject-foo')
+        end
+      end
     end
   end
 end