jarbler 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile +4 -3
- data/README.md +4 -4
- data/jarbler.gemspec +1 -1
- data/lib/jarbler/JarMain.java +18 -1
- data/lib/jarbler/builder.rb +53 -28
- data/lib/jarbler/config.rb +16 -7
- data/lib/jarbler/version.rb +2 -2
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69c4dfd51fa32af943ab9ada29536253dc516150cdff7e82e1944216098a92c8
|
4
|
+
data.tar.gz: 63e6752eba98d7cc27642fcbb13a199fc41867a6d044edf28051f025d292ef09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 882f6b8e791b8f7fc9cc4eff3d86867c2667f8d817fd4c46a1f10103bcf98e50aee1e98c10b49fe14ae5e4f5a63a992ff9bf9121d4a9459d87e20ca05560c42a
|
7
|
+
data.tar.gz: e8b9a10dbfacc4180710a62fe84cfa9595049d62cd6ff6625cf520d39d380357f13502f0e0f228057d85d226d4ef29fe255e5cc63cf011f5d00f92bc8c5d2c52
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
@@ -8,10 +8,11 @@ gemspec
|
|
8
8
|
# gem "rake", "~> 13.0"
|
9
9
|
gem "rake"
|
10
10
|
|
11
|
+
group(:development) do
|
12
|
+
gem 'rdoc'
|
13
|
+
end
|
14
|
+
|
11
15
|
group(:test) do
|
12
16
|
gem 'minitest'
|
13
17
|
gem 'minitest-reporters'
|
14
|
-
# needed for minitests
|
15
|
-
# test should install the jruby-jars in right version itself
|
16
|
-
# gem 'jruby-jars'
|
17
18
|
end
|
data/README.md
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# Jarbler
|
2
2
|
Pack a Ruby application into an executable jar file.
|
3
3
|
|
4
|
-
Jarbler
|
4
|
+
Jarbler creates a self executing Java jar file containing a Ruby application and all its Gem dependencies.
|
5
5
|
|
6
6
|
This tool is inspired by the widely used jRuby runner Warbler.
|
7
|
-
|
8
|
-
Instead the configured executable is executed using the jRuby runtime jars.
|
7
|
+
The configured Ruby program is directly executed inside the JVM using the jRuby runtime jars.
|
9
8
|
|
10
9
|
## Installation
|
11
10
|
|
@@ -28,6 +27,7 @@ To adjust Jarbler's configuration, modify the settings in config file ´config/j
|
|
28
27
|
$ jarble config
|
29
28
|
|
30
29
|
### Preconditions
|
30
|
+
* Dependency handling should be based on Bundler (existence of Gemfile is required)
|
31
31
|
* The Ruby app should be capable of running with jRuby
|
32
32
|
* Gems with native extensions should not be used (e.g. sassc)
|
33
33
|
* if needed for development or test such Gems with native extensions should be moved to the development and test group in the Gemfile.
|
@@ -43,7 +43,7 @@ Additional command line parameters are passed through to the executed Ruby app (
|
|
43
43
|
## Configuration
|
44
44
|
|
45
45
|
The file config/jarble.rb contains the configuration for Jarbler.
|
46
|
-
To create a template config file with information about the supported configuration options, execute:
|
46
|
+
To create a template config file with information about all the supported configuration options, execute:
|
47
47
|
|
48
48
|
$ jarble config
|
49
49
|
|
data/jarbler.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.email = ["Peter@ramm-oberhermsdorf.de"]
|
10
10
|
|
11
11
|
spec.summary = "Pack a Ruby app into a Java jar file"
|
12
|
-
spec.description = "Pack Ruby combined with jRuby runtime into a jar file to simply run the app on any Java platform by '> java -jar file.jar'"
|
12
|
+
spec.description = "Pack a Ruby app combined with jRuby runtime and all its Gem dependencies into a jar file to simply run the app on any Java platform by '> java -jar file.jar'"
|
13
13
|
spec.homepage = "https://github.com/rammpeter/jarbler"
|
14
14
|
spec.license = "MIT"
|
15
15
|
spec.required_ruby_version = ">= 2.6.0"
|
data/lib/jarbler/JarMain.java
CHANGED
@@ -27,13 +27,16 @@ import java.util.Map;
|
|
27
27
|
import java.util.HashMap;
|
28
28
|
import java.lang.reflect.Field;
|
29
29
|
import java.io.FileWriter;
|
30
|
+
import java.security.CodeSource;
|
31
|
+
import java.security.ProtectionDomain;
|
30
32
|
|
31
33
|
class JarMain {
|
32
34
|
|
33
35
|
// executed by java -jar <jar file name>
|
34
36
|
// No arguments are passed
|
35
37
|
public static void main(String[] args) {
|
36
|
-
debug("Start java process in jar file");
|
38
|
+
debug("Start java process in jar file "+jar_file_name());
|
39
|
+
debug("JVM: "+System.getProperty("java.vm.vendor")+" "+System.getProperty("java.vm.name")+" "+System.getProperty("java.vm.version")+" "+System.getProperty("java.home"));
|
37
40
|
if (args.length > 0) {
|
38
41
|
debug("Java command line arguments are: ");
|
39
42
|
for (String arg : args) {
|
@@ -225,4 +228,18 @@ class JarMain {
|
|
225
228
|
fw.write("BUNDLE_WITHOUT: test:development\n");
|
226
229
|
fw.close();
|
227
230
|
}
|
231
|
+
|
232
|
+
private static String jar_file_name() {
|
233
|
+
String jarFileName = "";
|
234
|
+
|
235
|
+
try {
|
236
|
+
ProtectionDomain protectionDomain = JarMain.class.getProtectionDomain();
|
237
|
+
CodeSource codeSource = protectionDomain.getCodeSource();
|
238
|
+
URL location = codeSource.getLocation();
|
239
|
+
jarFileName = new File(location.toURI()).getName();
|
240
|
+
} catch (Exception e) {
|
241
|
+
e.printStackTrace();
|
242
|
+
}
|
243
|
+
return jarFileName;
|
244
|
+
}
|
228
245
|
}
|
data/lib/jarbler/builder.rb
CHANGED
@@ -13,9 +13,8 @@ module Jarbler
|
|
13
13
|
def build_jar
|
14
14
|
debug "Running with Ruby version '#{RUBY_VERSION}' on platform '#{RUBY_PLATFORM}'. Engine '#{RUBY_ENGINE}' version '#{RUBY_ENGINE_VERSION}'"
|
15
15
|
|
16
|
-
#
|
17
|
-
staging_dir = Dir.mktmpdir
|
18
|
-
|
16
|
+
@config = nil # Ensure config is read from file or default. Necessary for testing only because of caching
|
17
|
+
staging_dir = Dir.mktmpdir # create a temporary directory for staging
|
19
18
|
app_root = Dir.pwd
|
20
19
|
debug "Project dir: #{app_root}"
|
21
20
|
|
@@ -31,12 +30,8 @@ module Jarbler
|
|
31
30
|
# Get the needed Gems
|
32
31
|
raise "Gemfile.lock not found in #{app_root}" unless File.exist?("#{app_root}/Gemfile.lock")
|
33
32
|
|
34
|
-
gem_target_location = "#{staging_dir}/gems/jruby/#{ruby_version}"
|
35
|
-
FileUtils.mkdir_p("#{gem_target_location}/gems")
|
36
|
-
FileUtils.mkdir_p("#{gem_target_location}/specifications")
|
37
|
-
|
38
33
|
# Copy the needed Gems to the staging directory
|
39
|
-
copy_needed_gems_to_staging(
|
34
|
+
copy_needed_gems_to_staging(staging_dir, ruby_version)
|
40
35
|
|
41
36
|
Dir.chdir(staging_dir) do
|
42
37
|
# create the manifest file
|
@@ -73,16 +68,25 @@ module Jarbler
|
|
73
68
|
file_utils_copy(config.jar_name, app_root)
|
74
69
|
puts "Created jar file #{app_root}/#{config.jar_name}"
|
75
70
|
end
|
76
|
-
|
71
|
+
rescue Exception => e
|
72
|
+
puts "Error: #{e.message}"
|
73
|
+
puts e.backtrace.join("\n")
|
74
|
+
raise
|
75
|
+
ensure
|
77
76
|
# remove temporary directory staging_dir
|
78
|
-
|
79
|
-
|
77
|
+
if ENV['DEBUG']
|
78
|
+
puts "Temporary directory #{staging_dir} not removed because of debug mode"
|
79
|
+
else
|
80
|
+
FileUtils.remove_entry staging_dir if staging_dir
|
81
|
+
end
|
80
82
|
end
|
81
83
|
|
82
84
|
private
|
83
85
|
|
84
86
|
|
85
87
|
# Check if there is an additional local bundle path in .bundle/config
|
88
|
+
# @param rails_root [String] the rails root directory
|
89
|
+
# @return [String] the local bundle path or nil if not configured
|
86
90
|
def bundle_config_bundle_path(rails_root)
|
87
91
|
bundle_path = nil # default
|
88
92
|
if File.exist?("#{rails_root}/.bundle/config")
|
@@ -96,30 +100,41 @@ module Jarbler
|
|
96
100
|
end
|
97
101
|
|
98
102
|
# Copy the needed Gems to the staging directory
|
99
|
-
# @param [String]
|
103
|
+
# @param staging_dir [String] the staging directory
|
104
|
+
# @param ruby_version [String] the corresponding ruby version of the jruby jars version
|
100
105
|
# @return [void]
|
101
|
-
def copy_needed_gems_to_staging(
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
106
|
+
def copy_needed_gems_to_staging(staging_dir, ruby_version)
|
107
|
+
gem_target_location = "#{staging_dir}/gems/jruby/#{ruby_version}"
|
108
|
+
FileUtils.mkdir_p("#{gem_target_location}/gems")
|
109
|
+
FileUtils.mkdir_p("#{gem_target_location}/specifications")
|
110
|
+
FileUtils.mkdir_p("#{gem_target_location}/bundler/gems")
|
111
|
+
|
112
|
+
needed_gems = gem_dependencies # get the full names of the dependencies
|
113
|
+
needed_gems.each do |needed_gem|
|
114
|
+
# Get the location of the needed gem
|
115
|
+
spec = Gem::Specification.find_by_name(needed_gem[:name], needed_gem[:version])
|
116
|
+
raise "Gem #{needed_gem[:full_name]} not found for copying" unless spec
|
117
|
+
debug "Found gem #{needed_gem[:full_name]} version #{needed_gem[:version]} in #{spec.gem_dir}"
|
118
|
+
|
119
|
+
# differentiate between Gems from git/bundler and Gems from rubygems
|
120
|
+
if spec.source.is_a?(Bundler::Source::Git)
|
121
|
+
# Copy the Gem from bundler/gems including the gemspec
|
122
|
+
file_utils_copy(spec.gem_dir, "#{gem_target_location}/bundler/gems")
|
123
|
+
else # Gem is from rubygems
|
124
|
+
# copy the Gem and gemspec separately
|
110
125
|
file_utils_copy(spec.gem_dir, "#{gem_target_location}/gems")
|
111
126
|
file_utils_copy("#{spec.gem_dir}/../../specifications/#{needed_gem[:full_name]}.gemspec", "#{gem_target_location}/specifications")
|
112
|
-
|
127
|
+
end
|
113
128
|
end
|
114
129
|
end
|
115
130
|
|
116
131
|
# Read the default/production dependencies from Gemfile.lock and Gemfile
|
117
|
-
# @return [Array] Array with
|
132
|
+
# @return [Array] Array with Hashes containing: name, version, full_name
|
118
133
|
def gem_dependencies
|
119
134
|
needed_gems = []
|
120
135
|
lockfile_specs = Bundler::LockfileParser.new(Bundler.read_file(Bundler.default_lockfile)).specs
|
121
136
|
|
122
|
-
|
137
|
+
Bundler.setup # Load Gems specified in Gemfile, ensure that Gem path also includes the Gems loaded into bundler dir
|
123
138
|
# filter Gems needed for production
|
124
139
|
gemfile_specs = Bundler.definition.dependencies.select do |d|
|
125
140
|
d.groups.include?(:default) || d.groups.include?(:production)
|
@@ -145,7 +160,7 @@ module Jarbler
|
|
145
160
|
# recurively find all indirect dependencies
|
146
161
|
# @param [Array] lockfile_specs Array of Bundler::LockfileParser::Spec objects
|
147
162
|
# @param [Bundler::LockfileParser::Spec] lockfile_spec current lockfile spec to check for their dependencies
|
148
|
-
# @param [Array] needed_gems Array with
|
163
|
+
# @param [Array] needed_gems Array with Hashes containing: name, version, full_name
|
149
164
|
# @return [void]
|
150
165
|
def add_indirect_dependencies(lockfile_specs, lockfile_spec, needed_gems)
|
151
166
|
lockfile_spec.dependencies.each do |lockfile_spec_dep|
|
@@ -161,12 +176,18 @@ module Jarbler
|
|
161
176
|
end
|
162
177
|
end
|
163
178
|
end
|
179
|
+
|
180
|
+
# Output debug message if DEBUG environment variable is set
|
181
|
+
# @param [String] msg Message to output
|
182
|
+
# @return [void]
|
164
183
|
def debug(msg)
|
165
184
|
puts msg if ENV['DEBUG']
|
166
185
|
end
|
167
186
|
|
187
|
+
# Get the config object
|
188
|
+
# @return [Config] the config object
|
168
189
|
def config
|
169
|
-
|
190
|
+
if !defined?(@config) || @config.nil?
|
170
191
|
@config = Config.create
|
171
192
|
debug("Config attributes:")
|
172
193
|
@config.instance_variables.each do |var|
|
@@ -179,7 +200,6 @@ module Jarbler
|
|
179
200
|
|
180
201
|
# Copy the jruby-jars to the staging directory
|
181
202
|
# @param [String] staging_dir Path to the staging directory
|
182
|
-
# @param [Array] gem_search_locations Array of Gem locations to look for jRuby jars
|
183
203
|
# @return [String] the ruby version of the jRuby jars
|
184
204
|
def copy_jruby_jars_to_staging(staging_dir)
|
185
205
|
|
@@ -207,7 +227,9 @@ module Jarbler
|
|
207
227
|
ruby_version
|
208
228
|
end
|
209
229
|
|
210
|
-
# Execute the command and return the output
|
230
|
+
# Execute the command in OS and return the output
|
231
|
+
# @param [String] command Command to execute
|
232
|
+
# @return [String] the output of the command
|
211
233
|
def exec_command(command)
|
212
234
|
lines = `#{command}`
|
213
235
|
raise "Command \"#{command}\"failed with return code #{$?} and output:\n#{lines}" unless $?.success?
|
@@ -216,6 +238,9 @@ module Jarbler
|
|
216
238
|
end
|
217
239
|
|
218
240
|
# Copy file or directory with error handling
|
241
|
+
# @param [String] source Path to the source file or directory
|
242
|
+
# @param [String] destination Path to the destination file or directory
|
243
|
+
# @return [void]
|
219
244
|
def file_utils_copy(source, destination)
|
220
245
|
if File.exist?(source) && File.directory?(source)
|
221
246
|
FileUtils.cp_r(source, destination)
|
data/lib/jarbler/config.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'json'
|
3
|
+
|
1
4
|
module Jarbler
|
2
5
|
class Config
|
3
6
|
attr_accessor :jar_name, :includes, :excludes, :jruby_version, :executable, :executable_params
|
4
7
|
|
5
8
|
CONFIG_FILE = 'config/jarble.rb'
|
6
|
-
# create
|
9
|
+
# create instance of Config class with defaults or from config file
|
7
10
|
# Should be called from rails/ruby root directory
|
8
11
|
def self.create
|
9
12
|
if File.exist?(CONFIG_FILE)
|
@@ -90,12 +93,18 @@ module Jarbler
|
|
90
93
|
else
|
91
94
|
# no .ruby-version file, use jRuby version of the latest Gem
|
92
95
|
# Fetch the gem specification from Rubygems.org
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
raise "
|
98
|
-
|
96
|
+
# search for the gem and get the JSON response
|
97
|
+
response = Gem::SpecFetcher.fetcher.search_for_dependency(Gem::Dependency.new('jruby-jars'))
|
98
|
+
# extract the versions from the response
|
99
|
+
self.jruby_version = response&.first&.first&.first&.version&.to_s
|
100
|
+
raise "Unable to determine the latest available version of jruby-jars gem!\Rsponse = #{response.inspect}" unless self.jruby_version
|
101
|
+
|
102
|
+
#command = "gem search --remote jruby-jars"
|
103
|
+
#lines = `#{command}`
|
104
|
+
#raise "Command \"#{command}\" failed with return code #{$?} and output:\n#{lines}" unless $?.success?
|
105
|
+
#jruby_jars_line = lines.match(/^jruby-jars \((.*)\)/)
|
106
|
+
#raise "No jruby-jars gem found in rubygems.org!" unless jruby_jars_line
|
107
|
+
#self.jruby_version = /\((.*?)\)/.match(jruby_jars_line.to_s)[1]
|
99
108
|
debug "jRuby version from latest jruby-jars gem: #{jruby_version}"
|
100
109
|
end
|
101
110
|
end
|
data/lib/jarbler/version.rb
CHANGED
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jarbler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ramm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: Pack Ruby combined with jRuby runtime
|
14
|
-
app on any Java platform by '> java -jar file.jar'
|
13
|
+
description: Pack a Ruby app combined with jRuby runtime and all its Gem dependencies
|
14
|
+
into a jar file to simply run the app on any Java platform by '> java -jar file.jar'
|
15
15
|
email:
|
16
16
|
- Peter@ramm-oberhermsdorf.de
|
17
17
|
executables:
|