buildr 0.20.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|