lib/jarbler/builder.rb in jarbler-0.1.2 vs lib/jarbler/builder.rb in jarbler-0.1.3
- old
+ new
@@ -1,27 +1,28 @@
+require 'rubygems'
+require 'rubygems/dependency_installer'
require 'bundler'
require 'find'
require 'fileutils'
+require 'yaml'
module Jarbler
class Builder
# Execute all functions needed to build the jar file
# Should be executed in application directory of Rails/Ruby application
# @return [void]
def build_jar
+ debug "Running with Ruby version '#{RUBY_VERSION}' on platform '#{RUBY_PLATFORM}'. Engine '#{RUBY_ENGINE}' version '#{RUBY_ENGINE_VERSION}'"
+
# create a temporary directory for staging
staging_dir = Dir.mktmpdir
- jarbler_lib_dir = __dir__
app_root = Dir.pwd
debug "Project dir: #{app_root}"
- # TODO: transform to internal bundler API call (check if jruby is installed + install if not)
- exec_command "gem install --no-doc jruby-jars -v #{config.jruby_version}" # Ensure that jruby-jars are installed in the requested version
- gem_search_locations = collect_gem_search_locations(app_root)
- ruby_version = copy_jruby_jars_to_staging(staging_dir, gem_search_locations) # Copy the jruby jars to the staging directory
- exec_command "javac -nowarn -Xlint:deprecation -source 8 -target 8 -d #{staging_dir} #{jarbler_lib_dir}/JarMain.java" # Compile the Java files
+ ruby_version = copy_jruby_jars_to_staging(staging_dir) # Copy the jruby jars to the staging directory
+ exec_command "javac -nowarn -Xlint:deprecation -source 8 -target 8 -d #{staging_dir} #{__dir__}/JarMain.java" # Compile the Java files
# Copy the application project to the staging directory
FileUtils.mkdir_p("#{staging_dir}/app_root")
config.includes.each do |dir|
file_utils_copy("#{app_root}/#{dir}", "#{staging_dir}/app_root") if File.exist?("#{app_root}/#{dir}")
@@ -32,14 +33,12 @@
gem_target_location = "#{staging_dir}/gems/jruby/#{ruby_version}"
FileUtils.mkdir_p("#{gem_target_location}/gems")
FileUtils.mkdir_p("#{gem_target_location}/specifications")
- needed_gems = gem_dependencies # get the full names of the dependencies
- needed_gems.each do |gem_full_name|
- copy_gem_to_staging(gem_full_name, gem_target_location, gem_search_locations)
- end
+ # Copy the needed Gems to the staging directory
+ copy_needed_gems_to_staging(gem_target_location, app_root)
Dir.chdir(staging_dir) do
# create the manifest file
File.open('Manifest.txt', 'w') do |file|
file.write("Comment: created by Jarbler (https://github.com/rammpeter/jarbler)\n")
@@ -80,84 +79,69 @@
end
private
- # Find the locations where Gems are installed
- # @param [String] app_root Application root directory
- # @return [Array] Array of Gem locations
- def collect_gem_search_locations(app_root)
- # All active search locations for Gems
- Bundler.setup
- possible_gem_search_locations = Gem.paths.path
- debug "Possible Gem locations: #{possible_gem_search_locations}"
- gem_search_locations = []
- # Check where inside this location the gems may be installed
- possible_gem_search_locations.each do |gem_search_location|
- if File.exist?(gem_search_location) && File.directory?(gem_search_location)
- valid_gem_search_location = nil # No valid path found yet
- Find.find(gem_search_location) do |path|
- if File.directory?(path) && File.exist?("#{path}/specifications") && File.exist?("#{path}/gems")
- valid_gem_search_location = path # Found a valid path
- Find.prune # Do not search deeper
- end
- end
- if valid_gem_search_location
- gem_search_locations << valid_gem_search_location
- else
- debug "No valid gem location found in #{gem_search_location}"
- end
- else
- debug("Gem location #{gem_search_location} does not exist or is not a directory")
+
+ # Check if there is an additional local bundle path in .bundle/config
+ def bundle_config_bundle_path(rails_root)
+ bundle_path = nil # default
+ if File.exist?("#{rails_root}/.bundle/config")
+ bundle_config = YAML.load_file("#{rails_root}/.bundle/config")
+ if bundle_config && bundle_config['BUNDLE_PATH']
+ bundle_path = "#{rails_root}/#{bundle_config['BUNDLE_PATH']}"
+ debug "Local Gem path configured in #{rails_root}/.bundle/config: #{bundle_path}"
end
end
- debug "Valid Gem locations: #{gem_search_locations}"
- gem_search_locations
+ bundle_path
end
- # Copy the Gem elements to the staging directory
- # @param [String] gem_full_name Full name of the Gem including version and platform
- # @param [String] staging_dir Path to the staging directory
- # @param [Array] gem_search_locations Array of Gem locations
+ # Copy the needed Gems to the staging directory
+ # @param [String] gem_target_location Path to the staging directory
# @return [void]
- def copy_gem_to_staging(gem_full_name, gem_target_location, gem_search_locations)
- gem_search_locations.each do |gem_search_location|
- gem_dir = "#{gem_search_location}/gems/#{gem_full_name}"
- if File.exist?(gem_dir)
- file_utils_copy(gem_dir, "#{gem_target_location}/gems")
- file_utils_copy("#{gem_search_location}/specifications/#{gem_full_name}.gemspec", "#{gem_target_location}/specifications")
- return
- end
+ def copy_needed_gems_to_staging(gem_target_location, app_root)
+ #Bundler.with_unbundled_env do # No previous setting inherited like Gemfile location
+ # Bundler.reset! # Reset settings from previous Bundler.with_unbundled_env
+ needed_gems = gem_dependencies # get the full names of the dependencies
+ needed_gems.each do |needed_gem|
+ # Get the location of the needed gem
+ spec = Gem::Specification.find_by_name(needed_gem[:name], needed_gem[:version])
+ raise "Gem #{needed_gem[:full_name]} not found for copying" unless spec
+ debug "Found gem #{needed_gem[:full_name]} version #{needed_gem[:version]} in #{spec.gem_dir}"
+ file_utils_copy(spec.gem_dir, "#{gem_target_location}/gems")
+ file_utils_copy("#{spec.gem_dir}/../../specifications/#{needed_gem[:full_name]}.gemspec", "#{gem_target_location}/specifications")
+ # end
end
- raise "Gem #{gem_name} (#{gem_version}) not found in any of the following locations:\n#{gem_search_locations.join("\n")}"
end
# Read the default/production dependencies from Gemfile.lock and Gemfile
# @return [Array] Array with full names of dependencies
def gem_dependencies
needed_gems = []
lockfile_specs = Bundler::LockfileParser.new(Bundler.read_file(Bundler.default_lockfile)).specs
- Bundler.setup # Load Gems specified in Gemfile
+ # Bundler.setup # Load Gems specified in Gemfile
# filter Gems needed for production
gemfile_specs = Bundler.definition.dependencies.select do |d|
d.groups.include?(:default) || d.groups.include?(:production)
end
debug "Gems from Gemfile needed for production:"
gemfile_specs.each do |gemfile_spec|
# find lockfile record for Gemfile spec
lockfile_spec = lockfile_specs.find { |lockfile_spec| lockfile_spec.name == gemfile_spec.name }
if lockfile_spec
- needed_gems << lockfile_spec.full_name unless needed_gems.include?(lockfile_spec.full_name)
+ unless needed_gems.map{|n| n[:fullname]}.include?(lockfile_spec.full_name)
+ needed_gems << { full_name: lockfile_spec.full_name, name: lockfile_spec.name, version: lockfile_spec.version }
+ end
debug "Direct Gem dependency: #{lockfile_spec.full_name}"
add_indirect_dependencies(lockfile_specs, lockfile_spec, needed_gems)
else
debug "Gem #{gemfile_spec.name} not found in Gemfile.lock"
end
end
- needed_gems.uniq.sort
+ needed_gems.uniq.sort{|a,b| a[:full_name] <=> b[:full_name]}
end
# recurively find all indirect dependencies
# @param [Array] lockfile_specs Array of Bundler::LockfileParser::Spec objects
# @param [Bundler::LockfileParser::Spec] lockfile_spec current lockfile spec to check for their dependencies
@@ -166,12 +150,12 @@
def add_indirect_dependencies(lockfile_specs, lockfile_spec, needed_gems)
lockfile_spec.dependencies.each do |lockfile_spec_dep|
lockfile_spec_found = lockfile_specs.find { |lockfile_spec| lockfile_spec.name == lockfile_spec_dep.name }
if lockfile_spec_found
debug "Indirect Gem dependency from #{lockfile_spec.full_name}: #{lockfile_spec_found.full_name}"
- unless needed_gems.include?(lockfile_spec_found.full_name)
- needed_gems << lockfile_spec_found.full_name
+ unless needed_gems.map{|n| n[:fullname]}.include?(lockfile_spec_found.full_name)
+ needed_gems << { full_name: lockfile_spec_found.full_name, name: lockfile_spec_found.name, version: lockfile_spec_found.version }
add_indirect_dependencies(lockfile_specs, lockfile_spec_found, needed_gems)
end
else
debug "Gem #{lockfile_spec_dep.name} not found in Gemfile.lock"
end
@@ -195,19 +179,23 @@
# Copy the jruby-jars to the staging directory
# @param [String] staging_dir Path to the staging directory
# @param [Array] gem_search_locations Array of Gem locations to look for jRuby jars
# @return [String] the ruby version of the jRuby jars
- def copy_jruby_jars_to_staging(staging_dir, gem_search_locations)
- jruby_jars_location = nil
- gem_search_locations.each do |gem_search_location|
- gem_dir = "#{gem_search_location}/gems/jruby-jars-#{config.jruby_version}"
- if File.exist?(gem_dir)
- jruby_jars_location = gem_dir
- break
- end
- end
- raise "Could not determine location of jRuby jars for release '#{config.jruby_version}' in the following locations:\n#{gem_search_locations}" unless jruby_jars_location
+ def copy_jruby_jars_to_staging(staging_dir)
+
+ # Ensure that jruby-jars gem is installed, otherwise install it. Accepts also bundler path in .bundle/config
+ installer = Gem::DependencyInstaller.new
+ installed = installer.install('jruby-jars', config.jruby_version)
+ raise "jruby-jars gem not installed in version #{config.jruby_version}" if installed.empty?
+
+ jruby_jars_location = installed[0]&.full_gem_path
+ debug "jRuby jars installed at: #{jruby_jars_location}"
+
+ # Get the location of the jruby-jars gem
+ # spec = Gem::Specification.find_by_name('jruby-jars', config.jruby_version)
+ # jruby_jars_location = spec.gem_dir
+
file_utils_copy("#{jruby_jars_location}/lib/jruby-core-#{config.jruby_version}-complete.jar", staging_dir)
file_utils_copy("#{jruby_jars_location}/lib/jruby-stdlib-#{config.jruby_version}.jar", staging_dir)
# Get the according Ruby version for the current jRuby version
lines = exec_command "java -cp #{jruby_jars_location}/lib/jruby-core-#{config.jruby_version}-complete.jar org.jruby.Main --version"
\ No newline at end of file