buildr 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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