pangolin 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +13 -0
- data/README.rdoc +72 -0
- data/Rakefile +40 -0
- data/VERSION +1 -0
- data/examples/compile/Rakefile +16 -0
- data/examples/compile/src/com/example/HelloWorld.java +10 -0
- data/examples/package/Rakefile +24 -0
- data/examples/package/src/com/example/HelloWorld.java +10 -0
- data/examples/test/Rakefile +21 -0
- data/examples/test/src/com/example/HelloWorld.java +10 -0
- data/examples/test/test/com/example/TestHelloWorld.java +31 -0
- data/java_tools.gemspec +74 -0
- data/lib/pangolin.rb +143 -0
- data/lib/pangolin/jar.rb +179 -0
- data/lib/pangolin/javac.rb +128 -0
- data/lib/pangolin/junit.rb +120 -0
- data/lib/pangolin/output/formatting.rb +65 -0
- data/spec/jar_cmd_spec.rb +121 -0
- data/spec/jar_spec.rb +259 -0
- data/spec/javac_cmd_spec.rb +101 -0
- data/spec/javac_spec.rb +203 -0
- data/spec/junit_cmd_spec.rb +24 -0
- data/spec/junit_spec.rb +24 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +1 -0
- data/tasks/gem.rake +21 -0
- data/tasks/rdoc.rake +10 -0
- data/tasks/spec.rake +9 -0
- metadata +89 -0
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2009 Theo Hultberg
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.rdoc
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
= Pangolin
|
2
|
+
|
3
|
+
Ruby wrappers for javac and jar that don't just exec.
|
4
|
+
|
5
|
+
Ant is a nice tool for writing Java build scripts, but Rake is nicer. The only thing missing from Rake is a way to run +javac+ and +jar+, and although it's easy to run these with exec you have to wait for the JVM to start for each invocation. In combination with JRuby this gem lets you run +javac+ and +jar+ in your Rake scripts without exec'ing, by using the programmatic interface to Javac and Java's ZIP file creation capabilities.
|
6
|
+
|
7
|
+
== Example
|
8
|
+
|
9
|
+
require 'pangolin'
|
10
|
+
|
11
|
+
|
12
|
+
task :compile do
|
13
|
+
javac FileList['src/**/*.java'], :destination => 'build, :class_path => FileList['lib/*.jar']
|
14
|
+
end
|
15
|
+
|
16
|
+
task :dist => :compile do
|
17
|
+
jar 'dist/my-awsome-app.jar', FileList['build/**/*.class'], :base_dir => 'build'
|
18
|
+
end
|
19
|
+
|
20
|
+
task :test => :compile do
|
21
|
+
test_classes = FileList['build/**/Test*.class'].pathmap('%{build/,}X').gsub('/', '.')
|
22
|
+
|
23
|
+
junit test_classes, :class_path => FileList['build', 'lib/*.jar']
|
24
|
+
end
|
25
|
+
|
26
|
+
There are more examples in the +examples+ directory.
|
27
|
+
|
28
|
+
== Installation
|
29
|
+
|
30
|
+
The new way, from Gemcutter:
|
31
|
+
|
32
|
+
sudo jruby -S gem install pangolin
|
33
|
+
|
34
|
+
To add Gemcutter as a gem source, run these commands:
|
35
|
+
|
36
|
+
jruby -S gem install gemcutter
|
37
|
+
jruby -S gem tumble
|
38
|
+
|
39
|
+
To add GitHub as a gem source, run this command:
|
40
|
+
|
41
|
+
jruby -S gem sources -a http://gems.github.com
|
42
|
+
|
43
|
+
== Command style
|
44
|
+
|
45
|
+
Many Rake add-ons look like this:
|
46
|
+
|
47
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
48
|
+
spec.spec_opts << '--options' << 'spec/spec.opts'
|
49
|
+
# ...
|
50
|
+
end
|
51
|
+
|
52
|
+
I think it ruins the DSL illusion, and I prefer to write tasks that contain commands, more like how +cp+, +rm+ and +sh+ work in Rake.
|
53
|
+
|
54
|
+
== Nailgun
|
55
|
+
|
56
|
+
Don't forget that since JRuby 1.3 you can minimize the startup by using the built-in Nailgun support. Run
|
57
|
+
|
58
|
+
jruby --ng-server &
|
59
|
+
|
60
|
+
to start a Nailgun server and then run Rake with this command
|
61
|
+
|
62
|
+
jruby --ng -S rake
|
63
|
+
|
64
|
+
you'll notice that the startup time decreases significantly the second time you run it. To avoid having to write all that every time you want to build create an alias, I call mine +jrk+.
|
65
|
+
|
66
|
+
== Upcomming
|
67
|
+
|
68
|
+
Even though the whole rationale behind Pangolin is to avoid exec it wouldn't be much effort to support non-JRuby runtimes since at least the +javac+ command needs to build the command string anyway.
|
69
|
+
|
70
|
+
== Pangolin?
|
71
|
+
|
72
|
+
Pangolins eats ants for breakfast.
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
|
3
|
+
|
4
|
+
task :default => :prepare
|
5
|
+
|
6
|
+
task :prepare do
|
7
|
+
require 'open-uri'
|
8
|
+
|
9
|
+
junit_url = "http://downloads.sourceforge.net/project/junit/junit/4.7/junit-4.7.jar"
|
10
|
+
ext_dir = 'lib/pangolin/ext'
|
11
|
+
local_path = "#{ext_dir}/junit.jar"
|
12
|
+
|
13
|
+
unless File.exists?(local_path)
|
14
|
+
mkdir_p ext_dir
|
15
|
+
|
16
|
+
$stderr.print 'Downloading JUnit 4.7... '
|
17
|
+
|
18
|
+
File.open(local_path, 'w') do |f|
|
19
|
+
f.write(open(junit_url).read)
|
20
|
+
end
|
21
|
+
|
22
|
+
$stderr.puts 'done'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# This is a workaround for a silly bug in RubyGems on JRuby:
|
27
|
+
# when running a rakefile as part of an install the 2>&1 redirect ends
|
28
|
+
# ends up as an argument to Rake, and Rake complains, which makes the
|
29
|
+
# build fail. The workaround is to declare a task with this name.
|
30
|
+
task '2>&1' => :default
|
31
|
+
|
32
|
+
|
33
|
+
# Import all .rake-files in the tasks directory
|
34
|
+
Dir['tasks/*.rake'].each do |tasks_file|
|
35
|
+
begin
|
36
|
+
load tasks_file
|
37
|
+
rescue Exception => e
|
38
|
+
$stderr.puts e.message
|
39
|
+
end
|
40
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.0
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/pangolin')
|
2
|
+
|
3
|
+
require 'rake/clean'
|
4
|
+
|
5
|
+
|
6
|
+
CLOBBER.include('build')
|
7
|
+
|
8
|
+
|
9
|
+
task :default => :compile
|
10
|
+
|
11
|
+
desc "Compile all classes"
|
12
|
+
task :compile => 'build' do
|
13
|
+
javac FileList['src/**/*.java'], :destination => 'build', :verbose => true
|
14
|
+
end
|
15
|
+
|
16
|
+
directory 'build'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/java_tools')
|
2
|
+
|
3
|
+
require 'rake/clean'
|
4
|
+
|
5
|
+
|
6
|
+
CLOBBER.include('build')
|
7
|
+
CLOBBER.include('dist')
|
8
|
+
|
9
|
+
|
10
|
+
task :default => :package
|
11
|
+
|
12
|
+
task :package => [:compile, 'dist'] do
|
13
|
+
jar 'dist/package.jar', FileList['build/**/*.class'], :base_dir => 'build',
|
14
|
+
:main_class => 'com.example.HelloWorld',
|
15
|
+
:manifest => {'X-Test', 'foo'},
|
16
|
+
:verbose => true
|
17
|
+
end
|
18
|
+
|
19
|
+
task :compile => 'build' do
|
20
|
+
javac FileList['src/**/*.java'], :destination => 'build', :verbose => true
|
21
|
+
end
|
22
|
+
|
23
|
+
directory 'build'
|
24
|
+
directory 'dist'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/java_tools')
|
2
|
+
|
3
|
+
require 'rake/clean'
|
4
|
+
|
5
|
+
|
6
|
+
CLOBBER.include('build')
|
7
|
+
|
8
|
+
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
task :compile => 'build' do
|
12
|
+
javac FileList['{src,test}/**/*.java'], :destination => 'build',
|
13
|
+
:class_path => FileList['lib/*.jar'],
|
14
|
+
:verbose => true
|
15
|
+
end
|
16
|
+
|
17
|
+
task :test => :compile do
|
18
|
+
junit FileList['build/**/Test*.class'].pathmap('%{build/,}X').gsub('/', '.'), :class_path => ['build/'], :colorize => true
|
19
|
+
end
|
20
|
+
|
21
|
+
directory 'build'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
package com.example;
|
2
|
+
|
3
|
+
|
4
|
+
import org.junit.Before;
|
5
|
+
import org.junit.Test;
|
6
|
+
|
7
|
+
import static org.junit.Assert.assertNotNull;
|
8
|
+
import static org.junit.Assert.assertEquals;
|
9
|
+
|
10
|
+
|
11
|
+
public class TestHelloWorld {
|
12
|
+
|
13
|
+
private HelloWorld helloWorld;
|
14
|
+
|
15
|
+
|
16
|
+
@Before
|
17
|
+
public void setUp( ) {
|
18
|
+
helloWorld = new HelloWorld();
|
19
|
+
}
|
20
|
+
|
21
|
+
@Test
|
22
|
+
public void testTheObvious( ) {
|
23
|
+
assertNotNull(helloWorld);
|
24
|
+
}
|
25
|
+
|
26
|
+
@Test
|
27
|
+
public void testThatFails( ) {
|
28
|
+
assertEquals(1, 2);
|
29
|
+
}
|
30
|
+
|
31
|
+
}
|
data/java_tools.gemspec
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{java_tools}
|
8
|
+
s.version = "0.2.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Theo Hultberg"]
|
12
|
+
s.date = %q{2009-10-08}
|
13
|
+
s.description = %q{Ant is a nice tool for writing Java build scripts, but Rake is nicer. The only thing missing from Rake is a way to run javac and jar, and although it's easy to run these as shell scripts you have to wait for the JVM to start. In combination with JRuby this gem lets you run javac and jar in your Rake scripts without exec'ing.}
|
14
|
+
s.email = %q{theo@iconara.net}
|
15
|
+
s.extensions = ["Rakefile"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
"LICENSE",
|
22
|
+
"README.rdoc",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"examples/compile/Rakefile",
|
26
|
+
"examples/compile/src/com/example/HelloWorld.java",
|
27
|
+
"examples/package/Rakefile",
|
28
|
+
"examples/package/src/com/example/HelloWorld.java",
|
29
|
+
"examples/test/Rakefile",
|
30
|
+
"examples/test/src/com/example/HelloWorld.java",
|
31
|
+
"examples/test/test/com/example/TestHelloWorld.java",
|
32
|
+
"java_tools.gemspec",
|
33
|
+
"lib/java_tools.rb",
|
34
|
+
"lib/java_tools/jar.rb",
|
35
|
+
"lib/java_tools/javac.rb",
|
36
|
+
"lib/java_tools/junit.rb",
|
37
|
+
"lib/java_tools/output/formatting.rb",
|
38
|
+
"spec/jar_cmd_spec.rb",
|
39
|
+
"spec/jar_spec.rb",
|
40
|
+
"spec/javac_cmd_spec.rb",
|
41
|
+
"spec/javac_spec.rb",
|
42
|
+
"spec/junit_cmd_spec.rb",
|
43
|
+
"spec/junit_spec.rb",
|
44
|
+
"spec/spec.opts",
|
45
|
+
"spec/spec_helper.rb",
|
46
|
+
"tasks/gem.rake",
|
47
|
+
"tasks/rdoc.rake",
|
48
|
+
"tasks/spec.rake"
|
49
|
+
]
|
50
|
+
s.homepage = %q{http://github.com/iconara/java_tools}
|
51
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
52
|
+
s.require_paths = ["lib"]
|
53
|
+
s.rubygems_version = %q{1.3.3}
|
54
|
+
s.summary = %q{Ruby wrappers for javac and jar that don't just exec}
|
55
|
+
s.test_files = [
|
56
|
+
"spec/jar_cmd_spec.rb",
|
57
|
+
"spec/jar_spec.rb",
|
58
|
+
"spec/javac_cmd_spec.rb",
|
59
|
+
"spec/javac_spec.rb",
|
60
|
+
"spec/junit_cmd_spec.rb",
|
61
|
+
"spec/junit_spec.rb",
|
62
|
+
"spec/spec_helper.rb"
|
63
|
+
]
|
64
|
+
|
65
|
+
if s.respond_to? :specification_version then
|
66
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
67
|
+
s.specification_version = 3
|
68
|
+
|
69
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
70
|
+
else
|
71
|
+
end
|
72
|
+
else
|
73
|
+
end
|
74
|
+
end
|
data/lib/pangolin.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
raise "Pangolin requires JRuby" unless RUBY_PLATFORM =~ /\bjava\b/
|
2
|
+
|
3
|
+
|
4
|
+
require File.expand_path(File.dirname(__FILE__)) + '/pangolin/output/formatting'
|
5
|
+
require File.expand_path(File.dirname(__FILE__)) + '/pangolin/javac'
|
6
|
+
require File.expand_path(File.dirname(__FILE__)) + '/pangolin/jar'
|
7
|
+
require File.expand_path(File.dirname(__FILE__)) + '/pangolin/junit'
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
module Pangolin # :nodoc:
|
12
|
+
|
13
|
+
def self.version # :nodoc:
|
14
|
+
version_file = File.join(File.dirname(__FILE__), '..', 'VERSION')
|
15
|
+
|
16
|
+
File.open(version_file) do |f|
|
17
|
+
f.readline.strip
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.exec_command( obj, options, block )
|
22
|
+
if block
|
23
|
+
block.call(obj)
|
24
|
+
elsif options
|
25
|
+
configure_command(obj, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
obj.execute or fail("Execution failed, see above")
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.configure_command( command, options ) # :nodoc:
|
32
|
+
options.each do |option, value|
|
33
|
+
setter_name = "#{option}="
|
34
|
+
|
35
|
+
if command.respond_to? setter_name
|
36
|
+
command.send(setter_name, value)
|
37
|
+
else
|
38
|
+
raise ArgumentError, "Invalid option: #{option}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
class Exception # :nodoc:
|
46
|
+
alias exception_backtrace backtrace
|
47
|
+
|
48
|
+
# Elide JRuby backtraces to remove all the internal stuff
|
49
|
+
def backtrace
|
50
|
+
exception_backtrace.reject do |line|
|
51
|
+
line =~ /^(org\/jruby|com\/mysql|sun\/|java\/)/
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Javac can be run in either command or yield mode: command mode
|
57
|
+
# looks roughly like this:
|
58
|
+
#
|
59
|
+
# javac [file1, file2], :destination => 'build'
|
60
|
+
#
|
61
|
+
# and yield mode like this:
|
62
|
+
#
|
63
|
+
# javac(file1, file2) do |conf|
|
64
|
+
# conf.destination = 'build'
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# In command mode you pass a hash with the configuration directives
|
68
|
+
# (listed below) and in yield mode an object is passed to the block,
|
69
|
+
# and the configuration directives should be set on that.
|
70
|
+
#
|
71
|
+
# The possible configuration directives are:
|
72
|
+
# * +source_path+
|
73
|
+
# * +destination+
|
74
|
+
# * +class_path+
|
75
|
+
# * +deprecation_warnings+
|
76
|
+
# * +warnings+
|
77
|
+
# * +encoding+
|
78
|
+
# * +verbose+
|
79
|
+
#
|
80
|
+
# The directives are the same as the properties of Pangolin::Javac.
|
81
|
+
#
|
82
|
+
def javac( source_files, options = nil, &block )
|
83
|
+
Pangolin::exec_command(Pangolin::Javac.new(*source_files), options, block)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Jar can be run in either command or yield mode: command mode
|
87
|
+
# looks roughly like this:
|
88
|
+
#
|
89
|
+
# jar 'output.jar', [file1, file2], :base_dir => 'build'
|
90
|
+
#
|
91
|
+
# and yield mode like this:
|
92
|
+
#
|
93
|
+
# jar('output.jar', [file1, file2]) do |conf|
|
94
|
+
# conf.base_dir = 'build'
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# In command mode you pass a hash with the configuration directives
|
98
|
+
# (listed below) and in yield mode an object is passed to the block,
|
99
|
+
# and the configuration directives should be set on that.
|
100
|
+
#
|
101
|
+
# The possible configuration directives are:
|
102
|
+
# * +base_dir+
|
103
|
+
# * +compression+
|
104
|
+
# * +verbose+
|
105
|
+
#
|
106
|
+
# The directives are the same as the properties of Pangolin::Jar.
|
107
|
+
#
|
108
|
+
def jar( output, files = nil, options = nil, &block )
|
109
|
+
base_dir = nil
|
110
|
+
|
111
|
+
if options && options[:base_dir]
|
112
|
+
base_dir = options[:base_dir]
|
113
|
+
end
|
114
|
+
|
115
|
+
Pangolin::exec_command(Pangolin::Jar.new(output, files, base_dir), options, block)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Junit can be run in either command or yield mode: command mode
|
119
|
+
# looks roughly like this:
|
120
|
+
#
|
121
|
+
# junit ['TestFoo', 'TestBar'], :class_path => ['build']
|
122
|
+
#
|
123
|
+
# (where +TestFoo+ and +TestBar+ are classes available from the class path).
|
124
|
+
#
|
125
|
+
# Yield mode looks like this:
|
126
|
+
#
|
127
|
+
# junit ['TestFoo', 'TestBar'] do |conf|
|
128
|
+
# conf.class_path = ['build']
|
129
|
+
# end
|
130
|
+
#
|
131
|
+
# In command mode you pass a hash with the configuration directives
|
132
|
+
# (listed below) and in yield mode an object is passed to the block,
|
133
|
+
# and the configuration directives should be set on that.
|
134
|
+
#
|
135
|
+
# The possible configuration directives are:
|
136
|
+
# * +class_path+
|
137
|
+
# * +colorize+
|
138
|
+
#
|
139
|
+
# The directives are the same as the properties of Pangolin::Junit.
|
140
|
+
#
|
141
|
+
def junit( classes, options = nil, &block )
|
142
|
+
Pangolin::exec_command(Pangolin::Junit.new(*classes), options, block)
|
143
|
+
end
|