puck 1.0.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +4 -0
- data/bin/puck +6 -0
- data/lib/puck.rb +10 -0
- data/lib/puck/bootstrap.rb +12 -0
- data/lib/puck/configuration.rb +52 -0
- data/lib/puck/dependency_resolver.rb +75 -0
- data/lib/puck/jar.rb +168 -0
- data/lib/puck/version.rb +5 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1d3c8ed8c414ffb5241dd8dd7b903686ea9d1bf5
|
4
|
+
data.tar.gz: 67e2972eaafcac0792998786d3d65b96942dc4f2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 32db0d6f29e15a77dc05cb24078c18333c1bf2de228ee1bf8b5fcd113c1eab0c1a4308d972411b6690e1f6da2f2b828376e704d94eba27e63cdcc0c4a20b89cd
|
7
|
+
data.tar.gz: 9fd222f28c53f4d6f61a4532b14d56cbd077d09efccdd68b05a334f891084e930cf541ac6e97d989bf4d6e0fe6637d8d6b0fe0daa50f8f59e82c52e1b0fa3fe9
|
data/.yardopts
ADDED
data/bin/puck
ADDED
data/lib/puck.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
if ARGV.any?
|
2
|
+
file_name = ARGV.shift
|
3
|
+
PUCK_BIN_PATH.each do |dir|
|
4
|
+
relative_path = File.join(dir, file_name)
|
5
|
+
if File.exists?("classpath:/#{relative_path}")
|
6
|
+
$0 = relative_path
|
7
|
+
load(relative_path)
|
8
|
+
return
|
9
|
+
end
|
10
|
+
end
|
11
|
+
abort(%(No "#{file_name}" in #{PUCK_BIN_PATH.join(File::PATH_SEPARATOR)}))
|
12
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
|
6
|
+
module Puck
|
7
|
+
# @private
|
8
|
+
class Configuration
|
9
|
+
def initialize(defaults={})
|
10
|
+
@argv = defaults[:argv] || ARGV
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.get(defaults={})
|
14
|
+
new(defaults).get
|
15
|
+
end
|
16
|
+
|
17
|
+
def get
|
18
|
+
command_line_options
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
SCALAR_ARGS = [:app_name, :app_dir, :build_dir, :jruby_complete].freeze
|
24
|
+
LIST_ARGS = [:extra_files].freeze
|
25
|
+
ARG_PREFIX = '--'.freeze
|
26
|
+
|
27
|
+
def command_line_options
|
28
|
+
state = nil
|
29
|
+
option = nil
|
30
|
+
@argv.each_with_object({}) do |arg, options|
|
31
|
+
if arg.start_with?(ARG_PREFIX)
|
32
|
+
option = arg.sub(/^--/, '').gsub('-', '_').to_sym
|
33
|
+
if LIST_ARGS.include?(option)
|
34
|
+
options[option] = []
|
35
|
+
state = :list
|
36
|
+
else
|
37
|
+
state = :scalar
|
38
|
+
end
|
39
|
+
else
|
40
|
+
case state
|
41
|
+
when :list
|
42
|
+
options[option] << arg
|
43
|
+
when :scalar
|
44
|
+
options[option] = arg
|
45
|
+
option = nil
|
46
|
+
state = nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
module Puck
|
5
|
+
# @private
|
6
|
+
class DependencyResolver
|
7
|
+
def resolve_gem_dependencies(options = {})
|
8
|
+
gem_home = options[:gem_home] || ENV['GEM_HOME']
|
9
|
+
gemfile = options[:gemfile] || File.expand_path('Gemfile', options[:app_dir] || Dir.pwd)
|
10
|
+
lockfile = options[:lockfile] || "#{gemfile}.lock"
|
11
|
+
groups = options[:gem_groups] || [:default]
|
12
|
+
|
13
|
+
bundler_specs = contained_bundler(gem_home, gemfile, lockfile, groups)
|
14
|
+
bundler_specs.delete_if { |spec| spec[:name] == 'bundler' }
|
15
|
+
bundler_specs.map do |spec|
|
16
|
+
base_path = spec[:full_gem_path].chomp('/')
|
17
|
+
load_paths = spec[:load_paths].map do |load_path|
|
18
|
+
unless load_path.start_with?(base_path)
|
19
|
+
raise PuckError, 'Unsupported load path "%s" in gem "%s"' % [load_path, bundler_spec.name]
|
20
|
+
end
|
21
|
+
load_path[base_path.size + 1, load_path.length - base_path.size - 1]
|
22
|
+
end
|
23
|
+
{
|
24
|
+
:name => spec[:name],
|
25
|
+
:versioned_name => spec[:full_name],
|
26
|
+
:base_path => base_path,
|
27
|
+
:load_paths => load_paths,
|
28
|
+
:bin_path => spec[:bindir],
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def contained_bundler(gem_home, gemfile, lockfile, groups)
|
36
|
+
Bundler.with_clean_env do
|
37
|
+
scripting_container = Java::OrgJrubyEmbed::ScriptingContainer.new(Java::OrgJrubyEmbed::LocalContextScope::SINGLETHREAD)
|
38
|
+
scripting_container.compat_version = Java::OrgJruby::CompatVersion::RUBY1_9
|
39
|
+
scripting_container.current_directory = Dir.pwd
|
40
|
+
scripting_container.environment = Hash[ENV.merge('GEM_HOME' => gem_home).map { |k,v| [k.to_java, v.to_java] }]
|
41
|
+
scripting_container.put('arguments', Marshal.dump([gemfile, lockfile, groups]).to_java_bytes)
|
42
|
+
begin
|
43
|
+
line = __LINE__ + 1 # as __LINE__ represents next statement line i JRuby, and that becomes difficult to offset
|
44
|
+
unit = scripting_container.parse(StringIO.new(<<-"EOS").to_inputstream, __FILE__, line)
|
45
|
+
begin
|
46
|
+
require 'bundler'
|
47
|
+
gemfile, lockfile, groups = Marshal.load(String.from_java_bytes(arguments))
|
48
|
+
definition = Bundler::Definition.build(gemfile, lockfile, false)
|
49
|
+
ENV['BUNDLE_WITHOUT'] = (definition.groups - groups).join(':')
|
50
|
+
specs = definition.specs.map do |gem_spec|
|
51
|
+
{
|
52
|
+
:name => gem_spec.name,
|
53
|
+
:full_name => gem_spec.full_name,
|
54
|
+
:full_gem_path => gem_spec.full_gem_path,
|
55
|
+
:load_paths => gem_spec.load_paths,
|
56
|
+
:bindir => gem_spec.bindir,
|
57
|
+
}
|
58
|
+
end
|
59
|
+
Marshal.dump([specs]).to_java_bytes
|
60
|
+
rescue => e
|
61
|
+
Marshal.dump([nil, e.class, e.message, e.backtrace]).to_java_bytes
|
62
|
+
end
|
63
|
+
EOS
|
64
|
+
result, error, message, backtrace = Marshal.load(String.from_java_bytes(unit.run))
|
65
|
+
if error
|
66
|
+
raise error, message, Array(backtrace)+caller
|
67
|
+
end
|
68
|
+
result
|
69
|
+
ensure
|
70
|
+
scripting_container.terminate
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/puck/jar.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'tmpdir'
|
5
|
+
require 'pathname'
|
6
|
+
require 'set'
|
7
|
+
require 'ant'
|
8
|
+
require 'puck/version'
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'jruby-jars'
|
12
|
+
rescue LoadError
|
13
|
+
end
|
14
|
+
|
15
|
+
module Puck
|
16
|
+
# Creates a standalone Jar file from your application.
|
17
|
+
#
|
18
|
+
# The Jar will contain your application code (which is assumed to be in the
|
19
|
+
# "lib" directory), bin files (assumed to be in the "bin" directory), all the
|
20
|
+
# gems in your default group (i.e. those that are not in a `group` block in
|
21
|
+
# your Gemfile), including gems loaded from git, or from a path. It will also
|
22
|
+
# contain a JRuby runtime so that to run it you only need a Java runtime.
|
23
|
+
#
|
24
|
+
# The Jar file will be configured so that you can run your application's bin
|
25
|
+
# files by passing their name as the first argument after the Jar file (see example below).
|
26
|
+
#
|
27
|
+
# @example Creating a Jar from a Rake task
|
28
|
+
# task :jar do
|
29
|
+
# Puck::Jar.new.create
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# @example Configuring the Jar file
|
33
|
+
# task :jar do
|
34
|
+
# jar = Puck::Jar.new(
|
35
|
+
# extra_files: Dir['config/*.yml'],
|
36
|
+
# jruby_complete: 'build/custom-jruby-complete.jar'
|
37
|
+
# )
|
38
|
+
# jar.create
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# @example Running a bin file
|
42
|
+
# java -jar path/to/application.jar my-bin-file arg1 arg2
|
43
|
+
#
|
44
|
+
class Jar
|
45
|
+
# Create a new instance with the specified configuration.
|
46
|
+
#
|
47
|
+
# Puck tries to use sane defaults like assuming that the application name
|
48
|
+
# is the same as the name of the directory containing the "lib" directory.
|
49
|
+
#
|
50
|
+
# @param [Hash] configuration
|
51
|
+
# @option configuration [String] :extra_files a list of files to include in
|
52
|
+
# the Jar. The paths must be below the `:app_dir`.
|
53
|
+
# @option configuration [String] :gem_groups ([:default]) a list of gem
|
54
|
+
# groups to include in the Jar. Remember to include the default group if
|
55
|
+
# you override this option.
|
56
|
+
# @option configuration [String] :jruby_complete a path to the
|
57
|
+
# `jruby-complete.jar` that you want to use. If you don't specify this
|
58
|
+
# option you need to have `jruby-jars` in your `Gemfile` (it contains
|
59
|
+
# the equivalent of `jruby-complete.jar`. This option is mostly useful
|
60
|
+
# when you have a customized JRuby runtime that you want to use.
|
61
|
+
# @option configuration [String] :app_dir (Dir.pwd)
|
62
|
+
# the application's base directory (i.e. the directory that contains the
|
63
|
+
# "lib" directory)
|
64
|
+
# @option configuration [String] :app_name (File.basename(configuration[:app_dir]))
|
65
|
+
# the name of the application, primarily used to name the Jar
|
66
|
+
# @option configuration [String] :build_dir ("build") the directory where
|
67
|
+
# the Jar file will be created
|
68
|
+
#
|
69
|
+
def initialize(configuration={})
|
70
|
+
@configuration = configuration.dup
|
71
|
+
@configuration[:app_dir] ||= Dir.pwd
|
72
|
+
@configuration[:app_name] ||= File.basename(@configuration[:app_dir])
|
73
|
+
@configuration[:build_dir] ||= File.join(@configuration[:app_dir], 'build')
|
74
|
+
@configuration[:jar_name] ||= @configuration[:app_name] + '.jar'
|
75
|
+
@configuration[:gem_groups] ||= [:default]
|
76
|
+
@dependency_resolver = @configuration[:dependency_resolver] || DependencyResolver.new
|
77
|
+
end
|
78
|
+
|
79
|
+
# Create the Jar file using the instance's configuration.
|
80
|
+
#
|
81
|
+
# @return The path to the Jar file
|
82
|
+
#
|
83
|
+
def create
|
84
|
+
FileUtils.mkdir_p(@configuration[:build_dir])
|
85
|
+
|
86
|
+
Dir.mktmpdir do |tmp_dir|
|
87
|
+
output_path = File.join(@configuration[:build_dir], @configuration[:jar_name])
|
88
|
+
project_dir = Pathname.new(@configuration[:app_dir]).expand_path.cleanpath
|
89
|
+
extra_files = @configuration[:extra_files] || []
|
90
|
+
jruby_complete_path = @configuration[:jruby_complete]
|
91
|
+
|
92
|
+
if !(defined? JRubyJars) && !(jruby_complete_path && File.exists?(jruby_complete_path))
|
93
|
+
raise PuckError, 'Cannot build Jar: jruby-jars must be installed, or :jruby_complete must be specified'
|
94
|
+
end
|
95
|
+
|
96
|
+
gem_dependencies = @dependency_resolver.resolve_gem_dependencies(@configuration)
|
97
|
+
create_jar_bootstrap!(tmp_dir, gem_dependencies)
|
98
|
+
|
99
|
+
ant = Ant.new(output_level: 1)
|
100
|
+
ant.jar(destfile: output_path) do
|
101
|
+
manifest do
|
102
|
+
attribute name: 'Main-Class', value: 'org.jruby.JarBootstrapMain'
|
103
|
+
attribute name: 'Created-By', value: "Puck v#{Puck::VERSION}"
|
104
|
+
end
|
105
|
+
|
106
|
+
zipfileset dir: tmp_dir, includes: 'jar-bootstrap.rb'
|
107
|
+
|
108
|
+
if jruby_complete_path
|
109
|
+
zipfileset src: jruby_complete_path
|
110
|
+
else
|
111
|
+
zipfileset src: JRubyJars.core_jar_path
|
112
|
+
zipfileset src: JRubyJars.stdlib_jar_path
|
113
|
+
end
|
114
|
+
|
115
|
+
%w[bin lib].each do |sub_dir|
|
116
|
+
path = project_dir + sub_dir
|
117
|
+
if File.exists?(path)
|
118
|
+
zipfileset dir: path, prefix: File.join(JAR_APP_HOME, sub_dir)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
extra_files.each do |ef|
|
123
|
+
path = Pathname.new(ef).expand_path.cleanpath
|
124
|
+
prefix = File.join(JAR_APP_HOME, path.relative_path_from(project_dir).dirname.to_s)
|
125
|
+
zipfileset dir: path.dirname, prefix: prefix, includes: path.basename
|
126
|
+
end
|
127
|
+
|
128
|
+
gem_dependencies.each do |spec|
|
129
|
+
base_path = Pathname.new(spec[:base_path]).expand_path.cleanpath
|
130
|
+
unless project_dir == base_path
|
131
|
+
zipfileset dir: spec[:base_path], prefix: File.join(JAR_GEM_HOME, spec[:versioned_name])
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
output_path
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# @deprecated Use #create
|
141
|
+
def create!
|
142
|
+
create
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
JAR_APP_HOME = 'META-INF/app.home'.freeze
|
148
|
+
JAR_GEM_HOME = 'META-INF/gem.home'.freeze
|
149
|
+
JAR_JRUBY_HOME = 'META-INF/jruby.home'.freeze
|
150
|
+
|
151
|
+
def create_jar_bootstrap!(tmp_dir, gem_dependencies)
|
152
|
+
File.open(File.join(tmp_dir, 'jar-bootstrap.rb'), 'w') do |io|
|
153
|
+
io.puts(%(PUCK_BIN_PATH = ['#{JAR_APP_HOME}/bin', '#{JAR_JRUBY_HOME}/bin']))
|
154
|
+
gem_dependencies.each do |spec|
|
155
|
+
io.puts("PUCK_BIN_PATH << '#{JAR_GEM_HOME}/#{spec[:versioned_name]}/#{spec[:bin_path]}'")
|
156
|
+
end
|
157
|
+
io.puts
|
158
|
+
gem_dependencies.each do |spec|
|
159
|
+
spec[:load_paths].each do |load_path|
|
160
|
+
io.puts(%($LOAD_PATH << 'classpath:#{JAR_GEM_HOME}/#{spec[:versioned_name]}/#{load_path}'))
|
161
|
+
end
|
162
|
+
end
|
163
|
+
io.puts
|
164
|
+
io.puts(File.read(File.expand_path('../bootstrap.rb', __FILE__)))
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
data/lib/puck/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: puck
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: java
|
6
|
+
authors:
|
7
|
+
- Theo Hultberg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-12 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Puck takes your app and packs it along with all your gems and a complete JRuby runtime in a standalone Jar file that can be run with just `java -jar …`
|
14
|
+
email:
|
15
|
+
- theo@iconara.net
|
16
|
+
executables:
|
17
|
+
- puck
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .yardopts
|
22
|
+
- bin/puck
|
23
|
+
- lib/puck.rb
|
24
|
+
- lib/puck/bootstrap.rb
|
25
|
+
- lib/puck/configuration.rb
|
26
|
+
- lib/puck/dependency_resolver.rb
|
27
|
+
- lib/puck/jar.rb
|
28
|
+
- lib/puck/version.rb
|
29
|
+
homepage: http://github.com/iconara/puck
|
30
|
+
licenses:
|
31
|
+
- Apache License 2.0
|
32
|
+
metadata: {}
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project: puck
|
49
|
+
rubygems_version: 2.2.2
|
50
|
+
signing_key:
|
51
|
+
specification_version: 4
|
52
|
+
summary: Packs your JRuby app as a standalone Jar file
|
53
|
+
test_files: []
|
54
|
+
has_rdoc:
|