raven 1.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.
- 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
|