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