lib/buildr/ivy_extension.rb in ivy4r-0.6.0 vs lib/buildr/ivy_extension.rb in ivy4r-0.7.0
- old
+ new
@@ -2,47 +2,55 @@
module Buildr
module Ivy
# TODO extend extension to download ivy stuff with dependencies automatically
-# VERSION = '2.1.0-rc1'
+ # VERSION = '2.1.0-rc1'
class << self
def setting(*keys)
setting = Buildr.settings.build['ivy']
keys.each { |key| setting = setting[key] unless setting.nil? }
setting
end
-# def version
-# setting['version'] || VERSION
-# end
-# def dependencies
-# @dependencies ||= [
-# "org.apache.ivy:ivy:jar:#{version}",
-# 'com.jcraft:jsch:jar:1.41',
-# 'oro:oro:jar:2.08'
-# ]
-# end
+ # def version
+ # setting['version'] || VERSION
+ # end
+ # def dependencies
+ # @dependencies ||= [
+ # "org.apache.ivy:ivy:jar:#{version}",
+ # 'com.jcraft:jsch:jar:1.41',
+ # 'oro:oro:jar:2.08'
+ # ]
+ # end
end
class IvyConfig
+ TARGETS = [:compile, :test, :package]
+ TYPES = [:conf, :include, :exclude]
attr_accessor :extension_dir, :resolved
+ attr_reader :post_resolve_task_list
+
# Store the current project and initialize ivy ant wrapper
def initialize(project)
@project = project
if project.parent.nil?
@extension_dir = @project.base_dir
+ @post_resolve_task_list = []
else
@extension_dir = @project.parent.ivy.extension_dir
@base_ivy = @project.parent.ivy unless own_file?
end
+ @target_config = Hash.new do
+ |hash, key| hash[key] = {}
+ end
end
-
+
def enabled?
@enabled ||= Ivy.setting('enabled') || true
end
def own_file?
@@ -68,14 +76,18 @@
def file_project
own_file? ? @project : @base_ivy.file_project
end
# Returns the artifacts for given configurations as array
+ # this is a post resolve task.
def deps(*confs)
configure
- pathid = "ivy.deps." + confs.join('.')
- ant.cachepath :conf => confs.join(','), :pathid => pathid
+ confs = confs.reject {|c| c.nil? || c.blank? }
+ unless confs.empty?
+ pathid = "ivy.deps." + confs.join('.')
+ ant.cachepath :conf => confs.join(','), :pathid => pathid
+ end
end
# Returns ivy info for configured ivy file using a new ant instance.
def info
if @base_ivy
@@ -107,10 +119,12 @@
if @base_ivy
@base_ivy.resolve
else
unless @resolved
@resolved = ant.resolve :file => file
+ @project.send(:info, "Calling '#{post_resolve_tasks.size}' post_resolve tasks for '#{@project.name}'")
+ post_resolve_tasks.each { |p| p.call(self) }
end
end
end
# Returns the additional infos for the manifest file.
@@ -310,67 +324,116 @@
@report_dir = report_dir[0]
self
end
end
- # Set the configuration artifacts to use in package tasks like +:war+ or +:ear+.
- # <tt>project.ivy.package_conf('server', 'client')</tt>
- # or
- # <tt>project.ivy.package_conf(['server', 'client'])</tt>
- def package_conf(*package_conf)
- if package_conf.empty?
- @package_conf ||= [Ivy.setting('package.conf') || 'prod'].flatten.uniq
- else
- @package_conf = [package_conf].flatten.uniq
- self
- end
+ # Adds given block as post resolve action that is executed directly after #resolve has been called.
+ # Yields this ivy config object into block.
+ # <tt>project.ivy.post_resolve { |ivy| p "all deps:" + ivy.deps('all').join(", ") }</tt>
+ def post_resolve(&block)
+ post_resolve_tasks << block if block
end
- # Sets the includes pattern(s) to use for packages. I.e.
- # <tt>project.ivy.package_include(/\.jar/, /\.gz/)</tt>
- def package_include(*includes)
- if includes.empty?
- @package_include ||= [Ivy.setting('package.include') || /\.jar/].flatten.uniq
- else
- @package_include = [includes].flatten.uniq
- self
+ # Filter artifacts for given configuration with provided filter values, this is a post resolve
+ # task like #deps.
+ # <tt>project.ivy.filter('server', 'client', :include => /b.*.jar/, :exclude => [/a\.jar/, /other.*\.jar/])</tt>
+ def filter(*confs)
+ filter = confs.last.kind_of?(Hash) ? confs.pop : {}
+ unless (filter.keys - [:include, :exclude]).empty?
+ raise ArgumentError, "Invalid filter use :include and/or :exclude only: given #{filter.keys.inspect}"
end
+ includes, excludes = filter[:include] || [], filter[:exclude] || []
+
+ artifacts = deps(*confs.flatten)
+ if artifacts
+ artifacts = artifacts.find_all do |lib|
+ lib = File.basename(lib)
+ includes = includes.reject {|i| i.nil? || i.blank? }
+ should_include = includes.empty? || includes.any? {|include| include === lib }
+ should_include && !excludes.any? {|exclude| exclude === lib}
+ end
+ end
+
+ artifacts
end
- # Sets the exclude pattern(s) to use for packages. I.e.
- # <tt>project.ivy.package_exclude(/\.zip/, /\.tar/)</tt>
- def package_exclude(*excludes)
- if excludes.empty?
- @package_exclude ||= [Ivy.setting('package.exlude') || ''].flatten.uniq
+ # :call-seq:
+ # for types:
+ # project.ivy.include(:compile => [/\.jar/, /\.gz/], :package => 'cglib.jar')
+ # project.ivy.exclude(:test => 'cglib.jar')
+ # project.ivy.conf(:compile => 'compile', :test => 'test', :package => 'prod')
+ # for targets:
+ # project.ivy.compile(:conf => 'compile', :exclude => /cglib.jar/)
+ # project.ivy.test(:conf => 'test')
+ # project.ivy.package(:conf => 'prod', :include => /.*.jar/, :exclude => /cglib.jar/)
+ # or verbose:
+ # project.ivy.compile_conf or project.ivy.conf_compile
+ # project.ivy.compile_include or project.ivy.include_compile
+ # the same for the other possible options.
+ #
+ # Uses #method_missing to handle the options.
+ # Generic handling of settings for +target+ and +type+. All calls in the form
+ # <tt>target_type({})</tt> or <tt>type_target({})</tt> are handled via this method see
+ # #TARGETS #TYPES for more information about valid targets and types.
+ def method_missing(methodname, *args, &block)
+ if block.nil? && valid_config_call?(methodname)
+ target, type = target(methodname), type(methodname)
+ if target && type
+ handle_variable(target, type, *args)
+ elsif target && args.size == 1 && args.last.kind_of?(Hash)
+ args[0].each { |type, value| handle_variable(target, type, *value) }
+ self
+ elsif type && args.size == 1 && args.last.kind_of?(Hash)
+ args[0].each { |target, value| handle_variable(target, type, *value) }
+ self
+ else
+ raise "Could not recognize config call for method '#{methodname}', args=#{args.inspect}"
+ end
else
- @package_exclude = [excludes].flatten.uniq
- self
+ super.method_missing(methodname, *args, &block)
end
end
+
+ private
+ def target(targets)
+ t = targets.to_s.split('_').find { |t| TARGETS.member? t.to_sym }
+ t ? t.to_sym : nil
+ end
- # Set the configuration artifacts to use for compile tasks, added to <tt>compile.with</tt>
- # <tt>project.ivy.compile_conf('server', 'client')</tt>
- def compile_conf(*compile_conf)
- if compile_conf.empty?
- @compile_conf ||= [Ivy.setting('compile.conf') || 'compile'].flatten.uniq
- else
- @compile_conf = [compile_conf].flatten.uniq
- self
+ def type(types)
+ t = types.to_s.split('_').find { |t| TYPES.member? t.to_sym }
+ t ? t.to_sym : nil
+ end
+
+ def valid_config_call?(method_name)
+ valid_calls = []
+ TYPES.each do|type|
+ TARGETS.each do|target|
+ valid_calls << type.to_s << target.to_s << "#{type}_#{target}" << "#{target}_#{type}"
+ end
end
+ valid_calls.member? method_name.to_s
end
- # Set the configuration artifacts to use for test tasks, added to <tt>test.compile.with</tt>
- # and <tt>test.with</tt>. Note that all artifacts from #compile_conf are added automatically.
- # <tt>project.ivy.test_conf('server', 'test')</tt>
- def test_conf(*test_conf)
- if test_conf.empty?
- @test_conf ||= [Ivy.setting('test.conf') || 'test'].flatten.uniq
+ # Sets a variable for given basename and type to given values. If values are empty returns the
+ # current value.
+ # I.e. <tt>handle_variable(:package, :include, /blua.*\.jar/, /da.*\.jar/)</tt>
+ def handle_variable(target, type, *values)
+ unless TARGETS.member?(target) && TYPES.member?(type)
+ raise ArgumentError, "Unknown config value for target #{target.inspect} and type #{type.inspect}"
+ end
+ if values.empty?
+ @target_config[target][type] ||= [Ivy.setting("#{target.to_s}.#{type.to_s}") || ''].flatten.uniq
else
- @test_conf = [test_conf].flatten.uniq
+ @target_config[target][type] = [values].flatten.uniq
self
end
end
+
+ def post_resolve_tasks
+ @base_ivy ? @base_ivy.post_resolve_task_list : post_resolve_task_list
+ end
end
=begin rdoc
The Ivy Buildr extension adding the new tasks for ivy.
@@ -396,28 +459,38 @@
class << self
def add_ivy_deps_to_java_tasks(project)
resolve_target = project.ivy.file_project.task('ivy:resolve')
project.task :compiledeps => resolve_target do
- compile_conf = [project.ivy.compile_conf].flatten
- project.compile.with project.ivy.deps(compile_conf)
- info "Ivy adding compile dependencies '#{compile_conf.join(', ')}' to project '#{project.name}'"
+ includes = project.ivy.compile_include
+ excludes = project.ivy.compile_exclude
+ confs = [project.ivy.compile_conf].flatten
+ if deps = project.ivy.filter(confs, :include => includes, :exclude => excludes)
+ project.compile.with deps
+ info "Ivy adding compile dependencies '#{confs.join(', ')}' to project '#{project.name}'"
+ end
end
project.task :compile => "#{project.name}:compiledeps"
project.task :testdeps => resolve_target do
+ includes = project.ivy.test_include
+ excludes = project.ivy.test_exclude
confs = [project.ivy.test_conf, project.ivy.compile_conf].flatten.uniq
- project.test.with project.ivy.deps(confs)
- info "Ivy adding test dependencies '#{confs.join(', ')}' to project '#{project.name}'"
+ if deps = project.ivy.filter(confs, :include => includes, :exclude => excludes)
+ project.test.with deps
+ info "Ivy adding test dependencies '#{confs.join(', ')}' to project '#{project.name}'"
+ end
end
project.task "test:compile" => "#{project.name}:testdeps"
project.task :javadocdeps => resolve_target do
confs = [project.ivy.test_conf, project.ivy.compile_conf].flatten.uniq
- project.javadoc.with project.ivy.deps(confs)
- info "Ivy adding javadoc dependencies '#{confs.join(', ')}' to project '#{project.name}'"
+ if deps = project.ivy.deps(confs)
+ project.javadoc.with deps
+ info "Ivy adding javadoc dependencies '#{confs.join(', ')}' to project '#{project.name}'"
+ end
end
project.task :javadoc => "#{project.name}:javadocdeps"
[project.task(:eclipse), project.task(:idea), project.task(:idea7x)].each do |task|
task.prerequisites.each{|p| p.enhance ["#{project.name}:compiledeps", "#{project.name}:testdeps"]}
@@ -435,25 +508,20 @@
project.task :build => task
end
end
def add_prod_libs_to_distributeables(project)
- includes = project.ivy.package_include
- excludes = project.ivy.package_exclude
pkgs = project.packages.find_all { |pkg| [:war, :ear].member? pkg.type }
pkgs.each do |pkg|
name = "#{pkg.name}deps"
task = project.task name => project.ivy.file_project.task('ivy:resolve') do
+ includes = project.ivy.package_include
+ excludes = project.ivy.package_exclude
confs = project.ivy.package_conf
- libs = project.ivy.deps(confs).find_all do |lib|
- lib = File.basename(lib)
- use = includes.any? {|include| include === lib } && !excludes.any? {|exclude| exclude === lib}
- verbose "Including '#{lib}' from package '#{pkg}' in project '#{project.name}'" if use
- info "Excluding '#{lib}' from package '#{pkg}' in project '#{project.name}'" unless use
- use
+ if deps = project.ivy.filter(confs, :include => includes, :exclude => excludes)
+ pkg.with :libs => deps
+ info "Adding production libs from conf '#{confs.join(', ')}' to package '#{pkg.name}' in project '#{project.name}'"
end
- pkg.with :libs => libs
- info "Adding production libs from conf '#{confs.join(', ')}' to package '#{pkg.name}' in project '#{project.name}'"
end
project.task :build => task
end
end