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
data/lib/core/build.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
module Buildr
|
2
|
+
|
3
|
+
class ReleaseTask < Rake::Task
|
4
|
+
|
5
|
+
VERSION_NUMBER_PATTERN = /VERSION_NUMBER\s*=\s*(["'])(.*)\1/
|
6
|
+
NEXT_VERSION_PATTERN = /NEXT_VERSION\s*=\s*(["'])(.*)\1/
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
super
|
10
|
+
enhance do |task|
|
11
|
+
# Make sure we don't have anything uncommitted in SVN.
|
12
|
+
fail "Uncommitted SVN files violate the First Principle Of Release!" unless
|
13
|
+
svn("status").empty?
|
14
|
+
# Load the Rakefile and find the version numbers.
|
15
|
+
next_ver = update_version
|
16
|
+
# Run the deployment externally using the new version number.
|
17
|
+
sh "rake deploy"
|
18
|
+
update_next_version next_ver
|
19
|
+
tag_repository
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Change the Rakefile and update the current version number to the
|
24
|
+
# next version number (VERSION_NUMBER = NEXT_VERSION). We need this
|
25
|
+
# before making a release with the next version. Return the next version.
|
26
|
+
def update_version()
|
27
|
+
rakefile = File.read(Rake.application.rakefile)
|
28
|
+
version = rakefile.scan(VERSION_NUMBER_PATTERN)[0][1] or
|
29
|
+
fail "Looking for VERSION_NUMBER = \"...\" in your Rakefile, none found"
|
30
|
+
next_ver = rakefile.scan(NEXT_VERSION_PATTERN)[0][1] or
|
31
|
+
fail "Looking for NEXT_VERSION = \"...\" in your Rakefile, none found"
|
32
|
+
if verbose
|
33
|
+
puts "Current version: #{version}"
|
34
|
+
puts "Next version: #{next_ver}"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Switch version numbers.
|
38
|
+
rakefile.gsub!(VERSION_NUMBER_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{next_ver}"}) }
|
39
|
+
File.open(Rake.application.rakefile, "w") { |file| file.write rakefile }
|
40
|
+
|
41
|
+
next_ver
|
42
|
+
end
|
43
|
+
|
44
|
+
# Change the Rakefile and update the next version number to one after
|
45
|
+
# (NEXT_VERSION = NEXT_VERSION + 1). We do this to automatically increment
|
46
|
+
# future version number after each successful release.
|
47
|
+
def update_next_version(version)
|
48
|
+
# Update to new version number.
|
49
|
+
nums = version.split(".")
|
50
|
+
nums[-1] = nums[-1].to_i + 1
|
51
|
+
next_ver = nums.join(".")
|
52
|
+
rakefile = File.read(Rake.application.rakefile)
|
53
|
+
rakefile.gsub!(NEXT_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{next_ver}"}) }
|
54
|
+
File.open(Rake.application.rakefile, "w") { |file| file.write rakefile }
|
55
|
+
|
56
|
+
# Commit new version number.
|
57
|
+
svn "commit", "-m", "Changed release number to #{version}"
|
58
|
+
end
|
59
|
+
|
60
|
+
# Create a tag in the SVN repository.
|
61
|
+
def tag_repository()
|
62
|
+
# Copy to tag.
|
63
|
+
cur_url = svn("info").scan(/URL: (.*)/)[0][0]
|
64
|
+
new_url = cur_url.sub(/trunk$/, "tags/#{cur_ver}")
|
65
|
+
svn "copy", cur_url, new_url
|
66
|
+
end
|
67
|
+
|
68
|
+
def svn(*args)
|
69
|
+
#args << { :verbose=>Rake.application.options.trace }
|
70
|
+
stdin, stdout, stderr = Open3.popen3("svn", *args)
|
71
|
+
stdin.close
|
72
|
+
error = stderr.read
|
73
|
+
fail error unless error.empty?
|
74
|
+
stdout.read
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Handles the build and clean tasks.
|
79
|
+
desc "Clean all projects"
|
80
|
+
LocalDirectoryTask.define_task("clean")
|
81
|
+
desc "Build all projects"
|
82
|
+
LocalDirectoryTask.define_task("build")
|
83
|
+
desc "Make a release"
|
84
|
+
ReleaseTask.define_task "release"
|
85
|
+
|
86
|
+
class Project
|
87
|
+
def build(*args, &block)
|
88
|
+
returning(@build_task ||= recursive_task("build")) do |task|
|
89
|
+
task.enhance args, &block
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def clean(*args, &block)
|
94
|
+
returning(@clean_task ||= recursive_task("clean")) do |task|
|
95
|
+
task.enhance args, &block
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
Project.on_create do |project|
|
101
|
+
desc "Clean all files generated during the build process"
|
102
|
+
project.clean
|
103
|
+
|
104
|
+
desc "Build this project"
|
105
|
+
project.build
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
data/lib/core/core.rb
ADDED
@@ -0,0 +1,49 @@
|
|
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
|
+
require "highline"
|
11
|
+
|
12
|
+
|
13
|
+
module Kernel
|
14
|
+
def warn_with_color(message)
|
15
|
+
warn_without_color HighLine.new.color(message.to_s, :red)
|
16
|
+
end
|
17
|
+
alias_method_chain :warn, :color
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
module Buildr
|
22
|
+
module Attributes
|
23
|
+
|
24
|
+
def self.included(mod)
|
25
|
+
mod.extend(self)
|
26
|
+
end
|
27
|
+
|
28
|
+
# An inherited attribute gets it value from an instance variable
|
29
|
+
# with the same name. If the value is not set it will defer to the
|
30
|
+
# parent object. If there is no parent object, it will use the
|
31
|
+
# default value; with a block, it evaluates the block by calling
|
32
|
+
# instance_eval on the object.
|
33
|
+
#
|
34
|
+
# For example:
|
35
|
+
# inherited_attr :version
|
36
|
+
# inherited_attr :src_dir, "src"
|
37
|
+
# inherited_attr :java_src_dir do src_dir + "/main/java"
|
38
|
+
def inherited_attr(symbol, default = nil, &block)
|
39
|
+
block ||= proc { default }
|
40
|
+
define_method symbol do
|
41
|
+
instance_variable_get("@#{symbol}") || (parent ? parent.send(symbol) : self.instance_eval(&block))
|
42
|
+
end
|
43
|
+
define_method "#{symbol}=" do |value|
|
44
|
+
instance_variable_set("@#{symbol}", value)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/lib/core/project.rb
ADDED
@@ -0,0 +1,313 @@
|
|
1
|
+
module Buildr
|
2
|
+
|
3
|
+
# A project is a means to assemble multiple related tasks.
|
4
|
+
#
|
5
|
+
# A project will create its own set of internal tasks, such as
|
6
|
+
# compile, build, clean, install. These tasks are fed with project
|
7
|
+
# properties, e.g. the clean task will remove the project.target_dir
|
8
|
+
# directory, where files are created during the build process.
|
9
|
+
#
|
10
|
+
# Projects can be organized hierarchically such that sub-projects
|
11
|
+
# inherit default properties from their parent project, and
|
12
|
+
# participate in tasks executed on the parent project.
|
13
|
+
#
|
14
|
+
# For example:
|
15
|
+
# define "parent" do |project|
|
16
|
+
# project.version = "1.1"
|
17
|
+
#
|
18
|
+
# define "child1"
|
19
|
+
# define "child2"
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# This definition will work for a directory structure of:
|
23
|
+
# . -- Parent project
|
24
|
+
# |__child 1
|
25
|
+
# |__child 2
|
26
|
+
#
|
27
|
+
# The sub-projects child1 and child2 inherit the project version number
|
28
|
+
# from the parent project. In addition, for certain tasks such as build,
|
29
|
+
# running the task on the parent project will also run it on all
|
30
|
+
# sub-projects.
|
31
|
+
#
|
32
|
+
# Use the #define method to define a new project, and within the context
|
33
|
+
# of a project to define a sub-project. Use the #project method to find
|
34
|
+
# an existing project, and within the context of a project, one of its
|
35
|
+
# sub-projects.
|
36
|
+
#
|
37
|
+
# The main block in the project definition is executed during the project
|
38
|
+
# definition. Use it to set project properties, and configure tasks.
|
39
|
+
# Do not do any actual work in there.
|
40
|
+
class Project
|
41
|
+
|
42
|
+
class << self
|
43
|
+
|
44
|
+
# See Buildr#define.
|
45
|
+
def define(*args, &block)
|
46
|
+
name, properties = name_and_properties_from_args(*args)
|
47
|
+
project(name).send :_define, properties, &block
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the specified project (top-level only).
|
51
|
+
def project(name)
|
52
|
+
@projects ||= {}
|
53
|
+
name.split(":").inject(nil) do |parent, name|
|
54
|
+
if parent
|
55
|
+
@projects["#{parent.name}:#{name}"] ||= Project.new(name, parent)
|
56
|
+
else
|
57
|
+
@projects[name] ||= Project.new(name, nil)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns all project definitions, including sub-projects.
|
63
|
+
def projects()
|
64
|
+
(@projects || []).map { |name, project| project }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Discard all project definitions.
|
68
|
+
def clear()
|
69
|
+
@projects.clear if @projects
|
70
|
+
end
|
71
|
+
|
72
|
+
# The Project class defines very little behavior for new process instances.
|
73
|
+
# Use #on_create to add behavior to new process instances.
|
74
|
+
#
|
75
|
+
# Every block you register with #on_create will be called with a project
|
76
|
+
# instance whenever a new project is created. You can then define tasks,
|
77
|
+
# set project properties, etc.
|
78
|
+
#
|
79
|
+
# Keep in mind that the order on which #on_create blocks are called is
|
80
|
+
# not determined. You cannot depend on tasks defined by another block to
|
81
|
+
# exist at the time your block is called. Use Project#enhance for that.
|
82
|
+
def on_create(&block)
|
83
|
+
(@on_create ||= []) << block if block
|
84
|
+
end
|
85
|
+
|
86
|
+
# :nodoc:
|
87
|
+
def name_and_properties_from_args(*args)
|
88
|
+
if Hash === args.last
|
89
|
+
properties = args.pop.clone
|
90
|
+
else
|
91
|
+
properties = {}
|
92
|
+
end
|
93
|
+
if String === args.first
|
94
|
+
name = args.shift
|
95
|
+
else
|
96
|
+
name = properties.delete(:name)
|
97
|
+
end
|
98
|
+
raise ArgumentError, "Expected project name followed by (optional) project properties." unless args.empty?
|
99
|
+
raise ArgumentError, "Missing project name." unless name
|
100
|
+
[ name, properties ]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
include Attributes
|
105
|
+
|
106
|
+
# The project name.
|
107
|
+
attr_reader :name
|
108
|
+
|
109
|
+
# The parent project if this is a sub-project.
|
110
|
+
attr_reader :parent
|
111
|
+
|
112
|
+
# The base directory of this project.
|
113
|
+
attr_reader :base_dir
|
114
|
+
|
115
|
+
# Always construct a project using Object#project or Project#project.
|
116
|
+
def initialize(name, parent)
|
117
|
+
fail "Missing project name" unless name
|
118
|
+
@name = parent ? "#{parent.name}:#{name}" : name
|
119
|
+
@parent = parent
|
120
|
+
if parent
|
121
|
+
# For sub-project, a good default is a directory in the parent's base_dir,
|
122
|
+
# using the same name as the project.
|
123
|
+
@base_dir = File.join(parent.base_dir, name)
|
124
|
+
else
|
125
|
+
# For top-level project, a good default is the directory where we found the Rakefile.
|
126
|
+
@base_dir = Dir.pwd
|
127
|
+
end
|
128
|
+
@actions = []
|
129
|
+
end
|
130
|
+
|
131
|
+
# Define a new sub-project within this project.
|
132
|
+
def define(*args, &block)
|
133
|
+
name, properties = Project.name_and_properties_from_args(*args)
|
134
|
+
Project.define("#{self.name}:#{name}", properties, &block)
|
135
|
+
end
|
136
|
+
|
137
|
+
def defined?()
|
138
|
+
@defined
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns a path made from the specified arguments. Relative paths are turned
|
142
|
+
# into absolute paths using the based directory of this project.
|
143
|
+
#
|
144
|
+
# If you pass multiple arguments, they are combined into a path using File#join.
|
145
|
+
# If one of the arguments is a symbol, it is used to retrieve that process
|
146
|
+
# property.
|
147
|
+
#
|
148
|
+
# For example:
|
149
|
+
# path_to("foo", "bar")
|
150
|
+
# path_to(:target_dir, "foo")
|
151
|
+
# path_to("/tmp")
|
152
|
+
# are equivalent to:
|
153
|
+
# File.join(base_dir, "foo", "bar")
|
154
|
+
# File.join(base_dir, project.target_dir, "foo")
|
155
|
+
# "/tmp"
|
156
|
+
def path_to(*args)
|
157
|
+
File.expand_path(File.join(args.map { |arg| Symbol === arg ? send(arg) : arg.to_s }), base_dir)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Returns the specified sub-project of this project, or any of its descendant,
|
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
|
169
|
+
def project(name)
|
170
|
+
Project.project(name)
|
171
|
+
end
|
172
|
+
|
173
|
+
# Returns all sub-projects defined in this project, including their
|
174
|
+
# sub-projects.
|
175
|
+
def projects()
|
176
|
+
prefix = name + ":"
|
177
|
+
Project.projects.map { |project| project.starts_with?(prefix) }
|
178
|
+
end
|
179
|
+
|
180
|
+
# The project ID is the project name, and for a sub-project the
|
181
|
+
# parent project ID followed by the project name, separated with a
|
182
|
+
# hyphen. For example, "foo" and "foo-bar".
|
183
|
+
def id()
|
184
|
+
name.gsub(":", "-")
|
185
|
+
end
|
186
|
+
|
187
|
+
# Define a recursive task.
|
188
|
+
#
|
189
|
+
# A recursive task for a project will execute all sub-project tasks of
|
190
|
+
# the same name before it executes itself. In addition, if a task with
|
191
|
+
# the same name exists (not prefixed with a project), it will execute
|
192
|
+
# same task but only for the current project -- as determined by the
|
193
|
+
# current working directory.
|
194
|
+
#
|
195
|
+
# For example:
|
196
|
+
# rake foo:build
|
197
|
+
# Will execute foo:build, foo:bar:build and foo:baz:build
|
198
|
+
#
|
199
|
+
# Inside the bar directory:
|
200
|
+
# rake build
|
201
|
+
# Will execute foo:bar:build.
|
202
|
+
#
|
203
|
+
# Note, this method is used to define the task as recursive. It will
|
204
|
+
# also define the task if the task does not already exist. However,
|
205
|
+
# you can define the task before calling #recursive_task, e.g. to
|
206
|
+
# create a file task, or any other special purpose task.
|
207
|
+
def recursive_task(arg, &block)
|
208
|
+
name = Hash === arg ? arg.keys.first : arg
|
209
|
+
returning(task(arg)) do |task|
|
210
|
+
if parent
|
211
|
+
Rake::Task["^#{parent.name}:#{name}"].enhance([ task ])
|
212
|
+
end
|
213
|
+
task.enhance &block
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def enhance(&block)
|
218
|
+
@actions << block if block
|
219
|
+
end
|
220
|
+
|
221
|
+
protected
|
222
|
+
|
223
|
+
def _define(properties, &block)
|
224
|
+
fail "Project #{name} already defined" if @defined
|
225
|
+
@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 tasks.
|
228
|
+
namespace name.split(":").last do
|
229
|
+
# On_create requires so we have attribute accessors for the properties.
|
230
|
+
(self.class.instance_variable_get(:@on_create) || []).each { |callback| callback.call self }
|
231
|
+
properties.each { |name, value| send "#{name}=", value }
|
232
|
+
if block
|
233
|
+
begin
|
234
|
+
# Evaluate in context of project, and pass project. And for that we need
|
235
|
+
# a method definition, on the singleton so we don't conflict with anyone else.
|
236
|
+
singleton = (class << self ; self ; end)
|
237
|
+
singleton.send :define_method, :__enhance__, &block
|
238
|
+
self.__enhance__ self
|
239
|
+
ensure
|
240
|
+
singleton.send :remove_method, :__enhance__
|
241
|
+
end
|
242
|
+
end
|
243
|
+
@actions.each { |callback| callback.call self }
|
244
|
+
@actions.clear
|
245
|
+
end
|
246
|
+
self
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
# :call-seq:
|
252
|
+
# define name { |project| ... }
|
253
|
+
# define name, properties { |project| ... }
|
254
|
+
# define properties { |project| ... }
|
255
|
+
#
|
256
|
+
# Defines a new project.
|
257
|
+
#
|
258
|
+
# The first argument is the project name. Each project must have a unique name,
|
259
|
+
# to distinguish it from other projects. The name must be unique either across
|
260
|
+
# all top-level projects, or all sub-projects belonging to the same parent.
|
261
|
+
#
|
262
|
+
# The second argument contains any number of properties that are set on the
|
263
|
+
# project at creation, before calling the block. There is no special preference
|
264
|
+
# to properties passed as arguments.
|
265
|
+
#
|
266
|
+
# The second argument is optional. You may omit the first argument, by passing
|
267
|
+
# the project name as the property :name.
|
268
|
+
#
|
269
|
+
# If a block is given, it is executed in the context of the project, and passed
|
270
|
+
# a reference to the project. These two are equivalent:
|
271
|
+
# define "foo", :version=>"1" do
|
272
|
+
# self.group = "foo-s"
|
273
|
+
# end
|
274
|
+
#
|
275
|
+
# define "foo" do |project|
|
276
|
+
# project.version = "1"
|
277
|
+
# project.group = "foo-s"
|
278
|
+
# end
|
279
|
+
def define(*args, &block)
|
280
|
+
Project.define(*args, &block)
|
281
|
+
end
|
282
|
+
|
283
|
+
# Returns a top-level project.
|
284
|
+
def project(name)
|
285
|
+
Project.project(name)
|
286
|
+
end
|
287
|
+
|
288
|
+
task "check" do |task|
|
289
|
+
# Find all projects that:
|
290
|
+
# - Are referenced but never defined.
|
291
|
+
# - Do not have a base directory.
|
292
|
+
Project.projects.each do |project|
|
293
|
+
warn "Project #{project.name} referenced but not defined" unless project.defined?
|
294
|
+
warn "Project #{project.name} does not have a base directory" unless File.exist?(project.base_dir)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
class LocalDirectoryTask < Rake::Task
|
299
|
+
|
300
|
+
def initialize(*args)
|
301
|
+
super
|
302
|
+
enhance do |task|
|
303
|
+
projects = Project.projects.select { |project| project.base_dir == Rake.application.original_dir }
|
304
|
+
if verbose && projects.empty?
|
305
|
+
warn "No projects defined for directory #{Rake.application.original_dir}"
|
306
|
+
end
|
307
|
+
projects.each { |project| task("#{project.name}:#{task.name}").invoke }
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
|
313
|
+
end
|