buildr 0.14.0

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