puck 1.0.0-java
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.
- 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:
|