lib/jarbler/builder.rb in jarbler-0.1.3 vs lib/jarbler/builder.rb in jarbler-0.1.4
- old
+ new
@@ -11,13 +11,12 @@
# 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
-
+ @config = nil # Ensure config is read from file or default. Necessary for testing only because of caching
+ staging_dir = Dir.mktmpdir # create a temporary directory for staging
app_root = Dir.pwd
debug "Project dir: #{app_root}"
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
@@ -29,16 +28,12 @@
end
# Get the needed Gems
raise "Gemfile.lock not found in #{app_root}" unless File.exist?("#{app_root}/Gemfile.lock")
- gem_target_location = "#{staging_dir}/gems/jruby/#{ruby_version}"
- FileUtils.mkdir_p("#{gem_target_location}/gems")
- FileUtils.mkdir_p("#{gem_target_location}/specifications")
-
# Copy the needed Gems to the staging directory
- copy_needed_gems_to_staging(gem_target_location, app_root)
+ copy_needed_gems_to_staging(staging_dir, ruby_version)
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")
@@ -71,20 +66,29 @@
# place the jar in project directory
file_utils_copy(config.jar_name, app_root)
puts "Created jar file #{app_root}/#{config.jar_name}"
end
-
+ rescue Exception => e
+ puts "Error: #{e.message}"
+ puts e.backtrace.join("\n")
+ raise
+ ensure
# remove temporary directory staging_dir
- FileUtils.remove_entry staging_dir
-
+ if ENV['DEBUG']
+ puts "Temporary directory #{staging_dir} not removed because of debug mode"
+ else
+ FileUtils.remove_entry staging_dir if staging_dir
+ end
end
private
# Check if there is an additional local bundle path in .bundle/config
+ # @param rails_root [String] the rails root directory
+ # @return [String] the local bundle path or nil if not configured
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']
@@ -94,34 +98,45 @@
end
bundle_path
end
# Copy the needed Gems to the staging directory
- # @param [String] gem_target_location Path to the staging directory
+ # @param staging_dir [String] the staging directory
+ # @param ruby_version [String] the corresponding ruby version of the jruby jars version
# @return [void]
- 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}"
+ def copy_needed_gems_to_staging(staging_dir, ruby_version)
+ gem_target_location = "#{staging_dir}/gems/jruby/#{ruby_version}"
+ FileUtils.mkdir_p("#{gem_target_location}/gems")
+ FileUtils.mkdir_p("#{gem_target_location}/specifications")
+ FileUtils.mkdir_p("#{gem_target_location}/bundler/gems")
+
+ 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}"
+
+ # differentiate between Gems from git/bundler and Gems from rubygems
+ if spec.source.is_a?(Bundler::Source::Git)
+ # Copy the Gem from bundler/gems including the gemspec
+ file_utils_copy(spec.gem_dir, "#{gem_target_location}/bundler/gems")
+ else # Gem is from rubygems
+ # copy the Gem and gemspec separately
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
end
end
# Read the default/production dependencies from Gemfile.lock and Gemfile
- # @return [Array] Array with full names of dependencies
+ # @return [Array] Array with Hashes containing: name, version, full_name
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, ensure that Gem path also includes the Gems loaded into bundler dir
# filter Gems needed for production
gemfile_specs = Bundler.definition.dependencies.select do |d|
d.groups.include?(:default) || d.groups.include?(:production)
end
@@ -143,11 +158,11 @@
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
- # @param [Array] needed_gems Array with full names of already found dependencies, add findings here
+ # @param [Array] needed_gems Array with Hashes containing: name, version, full_name
# @return [void]
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
@@ -159,16 +174,22 @@
else
debug "Gem #{lockfile_spec_dep.name} not found in Gemfile.lock"
end
end
end
+
+ # Output debug message if DEBUG environment variable is set
+ # @param [String] msg Message to output
+ # @return [void]
def debug(msg)
puts msg if ENV['DEBUG']
end
+ # Get the config object
+ # @return [Config] the config object
def config
- unless defined? @config
+ if !defined?(@config) || @config.nil?
@config = Config.create
debug("Config attributes:")
@config.instance_variables.each do |var|
debug("#{var}: #{@config.instance_variable_get(var)}")
end
@@ -177,11 +198,10 @@
@config
end
# 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)
# Ensure that jruby-jars gem is installed, otherwise install it. Accepts also bundler path in .bundle/config
installer = Gem::DependencyInstaller.new
@@ -205,18 +225,23 @@
ruby_version = match_result[0].tr('()', '')
debug "Corresponding Ruby version for jRuby (#{config.jruby_version}): #{ruby_version}"
ruby_version
end
- # Execute the command and return the output
+ # Execute the command in OS and return the output
+ # @param [String] command Command to execute
+ # @return [String] the output of the command
def exec_command(command)
lines = `#{command}`
raise "Command \"#{command}\"failed with return code #{$?} and output:\n#{lines}" unless $?.success?
debug "Command \"#{command}\" executed successfully with following output:\n#{lines}"
lines
end
# Copy file or directory with error handling
+ # @param [String] source Path to the source file or directory
+ # @param [String] destination Path to the destination file or directory
+ # @return [void]
def file_utils_copy(source, destination)
if File.exist?(source) && File.directory?(source)
FileUtils.cp_r(source, destination)
else
FileUtils.cp(source, destination)
\ No newline at end of file