buildr 0.15.0 → 0.16.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 +12 -0
- data/lib/buildr.rb +13 -8
- data/lib/core/artifact.rb +88 -75
- data/lib/core/build.rb +87 -41
- data/lib/core/core.rb +0 -9
- data/lib/core/project.rb +268 -127
- data/lib/core/transports.rb +2 -0
- data/lib/java/compile.rb +9 -4
- data/lib/java/java.rb +8 -11
- data/lib/java/openjpa.rb +2 -1
- data/lib/java/packaging.rb +10 -27
- data/lib/java/test.rb +105 -0
- data/lib/tasks/zip.rb +171 -36
- metadata +3 -2
data/lib/core/core.rb
CHANGED
@@ -1,12 +1,3 @@
|
|
1
|
-
# returning(obj) and with(obj)
|
2
|
-
require "facet/kernel/with"
|
3
|
-
# &:symbol goodness.
|
4
|
-
require "facet/symbol/to_proc"
|
5
|
-
# blank? on string and nil
|
6
|
-
require "facet/string/blank"
|
7
|
-
require "facet/nilclass/blank"
|
8
|
-
# What it says.
|
9
|
-
require "facet/module/alias_method_chain"
|
10
1
|
require "highline"
|
11
2
|
|
12
3
|
|
data/lib/core/project.rb
CHANGED
@@ -1,42 +1,68 @@
|
|
1
1
|
module Buildr
|
2
2
|
|
3
|
-
# A project is a
|
3
|
+
# A project is a convenient mechanism for managing all the tasks
|
4
|
+
# related to a given project. For complex applications, you may have
|
5
|
+
# several projects, or sub-projects for each of the modules.
|
4
6
|
#
|
5
|
-
# A project
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
7
|
+
# A project definition creates its own set of tasks, prefixed with
|
8
|
+
# the project name. For example, each project has a clean, build
|
9
|
+
# and deploy task. For project +foo+ the task names are +foo:clean+,
|
10
|
+
# +foo:build+ and +foo:deploy+.
|
9
11
|
#
|
10
|
-
# Projects
|
11
|
-
#
|
12
|
-
#
|
12
|
+
# Projects have properties, some of which they inherit from their
|
13
|
+
# parent project. Built it tasks use these properties, for example,
|
14
|
+
# the +clean+ task will remove the target directory specified by
|
15
|
+
# the +target_dir+ property. The +compile+ tasks uses the compiler
|
16
|
+
# option: you can set these options on the parent project and they
|
17
|
+
# will be inherited by all sub-projects.
|
18
|
+
#
|
19
|
+
# You can only define a project once using #define. You can obtain
|
20
|
+
# the project using #project. Note that, if you're obtain the project
|
21
|
+
# object before the project is defined, the values of the project
|
22
|
+
# properties are not set yet, neither are any of the default tasks.
|
23
|
+
# However, many tasks perform late binding, and so you can pass a
|
24
|
+
# project before defining it. For example, the +compile+ task can
|
25
|
+
# take a project definition and use it as a classpath dependency.
|
13
26
|
#
|
14
27
|
# For example:
|
15
|
-
# define "
|
16
|
-
#
|
28
|
+
# define "project1" do
|
29
|
+
# self.version = "1.1"
|
17
30
|
#
|
18
|
-
# define "
|
19
|
-
#
|
31
|
+
# define "module1" do
|
32
|
+
# package :jar
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# define "module2" do
|
36
|
+
# compile.with project("project1:module1")
|
37
|
+
# package :jar
|
38
|
+
# end
|
20
39
|
# end
|
21
40
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
41
|
+
# project("project1").projects.map(&:name)
|
42
|
+
# => [ "project1:module1", "project1:module2" ]
|
43
|
+
# project("project1:module1").parent.name
|
44
|
+
# => "project1"
|
45
|
+
# project("project1:module1").version
|
46
|
+
# => "1.1"
|
47
|
+
#
|
48
|
+
# Each project has a base directory (see #base_dir). By default,
|
49
|
+
# a top-level project uses the current directory, and each sub-project
|
50
|
+
# uses a sub-directory relative to the parent project.
|
26
51
|
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
52
|
+
# For the above example, the directory structure is:
|
53
|
+
# .
|
54
|
+
# |__module1
|
55
|
+
# |__module2
|
31
56
|
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# sub-projects.
|
57
|
+
# The project definition tasks a block and yields by passing the project
|
58
|
+
# definition. For convenience, the block is also executed in the context
|
59
|
+
# of the project object, as if with instance_eval.
|
36
60
|
#
|
37
|
-
# The
|
38
|
-
#
|
39
|
-
#
|
61
|
+
# The following two are equivalent:
|
62
|
+
# define "project1" do |project|
|
63
|
+
# project.version = "1.1"
|
64
|
+
# self.version = "1.1"
|
65
|
+
# end
|
40
66
|
class Project
|
41
67
|
|
42
68
|
class << self
|
@@ -44,10 +70,11 @@ module Buildr
|
|
44
70
|
# See Buildr#define.
|
45
71
|
def define(*args, &block)
|
46
72
|
name, properties = name_and_properties_from_args(*args)
|
47
|
-
project(
|
73
|
+
raise "The name #{name} means sub-project #{name.split(':').last} belonging to the parent project #{name.split(':')[0..-2]}, and you can only define a sub-project inside the parent project" if name =~ /:/
|
74
|
+
project(name)._define properties, &block
|
48
75
|
end
|
49
76
|
|
50
|
-
#
|
77
|
+
# See Buildr#project.
|
51
78
|
def project(name)
|
52
79
|
@projects ||= {}
|
53
80
|
name.split(":").inject(nil) do |parent, name|
|
@@ -59,9 +86,9 @@ module Buildr
|
|
59
86
|
end
|
60
87
|
end
|
61
88
|
|
62
|
-
#
|
89
|
+
# See Buildr#projects.
|
63
90
|
def projects()
|
64
|
-
(@projects
|
91
|
+
(@projects ||= {}).map { |name, project| project }.select(&:defined?).sort_by(&:name)
|
65
92
|
end
|
66
93
|
|
67
94
|
# Discard all project definitions.
|
@@ -69,18 +96,24 @@ module Buildr
|
|
69
96
|
@projects.clear if @projects
|
70
97
|
end
|
71
98
|
|
72
|
-
# The Project class defines
|
73
|
-
# Use #
|
99
|
+
# The Project class defines minimal behavior for new projects.
|
100
|
+
# Use #on_define to add behavior when defining new projects.
|
101
|
+
# Whenever a new project is defined, it will yield to the block
|
102
|
+
# with the project object.
|
74
103
|
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
104
|
+
# For example:
|
105
|
+
# # Set the default version of each project to "1.0".
|
106
|
+
# Project.on_define do |project|
|
107
|
+
# project.version ||= "1.0"
|
108
|
+
# end
|
78
109
|
#
|
79
|
-
# Keep in mind that the order
|
80
|
-
# not determined. You cannot depend on
|
81
|
-
#
|
82
|
-
|
83
|
-
|
110
|
+
# Keep in mind that the order in which #on_define blocks are
|
111
|
+
# called is not determined. You cannot depend on a previous
|
112
|
+
# #on_define to set properties or create new tasks. You would
|
113
|
+
# want to use the #after_block method instead, by calling it
|
114
|
+
# from within #after_block.
|
115
|
+
def on_define(&block)
|
116
|
+
(@on_define ||= []) << block if block
|
84
117
|
end
|
85
118
|
|
86
119
|
# :nodoc:
|
@@ -96,23 +129,45 @@ module Buildr
|
|
96
129
|
name = properties.delete(:name)
|
97
130
|
end
|
98
131
|
raise ArgumentError, "Expected project name followed by (optional) project properties." unless args.empty?
|
99
|
-
raise ArgumentError, "Missing project name
|
132
|
+
raise ArgumentError, "Missing project name, this is the first argument to the define method" unless name
|
100
133
|
[ name, properties ]
|
101
134
|
end
|
135
|
+
|
136
|
+
# :nodoc:
|
137
|
+
def warnings()
|
138
|
+
returning([]) do |msgs|
|
139
|
+
msgs << "There are no project definitions in your Rakefile" if @projects.nil? || @projects.empty?
|
140
|
+
# Find all projects that:
|
141
|
+
# * Are referenced but never defined. This is probably a typo.
|
142
|
+
# * Do not have a base directory.
|
143
|
+
(@projects || {}).each do |name, project|
|
144
|
+
msgs << "Project #{name} is referenced but not defined; you probably have a typo somewhere" unless project.defined?
|
145
|
+
msgs << "Project #{name} refers to the directory #{project.base_dir}, which does not exist" unless File.exist?(project.base_dir)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
102
150
|
end
|
103
151
|
|
104
152
|
include Attributes
|
105
153
|
|
106
|
-
# The project name.
|
154
|
+
# The project name. If this is a sub-project, it will be prefixed
|
155
|
+
# by the parent project's name. For example, "foo" and "foo:bar".
|
107
156
|
attr_reader :name
|
108
157
|
|
109
158
|
# The parent project if this is a sub-project.
|
110
159
|
attr_reader :parent
|
111
160
|
|
112
|
-
# The base directory of this project.
|
161
|
+
# The base directory of this project. The default for a top-level project
|
162
|
+
# is the same directory that holds the Rakefile. The default for a
|
163
|
+
# sub-project is a child directory with the same name.
|
164
|
+
#
|
165
|
+
# A project definition can change the base directory using the base_dir
|
166
|
+
# hash value. Be advised that the base directory and all values that
|
167
|
+
# depend on it can only be determined after the project is defined.
|
113
168
|
attr_reader :base_dir
|
114
169
|
|
115
|
-
#
|
170
|
+
# :nodoc:
|
116
171
|
def initialize(name, parent)
|
117
172
|
fail "Missing project name" unless name
|
118
173
|
@name = parent ? "#{parent.name}:#{name}" : name
|
@@ -125,123 +180,134 @@ module Buildr
|
|
125
180
|
# For top-level project, a good default is the directory where we found the Rakefile.
|
126
181
|
@base_dir = Dir.pwd
|
127
182
|
end
|
128
|
-
@
|
183
|
+
@after_block = []
|
184
|
+
@defined = false
|
129
185
|
end
|
130
186
|
|
131
187
|
# Define a new sub-project within this project.
|
132
188
|
def define(*args, &block)
|
133
189
|
name, properties = Project.name_and_properties_from_args(*args)
|
134
|
-
|
190
|
+
project("#{self.name}:#{name}")._define properties, &block
|
135
191
|
end
|
136
192
|
|
193
|
+
# Returns true if the project was already defined.
|
137
194
|
def defined?()
|
138
195
|
@defined
|
139
196
|
end
|
140
197
|
|
141
|
-
|
142
|
-
|
198
|
+
def to_s()
|
199
|
+
name
|
200
|
+
end
|
201
|
+
|
202
|
+
# Returns a path made from multiple arguments. Relative paths are turned into
|
203
|
+
# absolute paths using this project's base directory.
|
143
204
|
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
# property.
|
205
|
+
# Symbol arguments are converted to paths by calling the attribute accessor
|
206
|
+
# on the project. For example:
|
147
207
|
#
|
148
208
|
# For example:
|
149
209
|
# path_to("foo", "bar")
|
210
|
+
# => /projects/project1/foo/bar
|
150
211
|
# path_to(:target_dir, "foo")
|
212
|
+
# => /projects/project1/target/foo
|
151
213
|
# path_to("/tmp")
|
152
|
-
#
|
153
|
-
# File.join(base_dir, "foo", "bar")
|
154
|
-
# File.join(base_dir, project.target_dir, "foo")
|
155
|
-
# "/tmp"
|
214
|
+
# => /tmp
|
156
215
|
def path_to(*args)
|
157
216
|
File.expand_path(File.join(args.map { |arg| Symbol === arg ? send(arg) : arg.to_s }), base_dir)
|
158
217
|
end
|
159
218
|
|
160
|
-
#
|
161
|
-
# or a top-level project.
|
162
|
-
#
|
163
|
-
# For example:
|
164
|
-
# bar.project("baz")
|
165
|
-
# will find the first match from:
|
166
|
-
# foo:bar:baz
|
167
|
-
# foo:baz
|
168
|
-
# baz
|
219
|
+
# Same as Buildr#project.
|
169
220
|
def project(name)
|
170
221
|
Project.project(name)
|
171
222
|
end
|
172
223
|
|
173
|
-
#
|
174
|
-
# sub-projects.
|
224
|
+
# Same as Buildr#projects.
|
175
225
|
def projects()
|
176
|
-
|
177
|
-
Project.projects.map { |project| project.starts_with?(prefix) }
|
226
|
+
Project.projects
|
178
227
|
end
|
179
228
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
def id()
|
184
|
-
name.gsub(":", "-")
|
229
|
+
def sub_projects()
|
230
|
+
prefix = name + ":"
|
231
|
+
Project.projects.select { |project| project.name.starts_with?(prefix) }.sort_by(&:name)
|
185
232
|
end
|
186
233
|
|
187
234
|
# Define a recursive task.
|
188
235
|
#
|
189
|
-
# A recursive task
|
190
|
-
#
|
191
|
-
#
|
192
|
-
# same task but only for the current project -- as determined by the
|
193
|
-
# current working directory.
|
236
|
+
# A recursive task executes the task with the same name in the project,
|
237
|
+
# and in all its sub-projects. In fact, a recursive task actually adds
|
238
|
+
# itself as a prerequisite on the parent task.
|
194
239
|
#
|
195
240
|
# For example:
|
241
|
+
# define "foo" do
|
242
|
+
# define "bar" do
|
243
|
+
# define "baz" do
|
244
|
+
# end
|
245
|
+
# end
|
246
|
+
# end
|
247
|
+
#
|
196
248
|
# rake foo:build
|
197
249
|
# Will execute foo:build, foo:bar:build and foo:baz:build
|
198
250
|
#
|
199
251
|
# Inside the bar directory:
|
200
252
|
# rake build
|
201
|
-
# Will execute foo:bar:build.
|
253
|
+
# Will execute foo:bar:build and foo:baz:build.
|
202
254
|
#
|
203
|
-
#
|
204
|
-
#
|
205
|
-
# you can define the task before calling #recursive_task, e.g. to
|
206
|
-
# create a file task, or any other special purpose task.
|
255
|
+
# This method defines a RakeTask. If you need a different type of task,
|
256
|
+
# define the task first and then call #recursive_task.
|
207
257
|
def recursive_task(arg, &block)
|
208
258
|
name = Hash === arg ? arg.keys.first : arg
|
209
259
|
returning(task(arg)) do |task|
|
210
260
|
if parent
|
211
|
-
Rake::Task["^#{
|
261
|
+
Rake::Task["^#{name}"].enhance([ task ])
|
212
262
|
end
|
213
263
|
task.enhance &block
|
214
264
|
end
|
215
265
|
end
|
216
266
|
|
217
|
-
|
218
|
-
|
267
|
+
# Use this from Project#on_define to make each project definition yield
|
268
|
+
# to this block after it's done with the project block.
|
269
|
+
#
|
270
|
+
# Project.on_define do |project|
|
271
|
+
# puts "defining"
|
272
|
+
# project.after_block { puts "defined" }
|
273
|
+
# end
|
274
|
+
# define "foo" do
|
275
|
+
# puts "block"
|
276
|
+
# end
|
277
|
+
# => defining
|
278
|
+
# block
|
279
|
+
# defined
|
280
|
+
def after_block(&block)
|
281
|
+
@after_block << block if block
|
219
282
|
end
|
220
283
|
|
221
|
-
|
222
|
-
|
284
|
+
# :nodoc:
|
223
285
|
def _define(properties, &block)
|
224
286
|
fail "Project #{name} already defined" if @defined
|
225
287
|
@defined = true
|
226
|
-
@base_dir = properties.delete(:base_dir) if properties.has_key?(:base_dir)
|
227
|
-
# How convenient: project name is used to create compound namespace for
|
288
|
+
@base_dir = File.expand_path(properties.delete(:base_dir)) if properties.has_key?(:base_dir)
|
289
|
+
# How convenient: project name is used to create compound namespace for task.
|
290
|
+
# Keep in mind that we're already in a namespace context if it's a sub-project.
|
228
291
|
namespace name.split(":").last do
|
229
|
-
#
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
292
|
+
# Everything we do inside the project is relative to its working directory.
|
293
|
+
Dir.chdir File.exist?(@base_dir) ? @base_dir : Dir.pwd do
|
294
|
+
# on_define blocks may have use for project properties.
|
295
|
+
properties.each { |name, value| send "#{name}=", value }
|
296
|
+
(self.class.instance_variable_get(:@on_define) || []).each { |callback| callback.call self }
|
297
|
+
if block
|
298
|
+
begin
|
299
|
+
# Evaluate in context of project, and pass project. And for that we need
|
300
|
+
# a method definition, on the singleton so we don't conflict with anyone else.
|
301
|
+
singleton = (class << self ; self ; end)
|
302
|
+
singleton.send :define_method, :__enhance__, &block
|
303
|
+
self.__enhance__ self
|
304
|
+
ensure
|
305
|
+
singleton.send :remove_method, :__enhance__
|
306
|
+
end
|
241
307
|
end
|
308
|
+
# And now for all the callbacks created by on_define.
|
309
|
+
@after_block.each { |callback| callback.call self }
|
242
310
|
end
|
243
|
-
@actions.each { |callback| callback.call self }
|
244
|
-
@actions.clear
|
245
311
|
end
|
246
312
|
self
|
247
313
|
end
|
@@ -256,45 +322,93 @@ module Buildr
|
|
256
322
|
# Defines a new project.
|
257
323
|
#
|
258
324
|
# The first argument is the project name. Each project must have a unique name,
|
259
|
-
#
|
260
|
-
# all top-level projects, or all sub-projects belonging to the same parent.
|
325
|
+
# and you can only define a project once.
|
261
326
|
#
|
262
327
|
# The second argument contains any number of properties that are set on the
|
263
|
-
# project
|
264
|
-
#
|
328
|
+
# project. The project must have attribute accessors to support these properties.
|
329
|
+
# You can also pass the project name in the properties hash.
|
330
|
+
#
|
331
|
+
# The easiest way to define a project and configure its tasks is by passing
|
332
|
+
# a block. The #define method executes the block within the context of the
|
333
|
+
# project, as if with instance_eval. It also passes the project to the block.
|
265
334
|
#
|
266
|
-
#
|
267
|
-
#
|
335
|
+
# For example:
|
336
|
+
# define "foo", :version=>"1.0" do
|
337
|
+
# . . .
|
338
|
+
# end
|
268
339
|
#
|
269
|
-
#
|
270
|
-
#
|
271
|
-
#
|
272
|
-
# self.group = "foo-s"
|
340
|
+
# define "bar" do |project|
|
341
|
+
# project.version = "1.0"
|
342
|
+
# . . .
|
273
343
|
# end
|
274
344
|
#
|
275
|
-
# define "
|
276
|
-
#
|
277
|
-
# project.group = "foo-s"
|
345
|
+
# define "baz" do
|
346
|
+
# self.version = "1.0"
|
278
347
|
# end
|
348
|
+
#
|
349
|
+
# Each project also has a #define method that operates the same way, but
|
350
|
+
# defines a sub-project. A sub-project has a compound name using the parent
|
351
|
+
# project's name, and also inherits some of its properties. You can only
|
352
|
+
# define a sub-project as part of the parent project's definition.
|
353
|
+
#
|
354
|
+
# For example:
|
355
|
+
# define "foo", :version=>"1.0" do
|
356
|
+
# define "bar"
|
357
|
+
# puts name
|
358
|
+
# puts version
|
359
|
+
# end
|
360
|
+
# end
|
361
|
+
# => "foo:bar"
|
362
|
+
# "1.0"
|
279
363
|
def define(*args, &block)
|
280
364
|
Project.define(*args, &block)
|
281
365
|
end
|
282
366
|
|
283
|
-
# Returns
|
367
|
+
# Returns the named project.
|
368
|
+
#
|
369
|
+
# For a sub-project, use the full name, for example "foo:bar" to find
|
370
|
+
# the sub-project "bar" of the parent project "foo".
|
371
|
+
#
|
372
|
+
# You can reference a project before its definition. Be careful, though,
|
373
|
+
# since the referenced project will not have all its properties and tasks
|
374
|
+
# properly set. However, some tasks handle this well by accepting the
|
375
|
+
# project object and accessing it only when invoked, after all projects
|
376
|
+
# are defined.
|
377
|
+
#
|
378
|
+
# For example:
|
379
|
+
# def "project1" do
|
380
|
+
# compile.with project("project2")
|
381
|
+
# end
|
382
|
+
#
|
383
|
+
# def "project2" do
|
384
|
+
# . . .
|
385
|
+
# end
|
284
386
|
def project(name)
|
285
387
|
Project.project(name)
|
286
388
|
end
|
287
389
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
end
|
390
|
+
# Returns a list of all the projects defined so far.
|
391
|
+
#
|
392
|
+
# For example:
|
393
|
+
# files = projects.map { |prj| FileList[prj.path_to("src/**/*.java") }.flatten
|
394
|
+
# puts "There are #{files.size} source files in #{projects.size} projects"
|
395
|
+
def projects()
|
396
|
+
Project.projects
|
296
397
|
end
|
297
398
|
|
399
|
+
|
400
|
+
# The local directory task executes the same task on the project
|
401
|
+
# in the local directory.
|
402
|
+
#
|
403
|
+
# For example, if the current directory project is +foo+, then
|
404
|
+
# +rake task+ executes +rake foo:task+.
|
405
|
+
#
|
406
|
+
# The current directory project is a project with the base directory
|
407
|
+
# being the same as the current directory. For example:
|
408
|
+
# cd bar
|
409
|
+
# rake build
|
410
|
+
# Will execute the +foo:bar:build+ task, after switching to the directory
|
411
|
+
# of the sub-project +bar+.
|
298
412
|
class LocalDirectoryTask < Rake::Task
|
299
413
|
|
300
414
|
def initialize(*args)
|
@@ -310,4 +424,31 @@ module Buildr
|
|
310
424
|
|
311
425
|
end
|
312
426
|
|
427
|
+
|
428
|
+
class CheckTask < Rake::Task
|
429
|
+
|
430
|
+
def execute()
|
431
|
+
@warnings = []
|
432
|
+
super
|
433
|
+
report
|
434
|
+
end
|
435
|
+
|
436
|
+
def note(*msg)
|
437
|
+
@warnings += msg
|
438
|
+
end
|
439
|
+
|
440
|
+
def report()
|
441
|
+
if @warnings.empty?
|
442
|
+
puts HighLine.new.color("No warnings", :green)
|
443
|
+
else
|
444
|
+
warn "These are possible problems with your Rakefile"
|
445
|
+
@warnings.each { |msg| warn " #{msg}" }
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
end
|
450
|
+
|
451
|
+
desc "Check your Rakefile for common errors"
|
452
|
+
CheckTask.define_task("check") { |task| task.note *Project.warnings }
|
453
|
+
|
313
454
|
end
|