lib/java/idea.rb in buildr-1.1.3 vs lib/java/idea.rb in buildr-1.2.0

- old
+ new

@@ -1,8 +1,10 @@ require "pathname" require "core/project" require "java/artifact" +require 'stringio' +require 'rexml/document' module Buildr # Global task "idea" generates artifacts for all projects. desc "Generate Idea artifacts for all projects" @@ -13,112 +15,145 @@ project.enhance do |project| # We need paths relative to the top project's base directory. root_path = lambda { |p| f = lambda { |p| p.parent ? f[p.parent] : p.base_dir } ; f[p] }[project] - # We want the Eclipse files changed every time the Rakefile changes, but also anything loaded by - # the Rakefile (buildr.rb, separate file listing dependencies, etc), so we add anything required - # after the Rakefile. So which don't know where Buildr shows up exactly, ignore files that show + # We want the Eclipse files changed every time the Buildfile changes, but also anything loaded by + # the Buildfile (buildr.rb, separate file listing dependencies, etc), so we add anything required + # after the Buildfile. So which don't know where Buildr shows up exactly, ignore files that show # in $LOADED_FEATURES that we cannot resolve. sources = ($LOADED_FEATURES - Buildr.instance_eval("@loaded_features_to_ignore")). map { |file| File.expand_path(file) }.select { |file| File.exist?(file) } sources << File.expand_path(Rake.application.rakefile, root_path) if Rake.application.rakefile - # Only for projects that are packagable. - if project.packages.detect { |pkg| pkg.type.to_s =~ /(jar)|(war)|(rar)|(mar)|(aar)/ } - task_name = project.path_to("#{project.name.sub(':', '-')}.iml") - idea.enhance [ file(task_name) ] - - # The only thing we need to look for is a change in the Rakefile. - file(task_name=>sources) do |task| - puts "Writing #{task.name}" # if verbose + # Find a path relative to the project's root directory. + relative = lambda do |path| + msg = [:to_path, :to_str, :to_s].find { |msg| path.respond_to? msg } + path = path.__send__(msg) + Pathname.new(path).relative_path_from(Pathname.new(project.path_to)).to_s + end - # Find a path relative to the project's root directory. - relative = lambda do |path| - msg = [:to_path, :to_str, :to_s].find { |msg| path.respond_to? msg } - path = path.__send__(msg) - Pathname.new(path).relative_path_from(Pathname.new(project.path_to)).to_s - end + m2repo = Buildr::Repositories.instance.local + excludes = [ '**/.svn/', '**/CVS/' ].join('|') - m2repo = Buildr::Repositories.instance.local - excludes = [ '**/.svn/', '**/CVS/' ].join('|') + # Only for projects that are packageable. + task_name = project.path_to("#{project.name.sub(':', '-')}.iml") + idea.enhance [ file(task_name) ] - # Idea handles modules slightly differently if they're WARs - idea_types = {"jar"=>"JAVA_MODULE", "war"=>"J2EE_WEB_MODULE"} - idea_types["rar"] = idea_types["mar"] = idea_types["jar"] + # The only thing we need to look for is a change in the Buildfile. + file(task_name=>sources) do |task| + puts "Writing #{task.name}" if verbose - # Note: Use the test classpath since Eclipse compiles both "main" and "test" classes using the same classpath - cp = project.test.compile.classpath.map(&:to_s) - [ project.compile.target.to_s ] + # Idea handles modules slightly differently if they're WARs + idea_types = Hash.new("JAVA_MODULE") + idea_types["war"] = "J2EE_WEB_MODULE" - # Convert classpath elements into applicable Project objects - cp.collect! { |path| projects.detect { |prj| prj.packages.detect { |pkg| pkg.to_s == path } } || path } + # Note: Use the test classpath since Eclipse compiles both "main" and "test" classes using the same classpath + cp = project.test.compile.classpath.map(&:to_s) - [ project.compile.target.to_s ] - # project_libs: artifacts created by other projects - project_libs, others = cp.partition { |path| path.is_a?(Project) } + # Convert classpath elements into applicable Project objects + cp.collect! { |path| projects.detect { |prj| prj.packages.detect { |pkg| pkg.to_s == path } } || path } - # Separate artifacts from Maven2 repository - m2_libs, others = others.partition { |path| path.to_s.index(m2repo) == 0 } + # project_libs: artifacts created by other projects + project_libs, others = cp.partition { |path| path.is_a?(Project) } - # 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 } + # Separate artifacts from Maven2 repository + m2_libs, others = others.partition { |path| path.to_s.index(m2repo) == 0 } - File.open(task.name, "w") do |file| - xml = Builder::XmlMarkup.new(:target=>file, :indent=>2) - # Project type is going to be the first package type - xml.module(:version=>"4", :relativePaths=>"false", :type=>idea_types[project.packages.first.type.to_s]) do + # 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 } - xml.component :name=>"ModuleRootManager" - xml.component "name"=>"NewModuleRootManager", "inherit-compiler-output"=>"false" do - xml.output :url=>"file://$MODULE_DIR$/#{relative[project.compile.target]}" + File.open(task.name, "w") do |file| + xml = Builder::XmlMarkup.new(:target=>file, :indent=>2) + # Project type is going to be the first package type + xml.module(:version=>"4", :relativePaths=>"false", :type=>idea_types[project.packages.first.type.to_s]) do - # TODO project.test.target isn't recognized, what's the proper way to get the test compile path? - xml.tag! "output-test", :url=>"file://$MODULE_DIR$/target/test-classes" - xml.tag! "exclude-output" + xml.component :name=>"ModuleRootManager" + xml.component "name"=>"NewModuleRootManager", "inherit-compiler-output"=>"false" do + xml.output :url=>"file://$MODULE_DIR$/#{relative[project.compile.target]}" + xml.tag! "exclude-output" - xml.content do - srcs = project.compile.sources.map { |src| relative[src] } + generated.map { |src| relative[src] } - srcs.sort.uniq.each do |path| - xml.sourceFolder :url=>"file://$MODULE_DIR$/#{path}", :isTestSource=>"false" + # TODO project.test.target isn't recognized, what's the proper way to get the test compile path? + xml.tag! "output-test", :url=>"file://$MODULE_DIR$/target/test-classes" + + xml.content(:url=>"file://$MODULE_DIR$") do + srcs = project.compile.sources.map { |src| relative[src] } + generated.map { |src| relative[src] } + srcs.sort.uniq.each do |path| + xml.sourceFolder :url=>"file://$MODULE_DIR$/#{path}", :isTestSource=>"false" + end + test_sources = project.test.compile.sources.map { |src| relative[src] } + test_sources.each do |paths| + paths.sort.uniq.each do |path| + xml.sourceFolder :url=>"file://$MODULE_DIR$/#{path}", :isTestSource=>"true" end - test_sources = project.test.compile.sources.map { |src| relative[src] } - test_sources.each do |paths| - paths.sort.uniq.each do |path| - xml.sourceFolder :url=>"file://$MODULE_DIR$/#{path}", :isTestSource=>"true" - end - end - xml.excludeFolder :url=>"file://$MODULE_DIR$/#{relative[project.compile.target]}" end + {"src/main/resources"=>false, "src/test/resources"=>true}.each do |key, value| + xml.sourceFolder :url=>"file://$MODULE_DIR$/#{key}", :isTestSource=>"#{value}" if File.exist?(project.path_to(key)) + end + xml.excludeFolder :url=>"file://$MODULE_DIR$/#{relative[project.compile.target]}" + end - xml.orderEntry :type=>"sourceFolder", :forTests=>"false" - xml.orderEntry :type=>"inheritedJdk" + xml.orderEntry :type=>"sourceFolder", :forTests=>"false" + xml.orderEntry :type=>"inheritedJdk" - # Classpath elements from other projects - project_libs.map(&:id).sort.uniq.each do |project_id| - xml.orderEntry :type=>'module', :name=>project_id - end + # Classpath elements from other projects + project_libs.map(&:id).sort.uniq.each do |project_id| + xml.orderEntry :type=>'module', "module-name"=>project_id + end - # Libraries - ext_libs = libs.map {|path| "$MODULE_DIR$/#{path.to_s}" } + - m2_libs.map { |path| path.to_s.sub(m2repo, "$M2_REPO$") } - ext_libs.each do |path| - xml.orderEntry :type=>"module-library" do - xml.library do - xml.CLASSES do - xml.root :url=>"jar://#{path}!/" - end - xml.JAVADOC - xml.SOURCES + # Libraries + ext_libs = libs.map {|path| "$MODULE_DIR$/#{path.to_s}" } + + m2_libs.map { |path| path.to_s.sub(m2repo, "$M2_REPO$") } + ext_libs.each do |path| + xml.orderEntry :type=>"module-library" do + xml.library do + xml.CLASSES do + xml.root :url=>"jar://#{path}!/" end + xml.JAVADOC + xml.SOURCES end end - - xml.orderEntryProperties end + + xml.orderEntryProperties end end end + end + # Root project aggregates all the subprojects. + if project.parent == nil + task_name = project.path_to("#{project.name.sub(':', '-')}.ipr") + idea.enhance [ file(task_name) ] + + file(task_name=>sources) do |task| + puts "Writing #{task.name}" if verbose + + # Generating just the little stanza that chanages from one project to another + partial = StringIO.new + xml = Builder::XmlMarkup.new(:target=>partial, :indent=>2) + xml.component(:name=>"ProjectModuleManager") do + xml.modules do + project.projects.each do |subp| + module_name = subp.name.gsub(":", "-") + module_path = subp.name[/:(.*)/][1..-1] + path = "#{module_path}/#{module_name}.iml" + xml.module :fileurl=>"file://$PROJECT_DIR$/#{path}", :filepath=>"$PROJECT_DIR$/#{path}" + end + xml.module :fileurl=>"file://$PROJECT_DIR$/#{project.name}.iml", :filepath=>"$PROJECT_DIR$/#{project.name}.iml" + end + end + + # Loading the whole fairly constant crap + template_xml = REXML::Document.new(File.open(File.dirname(__FILE__)+"/idea.ipr.template")) + include_xml = REXML::Document.new(partial.string) + template_xml.root.add_element(include_xml.root) + template_xml.write(File.new(task.name, "w")) + + end end + end end end # module Buildr