raven 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +176 -0
- data/README.rdoc +68 -0
- data/bin/raven +5 -0
- data/lib/raven.rb +78 -0
- data/lib/raven/deps_tasks.rb +153 -0
- data/lib/raven/gem_init.rb +84 -0
- data/lib/raven/index_gem_repository.rb +284 -0
- data/lib/raven/java_tasks.rb +399 -0
- data/lib/raven/repo_builder.rb +266 -0
- metadata +64 -0
@@ -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
|