raven 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2006 Matthieu Riou
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'rubygems'
18
+ require 'fileutils'
19
+
20
+ module Gem
21
+ # Adding Gems Java platform
22
+ module Platform
23
+ JAVA = 'java'
24
+ end
25
+
26
+ # Unfortunately Maven artifacts have a rather free versioning scheme
27
+ class Version
28
+ def self.correct?(str)
29
+ true
30
+ end
31
+ end
32
+ end
33
+
34
+ begin
35
+ Gem.manage_gems
36
+ rescue NoMethodError => ex
37
+ # Using rubygems prior to 0.6.1
38
+ end
39
+
40
+ # Let the user add or redefine his sources (hopefully we'll be
41
+ # able to set a default one when a good soul will be able to
42
+ # donate us space and bandwidth to host a Raven Gems repository).
43
+ module Gem
44
+ def self.sources=(s)
45
+ @sources = s
46
+ end
47
+ end
48
+ require_gem("sources")
49
+ def sources; Gem.sources; end
50
+ def set_sources(s) Gem.sources = s; end
51
+ set_sources(["http://localhost:2233"])
52
+
53
+ # To avoid polluting the regular Gem repository, we store our gems
54
+ # under the user home directory.
55
+ GEMS_IN_HOME = true
56
+ USER_HOME = ENV['HOME'] ? ENV['HOME'] : ENV['USERPROFILE']
57
+ FileUtils.mkdir(USER_HOME + '/.raven_gems') unless File.exist?(USER_HOME + '/.raven_gems')
58
+ Dir.glob(USER_HOME + "/.raven_gems/specifications/*.gemspec").each do |file_name|
59
+ gemspec = Gem::SourceIndex.load_specification(file_name.untaint)
60
+ Gem::cache.add_spec(gemspec) if gemspec
61
+ end
62
+
63
+ module Gem
64
+ # Making the remote installer silent. Otherwise it always asks you to
65
+ # choose the version you want to install.
66
+ class RemoteInstaller
67
+ def find_gem_to_install(gem_name, version_requirement, caches)
68
+ specs_n_sources = []
69
+ caches.each do |source, cache|
70
+ cache.each do |name, spec|
71
+ if /^#{gem_name}$/i === spec.name &&
72
+ version_requirement.satisfied_by?(spec.version) then
73
+ specs_n_sources << [spec, source]
74
+ end
75
+ end
76
+ end
77
+ if specs_n_sources.empty? then
78
+ raise GemNotFoundException.new("Could not find #{gem_name} (#{version_requirement}) in the repository")
79
+ end
80
+ specs_n_sources = specs_n_sources.sort_by { |gs,| gs.version }.reverse
81
+ specs_n_sources[0]
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,284 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This file has been copied from the RubyGems distribution and
4
+ # included in Raven for users convenience. See the RubyGems
5
+ # site for license and more.
6
+
7
+ #
8
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
9
+ # All rights reserved.
10
+ # See LICENSE.txt for permissions.
11
+ #
12
+
13
+
14
+ # Generate the yaml/yaml.Z index files for a gem server directory.
15
+ #
16
+ # Usage: generate_yaml_index.rb --dir DIR [--verbose]
17
+
18
+ $:.unshift '~/rubygems' if File.exist? "~/rubygems"
19
+
20
+ require 'optparse'
21
+ require 'rubygems'
22
+ require 'zlib'
23
+ require 'digest/sha2'
24
+
25
+ Gem.manage_gems
26
+
27
+ ######################################################################
28
+ # Mixin that provides a +compress+ method for compressing files on
29
+ # disk.
30
+ #
31
+ module Compressor
32
+ # Compress the given file.
33
+ def compress(filename, ext="rz")
34
+ File.open(filename + ".#{ext}", "w") do |file|
35
+ file.write(zip(File.read(filename)))
36
+ end
37
+ end
38
+
39
+ # Return a compressed version of the given string.
40
+ def zip(string)
41
+ Zlib::Deflate.deflate(string)
42
+ end
43
+
44
+ # Return an uncompressed version of a compressed string.
45
+ def unzip(string)
46
+ Zlib::Inflate.inflate(string)
47
+ end
48
+ end
49
+
50
+ ######################################################################
51
+ # Announcer provides a way of announcing activities to the user.
52
+ #
53
+ module Announcer
54
+ # Announce +msg+ to the user.
55
+ def announce(msg)
56
+ puts msg if @options[:verbose]
57
+ end
58
+ end
59
+
60
+ ######################################################################
61
+ # Abstract base class for building gem indicies. Uses the template
62
+ # pattern with subclass specialization in the +begin_index+,
63
+ # +end_index+ and +cleanup+ methods.
64
+ #
65
+ class AbstractIndexBuilder
66
+ include Compressor
67
+ include Announcer
68
+
69
+ # Build a Gem index. Yields to block to handle the details of the
70
+ # actual building. Calls +begin_index+, # +end_index+ and +cleanup+
71
+ # at appropriate times to customize basic operations.
72
+ def build
73
+ if ! @enabled
74
+ yield
75
+ else
76
+ unless File.exist?(@directory)
77
+ FileUtils.mkdir_p(@directory)
78
+ end
79
+ fail "not a directory: #{@directory}" unless File.directory?(@directory)
80
+ File.open(File.join(@directory, @filename), "w") do |file|
81
+ @file = file
82
+ start_index
83
+ yield
84
+ end_index
85
+ end
86
+ cleanup
87
+ end
88
+ ensure
89
+ @file = nil
90
+ end
91
+
92
+ # Called immediately before the yield in build. The index file is
93
+ # open and availabe as @file.
94
+ def start_index
95
+ end
96
+
97
+ # Called immediately after the yield in build. The index file is
98
+ # still open and available as @file.
99
+ def end_index
100
+ end
101
+
102
+ # Called from within builder after the index file has been closed.
103
+ def cleanup
104
+ end
105
+ end
106
+
107
+ ######################################################################
108
+ # Construct the master Gem index file.
109
+ #
110
+ class MasterIndexBuilder < AbstractIndexBuilder
111
+ def initialize(filename, options)
112
+ @filename = filename
113
+ @options = options
114
+ @directory = options[:directory]
115
+ @enabled = true
116
+ end
117
+
118
+ def start_index
119
+ super
120
+ @file.puts "--- !ruby/object:Gem::Cache"
121
+ @file.puts "gems:"
122
+ end
123
+
124
+ def cleanup
125
+ super
126
+ index_file_name = File.join(@directory, @filename)
127
+ compress(index_file_name, "Z")
128
+ # Sometimes being paranoid isn't that good: there's a bug on Windows causing
129
+ # the failing of unzip.
130
+ # paranoid(index_file_name, "#{index_file_name}.Z")
131
+ end
132
+
133
+ def add(spec)
134
+ @file.puts " #{spec.full_name}: #{nest(spec.to_yaml)}"
135
+ end
136
+
137
+ def nest(yaml_string)
138
+ yaml_string[4..-1].gsub(/\n/, "\n ")
139
+ end
140
+
141
+ private
142
+
143
+ def paranoid(fn, compressed_fn)
144
+ data = File.read(fn)
145
+ compressed_data = File.read(compressed_fn)
146
+ if data != unzip(compressed_data)
147
+ fail "Compressed file #{compressed_fn} does not match uncompressed file #{fn}"
148
+ end
149
+ end
150
+ end
151
+
152
+ ######################################################################
153
+ # Construct a quick index file and all of the individual specs to
154
+ # support incremental loading.
155
+ #
156
+ class QuickIndexBuilder < AbstractIndexBuilder
157
+ def initialize(filename, options)
158
+ @filename = filename
159
+ @options = options
160
+ @directory = options[:quick_directory]
161
+ @enabled = options[:quick]
162
+ end
163
+
164
+ def cleanup
165
+ compress(File.join(@directory, @filename))
166
+ end
167
+
168
+ def add(spec)
169
+ return unless @enabled
170
+ @file.puts spec.full_name
171
+ fn = File.join(@directory, "#{spec.full_name}.gemspec.rz")
172
+ File.open(fn, "w") do |gsfile|
173
+ gsfile.write(zip(spec.to_yaml))
174
+ end
175
+ end
176
+ end
177
+
178
+ ######################################################################
179
+ # Top level class for building the repository index. Initialize with
180
+ # an options hash and call +build_index+.
181
+ #
182
+ class Indexer
183
+ include Compressor
184
+ include Announcer
185
+
186
+ # Create an indexer with the options specified by the options hash.
187
+ def initialize(options)
188
+ @options = options.dup
189
+ @directory = @options[:directory]
190
+ @options[:quick_directory] = File.join(@directory, "quick")
191
+ @master_index = MasterIndexBuilder.new("yaml", @options)
192
+ @quick_index = QuickIndexBuilder.new("index", @options)
193
+ end
194
+
195
+ # Build the index.
196
+ def build_index
197
+ announce "Building Server Index"
198
+ FileUtils.rm_r(@options[:quick_directory]) rescue nil
199
+ @master_index.build do
200
+ @quick_index.build do
201
+ gem_file_list.each do |gemfile|
202
+ spec = Gem::Format.from_file_by_path(gemfile).spec
203
+ abbreviate(spec)
204
+ announce " ... adding #{spec.full_name}"
205
+ @master_index.add(spec)
206
+ @quick_index.add(spec)
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ # List of gem file names to index.
213
+ def gem_file_list
214
+ Dir.glob(File.join(@directory, "gems", "*.gem"))
215
+ end
216
+
217
+ # Abbreviate the spec for downloading. Abbreviated specs are only
218
+ # used for searching, downloading and related activities and do not
219
+ # need deployment specific information (e.g. list of files). So we
220
+ # abbreviate the spec, making it much smaller for quicker downloads.
221
+ def abbreviate(spec)
222
+ spec.files = []
223
+ spec.test_files = []
224
+ spec.rdoc_options = []
225
+ spec.extra_rdoc_files = []
226
+ spec.cert_chain = []
227
+ spec
228
+ end
229
+ end
230
+
231
+ ######################################################################
232
+ # Top Level Functions
233
+ ######################################################################
234
+
235
+ def handle_options(args)
236
+ # default options
237
+ options = {
238
+ :directory => '.',
239
+ :verbose => false,
240
+ :quick => true,
241
+ }
242
+
243
+ args.options do |opts|
244
+ opts.on_tail("--help", "show this message") do
245
+ puts opts
246
+ exit
247
+ end
248
+ opts.on(
249
+ '-d', '--dir=DIRNAME', '--directory=DIRNAME',
250
+ "repository base dir containing gems subdir",
251
+ String) do |value|
252
+ options[:directory] = value
253
+ end
254
+ opts.on('--[no-]quick', "include quick index") do |value|
255
+ options[:quick] = value
256
+ end
257
+ opts.on('-v', '--verbose', "show verbose output") do |value|
258
+ options[:verbose] = value
259
+ end
260
+ opts.on('-V', '--version',
261
+ "show version") do |value|
262
+ puts Gem::RubyGemsVersion
263
+ exit
264
+ end
265
+ opts.parse!
266
+ end
267
+
268
+ if options[:directory].nil?
269
+ puts "Error, must specify directory name. Use --help"
270
+ exit
271
+ elsif ! File.exist?(options[:directory]) ||
272
+ ! File.directory?(options[:directory])
273
+ puts "Error, unknown directory name #{directory}."
274
+ exit
275
+ end
276
+ options
277
+ end
278
+
279
+ # Main program.
280
+ def main_index(args)
281
+ options = handle_options(args)
282
+ Indexer.new(options).build_index
283
+ end
284
+
@@ -0,0 +1,399 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2006 Matthieu Riou
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'rake'
18
+ require 'fileutils'
19
+ require 'set'
20
+
21
+ # Monkey patching FileUtils to support filtering in copy.
22
+ module FileUtils
23
+ class Entry_
24
+ alias original copy
25
+ def copy(dest)
26
+ unless path['.svn'] || path['.cvs']
27
+ original(dest)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ module Raven
34
+ CP_SEP = PLATFORM['mswin'] ? ';' : ':'
35
+
36
+ # Executes Javac by passing it everything it needs. Stuff like a
37
+ # classpath and sources. The classpath is built by checking the
38
+ # prerequisites of the javac task. When a prerequisite is a dependency
39
+ # declaration (dependency task), it takes each declared Gems and
40
+ # adds the jar files found in them to the classpath.
41
+ #
42
+ # Can be customized by adding directories to the <em>build_path</em>
43
+ # using the << operator (if none defined, default is src/main/java).
44
+ class JavacTask < Rake::Task
45
+
46
+ def execute
47
+ super
48
+ classpath = Raven.build_cp(prerequisites)
49
+ classpath << "target/classes"
50
+ @build_path = ["src/main/java"] unless @build_path
51
+
52
+ puts "Building path #{@build_path.join(' ')}" if RakeFileUtils.verbose_flag
53
+
54
+ Dir.mkdir("target") unless File.exist?("target")
55
+ Dir.mkdir("target/classes") unless File.exist?("target/classes")
56
+ # Getting the source files to compile. Filtrating sources already
57
+ # compiled having a fresh enough class
58
+ source_files = @build_path.collect do |d|
59
+ Dir.glob("#{d}/**/*.java").select do |java|
60
+ classfile = 'target/classes/' + java[d.length, (java.length - 5 - d.length)] + '.class'
61
+ File.exist?(classfile) ? File.stat(java).ctime > File.stat(classfile).ctime : true
62
+ end
63
+ end.flatten
64
+
65
+ if (source_files.size > 0)
66
+ # Getting only package names, it shortens the command line
67
+ source_pkg = Set.new
68
+ source_files.each { |src| source_pkg << File.join(File.dirname(src), '*.java') }
69
+ # Executing javac
70
+ puts "javac -cp #{classpath.join(CP_SEP)} -sourcepath #{@build_path.join(CP_SEP)} -d target/classes #{source_pkg.to_a.join(' ')}" if RakeFileUtils.verbose_flag
71
+ `javac -cp #{classpath.join(CP_SEP)} -sourcepath #{@build_path.join(CP_SEP)} -d target/classes #{source_pkg.to_a.join(' ')}`
72
+ unless $? == 0
73
+ puts "Build failed, see above errors."
74
+ exit
75
+ end
76
+ else
77
+ puts 'All class files are up to date.' if RakeFileUtils.verbose_flag
78
+ end
79
+ end
80
+
81
+ def build_path
82
+ @build_path ||= []
83
+ end
84
+ end
85
+
86
+ # Builds a jar file from your compiled sources. The jarfile produced
87
+ # will have the same name as your jar task.
88
+ class JarTask < Rake::Task
89
+ def execute
90
+ super
91
+ latest = Raven.latest_file('target/classes')
92
+
93
+ if !File.exist?("target/#{name}") || File.stat("target/#{name}").ctime < latest
94
+ `jar -cf target/#{name} -C target/classes .`
95
+ else
96
+ puts 'Nothing to do, jar is fresh enough.' if RakeFileUtils.verbose_flag
97
+ end
98
+ end
99
+ end
100
+
101
+ # Builds a jar file from your sources. Customized by adding directories
102
+ # to the <em>source_path</em> just like the JavacTask.
103
+ class JarSourceTask < Rake::Task
104
+ def execute
105
+ super
106
+ # Checking if any of our prerequisites is a JavacTask, if
107
+ # so we'll just use the build path to construct the jar.
108
+ Raven.prereq_filter(prerequisites, :build_path) do |javac_task|
109
+ (@source_path ||= []) << javac_task.build_path
110
+ end
111
+
112
+ # Initializing source path
113
+ @source_path = ["src/main/java"] unless @source_path
114
+ @source_path.flatten!
115
+
116
+ latest = Time.at(0)
117
+ @source_path.each do |dir|
118
+ dir_latest = Raven.latest_file(dir)
119
+ latest = dir_latest if dir_latest > latest
120
+ end
121
+
122
+ # Building the jar from all sources
123
+ if !File.exist?("target/#{name}") || File.stat("target/#{name}").ctime < latest
124
+ `jar -cf target/#{name} -C #{@source_path.pop} .`
125
+ while (p = @source_path.pop)
126
+ `jar -uf target/#{name} -C #{p} .`
127
+ end
128
+ end
129
+ end
130
+
131
+ def source_path
132
+ @source_path ||= []
133
+ end
134
+ end
135
+
136
+ # Produces a WAR from a web application directory. Includes the libraries
137
+ # needed in WEB-INF/lib (as long as the corresponding dependency task is
138
+ # declared as a prerequisite) and the compiled classes (if there are).
139
+ #
140
+ # Can be customized by setting <em>webapp_dir</em> to the directory
141
+ # containing your web application resources (web.xml, jsp, images, ...).
142
+ # The default is src/main/webapp.
143
+ class WarTask < Rake::Task
144
+ DEFAULT_TARGET = 'target/webapp/'
145
+ LIB_SUBDIR = 'WEB-INF/lib/'
146
+ CLASSES_SUBDIR = 'WEB-INF/classes/'
147
+
148
+ def execute
149
+ super
150
+
151
+ # Build target structure
152
+ @webapp_dir = @webapp_dir || 'src/main/webapp'
153
+ Raven.mkdir_recurse(DEFAULT_TARGET)
154
+
155
+ puts "Using web application directory #{@webapp_dir}" if RakeFileUtils.verbose_flag
156
+
157
+ FileUtils.cp_r(@webapp_dir, DEFAULT_TARGET)
158
+
159
+ # Eventually add classes compiled by javac
160
+ if (File.exist?('target/classes'))
161
+ Raven.mkdir_recurse(DEFAULT_TARGET + CLASSES_SUBDIR)
162
+ FileUtils.cp_r('target/classes/.', DEFAULT_TARGET + CLASSES_SUBDIR)
163
+ end
164
+
165
+ # Make lib directory with all dependencies
166
+ Raven.mkdir_recurse(DEFAULT_TARGET + LIB_SUBDIR)
167
+ Raven.mk_libs(DEFAULT_TARGET + LIB_SUBDIR, prerequisites)
168
+
169
+ # Build the war
170
+ `jar -cf target/#{name} -C #{DEFAULT_TARGET} .`
171
+ end
172
+
173
+ def webapp_dir=(param)
174
+ @webapp_dir = param
175
+ end
176
+ end
177
+
178
+ # Places all the dependencies in a given directory (useful mostly to
179
+ # build a distribution). The dependencies are selected from the
180
+ # prerequisites (using declared dependency tasks). The default
181
+ # directory is lib. Can be customized by setting <em>target</em>.
182
+ class LibDirTask < Rake::Task
183
+ def execute
184
+ super
185
+ puts "Copying libraries in #{@target}" if RakeFileUtils.verbose_flag
186
+ @target = @target || 'lib'
187
+ Raven.mk_libs(@target, prerequisites)
188
+ end
189
+
190
+ def target=(param)
191
+ @target = param
192
+ end
193
+ end
194
+
195
+ # Executes JavaDoc by passing it everything it needs. Stuff like a
196
+ # classpath and sources. The result is generated in target/jdoc. Can
197
+ # be customized exactly in the same way as the javac task.
198
+ class JavaDocTask < Rake::Task
199
+
200
+ def execute
201
+ super
202
+ classpath = Raven.build_cp(prerequisites)
203
+ classpath << "target/classes"
204
+ @build_path = ["src/main/java"] unless @build_path
205
+
206
+ puts "Executing JavaDoc using source path #{@build_path.join(' ')}" if RakeFileUtils.verbose_flag
207
+
208
+ Dir.mkdir("target") unless File.exist?("target")
209
+ Dir.mkdir("target/jdoc") unless File.exist?("target/jdoc")
210
+
211
+ packages = Set[]
212
+ @build_path.each do |d|
213
+ Dir.glob("#{d}/**/*.java").each do |java|
214
+ packages << java[(d.length + 1)..(java.rindex('/') - 1)].gsub(%r{[\\/]}, '.')
215
+ end
216
+ end
217
+ packages = packages.to_a
218
+
219
+ if (packages.size > 0)
220
+ puts "javadoc -classpath #{classpath.join(CP_SEP)} -sourcepath #{@build_path.join(CP_SEP)} -d target/jdoc #{packages.join(' ')}" if RakeFileUtils.verbose_flag
221
+ `javadoc -classpath #{classpath.join(CP_SEP)} -sourcepath #{@build_path.join(CP_SEP)} -d target/jdoc #{packages.join(' ')}`
222
+ unless $? == 0
223
+ puts "Build failed, see above errors."
224
+ exit
225
+ end
226
+ end
227
+ end
228
+
229
+ def build_path
230
+ @build_path ||= []
231
+ end
232
+ end
233
+
234
+ # Wraps a jar file around a Gem. Useful for distributing it around.
235
+ # The jar is taken from the target directory. You must at least
236
+ # specify <em>version</em> to produce the Gem. The artifact name and
237
+ # group name default to the current directory name and its parent
238
+ # directory name respectively. Convenient if you follow the classic
239
+ # project/module directory structure. Otherwise, just set the
240
+ # <em>artifact</em> and <em>group</em> to any value that suits you.
241
+ class GemWrapTask < Rake::Task
242
+ attr_writer :version, :artifact, :group
243
+
244
+ def execute
245
+ super
246
+ puts "Wrapping jar in a Gem" if RakeFileUtils.verbose_flag
247
+ unless @version
248
+ puts "A version must be provided to produce a Gem!"
249
+ end
250
+ pwd = Dir.pwd
251
+ @artifact = pwd[(pwd.rindex('/') + 1)..pwd.length] unless @artifact
252
+ pwd = pwd[0..pwd.rindex('/') - 1]
253
+ @group = pwd[(pwd.rindex('/') + 1)..pwd.length] unless @group
254
+ Raven.mkdir_recurse('target/gem/ext')
255
+ FileUtils.cp(Dir.glob('target/*.jar'), 'target/gem/ext')
256
+
257
+ Dir.chdir('target/gem') do
258
+ spec = Gem::Specification.new do |s|
259
+ s.platform = Gem::Platform::JAVA
260
+ s.summary = "Raven wrapped library #{@artifact} from project #{@group}."
261
+ s.name = "#{@group}-#{@artifact}"
262
+ s.version = @version
263
+ s.requirements << 'none'
264
+ s.require_path = 'ext'
265
+ s.autorequire = 'rake'
266
+ s.files = Dir.glob("{ext}/**/*")
267
+ end
268
+ Gem::Builder.new(spec).build
269
+ end
270
+ FileUtils.mv("target/gem/#{@group}-#{@artifact}-#{@version}-java.gem", 'target')
271
+ end
272
+ end
273
+
274
+ # Wraps a jar file around a Gem and automatically installs it in your
275
+ # local Gem repository. See the gem wrap task for more info (same rules
276
+ # apply).
277
+ class GemInstallTask < GemWrapTask
278
+ def execute
279
+ super
280
+ params = [false]
281
+ params << USER_HOME + "/.raven_gems" if defined?(GEMS_IN_HOME)
282
+ Gem::Installer.new("target/#{@group}-#{@artifact}-#{@version}-java.gem").install(*params)
283
+ end
284
+ end
285
+
286
+ private
287
+
288
+ # Builds the classpath by getting the path to the jars bundled
289
+ # in each gem dependency.
290
+ def self.build_cp(prerequisites)
291
+ classpath = []
292
+ Raven.prereq_filter(prerequisites, :gem_deps) do |dep_task|
293
+ dep_task.gem_deps.each do |gempath|
294
+ Dir.foreach(gempath + '/ext') do |file|
295
+ next if file == '.' || file == '..'
296
+ classpath << gempath + '/ext/' + file
297
+ end
298
+ end
299
+ end
300
+ classpath
301
+ end
302
+
303
+ # Copies the jars corresponding to each Gem dependency to a given
304
+ # directory.
305
+ def self.mk_libs(target, prereq)
306
+ Raven.mkdir_recurse(target)
307
+ Raven.prereq_filter(prereq, :gem_deps) do |dep_task|
308
+ dep_task.gem_deps.each do |gempath|
309
+ Dir.foreach(gempath + '/ext') do |file|
310
+ next if file == '.' || file == '..'
311
+ FileUtils.copy(gempath + '/ext/' + file, target)
312
+ end
313
+ end
314
+ end
315
+ end
316
+
317
+ # Duck typing selection of prerequisites
318
+ def self.prereq_filter(prerequisites, respond_to)
319
+ prerequisites.each do |prereq|
320
+ prereq_task = Rake::Task[prereq]
321
+ if prereq_task.respond_to?(respond_to)
322
+ yield(prereq_task)
323
+ end
324
+ end
325
+ end
326
+
327
+ # Recursively creates a directory
328
+ def self.mkdir_recurse(dir)
329
+ if dir.rindex('/')
330
+ parent = dir[0, dir.rindex('/')]
331
+ mkdir_recurse(parent) unless File.exist?(parent)
332
+ end
333
+ Dir.mkdir(dir) unless File.exist?(dir)
334
+ end
335
+
336
+ # Receursively browse a directory yielding on each file found.
337
+ def self.browse_files(root)
338
+ queue = [root]
339
+ while !queue.empty?
340
+ filename = queue.pop
341
+ if File.file?(filename)
342
+ yield(filename)
343
+ else
344
+ Dir.new(filename).each do |child|
345
+ unless ['..', '.', '.svn', '.cvs'].include?(child)
346
+ queue.push(filename + "/" + child)
347
+ end
348
+ end
349
+ end
350
+ end
351
+ end
352
+
353
+ # Returns the latest file timestamp in a directory structure
354
+ def self.latest_file(dir)
355
+ latest = Time.at(0)
356
+ Raven.browse_files(dir) do |f|
357
+ change = File.stat(f).ctime
358
+ latest = change if change > latest
359
+ end
360
+ latest
361
+ end
362
+
363
+ end
364
+
365
+
366
+ # Shortcut to the Javac task creation. Makes it handy.
367
+ def javac(args, &block)
368
+ Raven::JavacTask.define_task(args, &block)
369
+ end
370
+
371
+ # Shortcut to jar. Only 3 letters, isn't that beautiful?
372
+ def jar(args, &block)
373
+ Raven::JarTask.define_task(args, &block)
374
+ end
375
+
376
+ # I think you've got it now.
377
+ def jar_source(args, &block)
378
+ Raven::JarSourceTask.define_task(args, &block)
379
+ end
380
+
381
+ def lib_dir(args, &block)
382
+ Raven::LibDirTask.define_task(args, &block)
383
+ end
384
+
385
+ def war(args, &block)
386
+ Raven::WarTask.define_task(args, &block)
387
+ end
388
+
389
+ def javadoc(args, &block)
390
+ Raven::JavaDocTask.define_task(args, &block)
391
+ end
392
+
393
+ def gem_wrap(args, &block)
394
+ Raven::GemWrapTask.define_task(args, &block)
395
+ end
396
+
397
+ def gem_wrap_inst(args, &block)
398
+ Raven::GemInstallTask.define_task(args, &block)
399
+ end