buildr 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +151 -0
- data/LICENSE +202 -0
- data/README +0 -0
- data/lib/buildr.rb +43 -0
- data/lib/core/artifact.rb +394 -0
- data/lib/core/build.rb +108 -0
- data/lib/core/core.rb +49 -0
- data/lib/core/project.rb +313 -0
- data/lib/core/transports.rb +381 -0
- data/lib/java/compile.rb +316 -0
- data/lib/java/java.rb +117 -0
- data/lib/java/javacc.rb +88 -0
- data/lib/java/openjpa.rb +52 -0
- data/lib/java/packaging.rb +217 -0
- data/lib/java/xmlbeans.rb +64 -0
- data/lib/tasks/download.rb +38 -0
- data/lib/tasks/filter.rb +96 -0
- data/lib/tasks/zip.rb +313 -0
- metadata +134 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
module Buildr
|
2
|
+
|
3
|
+
module XMLBeans
|
4
|
+
|
5
|
+
REQUIRES = [ "xmlbeans:xbean:jar:2.2.0", "stax:stax-api:jar:1.0" ]
|
6
|
+
|
7
|
+
def self.compile(*args)
|
8
|
+
options = Hash === args.last ? args.pop : {}
|
9
|
+
options[:verbose] ||= Rake.application.options.trace || false
|
10
|
+
fu_check_options options, :verbose, :noop, :javasource, :jar, :classes, :output
|
11
|
+
|
12
|
+
# Classpath for XMLBeans.
|
13
|
+
cp = REQUIRES.map { |id| artifact(id) }.each(&:invoke).map(&:to_s).join(File::PATH_SEPARATOR)
|
14
|
+
# Options for SchemaCompiler.
|
15
|
+
cmd_args = [ options[:verbose] ? "-verbose" : "-quiet" ]
|
16
|
+
cmd_args << "-javasource" << options[:javasource].collect.join(File::PATH_SEPARATOR) if options[:javasource]
|
17
|
+
cmd_args << "-out" << options[:jar] if options[:jar]
|
18
|
+
cmd_args << "-d" << options[:classes] if options[:classes]
|
19
|
+
cmd_args << "-src" << options[:output] if options[:output]
|
20
|
+
cmd_args += args
|
21
|
+
cmd_args << { :verbose=>options[:verbose] }
|
22
|
+
|
23
|
+
unless options[:noop]
|
24
|
+
verbose { puts "Running XMLBeans schema compiler" }
|
25
|
+
mkpath options[:classes], :verbose=>false rescue nil if options[:classes]
|
26
|
+
mkpath options[:output], :verbose=>false rescue nil if options[:output]
|
27
|
+
sh(Java.path_to_bin("java"), "-Xmx256m", "-cp", cp,
|
28
|
+
"org.apache.xmlbeans.impl.tool.SchemaCompiler", *cmd_args) { |ok, res|
|
29
|
+
fail "Failed to compile schemas, see errors above" unless ok }
|
30
|
+
# Touch paths to let other tasks know there's an update.
|
31
|
+
touch options[:classes], :verbose=>false if options[:classes]
|
32
|
+
touch options[:output], :verbose=>false if options[:output]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class CompileTask < Rake::FileTask
|
37
|
+
|
38
|
+
def initialize(*args)
|
39
|
+
super
|
40
|
+
enhance do |task|
|
41
|
+
XMLBeans.compile *task.prerequisites + [options.merge(:output=>task.name)]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def options()
|
46
|
+
@options ||= {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def using(options)
|
50
|
+
self.options.merge!(options)
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.compile_task(args)
|
57
|
+
output = args.keys.first
|
58
|
+
files = args.values.first.collect { |f| File.directory?(f) ? FileList[f + "/**/*"] : f }.flatten
|
59
|
+
CompileTask.define_task(output=>files)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
|
3
|
+
module Buildr
|
4
|
+
|
5
|
+
# Create a task that will download a file from a URL.
|
6
|
+
#
|
7
|
+
# Takes a single argument, a hash with one pair. The key is the file being
|
8
|
+
# created, the value if the URL to download. The task executes only if the
|
9
|
+
# file does not exist; the URL is not checked for updates.
|
10
|
+
#
|
11
|
+
# The task will show download progress on the console; if there are MD5/SHA1
|
12
|
+
# checksums on the server it will verify the download before saving it.
|
13
|
+
#
|
14
|
+
# For example:
|
15
|
+
# download "image.jpg"=>"http://example.com/theme/image.jpg"
|
16
|
+
def download(args)
|
17
|
+
if String === args || URI === args
|
18
|
+
# Given only a download URL, download into a temporary file.
|
19
|
+
# You can infer the file from task name.
|
20
|
+
temp = Tempfile.new(File.basename(args.to_s))
|
21
|
+
task = file_create(temp.path) do |task|
|
22
|
+
Transports.download task.source, task.name
|
23
|
+
end
|
24
|
+
task.sources << args
|
25
|
+
else
|
26
|
+
# Download to a file created by the task.
|
27
|
+
fail unless args.keys.size == 1
|
28
|
+
url = args.values.first
|
29
|
+
task = file_create(args.keys.first) do |task|
|
30
|
+
mkpath File.dirname(task.name), :verbose=>false
|
31
|
+
Transports.download task.source, task.name
|
32
|
+
end
|
33
|
+
task.sources << url
|
34
|
+
end
|
35
|
+
task
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/lib/tasks/filter.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
module Buildr
|
2
|
+
|
3
|
+
class Filter < Rake::Task
|
4
|
+
|
5
|
+
# The target directory.
|
6
|
+
attr_accessor :target
|
7
|
+
# Filter to use.
|
8
|
+
attr_accessor :filter
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
super
|
12
|
+
enhance do |task|
|
13
|
+
fail "No target directory specified" if !target || (File.exist?(target) && !File.directory?(target))
|
14
|
+
unless copy_map.empty?
|
15
|
+
verbose(Rake.application.options.trace || false) do
|
16
|
+
copy_map do |dest, src|
|
17
|
+
mkpath File.dirname(dest) rescue nil
|
18
|
+
case filter
|
19
|
+
when Proc, Method
|
20
|
+
filtered = filter.call(File.read(src))
|
21
|
+
File.open(dest, "w") { |file| file.write filtered }
|
22
|
+
when Hash
|
23
|
+
filtered = File.read(src).gsub(/\$\{.*\}/) { |str| filter[str[2..-2]] || str }
|
24
|
+
File.open(dest, "w") { |file| file.write filtered }
|
25
|
+
when nil
|
26
|
+
cp src, dest
|
27
|
+
else
|
28
|
+
fail "Filter can be a hash (key=>value), or a proc/method; I don't understand #{filter}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
touch target if File.exist?(target)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def include(*files)
|
38
|
+
prerequisites.include *files
|
39
|
+
self
|
40
|
+
end
|
41
|
+
alias :add :include
|
42
|
+
|
43
|
+
def exclude(*files)
|
44
|
+
prerequisites.exclude *files
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def into(dir)
|
49
|
+
self.target = dir
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def using(filter, &block)
|
54
|
+
self.filter = filter || block
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
# Return a copy map of all the files that need copying: the key is
|
61
|
+
# the file to copy to, the value is the source file. If called with
|
62
|
+
# a block, yields with each dest/source pair.
|
63
|
+
def copy_map(&block)
|
64
|
+
# Create a map between the source file and the similarly named
|
65
|
+
# file in the target directory, including all files nested inside
|
66
|
+
# directories.
|
67
|
+
@copy_map ||= prerequisites.map(&:to_s).inject({}) do |map, path|
|
68
|
+
if File.directory?(path)
|
69
|
+
Dir[File.join(path, "**", "*")].each do |file|
|
70
|
+
map[file.sub(File.dirname(path), target)] = file unless
|
71
|
+
File.directory?(file) || prerequisites.exclude?(file)
|
72
|
+
end
|
73
|
+
elsif File.exist?(path)
|
74
|
+
map[File.join(target, File.basename(path))] = path
|
75
|
+
end
|
76
|
+
map
|
77
|
+
end.reject do |dest, src|
|
78
|
+
# ... while ignoring that which does not need updating.
|
79
|
+
File.exist?(dest) && File.stat(dest).mtime > File.stat(src).mtime
|
80
|
+
end
|
81
|
+
if block_given?
|
82
|
+
@copy_map.each(&block)
|
83
|
+
else
|
84
|
+
@copy_map
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
def filter(*files)
|
91
|
+
task = nil
|
92
|
+
namespace { task = Filter.define_task("filter").include *files }
|
93
|
+
task
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
data/lib/tasks/zip.rb
ADDED
@@ -0,0 +1,313 @@
|
|
1
|
+
require "zip/zip"
|
2
|
+
require "zip/zipfilesystem"
|
3
|
+
|
4
|
+
|
5
|
+
module Buildr
|
6
|
+
|
7
|
+
# The ZipTask creates a new ZIP file. You can include any number of files and
|
8
|
+
# and directories, use exclusion patterns, and include files into specific
|
9
|
+
# directories.
|
10
|
+
class ZipTask < Rake::FileTask
|
11
|
+
|
12
|
+
def initialize(*args)
|
13
|
+
super
|
14
|
+
@paths = {}
|
15
|
+
enhance do |task|
|
16
|
+
verbose { puts "Creating #{task.name}" }
|
17
|
+
# We're here because the Zip file does not exist, or one of the files is
|
18
|
+
# newer than the Zip contents; in the later case, opening the Zip file
|
19
|
+
# will add to its contents instead of replacing it, so we want the Zip
|
20
|
+
# gone before we change it. We also don't want to see any partial updates.
|
21
|
+
rm task.name, :verbose=>false rescue nil
|
22
|
+
mkpath File.dirname(task.name), :verbose=>false
|
23
|
+
begin
|
24
|
+
Zip::ZipFile.open(task.name, Zip::ZipFile::CREATE) { |zip| create zip }
|
25
|
+
rescue
|
26
|
+
rm task.name, :verbose=>false rescue nil
|
27
|
+
raise
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Include the specified files and directories. Returns self.
|
33
|
+
#
|
34
|
+
# You can specify a path for inclusion by passing :path=> as the
|
35
|
+
# last argument. For example:
|
36
|
+
# task.include "src" # Include the src directory
|
37
|
+
# task.include foobar, :path=>"libs" # Include under /libs/
|
38
|
+
def include(*files)
|
39
|
+
if Hash === files.last
|
40
|
+
path = files.pop[:path]
|
41
|
+
end
|
42
|
+
(@paths[path] ||= FileList[]).include *files
|
43
|
+
self
|
44
|
+
end
|
45
|
+
alias :add :include
|
46
|
+
|
47
|
+
# Excludes the specified files and directories. Returns self. Use this
|
48
|
+
# in combination with include; make sure to use the same path.
|
49
|
+
def exclude(*files)
|
50
|
+
if Hash === files.last
|
51
|
+
path = files.pop[:path]
|
52
|
+
end
|
53
|
+
(@paths[path] ||= FileList[]).exclude *files
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns a path to which you can include/exclude files.
|
58
|
+
#
|
59
|
+
# zip(..).include("foo", :path=>"bar")
|
60
|
+
# is equivalen to:
|
61
|
+
# zip(..).path("bar").include("foo")
|
62
|
+
def path(path)
|
63
|
+
@paths[path] ||= FileList[]
|
64
|
+
end
|
65
|
+
|
66
|
+
# Pass options to the task. Returns self.
|
67
|
+
def with(options)
|
68
|
+
options.each do |key, value|
|
69
|
+
self[key] = value
|
70
|
+
end
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def []=(key, value)
|
75
|
+
fail "#{self.class} does not support the attribute #{key}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def invoke_prerequisites()
|
79
|
+
super
|
80
|
+
@paths.each { |p, files| artifacts(*files).each { |f| file(f).invoke } }
|
81
|
+
end
|
82
|
+
|
83
|
+
def needed?()
|
84
|
+
# You can do something like:
|
85
|
+
# include("foo", :path=>"foo").exclude("foo/bar", path=>"foo").
|
86
|
+
# include("foo/bar", :path=>"foo/bar")
|
87
|
+
# This will play havoc if we handled all the prerequisites together
|
88
|
+
# under the task, so instead we handle them individually for each path.
|
89
|
+
#@paths.collect{ |p, files| files }.flatten.each { |f| file(f).invoke }
|
90
|
+
return true unless File.exist?(name)
|
91
|
+
# We need to check that any file we include is not newer than the
|
92
|
+
# contents of the ZIP. The file itself but also the directory it's
|
93
|
+
# coming from, since some tasks touch the directory, e.g. when the
|
94
|
+
# content of target/classes is included into a WAR.
|
95
|
+
files = @paths.collect { |path, files| files.map(&:to_s) }.flatten
|
96
|
+
files = files.collect { |f| File.directory?(f) ? FileList[File.join(f, "**", "*")].collect | [f] : f }.flatten
|
97
|
+
most_recent = files.select { |f| File.exist?(f) }.collect { |f| File.stat(f).mtime }.max
|
98
|
+
File.stat(name).mtime < (most_recent || Rake::EARLY)
|
99
|
+
end
|
100
|
+
|
101
|
+
protected
|
102
|
+
|
103
|
+
def create(zip)
|
104
|
+
zip_map.keys.sort.each do |path|
|
105
|
+
puts "Adding #{path}" if Rake.application.options.trace
|
106
|
+
zip.add path, zip_map[path]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def zip_map()
|
111
|
+
unless @zip_map
|
112
|
+
args = @paths.collect do |path, files|
|
113
|
+
if path
|
114
|
+
dest_for = proc { |f| File.join(path, f) }
|
115
|
+
else
|
116
|
+
dest_for = proc { |f| f }
|
117
|
+
end
|
118
|
+
artifacts(*files).map(&:to_s).collect do |file|
|
119
|
+
if File.directory?(file)
|
120
|
+
# Include all files inside the directory, with path starting
|
121
|
+
# from the directory itself.
|
122
|
+
prefix = File.dirname(file) + File::SEPARATOR
|
123
|
+
Dir[File.join(file, "**", "*")].sort.
|
124
|
+
reject { |file| File.directory?(file) || files.exclude?(file) }.
|
125
|
+
collect { |file| [ dest_for[file.sub(prefix, "")], file ] }
|
126
|
+
else
|
127
|
+
# Include just that one file, sans its diectory path.
|
128
|
+
[ dest_for[File.basename(file)], file ]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end.flatten
|
132
|
+
@zip_map = Hash[ *args ]
|
133
|
+
end
|
134
|
+
@zip_map
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
# The ZipTask creates a new ZIP file. You can include any number of files and
|
140
|
+
# and directories, use exclusion patterns, and include files into specific
|
141
|
+
# directories.
|
142
|
+
#
|
143
|
+
# For example:
|
144
|
+
# returning(zip("test.zip")) { |task|
|
145
|
+
# task.include "srcs"
|
146
|
+
# task.include "README", "LICENSE"
|
147
|
+
# end
|
148
|
+
def zip(file)
|
149
|
+
ZipTask.define_task(file)
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
# The UnzipTask expands the contents of a ZIP file into a target directory.
|
154
|
+
# You can include any number of files and directories, use exclusion patterns,
|
155
|
+
# and expand files from relative paths.
|
156
|
+
#
|
157
|
+
# The file(s) to unzip is the first prerequisite.
|
158
|
+
class UnzipTask < Rake::Task
|
159
|
+
|
160
|
+
# The target directory.
|
161
|
+
attr_accessor :target
|
162
|
+
|
163
|
+
def initialize(*args)
|
164
|
+
super
|
165
|
+
@paths = {}
|
166
|
+
enhance do |task|
|
167
|
+
fail "Where do you want the file unzipped" unless target
|
168
|
+
|
169
|
+
# If no paths specified, then no include/exclude patterns
|
170
|
+
# specified. Nothing will happen unless we include all files.
|
171
|
+
if @paths.empty?
|
172
|
+
@paths[nil] = FromPath.new(nil)
|
173
|
+
@paths[nil].include "*"
|
174
|
+
end
|
175
|
+
|
176
|
+
# Otherwise, empty unzip creates target as a file when touching.
|
177
|
+
mkpath target, :verbose=>false
|
178
|
+
prerequisites.each do |file|
|
179
|
+
Zip::ZipFile.open(file) do |zip|
|
180
|
+
entries = zip.collect
|
181
|
+
@paths.each do |path, patterns|
|
182
|
+
patterns.map(entries).each do |dest, entry|
|
183
|
+
next if entry.directory?
|
184
|
+
dest = File.expand_path(dest, target)
|
185
|
+
puts "Extracting #{dest}" if Rake.application.options.trace
|
186
|
+
mkpath File.dirname(dest), :verbose=>false rescue nil
|
187
|
+
entry.extract(dest) { true }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
# Let other tasks know we updated the target directory.
|
193
|
+
touch target, :verbose=>false
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Specifies directory to unzip to and return self.
|
198
|
+
def into(target)
|
199
|
+
self.target = target
|
200
|
+
self
|
201
|
+
end
|
202
|
+
|
203
|
+
# Include all files that match the patterns and returns self.
|
204
|
+
#
|
205
|
+
# Use include if you only want to unzip some of the files, by specifying
|
206
|
+
# them instead of using exclusion. You can use #include in combination
|
207
|
+
# with #exclude.
|
208
|
+
def include(*files)
|
209
|
+
if Hash === files.last
|
210
|
+
from_path(files.pop[:path]).include *files
|
211
|
+
else
|
212
|
+
from_path(nil).include *files
|
213
|
+
end
|
214
|
+
self
|
215
|
+
end
|
216
|
+
alias :add :include
|
217
|
+
|
218
|
+
# Exclude all files that match the patterns and return self.
|
219
|
+
#
|
220
|
+
# Use exclude to unzip all files except those that match the pattern.
|
221
|
+
# You can use #exclude in combination with #include.
|
222
|
+
def exclude(*files)
|
223
|
+
if Hash === files.last
|
224
|
+
from_path(files.pop[:path]).exclude *files
|
225
|
+
else
|
226
|
+
from_path(nil).exclude *files
|
227
|
+
end
|
228
|
+
self
|
229
|
+
end
|
230
|
+
|
231
|
+
# Allows you to unzip from a path. Returns an object you can use to
|
232
|
+
# specify which files to include/exclude relative to that path.
|
233
|
+
# Expands the file relative to that path.
|
234
|
+
#
|
235
|
+
# For example:
|
236
|
+
# unzip("test.jar").into(Dir.pwd).from_path("etc").include("LICENSE")
|
237
|
+
# will unzip etc/LICENSE into ./LICENSE.
|
238
|
+
#
|
239
|
+
# This is different from:
|
240
|
+
# unzip("test.jar").into(Dir.pwd).include("etc/LICENSE")
|
241
|
+
# which unzips etc/LICENSE into ./etc/LICENSE.
|
242
|
+
def from_path(path)
|
243
|
+
@paths[path] ||= FromPath.new(path)
|
244
|
+
end
|
245
|
+
|
246
|
+
def needed?()
|
247
|
+
return true unless target && File.exist?(target)
|
248
|
+
return true if prerequisites.any? { |prereq| File.stat(prereq).mtime > File.stat(target).mtime }
|
249
|
+
false
|
250
|
+
end
|
251
|
+
|
252
|
+
# :nodoc:
|
253
|
+
class FromPath
|
254
|
+
|
255
|
+
def initialize(path)
|
256
|
+
if path
|
257
|
+
@path = path[-1] == ?/ ? path : path + "/"
|
258
|
+
else
|
259
|
+
@path = ""
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# See UnzipTask#include
|
264
|
+
def include(*files)
|
265
|
+
@include ||= []
|
266
|
+
@include |= files
|
267
|
+
self
|
268
|
+
end
|
269
|
+
|
270
|
+
# See UnzipTask#exclude
|
271
|
+
def exclude(*files)
|
272
|
+
@exclude ||= []
|
273
|
+
@exclude |= files
|
274
|
+
self
|
275
|
+
end
|
276
|
+
|
277
|
+
# :nodoc:
|
278
|
+
def map(entries)
|
279
|
+
includes = @include || ["*"]
|
280
|
+
excludes = @exclude || []
|
281
|
+
entries.inject({}) do |map, entry|
|
282
|
+
short = entry.name.sub(@path, "")
|
283
|
+
if includes.any? { |pat| File.fnmatch(pat, short) } &&
|
284
|
+
!excludes.any? { |pat| File.fnmatch(pat, short) }
|
285
|
+
map[short] = entry
|
286
|
+
end
|
287
|
+
map
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
end
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
# Defines a task that will unzip the specified file, into the directory
|
296
|
+
# specified by calling #into. It is the second call to into that creates
|
297
|
+
# and returns the task.
|
298
|
+
#
|
299
|
+
# You can unzip only some files by specifying an inclusion or exclusion
|
300
|
+
# pattern, and unzip files from a path in the ZIP file. See UnzipTask
|
301
|
+
# for more information.
|
302
|
+
#
|
303
|
+
# For example:
|
304
|
+
# unzip("test.zip").into("test")
|
305
|
+
# unzip("test.zip").into("etc").include("README", "LICENSE")
|
306
|
+
# unzip("test.zip").into("src").from_path("srcs")
|
307
|
+
def unzip(file)
|
308
|
+
task = nil
|
309
|
+
namespace { task = UnzipTask.define_task("unzip"=>file) }
|
310
|
+
task
|
311
|
+
end
|
312
|
+
|
313
|
+
end
|