buildr 1.3.2 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +66 -4
- data/{README → README.rdoc} +29 -16
- data/Rakefile +16 -20
- data/_buildr +38 -0
- data/addon/buildr/cobertura.rb +49 -45
- data/addon/buildr/emma.rb +238 -0
- data/addon/buildr/jetty.rb +1 -1
- data/addon/buildr/nailgun.rb +585 -661
- data/{lib/buildr/java → addon/buildr}/org/apache/buildr/BuildrNail$Main.class +0 -0
- data/{lib/buildr/java → addon/buildr}/org/apache/buildr/BuildrNail.class +0 -0
- data/{lib/buildr/java → addon/buildr}/org/apache/buildr/BuildrNail.java +0 -0
- data/bin/buildr +9 -2
- data/buildr.buildfile +53 -0
- data/buildr.gemspec +21 -14
- data/doc/css/default.css +51 -48
- data/doc/css/print.css +60 -55
- data/doc/images/favicon.png +0 -0
- data/doc/images/growl-icon.tiff +0 -0
- data/doc/images/project-structure.png +0 -0
- data/doc/pages/artifacts.textile +46 -156
- data/doc/pages/building.textile +63 -323
- data/doc/pages/contributing.textile +112 -102
- data/doc/pages/download.textile +19 -27
- data/doc/pages/extending.textile +27 -81
- data/doc/pages/getting_started.textile +44 -119
- data/doc/pages/index.textile +26 -47
- data/doc/pages/languages.textile +407 -0
- data/doc/pages/more_stuff.textile +92 -173
- data/doc/pages/packaging.textile +71 -239
- data/doc/pages/projects.textile +58 -233
- data/doc/pages/recipes.textile +19 -43
- data/doc/pages/settings_profiles.textile +39 -104
- data/doc/pages/testing.textile +41 -304
- data/doc/pages/troubleshooting.textile +29 -47
- data/doc/pages/whats_new.textile +69 -167
- data/doc/print.haml +0 -1
- data/doc/print.toc.yaml +1 -0
- data/doc/scripts/buildr-git.rb +1 -1
- data/doc/site.haml +1 -0
- data/doc/site.toc.yaml +8 -5
- data/{KEYS → etc/KEYS} +0 -0
- data/etc/git-svn-authors +16 -0
- data/lib/buildr.rb +2 -5
- data/lib/buildr/core/application.rb +192 -98
- data/lib/buildr/core/build.rb +140 -91
- data/lib/buildr/core/checks.rb +5 -5
- data/lib/buildr/core/common.rb +1 -1
- data/lib/buildr/core/compile.rb +12 -10
- data/lib/buildr/core/filter.rb +151 -46
- data/lib/buildr/core/generate.rb +9 -9
- data/lib/buildr/core/progressbar.rb +1 -1
- data/lib/buildr/core/project.rb +8 -7
- data/lib/buildr/core/test.rb +51 -26
- data/lib/buildr/core/transports.rb +22 -38
- data/lib/buildr/core/util.rb +78 -26
- data/lib/buildr/groovy.rb +18 -0
- data/lib/buildr/groovy/bdd.rb +105 -0
- data/lib/buildr/groovy/compiler.rb +138 -0
- data/lib/buildr/ide/eclipse.rb +102 -71
- data/lib/buildr/ide/idea.rb +7 -12
- data/lib/buildr/ide/idea7x.rb +7 -8
- data/lib/buildr/java.rb +4 -7
- data/lib/buildr/java/ant.rb +26 -5
- data/lib/buildr/java/bdd.rb +449 -0
- data/lib/buildr/java/commands.rb +9 -9
- data/lib/buildr/java/{compilers.rb → compiler.rb} +8 -90
- data/lib/buildr/java/jruby.rb +29 -11
- data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
- data/lib/buildr/java/packaging.rb +23 -16
- data/lib/buildr/java/pom.rb +1 -1
- data/lib/buildr/java/rjb.rb +21 -8
- data/lib/buildr/java/test_result.rb +308 -0
- data/lib/buildr/java/tests.rb +324 -0
- data/lib/buildr/packaging/artifact.rb +12 -11
- data/lib/buildr/packaging/artifact_namespace.rb +7 -4
- data/lib/buildr/packaging/gems.rb +3 -3
- data/lib/buildr/packaging/zip.rb +13 -10
- data/lib/buildr/resources/buildr.icns +0 -0
- data/lib/buildr/scala.rb +19 -0
- data/lib/buildr/scala/compiler.rb +109 -0
- data/lib/buildr/scala/tests.rb +203 -0
- data/rakelib/apache.rake +71 -45
- data/rakelib/doc.rake +2 -2
- data/rakelib/package.rake +3 -2
- data/rakelib/rspec.rake +23 -21
- data/rakelib/setup.rake +34 -9
- data/rakelib/stage.rake +4 -1
- data/spec/addon/cobertura_spec.rb +77 -0
- data/spec/addon/emma_spec.rb +120 -0
- data/spec/addon/test_coverage_spec.rb +255 -0
- data/spec/{application_spec.rb → core/application_spec.rb} +82 -4
- data/spec/{artifact_namespace_spec.rb → core/artifact_namespace_spec.rb} +12 -1
- data/spec/core/build_spec.rb +415 -0
- data/spec/{checks_spec.rb → core/checks_spec.rb} +2 -2
- data/spec/{common_spec.rb → core/common_spec.rb} +119 -30
- data/spec/{compile_spec.rb → core/compile_spec.rb} +17 -13
- data/spec/core/generate_spec.rb +33 -0
- data/spec/{project_spec.rb → core/project_spec.rb} +9 -6
- data/spec/{test_spec.rb → core/test_spec.rb} +222 -28
- data/spec/{transport_spec.rb → core/transport_spec.rb} +5 -9
- data/spec/groovy/bdd_spec.rb +80 -0
- data/spec/{groovy_compilers_spec.rb → groovy/compiler_spec.rb} +1 -1
- data/spec/ide/eclipse_spec.rb +243 -0
- data/spec/{java_spec.rb → java/ant.rb} +7 -17
- data/spec/java/bdd_spec.rb +358 -0
- data/spec/{java_compilers_spec.rb → java/compiler_spec.rb} +1 -1
- data/spec/java/java_spec.rb +88 -0
- data/spec/{java_packaging_spec.rb → java/packaging_spec.rb} +65 -4
- data/spec/{java_test_frameworks_spec.rb → java/tests_spec.rb} +31 -10
- data/spec/{archive_spec.rb → packaging/archive_spec.rb} +12 -2
- data/spec/{artifact_spec.rb → packaging/artifact_spec.rb} +12 -5
- data/spec/{packaging_helper.rb → packaging/packaging_helper.rb} +0 -0
- data/spec/{packaging_spec.rb → packaging/packaging_spec.rb} +1 -1
- data/spec/sandbox.rb +22 -5
- data/spec/{scala_compilers_spec.rb → scala/compiler_spec.rb} +1 -1
- data/spec/{scala_test_frameworks_spec.rb → scala/tests_spec.rb} +11 -12
- data/spec/spec_helpers.rb +38 -17
- metadata +103 -70
- data/lib/buildr/java/bdd_frameworks.rb +0 -265
- data/lib/buildr/java/groovyc.rb +0 -137
- data/lib/buildr/java/test_frameworks.rb +0 -450
- data/spec/build_spec.rb +0 -193
- data/spec/java_bdd_frameworks_spec.rb +0 -238
- data/spec/spec.opts +0 -6
data/lib/buildr/core/build.rb
CHANGED
@@ -27,7 +27,7 @@ module Buildr
|
|
27
27
|
# Runs the build in parallel when true (defaults to false). You can force a parallel build by
|
28
28
|
# setting this option directly, or by running the parallel task ahead of the build task.
|
29
29
|
#
|
30
|
-
# This option only affects
|
30
|
+
# This option only affects recursive tasks. For example:
|
31
31
|
# buildr parallel package
|
32
32
|
# will run all package tasks (from the sub-projects) in parallel, but each sub-project's package
|
33
33
|
# task runs its child tasks (prepare, compile, resources, etc) in sequence.
|
@@ -48,7 +48,7 @@ module Buildr
|
|
48
48
|
desc 'Clean files generated during a build'
|
49
49
|
Project.local_task('clean') { |name| "Cleaning #{name}" }
|
50
50
|
|
51
|
-
desc 'The default task
|
51
|
+
desc 'The default task is build'
|
52
52
|
task 'default'=>'build'
|
53
53
|
end
|
54
54
|
|
@@ -109,146 +109,195 @@ module Buildr
|
|
109
109
|
end
|
110
110
|
|
111
111
|
|
112
|
+
class Svn
|
113
|
+
|
114
|
+
class << self
|
115
|
+
def commit(file, message)
|
116
|
+
svn 'commit', '-m', message, file
|
117
|
+
end
|
118
|
+
|
119
|
+
def copy(dir, url, message)
|
120
|
+
svn 'copy', dir, url, '-m', message
|
121
|
+
end
|
122
|
+
|
123
|
+
# Return the current SVN URL
|
124
|
+
def repo_url
|
125
|
+
svn('info').scan(/URL: (.*)/)[0][0]
|
126
|
+
end
|
127
|
+
|
128
|
+
def remove(url, message)
|
129
|
+
svn 'remove', url, '-m', message
|
130
|
+
end
|
131
|
+
|
132
|
+
# Status check reveals modified files, but also SVN externals which we can safely ignore.
|
133
|
+
def uncommitted_files
|
134
|
+
svn('status', '--ignore-externals').reject { |line| line =~ /^X\s/ }
|
135
|
+
end
|
136
|
+
|
137
|
+
# :call-seq:
|
138
|
+
# svn(*args)
|
139
|
+
#
|
140
|
+
# Executes SVN command and returns the output.
|
141
|
+
def svn(*args)
|
142
|
+
cmd = 'svn ' + args.map { |arg| arg[' '] ? %Q{"#{arg}"} : arg }.join(' ')
|
143
|
+
trace cmd
|
144
|
+
`#{cmd}`.tap { fail 'SVN command failed' unless $?.exitstatus == 0 }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
|
112
150
|
class Release
|
113
151
|
|
114
|
-
THIS_VERSION_PATTERN = /THIS_VERSION|VERSION_NUMBER\s*=\s*(["'])(.*)\
|
115
|
-
NEXT_VERSION_PATTERN = /NEXT_VERSION\s*=\s*(["'])(.*)\1/
|
152
|
+
THIS_VERSION_PATTERN = /(THIS_VERSION|VERSION_NUMBER)\s*=\s*(["'])(.*)\2/
|
116
153
|
|
117
154
|
class << self
|
155
|
+
|
156
|
+
# Use this to specify a different tag name for tagging the release in source control.
|
157
|
+
# You can set the tag name or a proc that will be called with the version number,
|
158
|
+
# for example:
|
159
|
+
# Release.tag_name = lambda { |ver| "foo-#{ver}" }
|
160
|
+
attr_accessor :tag_name
|
118
161
|
|
119
162
|
# :call-seq:
|
120
163
|
# make()
|
121
164
|
#
|
122
165
|
# Make a release.
|
123
|
-
def make
|
166
|
+
def make
|
124
167
|
check
|
125
|
-
|
126
|
-
options = ['--buildfile',
|
168
|
+
with_release_candidate_version do |release_candidate_buildfile|
|
169
|
+
options = ['--buildfile', release_candidate_buildfile, 'DEBUG=no']
|
127
170
|
options << '--environment' << Buildr.environment unless Buildr.environment.to_s.empty?
|
128
|
-
|
171
|
+
buildr %w{clean upload}, options
|
129
172
|
end
|
130
|
-
|
131
|
-
|
173
|
+
tag_release
|
174
|
+
commit_new_snapshot
|
132
175
|
end
|
133
176
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
177
|
+
# :call-seq:
|
178
|
+
# extract_version() => this_version
|
179
|
+
#
|
180
|
+
# Extract the current version number from the buildfile.
|
181
|
+
# Raise an error if not found.
|
182
|
+
def extract_version
|
183
|
+
buildfile = File.read(Buildr.application.buildfile.to_s)
|
184
|
+
buildfile.scan(THIS_VERSION_PATTERN)[0][2]
|
185
|
+
rescue
|
186
|
+
fail 'Looking for THIS_VERSION = "..." in your Buildfile, none found'
|
138
187
|
end
|
139
|
-
|
188
|
+
|
189
|
+
# :call-seq:
|
190
|
+
# tag_url(svn_url, version) => tag_url
|
191
|
+
#
|
192
|
+
# Returns the SVN url for the tag.
|
193
|
+
# Can tag from the trunk or from branches.
|
194
|
+
# Can handle the two standard repository layouts.
|
195
|
+
# - http://my.repo/foo/trunk => http://my.repo/foo/tags/1.0.0
|
196
|
+
# - http://my.repo/trunk/foo => http://my.repo/tags/foo/1.0.0
|
197
|
+
def tag_url(svn_url, version)
|
198
|
+
trunk_or_branches = Regexp.union(%r{^(.*)/trunk(.*)$}, %r{^(.*)/branches(.*)/([^/]*)$})
|
199
|
+
match = trunk_or_branches.match(svn_url)
|
200
|
+
prefix = match[1] || match[3]
|
201
|
+
suffix = match[2] || match[4]
|
202
|
+
tag = tag_name || version
|
203
|
+
tag = tag.call(version) if Proc === tag
|
204
|
+
prefix + '/tags' + suffix + '/' + tag
|
205
|
+
end
|
206
|
+
|
140
207
|
# :call-seq:
|
141
208
|
# check()
|
142
209
|
#
|
143
210
|
# Check that we don't have any local changes in the working copy. Fails if it finds anything
|
144
211
|
# in the working copy that is not checked into source control.
|
145
|
-
def check
|
146
|
-
fail "SVN URL must
|
147
|
-
|
148
|
-
status = svn('status', '--ignore-externals').reject { |line| line =~ /^X\s/ }
|
149
|
-
fail "Uncommitted SVN files violate the First Principle Of Release!\n#{status}" unless
|
150
|
-
status.empty?
|
212
|
+
def check
|
213
|
+
fail "SVN URL must contain 'trunk' or 'branches/...'" unless Svn.repo_url =~ /(trunk)|(branches.*)$/
|
214
|
+
fail "Uncommitted SVN files violate the First Principle Of Release!\n#{Svn.uncommitted_files}" unless Svn.uncommitted_files.empty?
|
151
215
|
end
|
152
216
|
|
217
|
+
protected
|
218
|
+
|
153
219
|
# :call-seq:
|
154
|
-
#
|
220
|
+
# buildr(tasks, options)
|
155
221
|
#
|
156
|
-
#
|
157
|
-
|
222
|
+
# Calls another instance of buildr.
|
223
|
+
def buildr(tasks, options)
|
224
|
+
sh "#{command} _#{Buildr::VERSION}_ #{tasks.join(' ')} #{options.join(' ')}"
|
225
|
+
end
|
226
|
+
|
227
|
+
def command #:nodoc:
|
228
|
+
Config::CONFIG['arch'] =~ /dos|win32/i ? $PROGRAM_NAME.ext('cmd') : $PROGRAM_NAME
|
229
|
+
end
|
230
|
+
|
231
|
+
# :call-seq:
|
232
|
+
# with_release_candidate_version() { |filename| ... }
|
233
|
+
#
|
234
|
+
# Yields to block with release candidate buildfile, before committing to use it.
|
158
235
|
#
|
159
236
|
# We need a Buildfile with upgraded version numbers to run the build, but we don't want the
|
160
|
-
# Buildfile modified unless the build succeeds. So this method updates the version
|
237
|
+
# Buildfile modified unless the build succeeds. So this method updates the version number in
|
161
238
|
# a separate (Buildfile.next) file, yields to the block with that filename, and if successful
|
162
239
|
# copies the new file over the existing one.
|
163
240
|
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
# THIS_VERSION = 1.1.0
|
167
|
-
# NEXT_VERSION = 1.2.0
|
241
|
+
# The release version is the current version without '-SNAPSHOT'. So:
|
242
|
+
# THIS_VERSION = 1.1.0-SNAPSHOT
|
168
243
|
# becomes:
|
169
|
-
# THIS_VERSION = 1.
|
170
|
-
#
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
one_after = next_version.split('.')
|
176
|
-
one_after[-1] = one_after[-1].to_i + 1
|
177
|
-
[ next_version, one_after.join('.') ]
|
178
|
-
end
|
179
|
-
File.open(new_filename, 'w') { |file| file.write modified }
|
244
|
+
# THIS_VERSION = 1.1.0
|
245
|
+
# for the release buildfile.
|
246
|
+
def with_release_candidate_version
|
247
|
+
release_candidate_buildfile = Buildr.application.buildfile.to_s + '.next'
|
248
|
+
release_candidate_buildfile_contents = change_version { |version| version[-1] = version[-1].to_i }
|
249
|
+
File.open(release_candidate_buildfile, 'w') { |file| file.write release_candidate_buildfile_contents }
|
180
250
|
begin
|
181
|
-
yield
|
182
|
-
mv
|
251
|
+
yield release_candidate_buildfile
|
252
|
+
mv release_candidate_buildfile, Buildr.application.buildfile.to_s
|
183
253
|
ensure
|
184
|
-
rm
|
254
|
+
rm release_candidate_buildfile rescue nil
|
185
255
|
end
|
186
|
-
File.read(Buildr.application.buildfile).scan(THIS_VERSION_PATTERN)[0][1]
|
187
256
|
end
|
188
257
|
|
189
258
|
# :call-seq:
|
190
|
-
# change_version() { |
|
259
|
+
# change_version() { |this_version| ... } => buildfile
|
191
260
|
#
|
192
|
-
# Change version
|
193
|
-
# Returns the contents of the Buildfile with the modified version
|
261
|
+
# Change version number in the current Buildfile, but without writing a new file (yet).
|
262
|
+
# Returns the contents of the Buildfile with the modified version number.
|
194
263
|
#
|
195
|
-
# This method yields to the block with the current (this)
|
196
|
-
#
|
197
|
-
def change_version
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
if verbose
|
205
|
-
puts 'Upgrading version numbers:'
|
206
|
-
puts " This: #{this_version}"
|
207
|
-
puts " Next: #{next_version}"
|
208
|
-
end
|
209
|
-
buildfile.gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{this_version}"}) }.
|
210
|
-
gsub(NEXT_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{next_version}"}) }
|
264
|
+
# This method yields to the block with the current (this) version number as an array and expects
|
265
|
+
# the block to update it.
|
266
|
+
def change_version
|
267
|
+
this_version = extract_version
|
268
|
+
new_version = this_version.split('.')
|
269
|
+
yield(new_version)
|
270
|
+
new_version = new_version.join('.')
|
271
|
+
buildfile = File.read(Buildr.application.buildfile.to_s)
|
272
|
+
buildfile.gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{new_version}"}) }
|
211
273
|
end
|
212
274
|
|
213
275
|
# :call-seq:
|
214
|
-
#
|
276
|
+
# tag_release()
|
215
277
|
#
|
216
278
|
# Tags the current working copy with the release version number.
|
217
|
-
def
|
218
|
-
|
219
|
-
|
220
|
-
|
279
|
+
def tag_release
|
280
|
+
version = extract_version
|
281
|
+
info "Tagging release #{version}"
|
282
|
+
url = tag_url Svn.repo_url, version
|
283
|
+
Svn.remove url, 'Removing old copy' rescue nil
|
284
|
+
Svn.copy Dir.pwd, url, "Release #{version}"
|
221
285
|
end
|
222
286
|
|
223
287
|
# :call-seq:
|
224
|
-
#
|
288
|
+
# commit_new_snapshot()
|
225
289
|
#
|
226
|
-
# Last, we commit what we currently have in the working copy.
|
227
|
-
def
|
228
|
-
buildfile =
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
end
|
233
|
-
|
234
|
-
# :call-seq:
|
235
|
-
# svn(*args)
|
236
|
-
#
|
237
|
-
# Executes SVN command and returns the output.
|
238
|
-
def svn(*args)
|
239
|
-
cmd = 'svn ' + args.map { |arg| arg[' '] ? %Q{"#{arg}"} : arg }.join(' ')
|
240
|
-
puts cmd if verbose
|
241
|
-
`#{cmd}`.tap { fail 'SVN command failed' unless $?.exitstatus == 0 }
|
242
|
-
end
|
243
|
-
|
244
|
-
# Return the current SVN URL
|
245
|
-
def svn_url
|
246
|
-
url = svn('info').scan(/URL: (.*)/)[0][0]
|
290
|
+
# Last, we commit what we currently have in the working copy with an upgraded version number.
|
291
|
+
def commit_new_snapshot
|
292
|
+
buildfile = change_version { |version| version[-1] = (version[-1].to_i + 1).to_s + '-SNAPSHOT' }
|
293
|
+
File.open(Buildr.application.buildfile.to_s, 'w') { |file| file.write buildfile }
|
294
|
+
Svn.commit Buildr.application.buildfile.to_s, "Changed version number to #{extract_version}"
|
295
|
+
info "Current version is now #{extract_version}"
|
247
296
|
end
|
248
297
|
end
|
249
|
-
|
250
298
|
end
|
251
299
|
|
300
|
+
|
252
301
|
desc 'Make a release'
|
253
302
|
task 'release' do |task|
|
254
303
|
Release.make
|
data/lib/buildr/core/checks.rb
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
|
17
17
|
require 'buildr/core/project'
|
18
18
|
require 'buildr/packaging/zip'
|
19
|
-
require 'test/unit'
|
19
|
+
#require 'test/unit'
|
20
20
|
require 'spec/matchers'
|
21
21
|
require 'spec/expectations'
|
22
22
|
|
@@ -130,7 +130,7 @@ module Buildr
|
|
130
130
|
# Run the expectation. We only print the expectation name when tracing (to know they all ran),
|
131
131
|
# or when we get a failure.
|
132
132
|
begin
|
133
|
-
|
133
|
+
trace description
|
134
134
|
klass.new.instance_eval &@block
|
135
135
|
rescue Exception=>error
|
136
136
|
raise error.exception("#{description}\n#{error}").tap { |wrapped| wrapped.set_backtrace(error.backtrace) }
|
@@ -149,10 +149,10 @@ module Buildr
|
|
149
149
|
begin
|
150
150
|
expect.run_against project
|
151
151
|
passed
|
152
|
-
rescue Exception=>
|
152
|
+
rescue Exception=>ex
|
153
153
|
if verbose
|
154
|
-
|
155
|
-
|
154
|
+
error ex.backtrace.select { |line| line =~ /#{Buildr.application.buildfile}/ }.join("\n")
|
155
|
+
error ex
|
156
156
|
end
|
157
157
|
false
|
158
158
|
end
|
data/lib/buildr/core/common.rb
CHANGED
@@ -111,7 +111,7 @@ module Buildr
|
|
111
111
|
# Download to a file created by the task.
|
112
112
|
fail unless args.keys.size == 1
|
113
113
|
uri = URI.parse(args.values.first.to_s)
|
114
|
-
file(args.keys.first).tap do |task|
|
114
|
+
file(args.keys.first.to_s).tap do |task|
|
115
115
|
task.sources << uri
|
116
116
|
task.enhance { uri.download task.name }
|
117
117
|
end
|
data/lib/buildr/core/compile.rb
CHANGED
@@ -122,6 +122,8 @@ module Buildr
|
|
122
122
|
map = compile_map(sources, target)
|
123
123
|
return false if map.empty?
|
124
124
|
return true unless File.exist?(target.to_s)
|
125
|
+
source_files_not_yet_compiled = map.select { |source, target| !File.exist?(target) }
|
126
|
+
trace "Compile needed because source file #{source_files_not_yet_compiled[0][0]} has no corresponding #{source_files_not_yet_compiled[0][1]}" unless source_files_not_yet_compiled.empty?
|
125
127
|
return true if map.any? { |source, target| !File.exist?(target) || File.stat(source).mtime > File.stat(target).mtime }
|
126
128
|
oldest = map.map { |source, target| File.stat(target).mtime }.min
|
127
129
|
return dependencies.any? { |path| file(path).timestamp > oldest }
|
@@ -173,7 +175,7 @@ module Buildr
|
|
173
175
|
FileList["#{source}/**/*.{#{ext_glob}}"].reject { |file| File.directory?(file) }.
|
174
176
|
each { |file| map[file] = File.join(target, Util.relative_path(file, source).ext(target_ext)) }
|
175
177
|
else
|
176
|
-
map[source] = File.join(target, File.basename(source).ext(target_ext))
|
178
|
+
map[source] = target # File.join(target, File.basename(source).ext(target_ext))
|
177
179
|
end
|
178
180
|
map
|
179
181
|
end
|
@@ -223,7 +225,7 @@ module Buildr
|
|
223
225
|
raise 'No compiler selected and can\'t determine which compiler to use' unless compiler
|
224
226
|
raise 'No target directory specified' unless target
|
225
227
|
mkpath target.to_s, :verbose=>false
|
226
|
-
|
228
|
+
info "Compiling #{task.name.gsub(/:[^:]*$/, '')} into #{target.to_s}"
|
227
229
|
@compiler.compile(sources.map(&:to_s), target.to_s, dependencies.map(&:to_s))
|
228
230
|
# By touching the target we let other tasks know we did something,
|
229
231
|
# and also prevent recompiling again for dependencies.
|
@@ -244,6 +246,7 @@ module Buildr
|
|
244
246
|
# compile.from('src/java').into('classes').with('module1.jar')
|
245
247
|
def from(*sources)
|
246
248
|
@sources |= sources.flatten
|
249
|
+
guess_compiler if @compiler.nil? && sources.flatten.any? { |source| File.exist?(source) }
|
247
250
|
self
|
248
251
|
end
|
249
252
|
|
@@ -316,10 +319,7 @@ module Buildr
|
|
316
319
|
# based on existing source directories (e.g. src/main/java), or by requesting
|
317
320
|
# a specific compiler (see #using).
|
318
321
|
def compiler
|
319
|
-
unless @compiler
|
320
|
-
candidate = Compiler.compilers.detect { |cls| cls.applies_to?(project, self) }
|
321
|
-
self.compiler = candidate if candidate
|
322
|
-
end
|
322
|
+
guess_compiler unless @compiler
|
323
323
|
@compiler && @compiler.class.to_sym
|
324
324
|
end
|
325
325
|
|
@@ -363,7 +363,11 @@ module Buildr
|
|
363
363
|
# Associates this task with project and particular usage (:main, :test).
|
364
364
|
def associate_with(project, usage) #:nodoc:
|
365
365
|
@project, @usage = project, usage
|
366
|
-
|
366
|
+
guess_compiler
|
367
|
+
end
|
368
|
+
|
369
|
+
# Try to guess if we have a compiler to match source files.
|
370
|
+
def guess_compiler #:nodoc:
|
367
371
|
candidate = Compiler.compilers.detect { |cls| cls.applies_to?(project, self) }
|
368
372
|
self.compiler = candidate if candidate
|
369
373
|
end
|
@@ -496,9 +500,7 @@ module Buildr
|
|
496
500
|
# This comes last because the target path is set inside the project definition.
|
497
501
|
project.build project.compile.target
|
498
502
|
project.clean do
|
499
|
-
verbose
|
500
|
-
rm_rf project.compile.target.to_s
|
501
|
-
end
|
503
|
+
rm_rf project.compile.target.to_s, :verbose=>false
|
502
504
|
end
|
503
505
|
end
|
504
506
|
end
|
data/lib/buildr/core/filter.rb
CHANGED
@@ -13,7 +13,6 @@
|
|
13
13
|
# License for the specific language governing permissions and limitations under
|
14
14
|
# the License.
|
15
15
|
|
16
|
-
|
17
16
|
module Buildr
|
18
17
|
|
19
18
|
# A filter knows how to copy files from one directory to another, applying mappings to the
|
@@ -56,7 +55,8 @@ module Buildr
|
|
56
55
|
def clear
|
57
56
|
@include = []
|
58
57
|
@exclude = []
|
59
|
-
@sources = []
|
58
|
+
@sources = FileList[]
|
59
|
+
@mapper = Mapper.new
|
60
60
|
self
|
61
61
|
end
|
62
62
|
|
@@ -93,7 +93,7 @@ module Buildr
|
|
93
93
|
# Specifies files to include and returns self. See FileList#include.
|
94
94
|
#
|
95
95
|
# By default all files are included. You can use this method to only include specific
|
96
|
-
# files
|
96
|
+
# files from the source directory.
|
97
97
|
def include(*files)
|
98
98
|
@include += files
|
99
99
|
self
|
@@ -110,10 +110,14 @@ module Buildr
|
|
110
110
|
end
|
111
111
|
|
112
112
|
# The mapping. See #using.
|
113
|
-
|
113
|
+
def mapping #:nodoc:
|
114
|
+
@mapper.config
|
115
|
+
end
|
114
116
|
|
115
117
|
# The mapper to use. See #using.
|
116
|
-
|
118
|
+
def mapper #:nodoc:
|
119
|
+
@mapper.mapper_type
|
120
|
+
end
|
117
121
|
|
118
122
|
# :call-seq:
|
119
123
|
# using(mapping) => self
|
@@ -127,6 +131,7 @@ module Buildr
|
|
127
131
|
# * :ant -- Map <code>@key@</code>.
|
128
132
|
# * :maven -- Map <code>${key}</code> (default).
|
129
133
|
# * :ruby -- Map <code>#{key}</code>.
|
134
|
+
# * :erb -- Map <code><%= key %></code>.
|
130
135
|
# * Regexp -- Maps the matched data (e.g. <code>/=(.*?)=/</code>
|
131
136
|
#
|
132
137
|
# For example:
|
@@ -138,20 +143,10 @@ module Buildr
|
|
138
143
|
# to return the mapped content.
|
139
144
|
#
|
140
145
|
# Without any mapping, all files are copied as is.
|
146
|
+
#
|
147
|
+
# To register new mapping type see the Mapper class.
|
141
148
|
def using(*args, &block)
|
142
|
-
|
143
|
-
when Hash # Maven hash mapping
|
144
|
-
using :maven, *args
|
145
|
-
when Symbol # Mapping from a method
|
146
|
-
raise ArgumentError, 'Expected mapper type followed by mapping hash' unless args.size == 2 && Hash === args[1]
|
147
|
-
@mapper, @mapping = *args
|
148
|
-
when Regexp # Mapping using a regular expression
|
149
|
-
raise ArgumentError, 'Expected regular expression followed by mapping hash' unless args.size == 2 && Hash === args[1]
|
150
|
-
@mapper, @mapping = *args
|
151
|
-
else
|
152
|
-
raise ArgumentError, 'Expected proc, method or a block' if args.size > 1 || (args.first && block)
|
153
|
-
@mapping = args.first || block
|
154
|
-
end
|
149
|
+
@mapper.using(*args, &block)
|
155
150
|
self
|
156
151
|
end
|
157
152
|
|
@@ -185,24 +180,12 @@ module Buildr
|
|
185
180
|
mkpath dest
|
186
181
|
else
|
187
182
|
mkpath File.dirname(dest)
|
188
|
-
|
189
|
-
|
190
|
-
mapped = mapping.call(path, File.open(source, 'rb') { |file| file.read })
|
183
|
+
if @mapper.mapper_type
|
184
|
+
mapped = @mapper.transform(File.open(source, 'rb') { |file| file.read }, path)
|
191
185
|
File.open(dest, 'wb') { |file| file.write mapped }
|
192
|
-
|
193
|
-
content = File.open(source, 'rb') { |file| file.read }
|
194
|
-
if Symbol === @mapper
|
195
|
-
mapped = send("#{@mapper}_mapper", content) { |key| mapping[key] }
|
196
|
-
else
|
197
|
-
mapped = regexp_mapper(content) { |key| mapping[key] }
|
198
|
-
end
|
199
|
-
#gsub(/\$\{[^}]*\}/) { |str| mapping[str[2..-2]] || str }
|
200
|
-
File.open(dest, 'wb') { |file| file.write mapped }
|
201
|
-
when nil # No mapping.
|
186
|
+
else # no mapping
|
202
187
|
cp source, dest
|
203
188
|
File.chmod(0664, dest)
|
204
|
-
else
|
205
|
-
fail "Filter can be a hash (key=>value), or a proc/method; I don't understand #{mapping}"
|
206
189
|
end
|
207
190
|
end
|
208
191
|
end
|
@@ -216,23 +199,145 @@ module Buildr
|
|
216
199
|
@target.to_s
|
217
200
|
end
|
218
201
|
|
219
|
-
|
202
|
+
# This class implements content replacement logic for Filter.
|
203
|
+
#
|
204
|
+
# To register a new template engine @:foo@, extend this class with a method like:
|
205
|
+
#
|
206
|
+
# def foo_transform(content, path = nil)
|
207
|
+
# # if this method yields a key, the value comes from the mapping hash
|
208
|
+
# content.gsub(/world/) { |str| yield :bar }
|
209
|
+
# end
|
210
|
+
#
|
211
|
+
# Then you can use :foo mapping type on a Filter
|
212
|
+
#
|
213
|
+
# filter.using :foo, :bar => :baz
|
214
|
+
#
|
215
|
+
# Or all by your own, simply
|
216
|
+
#
|
217
|
+
# Mapper.new(:foo, :bar => :baz).transform("Hello world") # => "Hello baz"
|
218
|
+
#
|
219
|
+
# You can handle configuration arguments by providing a @*_config@ method like:
|
220
|
+
#
|
221
|
+
# # The return value of this method is available with the :config accessor.
|
222
|
+
# def moo_config(*args, &block)
|
223
|
+
# raise ArgumentError, "Expected moo block" unless block_given?
|
224
|
+
# { :moos => args, :callback => block }
|
225
|
+
# end
|
226
|
+
#
|
227
|
+
# def moo_transform(content, path = nil)
|
228
|
+
# content.gsub(/moo+/i) do |str|
|
229
|
+
# moos = yield :moos # same than config[:moos]
|
230
|
+
# moo = moos[str.size - 3] || str
|
231
|
+
# config[:callback].call(moo)
|
232
|
+
# end
|
233
|
+
# end
|
234
|
+
#
|
235
|
+
# Usage for the @:moo@ mapper would be something like:
|
236
|
+
#
|
237
|
+
# mapper = Mapper.new(:moo, 'ooone', 'twoo') do |str|
|
238
|
+
# i = nil; str.capitalize.gsub(/\w/) { |s| s.send( (i = !i) ? 'upcase' : 'downcase' ) }
|
239
|
+
# end
|
240
|
+
# mapper.transform('Moo cow, mooo cows singing mooooo') # => 'OoOnE cow, TwOo cows singing MoOoOo'
|
241
|
+
class Mapper
|
220
242
|
|
221
|
-
|
222
|
-
content.gsub(/\$\{.*?\}/) { |str| yield(str[2..-2]) || str }
|
223
|
-
end
|
243
|
+
attr_reader :mapper_type, :config
|
224
244
|
|
225
|
-
|
226
|
-
|
227
|
-
|
245
|
+
def initialize(*args, &block) #:nodoc:
|
246
|
+
using(*args, &block)
|
247
|
+
end
|
248
|
+
|
249
|
+
def using(*args, &block)
|
250
|
+
case args.first
|
251
|
+
when Hash # Maven hash mapping
|
252
|
+
using :maven, *args
|
253
|
+
when Binding # Erb binding
|
254
|
+
using :erb, *args
|
255
|
+
when Symbol # Mapping from a method
|
256
|
+
raise ArgumentError, "Unknown mapping type: #{args.first}" unless respond_to?("#{args.first}_transform", true)
|
257
|
+
configure(*args, &block)
|
258
|
+
when Regexp # Mapping using a regular expression
|
259
|
+
raise ArgumentError, 'Expected regular expression followed by mapping hash' unless args.size == 2 && Hash === args[1]
|
260
|
+
@mapper_type, @config = *args
|
261
|
+
else
|
262
|
+
unless args.empty? && block.nil?
|
263
|
+
raise ArgumentError, 'Expected proc, method or a block' if args.size > 1 || (args.first && block)
|
264
|
+
@mapper_type = :callback
|
265
|
+
config = args.first || block
|
266
|
+
raise ArgumentError, 'Expected proc, method or callable' unless config.respond_to?(:call)
|
267
|
+
@config = config
|
268
|
+
end
|
269
|
+
end
|
270
|
+
self
|
271
|
+
end
|
228
272
|
|
229
|
-
|
230
|
-
|
231
|
-
|
273
|
+
def transform(content, path = nil)
|
274
|
+
type = Regexp === mapper_type ? :regexp : mapper_type
|
275
|
+
raise ArgumentError, "Invalid mapper type: #{type.inspect}" unless respond_to?("#{type}_transform", true)
|
276
|
+
self.__send__("#{type}_transform", content, path) { |key| config[key] || config[key.to_s.to_sym] }
|
277
|
+
end
|
232
278
|
|
233
|
-
|
234
|
-
|
235
|
-
|
279
|
+
private
|
280
|
+
def configure(mapper_type, *args, &block)
|
281
|
+
configurer = method("#{mapper_type}_config") rescue nil
|
282
|
+
if configurer
|
283
|
+
@config = configurer.call(*args, &block)
|
284
|
+
else
|
285
|
+
raise ArgumentError, "Missing hash argument after :#{mapper_type}" unless args.size == 1 && Hash === args[0]
|
286
|
+
@config = *args
|
287
|
+
end
|
288
|
+
@mapper_type = mapper_type
|
289
|
+
end
|
290
|
+
|
291
|
+
def maven_transform(content, path = nil)
|
292
|
+
content.gsub(/\$\{.*?\}/) { |str| yield(str[2..-2]) || str }
|
293
|
+
end
|
294
|
+
|
295
|
+
def ant_transform(content, path = nil)
|
296
|
+
content.gsub(/@.*?@/) { |str| yield(str[1..-2]) || str }
|
297
|
+
end
|
298
|
+
|
299
|
+
def ruby_transform(content, path = nil)
|
300
|
+
content.gsub(/#\{.*?\}/) { |str| yield(str[2..-2]) || str }
|
301
|
+
end
|
302
|
+
|
303
|
+
def regexp_transform(content, path = nil)
|
304
|
+
content.gsub(mapper_type) { |str| yield(str.scan(mapper_type).join) || str }
|
305
|
+
end
|
306
|
+
|
307
|
+
def callback_transform(content, path = nil)
|
308
|
+
config.call(path, content)
|
309
|
+
end
|
310
|
+
|
311
|
+
def erb_transform(content, path = nil)
|
312
|
+
case config
|
313
|
+
when Binding, Proc
|
314
|
+
bnd = config
|
315
|
+
when Method
|
316
|
+
bnd = config.to_proc
|
317
|
+
when Hash
|
318
|
+
bnd = OpenStruct.new
|
319
|
+
table = config.inject({}) { |h, e| h[e.first.to_sym] = e.last; h }
|
320
|
+
bnd.instance_variable_set(:@table, table)
|
321
|
+
bnd = bnd.instance_eval { binding }
|
322
|
+
else
|
323
|
+
bnd = config.instance_eval { binding }
|
324
|
+
end
|
325
|
+
require 'erb'
|
326
|
+
ERB.new(content).result(bnd)
|
327
|
+
end
|
328
|
+
|
329
|
+
def erb_config(*args, &block)
|
330
|
+
if block_given?
|
331
|
+
raise ArgumentError, "Expected block or single argument, but both given." unless args.empty?
|
332
|
+
block
|
333
|
+
elsif args.size > 1
|
334
|
+
raise ArgumentError, "Expected block or single argument."
|
335
|
+
else
|
336
|
+
args.first
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
end # class Mapper
|
236
341
|
|
237
342
|
end
|
238
343
|
|