buildr 0.20.0 → 0.21.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 +20 -25
- data/lib/buildr.rb +1 -1
- data/lib/core/build.rb +2 -2
- data/lib/core/common.rb +260 -0
- data/lib/core/project.rb +3 -1
- data/lib/java/artifact.rb +9 -9
- data/lib/java/compile.rb +20 -4
- data/lib/java/eclipse.rb +53 -14
- data/lib/java/packaging.rb +42 -27
- data/lib/java/test.rb +8 -10
- data/lib/tasks/zip.rb +1 -1
- metadata +4 -4
- data/lib/tasks/download.rb +0 -43
- data/lib/tasks/filter.rb +0 -159
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
0.21 (4/20/2007)
|
2
|
+
* Added: Methods to read and write a file (shortcut for File.read/File.open.write).
|
3
|
+
* Changed: Filter task now takes a source directory and target directory, and copies all included (sans excluded) files between the two.
|
4
|
+
* Changed: Artifact type is now symbol instead of string (so :jar instead of "jar"). You can still specify a string, but the return value from #to_spec or #type is a symbol.
|
5
|
+
* Changed: Eclipse task now adds "src/main/resources", "src/test/java", "src/test/resources" to build path, and excludes ".svn" and "CVS" directories from being copied into target directories.
|
6
|
+
* Changed: The test task will now run JUnit test cases from classes ending with Test or Suite. And the inclusion pattern is always set.
|
7
|
+
* Fixed: Project property not inherited if false.
|
8
|
+
|
1
9
|
0.20 (4/18/2007)
|
2
10
|
* Added: JavadocTask to generate Javadoc documentation for the project, javadoc method on the project itself to return its javadoc task, and Java.javadoc to do all the heavy lifting.
|
3
11
|
* Changed: Release code is now implemented as module instead of class. SVN copy made from working copy instead of double commit.
|
@@ -22,46 +30,33 @@
|
|
22
30
|
* Added: jetty:start and jetty:stop tasks to start/stop the server from the console.
|
23
31
|
* Added: jetty:use to start Jetty inside the build or hook to an existing server.
|
24
32
|
* Added: jetty:setup and jetty:teardown to perform tasks around jetty:use.
|
25
|
-
* Added: The local build task will now execute the local test task. So building a project (or sub-project)
|
26
|
-
will run the test cases on that project (or sub-project) but not any of its dependencies.
|
33
|
+
* Added: The local build task will now execute the local test task. So building a project (or sub-project) will run the test cases on that project (or sub-project) but not any of its dependencies.
|
27
34
|
* Added: ZipTask accepts nested path (i.e. calling path inside a path).
|
28
|
-
* Added: package(:war) by defaults picks libraries from the compiler classpath. You can always override by
|
29
|
-
|
30
|
-
* Changed:
|
31
|
-
where appropriate
|
32
|
-
* Changed: compile.target (CompileTask) and resources.target (Filter) are now file tasks, not strings.
|
33
|
-
So passing the target to someone else will hopefully convience them to invoke or enhance it.
|
35
|
+
* Added: package(:war) by defaults picks libraries from the compiler classpath. You can always override by passing the :libs option.
|
36
|
+
* Changed: Eclipse task now generates library path with M2_REPO variable or project-relative paths where appropriate
|
37
|
+
* Changed: compile.target (CompileTask) and resources.target (Filter) are now file tasks, not strings. So passing the target to someone else will hopefully convience them to invoke or enhance it.
|
34
38
|
* Changed: Java related tasks like OpenJPA, XMLBeans, JavaCC all moved to the Buildr::Java module.
|
35
39
|
* Changed: Handling of package_as arguments to support JBI packaging.
|
36
40
|
* Changed: meta_inf project property is an array accepting filenames (strings) and file tasks.
|
37
41
|
* Changed: meta_info by default only includes the LICENSE file from the top-level project.
|
38
42
|
* Changed: The WarTask :classes argument is now a directory name, and will include all files in this directory.
|
39
43
|
* Changed: WarTask and JarTask accept meta_inf argument.
|
40
|
-
* Changed: Behavior of needed? and prerequsities in base Rake::Task. This will probably not affect you,
|
41
|
-
|
42
|
-
* Changed: Were previous the test task would link to test.run, it now executes the entire test lifecycle,
|
43
|
-
and is the major point for extending the test lifecycle.
|
44
|
+
* Changed: Behavior of needed? and prerequsities in base Rake::Task. This will probably not affect you, but don't be surprised if it disappears (see lib/core/rake_ext.rb for details).
|
45
|
+
* Changed: Were previous the test task would link to test.run, it now executes the entire test lifecycle, and is the major point for extending the test lifecycle.
|
44
46
|
* Changed: test.run is now test.junit.
|
45
47
|
* Changed: Ant.define is now Ant.declarative, Ant.execute is now Ant.executable.
|
46
|
-
* Changed: The filter method now returns a Filter class that can be used to set a filter, but is not itself
|
47
|
-
|
48
|
-
* Changed:
|
49
|
-
using the accessor filter.
|
50
|
-
* Changed: UnzipTask eliminated and replaced with Unzip which you now have to run directly by calling extract.
|
51
|
-
However, unzip method creates a file task and returns an Unzip object that can be used as a reference to
|
52
|
-
that file task.
|
48
|
+
* Changed: The filter method now returns a Filter class that can be used to set a filter, but is not itself a task. Instead, it creates a task when setting its target.
|
49
|
+
* Changed: Project.resources now returns a ResourceTask that includes, but is not itself a filter, accessed using the accessor filter.
|
50
|
+
* Changed: UnzipTask eliminated and replaced with Unzip which you now have to run directly by calling extract. However, unzip method creates a file task and returns an Unzip object that can be used as a reference to that file task.
|
53
51
|
* Changed: Attributes is now InheritedAttributes.
|
54
|
-
* Changed: The first call to package configures the package task from the options, the second call only returns
|
55
|
-
the package task.
|
52
|
+
* Changed: The first call to package configures the package task from the options, the second call only returns the package task.
|
56
53
|
* Removed: :cp argument, always use :classpath.
|
57
54
|
* Removed: src_dir, java_src_dir, target_dir, webapp_src_dir and all other premature configuration attributes.
|
58
|
-
* Removed: Project tests method deprecated in favor of a single test method; it now accepts an enhancement
|
59
|
-
block, not an instance_eval block.
|
55
|
+
* Removed: Project tests method deprecated in favor of a single test method; it now accepts an enhancement block, not an instance_eval block.
|
60
56
|
* Removed: FilterTask is dead.
|
61
57
|
* Removed: sub_projects method. Is anyone using this?
|
62
58
|
* Fixed: Local buildr.rb not loaded from running from inside a sub-project directory.
|
63
|
-
* Fixed: Eclipse task now executed whenever a change is made in the Rakefile, or any file it requires,
|
64
|
-
include buildr.rb and task files.
|
59
|
+
* Fixed: Eclipse task now executed whenever a change is made in the Rakefile, or any file it requires, include buildr.rb and task files.
|
65
60
|
* Fixed: Circular dependency in release task.
|
66
61
|
|
67
62
|
0.18 (3/26/2007)
|
data/lib/buildr.rb
CHANGED
data/lib/core/build.rb
CHANGED
@@ -77,7 +77,7 @@ module Buildr
|
|
77
77
|
fail "Uncommitted SVN files violate the First Principle Of Release!\n#{status}" unless
|
78
78
|
status.empty?
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
# :call-seq:
|
82
82
|
# with_next_version() { |filename| ... } => version
|
83
83
|
#
|
@@ -154,7 +154,7 @@ module Buildr
|
|
154
154
|
# Last, we commit what we currently have in the working copy.
|
155
155
|
def commit(version)
|
156
156
|
rakefile = File.read(Rake.application.rakefile).
|
157
|
-
gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{version}"}) }
|
157
|
+
gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{version}"}) }
|
158
158
|
File.open(Rake.application.rakefile, "w") { |file| file.write rakefile }
|
159
159
|
svn "commit", "-m", "Changed version number to #{version}", Rake.application.rakefile
|
160
160
|
end
|
data/lib/core/common.rb
ADDED
@@ -0,0 +1,260 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
require "pathname"
|
3
|
+
require "core/transports"
|
4
|
+
|
5
|
+
module Buildr
|
6
|
+
|
7
|
+
# :call-seq:
|
8
|
+
# write(name, content)
|
9
|
+
# write(name) { ... }
|
10
|
+
#
|
11
|
+
# Write the contents into a file. The second form calls the block and writes the result.
|
12
|
+
#
|
13
|
+
# For example:
|
14
|
+
# write "TIMESTAMP", Time.now
|
15
|
+
# write("TIMESTAMP") { Time.now }
|
16
|
+
#
|
17
|
+
# Yields to the block before writing the file, so you can chain read and write together.
|
18
|
+
# For example:
|
19
|
+
# write("README") { read("README").sub("${build}", Time.now) }
|
20
|
+
def write(name, content = nil)
|
21
|
+
mkpath File.dirname(name)
|
22
|
+
content = yield if block_given?
|
23
|
+
File.open(name.to_s, "w") { |file| file.write content.to_s }
|
24
|
+
content.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
# :call-seq:
|
28
|
+
# read(name) => string
|
29
|
+
# read(name) { |string| ... } => result
|
30
|
+
#
|
31
|
+
# Reads and returns the contents of a file. The second form yields to the block and returns
|
32
|
+
# the result of the block.
|
33
|
+
#
|
34
|
+
# For example:
|
35
|
+
# puts read("README")
|
36
|
+
# read("README") { |text| puts text }
|
37
|
+
def read(name)
|
38
|
+
if block_given?
|
39
|
+
yield File.read(name.to_s)
|
40
|
+
else
|
41
|
+
File.read(name.to_s)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# :call-seq:
|
46
|
+
# download(url_or_uri) => task
|
47
|
+
# download(path=>url_or_uri) =>task
|
48
|
+
#
|
49
|
+
# Create a task that will download a file from a URL.
|
50
|
+
#
|
51
|
+
# Takes a single argument, a hash with one pair. The key is the file being
|
52
|
+
# created, the value if the URL to download. The task executes only if the
|
53
|
+
# file does not exist; the URL is not checked for updates.
|
54
|
+
#
|
55
|
+
# The task will show download progress on the console; if there are MD5/SHA1
|
56
|
+
# checksums on the server it will verify the download before saving it.
|
57
|
+
#
|
58
|
+
# For example:
|
59
|
+
# download "image.jpg"=>"http://example.com/theme/image.jpg"
|
60
|
+
def download(args)
|
61
|
+
if String === args || URI === args
|
62
|
+
# Given only a download URL, download into a temporary file.
|
63
|
+
# You can infer the file from task name.
|
64
|
+
temp = Tempfile.new(File.basename(args.to_s))
|
65
|
+
task = file_create(temp.path) do |task|
|
66
|
+
Transports.download task.source, task.name
|
67
|
+
end
|
68
|
+
task.sources << args
|
69
|
+
else
|
70
|
+
# Download to a file created by the task.
|
71
|
+
fail unless args.keys.size == 1
|
72
|
+
url = args.values.first
|
73
|
+
task = file_create(args.keys.first) do |task|
|
74
|
+
mkpath File.dirname(task.name), :verbose=>false
|
75
|
+
Transports.download task.source, task.name
|
76
|
+
end
|
77
|
+
task.sources << url
|
78
|
+
end
|
79
|
+
task
|
80
|
+
end
|
81
|
+
|
82
|
+
# A filter knows how to copy files from one directory to another, applying mappings to the
|
83
|
+
# contents of these files.
|
84
|
+
#
|
85
|
+
# You can specify the mapping using a Hash, and it will map ${key} fields found in each source
|
86
|
+
# file into the appropriate value in the target file. For example:
|
87
|
+
# filter.using "version"=>"1.2", "build"=>Time.now
|
88
|
+
# will replace all occurrences of <tt>${version}</tt> with <tt>1.2</tt>, and <tt>${build}</tt>
|
89
|
+
# with the current date/time.
|
90
|
+
#
|
91
|
+
# You can also specify the mapping by passing a proc or a method, that will be called for
|
92
|
+
# each source file, with the file name and content, returning the modified content.
|
93
|
+
#
|
94
|
+
# Without any mapping, the filter simply copies files from the source directory into the target
|
95
|
+
# directory.
|
96
|
+
#
|
97
|
+
# See Buildr#filter.
|
98
|
+
class Filter
|
99
|
+
|
100
|
+
def initialize() #:nodoc:
|
101
|
+
@include = []
|
102
|
+
@exclude = []
|
103
|
+
end
|
104
|
+
|
105
|
+
# The source directory as a file task.
|
106
|
+
attr_accessor :source
|
107
|
+
|
108
|
+
# :call-seq:
|
109
|
+
# from(dir) => self
|
110
|
+
#
|
111
|
+
# Sets the source directory from which files are copied and returns self.
|
112
|
+
#
|
113
|
+
# For example:
|
114
|
+
# filter.from("src").into("target").using("build"=>Time.now)
|
115
|
+
def from(dir)
|
116
|
+
@source = file(File.expand_path(dir.to_s))
|
117
|
+
self
|
118
|
+
end
|
119
|
+
|
120
|
+
# The target directory as a file task.
|
121
|
+
attr_reader :target
|
122
|
+
|
123
|
+
# :call-seq:
|
124
|
+
# into(dir) => self
|
125
|
+
#
|
126
|
+
# Sets the target directory into which files are copied and returns self.
|
127
|
+
#
|
128
|
+
# For example:
|
129
|
+
# filter.from("src").into("target").using("build"=>Time.now)
|
130
|
+
def into(dir)
|
131
|
+
@target = file(File.expand_path(dir.to_s))
|
132
|
+
self
|
133
|
+
end
|
134
|
+
|
135
|
+
# :call-seq:
|
136
|
+
# include(*files) => self
|
137
|
+
#
|
138
|
+
# Specifies files to include and returns self. See FileList#include.
|
139
|
+
#
|
140
|
+
# By default all files are included. You can use this method to only include specific
|
141
|
+
# files form the source directory.
|
142
|
+
def include(*files)
|
143
|
+
@include += files
|
144
|
+
self
|
145
|
+
end
|
146
|
+
alias :add :include
|
147
|
+
|
148
|
+
# :call-seq:
|
149
|
+
# exclude(*files) => self
|
150
|
+
#
|
151
|
+
# Specifies files to exclude and returns self. See FileList#exclude.
|
152
|
+
def exclude(*files)
|
153
|
+
@exclude += files
|
154
|
+
self
|
155
|
+
end
|
156
|
+
|
157
|
+
# The mapping. See #using.
|
158
|
+
attr_accessor :mapping
|
159
|
+
|
160
|
+
# :call-seq:
|
161
|
+
# using(mapping) => self
|
162
|
+
# using() { |file_name, contents| ... } => self
|
163
|
+
#
|
164
|
+
# Specifies the mapping to use and returns self.
|
165
|
+
#
|
166
|
+
# The mapping can be a proc or a method called with the file name and content, returning
|
167
|
+
# the modified content. Or the mapping can be a Hash for mapping each ${key} into a value.
|
168
|
+
# Without any mapping, all files are copied as is.
|
169
|
+
#
|
170
|
+
# For example:
|
171
|
+
# filter.using "version"=>"1.2"
|
172
|
+
# will replace all occurrences of "${version}" with "1.2".
|
173
|
+
def using(mapping, &block)
|
174
|
+
self.mapping = mapping || block
|
175
|
+
self
|
176
|
+
end
|
177
|
+
|
178
|
+
# Runs the filter.
|
179
|
+
def run()
|
180
|
+
if needed?
|
181
|
+
unless copy_map.empty?
|
182
|
+
verbose(Rake.application.options.trace || false) do
|
183
|
+
mkpath target.to_s
|
184
|
+
copy_map do |dest, src|
|
185
|
+
mkpath File.dirname(dest) rescue nil
|
186
|
+
case mapping
|
187
|
+
when Proc, Method # Call on input, accept output.
|
188
|
+
mapped = mapping.call(src, File.open(src, "rb") { |file| file.read })
|
189
|
+
File.open(dest, "wb") { |file| file.write mapped }
|
190
|
+
when Hash # Map ${key} to value
|
191
|
+
mapped = File.open(src, "rb") { |file| file.read }.
|
192
|
+
gsub(/\$\{.*\}/) { |str| mapping[str[2..-2]] || str }
|
193
|
+
File.open(dest, "wb") { |file| file.write mapped }
|
194
|
+
when nil # No mapping.
|
195
|
+
cp src, dest
|
196
|
+
else
|
197
|
+
fail "Filter can be a hash (key=>value), or a proc/method; I don't understand #{mapping}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
touch target.to_s
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# Returns the target directory.
|
207
|
+
def to_s()
|
208
|
+
@target.to_s
|
209
|
+
end
|
210
|
+
|
211
|
+
private
|
212
|
+
|
213
|
+
def needed?()
|
214
|
+
return false if target.nil? || source.nil? || !File.exist?(source.to_s)
|
215
|
+
return true unless File.exist?(target.to_s)
|
216
|
+
!copy_map.empty?
|
217
|
+
end
|
218
|
+
|
219
|
+
# Return a copy map of all the files that need copying: the key is the file to copy to,
|
220
|
+
# the value is the source file. If called with a block, yields with each dest/source pair.
|
221
|
+
def copy_map(&block)
|
222
|
+
unless @copy_map
|
223
|
+
@include = ["*"] if @include.empty?
|
224
|
+
base = Pathname.new(source.to_s)
|
225
|
+
@copy_map = Dir[File.join(source.to_s, "**/*")].reject { |file| File.directory?(file) }.
|
226
|
+
map { |src| Pathname.new(src).relative_path_from(base).to_s }.
|
227
|
+
select { |file| @include.any? { |pattern| File.fnmatch(pattern, file) } }.
|
228
|
+
reject { |file| @exclude.any? { |pattern| File.fnmatch(pattern, file) } }.
|
229
|
+
map { |file| [File.expand_path(file, target.to_s), File.expand_path(file, source.to_s)] }.
|
230
|
+
select { |dest, src| !File.exist?(dest) || File.stat(src).mtime > File.stat(dest).mtime }
|
231
|
+
end
|
232
|
+
if block_given?
|
233
|
+
@copy_map.each(&block)
|
234
|
+
else
|
235
|
+
@copy_map
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
# :call-seq:
|
242
|
+
# filter(target=>source) => Filter
|
243
|
+
#
|
244
|
+
# Creates a filter that will copy files from the source directory into the target directory.
|
245
|
+
# You can extend the filter to modify files by mapping <tt>${key}</tt> into values in each
|
246
|
+
# of the copied files, and by including or excluding specific files.
|
247
|
+
#
|
248
|
+
# A filter is not a task, you must call the Filter#run method to execute it.
|
249
|
+
#
|
250
|
+
# For example, to copy all files from one directory to another:
|
251
|
+
# filter("target/classes"=>"src/files")
|
252
|
+
# To include only the text files, and replace each instance of <tt>${build}</tt> with the current
|
253
|
+
# date/time:
|
254
|
+
# filter("target/classes"=>"src/files").include("*.txt").using("build"=>Time.now)
|
255
|
+
def filter(args)
|
256
|
+
target, source = Rake.application.resolve_args(args)
|
257
|
+
Filter.new.into(target).tap { |filter| filter.from(source) if source }
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
data/lib/core/project.rb
CHANGED
@@ -31,7 +31,8 @@ module Buildr
|
|
31
31
|
block ||= proc { default }
|
32
32
|
attr_accessor symbol
|
33
33
|
define_method "#{symbol}_with_inheritence" do
|
34
|
-
|
34
|
+
value = send("#{symbol}_without_inheritence")
|
35
|
+
if value.nil?
|
35
36
|
value = parent ? parent.send(symbol) : self.instance_eval(&block)
|
36
37
|
send "#{symbol}=", value
|
37
38
|
end
|
@@ -454,6 +455,7 @@ module Buildr
|
|
454
455
|
end
|
455
456
|
|
456
457
|
def execute() #:nodoc:
|
458
|
+
# Reset the namespace, so all tasks are automatically defined in the project's namespace.
|
457
459
|
Rake.application.in_namespace ":#{name}" do
|
458
460
|
# Everything we do inside the project is relative to its working directory.
|
459
461
|
Dir.chdir(base_dir) { super }
|
data/lib/java/artifact.rb
CHANGED
@@ -29,7 +29,7 @@ module Buildr
|
|
29
29
|
attr_reader :id
|
30
30
|
# The group identifier.
|
31
31
|
attr_reader :group
|
32
|
-
# The file type.
|
32
|
+
# The file type. (Symbol)
|
33
33
|
attr_reader :type
|
34
34
|
# The version number.
|
35
35
|
attr_reader :version
|
@@ -44,7 +44,7 @@ module Buildr
|
|
44
44
|
# becomes:
|
45
45
|
# { :group=>"com.example",
|
46
46
|
# :id=>"app",
|
47
|
-
# :type
|
47
|
+
# :type=>:jar,
|
48
48
|
# :version=>"1.2" }
|
49
49
|
def to_spec_hash()
|
50
50
|
base = { :group=>group, :id=>id, :type=>type, :version=>version }
|
@@ -68,8 +68,8 @@ module Buildr
|
|
68
68
|
#
|
69
69
|
# Convenience method that returns a POM artifact.
|
70
70
|
def pom()
|
71
|
-
return self if type
|
72
|
-
artifact(:group=>group, :id=>id, :version=>version, :type
|
71
|
+
return self if type == :pom
|
72
|
+
artifact(:group=>group, :id=>id, :version=>version, :type=>:pom, :classifier=>classifier)
|
73
73
|
end
|
74
74
|
|
75
75
|
protected
|
@@ -94,8 +94,8 @@ module Buildr
|
|
94
94
|
# a site that doesn't have a remote repository structure, copy it from a different disk, etc.
|
95
95
|
class Artifact < Rake::FileCreationTask
|
96
96
|
|
97
|
-
# The default
|
98
|
-
|
97
|
+
# The default artifact type.
|
98
|
+
DEFAULT_TYPE = :jar
|
99
99
|
|
100
100
|
include ActsAsArtifact
|
101
101
|
|
@@ -142,7 +142,7 @@ module Buildr
|
|
142
142
|
fail "Missing group identifier for #{spec.inspect}" if spec[:group].blank?
|
143
143
|
fail "Missing artifact identifier for #{spec.inspect}" if spec[:id].blank?
|
144
144
|
fail "Missing version for #{spec.inspect}" if spec[:version].blank?
|
145
|
-
spec[:type] =
|
145
|
+
spec[:type] = spec[:type].blank? ? DEFAULT_TYPE : spec[:type].to_sym
|
146
146
|
spec
|
147
147
|
elsif String === spec
|
148
148
|
group, id, type, version, *rest = spec.split(":")
|
@@ -166,7 +166,7 @@ module Buildr
|
|
166
166
|
hash = to_hash(hash) unless Hash === hash
|
167
167
|
version = ":#{hash[:version]}" unless hash[:version].blank?
|
168
168
|
classifier = ":#{hash[:classifier]}" unless hash[:classifier].blank?
|
169
|
-
"#{hash[:group]}:#{hash[:id]}:#{hash[:type] ||
|
169
|
+
"#{hash[:group]}:#{hash[:id]}:#{hash[:type] || DEFAULT_TYPE}#{classifier}#{version}"
|
170
170
|
end
|
171
171
|
|
172
172
|
# :call-seq:
|
@@ -176,7 +176,7 @@ module Buildr
|
|
176
176
|
def hash_to_file_name(hash)
|
177
177
|
version = "-#{hash[:version]}" unless hash[:version].blank?
|
178
178
|
classifier = "-#{hash[:classifier]}" unless hash[:classifier].blank?
|
179
|
-
"#{hash[:id]}#{version}#{classifier}.#{hash[:type] ||
|
179
|
+
"#{hash[:id]}#{version}#{classifier}.#{hash[:type] || DEFAULT_TYPE}"
|
180
180
|
end
|
181
181
|
|
182
182
|
end
|
data/lib/java/compile.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require "core/project"
|
2
2
|
require "core/build"
|
3
|
+
require "core/common"
|
3
4
|
require "java/artifact"
|
4
5
|
require "java/java"
|
5
|
-
require "tasks/filter"
|
6
6
|
|
7
7
|
module Buildr
|
8
8
|
module Java
|
@@ -253,7 +253,7 @@ module Buildr
|
|
253
253
|
|
254
254
|
def initialize(*args) #:nodoc:
|
255
255
|
super
|
256
|
-
@filter = Buildr::
|
256
|
+
@filter = Buildr::Filter.new
|
257
257
|
enhance { filter.run }
|
258
258
|
end
|
259
259
|
|
@@ -275,8 +275,24 @@ module Buildr
|
|
275
275
|
self
|
276
276
|
end
|
277
277
|
|
278
|
+
# :call-seq:
|
279
|
+
# source() => task
|
280
|
+
#
|
281
|
+
# Returns the filter's source directory as a file task.
|
282
|
+
def source()
|
283
|
+
filter.source
|
284
|
+
end
|
285
|
+
|
286
|
+
# :call-seq:
|
287
|
+
# target() => task
|
288
|
+
#
|
289
|
+
# Returns the filter's target directory as a file task.
|
290
|
+
def target()
|
291
|
+
filter.target
|
292
|
+
end
|
293
|
+
|
278
294
|
def prerequisites() #:nodoc:
|
279
|
-
super + filter.
|
295
|
+
super + [filter.source].compact
|
280
296
|
end
|
281
297
|
|
282
298
|
end
|
@@ -520,7 +536,7 @@ module Buildr
|
|
520
536
|
prepare = task("prepare")
|
521
537
|
# Resources task is a filter.
|
522
538
|
resources = Java::ResourcesTask.define_task("resources")
|
523
|
-
project.path_to("src/main/resources")
|
539
|
+
resources.filter.from project.path_to("src/main/resources")
|
524
540
|
# Compile task requires prepare and performs resources, if anything compiled.
|
525
541
|
compile = Java::CompileTask.define_task("compile"=>[prepare, resources]) { |task| project.resources.invoke }
|
526
542
|
project.path_to("src/main/java").tap { |dir| compile.from dir if File.exist?(dir) }
|
data/lib/java/eclipse.rb
CHANGED
@@ -37,32 +37,71 @@ module Buildr
|
|
37
37
|
path = path.__send__(msg)
|
38
38
|
Pathname.new(path).relative_path_from(Pathname.new(project.path_to)).to_s
|
39
39
|
end
|
40
|
+
|
40
41
|
m2repo = Buildr::Repositories.instance.local
|
42
|
+
excludes = [ '**/.svn/', '**/CVS/' ].join('|')
|
41
43
|
|
42
44
|
File.open(task.name, "w") do |file|
|
43
45
|
xml = Builder::XmlMarkup.new(:target=>file, :indent=>2)
|
44
46
|
xml.classpath do
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
# Note: Use the test classpath since Eclipse compiles both "main" and "test" classes using the same classpath
|
48
|
+
cp = project.test.compile.classpath.map(&:to_s) - [ project.compile.target.to_s ]
|
49
|
+
|
50
|
+
# Convert classpath elements into applicable Project objects
|
51
|
+
cp.collect! { |path| projects.detect { |prj| prj.packages.detect { |pkg| pkg.to_s == path } } || path }
|
52
|
+
|
53
|
+
# project_libs: artifacts created by other projects
|
54
|
+
project_libs, others = cp.partition { |path| path.is_a?(Project) }
|
55
|
+
|
56
|
+
# Separate artifacts from Maven2 repository
|
57
|
+
m2_libs, others = others.partition { |path| path.to_s.index(m2repo) == 0 }
|
58
|
+
|
59
|
+
# Generated: classpath elements in the project are assumed to be generated
|
60
|
+
generated, libs = others.partition { |path| path.to_s.index(project.path_to.to_s) == 0 }
|
61
|
+
|
52
62
|
xml.classpathentry :kind=>'con', :path=>'org.eclipse.jdt.launching.JRE_CONTAINER'
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
:
|
63
|
+
|
64
|
+
srcs = project.compile.sources.map { |src| relative[src] } + generated.map { |src| relative[src] }
|
65
|
+
srcs.sort.uniq.each do |path|
|
66
|
+
xml.classpathentry :kind=>'src', :path=>path, :excluding=>excludes
|
67
|
+
end
|
68
|
+
|
69
|
+
{ :output => relative[project.compile.target],
|
57
70
|
:lib => libs.map(&:to_s),
|
58
|
-
:var =>
|
71
|
+
:var => m2_libs.map { |path| path.to_s.sub(m2repo, 'M2_REPO') }
|
59
72
|
}.each do |kind, paths|
|
60
73
|
paths.sort.uniq.each do |path|
|
61
74
|
xml.classpathentry :kind=>kind, :path=>path
|
62
75
|
end
|
63
76
|
end
|
64
|
-
|
65
|
-
|
77
|
+
|
78
|
+
# Classpath elements from other projects
|
79
|
+
project_libs.map(&:name).sort.uniq.each do |prj_name|
|
80
|
+
xml.classpathentry :kind=>'src', :combineaccessrules=>"false", :path=>"/#{prj_name}"
|
81
|
+
end
|
82
|
+
|
83
|
+
# Main resources implicitly copied into project.compile.target
|
84
|
+
# TODO: find solution that uses project.test.resources.filter.sources
|
85
|
+
[ "src/main/resources" ].each do |path|
|
86
|
+
if File.exist? project.path_to(path)
|
87
|
+
xml.classpathentry :kind=>'src', :path=>path, :excluding=>excludes
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Test classes are generated in a separate output directory
|
92
|
+
test_sources = project.test.compile.sources.map { |src| relative[src] }
|
93
|
+
test_sources.each do |paths|
|
94
|
+
paths.sort.uniq.each do |path|
|
95
|
+
xml.classpathentry :kind=>'src', :path=>path, :output => relative[project.test.compile.target], :excluding=>excludes
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Test resources go in separate output directory as well
|
100
|
+
# TODO: find solution that uses project.test.resources.filter.sources
|
101
|
+
[ "src/test/resources" ].each do |path|
|
102
|
+
if File.exist? project.path_to(path)
|
103
|
+
xml.classpathentry :kind=>'src', :path=>path, :output => relative[project.test.compile.target], :excluding=>excludes
|
104
|
+
end
|
66
105
|
end
|
67
106
|
end
|
68
107
|
end
|
data/lib/java/packaging.rb
CHANGED
@@ -23,6 +23,7 @@ module Buildr
|
|
23
23
|
# * A hash of manifest properties (name/value pairs).
|
24
24
|
# * An array of hashes, one for each section of the manifest.
|
25
25
|
# * A string providing the name of an existing manifest file.
|
26
|
+
# * A file task can be used the same way.
|
26
27
|
# * Proc or method called to return the contents of the manifest file.
|
27
28
|
# * False to not generate a manifest file.
|
28
29
|
#
|
@@ -50,7 +51,7 @@ module Buildr
|
|
50
51
|
if key.to_sym == :manifest
|
51
52
|
self.manifest = value
|
52
53
|
elsif key.to_sym == :meta_inf
|
53
|
-
self.meta_inf = value
|
54
|
+
self.meta_inf = [value].flatten
|
54
55
|
else
|
55
56
|
super key, value
|
56
57
|
end
|
@@ -59,32 +60,30 @@ module Buildr
|
|
59
60
|
|
60
61
|
def prerequisites() #:nodoc:
|
61
62
|
super + [ String === manifest ? file(manifest) : nil ].compact +
|
62
|
-
meta_inf.map { |file| String === file ? file(file) : file }
|
63
|
+
[meta_inf].flatten.map { |file| String === file ? file(file) : file }
|
63
64
|
end
|
64
65
|
|
65
66
|
protected
|
66
67
|
|
67
68
|
def create(zip) #:nodoc:
|
68
|
-
meta_inf.map(&:to_s).uniq.each { |file| zip.add "META-INF/#{File.basename(file)}", file }
|
69
|
+
[meta_inf].flatten.map(&:to_s).uniq.each { |file| zip.add "META-INF/#{File.basename(file)}", file }
|
69
70
|
unless manifest == false
|
70
71
|
zip.file.open("META-INF/MANIFEST.MF", "w") do |output|
|
71
|
-
output
|
72
|
+
output << MANIFEST_HEADER
|
72
73
|
if manifest
|
73
74
|
case manifest
|
74
75
|
when Hash
|
75
|
-
output
|
76
|
+
output << manifest.map { |pair| pair.map(&:to_s).join(": ") }.sort.join("\n")
|
76
77
|
when Array
|
77
|
-
manifest.
|
78
|
-
|
79
|
-
|
80
|
-
end
|
78
|
+
output << manifest.reject { |section| section.empty? }.map { |section|
|
79
|
+
section.map { |pair| pair.join(": ") }.sort.join("\n").concat("\n")
|
80
|
+
}.join("\n")
|
81
81
|
when Proc, Method
|
82
|
-
output
|
83
|
-
when String
|
84
|
-
output
|
82
|
+
output << manifest.call
|
83
|
+
when String, Task
|
84
|
+
output << File.read(manifest.to_s)
|
85
85
|
end
|
86
86
|
end
|
87
|
-
output.write "\n"
|
88
87
|
end
|
89
88
|
end
|
90
89
|
super zip
|
@@ -124,21 +123,35 @@ module Buildr
|
|
124
123
|
|
125
124
|
class Project
|
126
125
|
|
126
|
+
# Options accepted by #package method for all package types.
|
127
|
+
PACKAGE_OPTIONS = [:group, :id, :version, :type, :classifier]
|
128
|
+
|
129
|
+
# The project's identifier. Same as the project name, with colons replaced by dashes.
|
130
|
+
# The ID for project foo:bar is foo-bar.
|
131
|
+
attr_reader :id
|
132
|
+
def id()
|
133
|
+
name.gsub(":", "-")
|
134
|
+
end
|
135
|
+
|
127
136
|
# Group used for packaging. Inherited from parent project. Defaults to the top-level project name.
|
128
137
|
attr_accessor :group
|
129
138
|
inherited_attr(:group) { |project| project.name }
|
139
|
+
|
130
140
|
# Version used for packaging. Inherited from parent project.
|
131
141
|
attr_accessor :version
|
132
142
|
inherited_attr :version
|
133
|
-
|
134
|
-
#
|
135
|
-
#
|
143
|
+
|
144
|
+
# Manifest used for packaging. Inherited from parent project. The default value is a hash that includes
|
145
|
+
# the Build-By, Build-Jdk, Implementation-Title and Implementation-Version values.
|
146
|
+
# The later are taken from the project's comment (or name) and version number.
|
136
147
|
attr_accessor :manifest
|
137
148
|
inherited_attr :manifest do |project|
|
138
149
|
manifest = { "Build-By"=>ENV['USER'], "Build-Jdk"=>Java.version }
|
150
|
+
manifest["Implementation-Title"] = self.comment || self.name
|
139
151
|
manifest["Implementation-Version"] = project.version if project.version
|
140
152
|
manifest
|
141
153
|
end
|
154
|
+
|
142
155
|
# Files to always include in the package META-INF directory. The default value include
|
143
156
|
# the LICENSE file if one exists in the project's base directory.
|
144
157
|
attr_accessor :meta_inf
|
@@ -147,13 +160,6 @@ module Buildr
|
|
147
160
|
File.exist?(license.to_s) ? [license] : []
|
148
161
|
end
|
149
162
|
|
150
|
-
# The project's identifier. Same as the project name, with colons replaced by dashes.
|
151
|
-
# The ID for project foo:bar is foo-bar.
|
152
|
-
attr_reader :id
|
153
|
-
def id()
|
154
|
-
name.gsub(":", "-")
|
155
|
-
end
|
156
|
-
|
157
163
|
# :call-seq:
|
158
164
|
# package(type, options?) => task
|
159
165
|
#
|
@@ -221,7 +227,7 @@ module Buildr
|
|
221
227
|
# that accepts two arguments, the file name and a hash of options. The method must yield to the
|
222
228
|
# block with the package only when first called to define the package, and must return the package
|
223
229
|
# from each call.
|
224
|
-
def package(type, options = nil)
|
230
|
+
def package(type = :jar, options = nil)
|
225
231
|
options = options.nil? ? {} : options.dup
|
226
232
|
options[:id] ||= self.id
|
227
233
|
options[:group] ||= self.group
|
@@ -230,7 +236,7 @@ module Buildr
|
|
230
236
|
file_name = path_to("target", Artifact.hash_to_file_name(options))
|
231
237
|
|
232
238
|
packager = method("package_as_#{type}") rescue
|
233
|
-
fail("
|
239
|
+
fail("Don't know how to create a package of type #{type}")
|
234
240
|
packager.call(file_name, options) do |package|
|
235
241
|
# Make it an artifact using the specifications, and tell it how to create a POM.
|
236
242
|
package.extend ActsAsArtifact
|
@@ -299,8 +305,9 @@ module Buildr
|
|
299
305
|
|
300
306
|
def package_as_jar(file_name, options) #:nodoc:
|
301
307
|
unless Rake::Task.task_defined?(file_name)
|
308
|
+
fu_check_options options, *PACKAGE_OPTIONS + [:manifest, :meta_inf, :include]
|
302
309
|
Java::Packaging::JarTask.define_task(file_name).tap do |jar|
|
303
|
-
jar.manifest = options[:manifest]
|
310
|
+
jar.manifest = options.has_key?(:manifest) ? options[:manifest] : manifest
|
304
311
|
jar.meta_inf = options[:meta_inf] || meta_inf
|
305
312
|
if options[:include]
|
306
313
|
jar.include options[:include]
|
@@ -310,14 +317,17 @@ module Buildr
|
|
310
317
|
end
|
311
318
|
yield jar
|
312
319
|
end
|
320
|
+
else
|
321
|
+
fu_check_options options, *PACKAGE_OPTIONS
|
313
322
|
end
|
314
323
|
file(file_name)
|
315
324
|
end
|
316
325
|
|
317
326
|
def package_as_war(file_name, options) #:nodoc:
|
318
327
|
unless Rake::Task.task_defined?(file_name)
|
328
|
+
fu_check_options options, *PACKAGE_OPTIONS + [:manifest, :meta_inf, :classes, :libs, :include]
|
319
329
|
Java::Packaging::WarTask.define_task(file_name).tap do |war|
|
320
|
-
war.manifest = options[:manifest]
|
330
|
+
war.manifest = options.has_key?(:manifest) ? options[:manifest] : manifest
|
321
331
|
war.meta_inf = options[:meta_inf] || meta_inf
|
322
332
|
# Add libraries in WEB-INF lib, and classes in WEB-INF classes
|
323
333
|
if options[:classes]
|
@@ -340,18 +350,23 @@ module Buildr
|
|
340
350
|
end
|
341
351
|
yield war
|
342
352
|
end
|
353
|
+
else
|
354
|
+
fu_check_options options, *PACKAGE_OPTIONS
|
343
355
|
end
|
344
356
|
file(file_name)
|
345
357
|
end
|
346
358
|
|
347
359
|
def package_as_zip(file_name, options) #:nodoc:
|
348
360
|
unless Rake::Task.task_defined?(file_name)
|
361
|
+
fu_check_options options, *PACKAGE_OPTIONS + [:include]
|
349
362
|
ZipTask.define_task(file_name).tap do |zip|
|
350
363
|
if options[:include]
|
351
364
|
zip.include options[:include]
|
352
365
|
end
|
353
366
|
yield zip
|
354
367
|
end
|
368
|
+
else
|
369
|
+
fu_check_options options, *PACKAGE_OPTIONS
|
355
370
|
end
|
356
371
|
file(file_name)
|
357
372
|
end
|
data/lib/java/test.rb
CHANGED
@@ -19,7 +19,7 @@ module Buildr
|
|
19
19
|
super
|
20
20
|
@classpath = []
|
21
21
|
@paths = []
|
22
|
-
@include = []
|
22
|
+
@include = ["*Test", "*Suite"]
|
23
23
|
@exclude = []
|
24
24
|
enhance do |task|
|
25
25
|
unless test_cases.empty?
|
@@ -43,10 +43,9 @@ module Buildr
|
|
43
43
|
# test.include "com.example.Module*"
|
44
44
|
# test.include "*.{First,Second}Test"
|
45
45
|
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
# that do not implement test cases (e.g. mock objects, helpers, etc).
|
46
|
+
# By default, all classes that have a name ending with Test or Suite are included.
|
47
|
+
# Use these suffixes for your test and test suite classes respectively, to distinguish them
|
48
|
+
# from stubs, helper classes, etc.
|
50
49
|
def include(*classes)
|
51
50
|
@include += classes
|
52
51
|
self
|
@@ -85,7 +84,6 @@ module Buildr
|
|
85
84
|
|
86
85
|
def test_cases()
|
87
86
|
unless @cases
|
88
|
-
@include << "*Test" if @include.empty?
|
89
87
|
@cases = @paths.map do |path|
|
90
88
|
base = Pathname.new(path.to_s)
|
91
89
|
FileList["#{path}/**/*.class"].
|
@@ -164,9 +162,9 @@ module Buildr
|
|
164
162
|
# Returns the JUnit task. This task executes JUnit test cases, from classes compiled by
|
165
163
|
# the test task.
|
166
164
|
#
|
167
|
-
# By default it includes all classes with the suffix Test, and excludes all other classes.
|
168
|
-
# Use the Test suffix for classes that implement test cases, avoid this suffix for other
|
169
|
-
# classes (e.g.
|
165
|
+
# By default it includes all classes with the suffix Test or Suite, and excludes all other classes.
|
166
|
+
# Use the Test/Suite suffix for classes that implement test cases, avoid this suffix for other
|
167
|
+
# classes (e.g. stubs, helper objects).
|
170
168
|
#
|
171
169
|
# You can also include only specific test cases, or exclude otherwise included test cases
|
172
170
|
# using #include and #exclude.
|
@@ -267,7 +265,7 @@ module Buildr
|
|
267
265
|
project.recursive_task("test")
|
268
266
|
# Similar to the regular resources task but using different paths.
|
269
267
|
resources = Java::ResourcesTask.define_task("test:resources")
|
270
|
-
project.path_to("src/test/resources")
|
268
|
+
resources.filter.from project.path_to("src/test/resources")
|
271
269
|
# Similar to the regular compile task but using different paths.
|
272
270
|
compile = Java::CompileTask.define_task("test:compile"=>[project.compile, project.test.prepare, project.test.resources])
|
273
271
|
compile.enhance { project.test.resources.invoke }
|
data/lib/tasks/zip.rb
CHANGED
@@ -312,7 +312,7 @@ module Buildr
|
|
312
312
|
# Or:
|
313
313
|
# package(:jar)[:manifest] = "MANIFEST_MF"
|
314
314
|
def []=(key, value)
|
315
|
-
|
315
|
+
raise ArgumentError, "#{self.class} does not support the option #{key}"
|
316
316
|
end
|
317
317
|
|
318
318
|
def prerequisites() #:nodoc:
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: buildr
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-04-
|
6
|
+
version: 0.21.0
|
7
|
+
date: 2007-04-20 00:00:00 -07:00
|
8
8
|
summary: A build system that doesn't suck
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -33,14 +33,13 @@ files:
|
|
33
33
|
- lib/core
|
34
34
|
- lib/buildr.rb
|
35
35
|
- lib/java
|
36
|
-
- lib/tasks/download.rb
|
37
|
-
- lib/tasks/filter.rb
|
38
36
|
- lib/tasks/concat.rb
|
39
37
|
- lib/tasks/zip.rb
|
40
38
|
- lib/core/transports.rb
|
41
39
|
- lib/core/build.rb
|
42
40
|
- lib/core/project.rb
|
43
41
|
- lib/core/rake_ext.rb
|
42
|
+
- lib/core/common.rb
|
44
43
|
- lib/java/test.rb
|
45
44
|
- lib/java/eclipse.rb
|
46
45
|
- lib/java/jetty.rb
|
@@ -68,6 +67,7 @@ rdoc_options:
|
|
68
67
|
- --main
|
69
68
|
- README
|
70
69
|
- --line-numbers
|
70
|
+
- -inline-source
|
71
71
|
extra_rdoc_files:
|
72
72
|
- README
|
73
73
|
- CHANGELOG
|
data/lib/tasks/download.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
require "tempfile"
|
2
|
-
require "core/transports"
|
3
|
-
|
4
|
-
module Buildr
|
5
|
-
|
6
|
-
# :call-seq:
|
7
|
-
# download(url_or_uri) => task
|
8
|
-
# download(path=>url_or_uri) =>task
|
9
|
-
#
|
10
|
-
# Create a task that will download a file from a URL.
|
11
|
-
#
|
12
|
-
# Takes a single argument, a hash with one pair. The key is the file being
|
13
|
-
# created, the value if the URL to download. The task executes only if the
|
14
|
-
# file does not exist; the URL is not checked for updates.
|
15
|
-
#
|
16
|
-
# The task will show download progress on the console; if there are MD5/SHA1
|
17
|
-
# checksums on the server it will verify the download before saving it.
|
18
|
-
#
|
19
|
-
# For example:
|
20
|
-
# download "image.jpg"=>"http://example.com/theme/image.jpg"
|
21
|
-
def download(args)
|
22
|
-
if String === args || URI === args
|
23
|
-
# Given only a download URL, download into a temporary file.
|
24
|
-
# You can infer the file from task name.
|
25
|
-
temp = Tempfile.new(File.basename(args.to_s))
|
26
|
-
task = file_create(temp.path) do |task|
|
27
|
-
Transports.download task.source, task.name
|
28
|
-
end
|
29
|
-
task.sources << args
|
30
|
-
else
|
31
|
-
# Download to a file created by the task.
|
32
|
-
fail unless args.keys.size == 1
|
33
|
-
url = args.values.first
|
34
|
-
task = file_create(args.keys.first) do |task|
|
35
|
-
mkpath File.dirname(task.name), :verbose=>false
|
36
|
-
Transports.download task.source, task.name
|
37
|
-
end
|
38
|
-
task.sources << url
|
39
|
-
end
|
40
|
-
task
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
data/lib/tasks/filter.rb
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
module Buildr
|
2
|
-
|
3
|
-
# A filter knows how to copy a set of source files into a target directory, and apply
|
4
|
-
# mapping to these files.
|
5
|
-
#
|
6
|
-
# You can specify the mapping using a Hash, and it will map ${key} fields found in each
|
7
|
-
# source file into the appropriate value. For example:
|
8
|
-
# filter.using "version"=>"1.2"
|
9
|
-
# will replace all occurrences of "${version}" with "1.2".
|
10
|
-
#
|
11
|
-
# You can also specify the mapping by passing a proc or a method, that will be called for
|
12
|
-
# each source file, with the file name and content, returning the modified content.
|
13
|
-
#
|
14
|
-
# Without any mapping, the filter simply copies the source files into the target directory.
|
15
|
-
#
|
16
|
-
# See Buildr#filter.
|
17
|
-
class Filter
|
18
|
-
|
19
|
-
# The target directory.
|
20
|
-
attr_reader :target
|
21
|
-
# The mapping. See #using.
|
22
|
-
attr_accessor :mapping
|
23
|
-
# The source files and directories.
|
24
|
-
attr_accessor :sources
|
25
|
-
|
26
|
-
def initialize() #:nodoc:
|
27
|
-
@sources = FileList[]
|
28
|
-
end
|
29
|
-
|
30
|
-
# :call-seq:
|
31
|
-
# include(*files) => self
|
32
|
-
#
|
33
|
-
# Specifies files to include and returns self. See FileList#include.
|
34
|
-
def include(*files)
|
35
|
-
@sources.include *files
|
36
|
-
self
|
37
|
-
end
|
38
|
-
alias :add :include
|
39
|
-
|
40
|
-
# :call-seq:
|
41
|
-
# exclude(*files) => self
|
42
|
-
#
|
43
|
-
# Specifies files to exclude and returns self. See FileList#exclude.
|
44
|
-
def exclude(*files)
|
45
|
-
@sources.exclude *files
|
46
|
-
self
|
47
|
-
end
|
48
|
-
|
49
|
-
# :call-seq:
|
50
|
-
# into(dir) => self
|
51
|
-
#
|
52
|
-
# Specifies the target directory and return self. This tells the filter task where
|
53
|
-
# to copy the source files to.
|
54
|
-
#
|
55
|
-
# For example:
|
56
|
-
# filter.include("*.HTML").into("docs").run
|
57
|
-
def into(dir)
|
58
|
-
@target = File.expand_path(dir.to_s)
|
59
|
-
self
|
60
|
-
end
|
61
|
-
|
62
|
-
# :call-seq:
|
63
|
-
# using(mapping) => self
|
64
|
-
# using() { |file_name, contents| ... } => self
|
65
|
-
#
|
66
|
-
# Specifies the mapping to use and returns self.
|
67
|
-
#
|
68
|
-
# The mapping can be a proc or a method called with the file name and content, returning
|
69
|
-
# the modified content. Or the mapping can be a Hash for mapping each ${key} into a value.
|
70
|
-
# Without any mapping, all files are copied as is.
|
71
|
-
#
|
72
|
-
# For example:
|
73
|
-
# filter.using "version"=>"1.2"
|
74
|
-
# will replace all occurrences of "${version}" with "1.2".
|
75
|
-
def using(mapping, &block)
|
76
|
-
self.mapping = mapping || block
|
77
|
-
self
|
78
|
-
end
|
79
|
-
|
80
|
-
# Run the filter.
|
81
|
-
def run()
|
82
|
-
#@sources.each { |src| Rake.application[src, Rake.application.current_scope].invoke }
|
83
|
-
if needed?
|
84
|
-
fail "No target directory specified" if !target || (File.exist?(target.to_s) && !File.directory?(target.to_s))
|
85
|
-
unless copy_map.empty?
|
86
|
-
verbose(Rake.application.options.trace || false) do
|
87
|
-
mkpath target.to_s
|
88
|
-
copy_map do |dest, src|
|
89
|
-
mkpath File.dirname(dest) rescue nil
|
90
|
-
case mapping
|
91
|
-
when Proc, Method # Call on input, accept output.
|
92
|
-
mapped = mapping.call(src, File.read(src))
|
93
|
-
File.open(dest, "w") { |file| file.write mapped }
|
94
|
-
when Hash # Map ${key} to value
|
95
|
-
mapped = File.read(src).gsub(/\$\{.*\}/) { |str| mapping[str[2..-2]] || str }
|
96
|
-
File.open(dest, "w") { |file| file.write mapped }
|
97
|
-
when nil # No mapping.
|
98
|
-
cp src, dest
|
99
|
-
else
|
100
|
-
fail "Filter can be a hash (key=>value), or a proc/method; I don't understand #{mapping}"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
touch target.to_s
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# Returns the target directory.
|
110
|
-
def to_s()
|
111
|
-
@target.to_s
|
112
|
-
end
|
113
|
-
|
114
|
-
private
|
115
|
-
|
116
|
-
def needed?()
|
117
|
-
return false if target.nil? || copy_map.empty?
|
118
|
-
return true unless File.exist?(target.to_s)
|
119
|
-
return true if copy_map.any? { |dest, src| !File.exist?(dest) || File.mtime(src) > File.mtime(dest) }
|
120
|
-
false
|
121
|
-
end
|
122
|
-
|
123
|
-
# Return a copy map of all the files that need copying: the key is the file to copy to,
|
124
|
-
# the value is the source file. If called with a block, yields with each dest/source pair.
|
125
|
-
def copy_map(&block)
|
126
|
-
# Create a map between the source file and the similarly named file in the target directory,
|
127
|
-
# including all files nested inside directories.
|
128
|
-
@copy_map ||= @sources.map(&:to_s).inject({}) do |map, path|
|
129
|
-
if File.directory?(path)
|
130
|
-
Dir["#{path}/**/*"].each do |file|
|
131
|
-
map[file.sub(File.dirname(path), target.to_s)] = file unless
|
132
|
-
File.directory?(file) || @sources.exclude?(file)
|
133
|
-
end
|
134
|
-
elsif File.exist?(path)
|
135
|
-
map[File.join(target.to_s, File.basename(path))] = path
|
136
|
-
end
|
137
|
-
map
|
138
|
-
end.reject do |dest, src|
|
139
|
-
# ... while ignoring that which does not need updating.
|
140
|
-
File.exist?(dest) && File.stat(dest).mtime > File.stat(src).mtime
|
141
|
-
end
|
142
|
-
if block_given?
|
143
|
-
@copy_map.each(&block)
|
144
|
-
else
|
145
|
-
@copy_map
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
end
|
150
|
-
|
151
|
-
# :call-seq:
|
152
|
-
# filter(*files) => Filter
|
153
|
-
#
|
154
|
-
# Creates a filter task to operate on all the specified files.
|
155
|
-
def filter(*files)
|
156
|
-
Filter.new.include *files
|
157
|
-
end
|
158
|
-
|
159
|
-
end
|