# frozen_string_literal: true module LicenseFinder class Bundler def prepare create_vendor_path with_clean_bundler do tool_box.install(tool: :ruby, version: ruby_version, env: default_env) Pathname.glob('/opt/toolcache/*.gem').each do |gem| shell.execute([ :gem, :install, gem, '--no-document', '--no-update-sources', '--ignore-dependencies', '--no-suggestions', '--local' ], env: default_env, capture: false) end shell.execute([:asdf, :reshim], env: default_env, capture: false) shell.execute([:bundle, :config, '--local', :path, vendor_path], env: default_env, capture: false) shell.execute([:bundle, :install], env: default_env, capture: false) end end def current_packages with_clean_bundler do stdout, _stderr, status = shell.execute(scan_command, env: default_env) return [] unless status.success? stdout.each_line.map do |line| map_from(JSON.parse(line, symbolize_names: true)) end end end def possible_package_paths if ENV['BUNDLE_GEMFILE'] && File.exist?(ENV['BUNDLE_GEMFILE']) [project_path.join(File.basename(ENV['BUNDLE_GEMFILE']))] else [project_path.join('Gemfile'), project_path.join('gems.rb')] end end private def gemfile if ENV['BUNDLE_GEMFILE'] custom_gemfile = project_path.join(File.basename(ENV['BUNDLE_GEMFILE'])) return custom_gemfile.basename.to_s if custom_gemfile.exist? end project_path.join("gems.rb").exist? ? "gems.rb" : "Gemfile" end def lockfile gemfile == 'gems.rb' ? 'gems.locked' : "#{gemfile}.lock" end def lockfile_path project_path.join(lockfile) end def scan_command [ :ruby, '-W0', ::License::Management.root.join('exe', 'scan_bundler'), detected_package_path, lockfile_path ] end def default_env @default_env ||= { 'BUNDLE_ALLOW_OFFLINE_INSTALL' => 'true', 'BUNDLE_DISABLE_VERSION_CHECK' => 'true', 'BUNDLE_ERROR_ON_STDERR' => 'true', 'BUNDLE_GEMFILE' => "#{project_path}/#{gemfile}", 'BUNDLE_IGNORE_MESSAGES' => 'true', 'BUNDLE_JOBS' => ENV.fetch('BUNDLE_JOBS', `nproc`.chomp), 'BUNDLE_SILENCE_ROOT_WARNING' => 'true', 'BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES' => 'true', 'BUNDLE_WITHOUT' => ENV.fetch('BUNDLE_WITHOUT', ignored_groups.to_a.join(':')), 'PATH' => "/opt/asdf/shims:/opt/asdf/bin:#{ENV['PATH']}" }.tap do |env| env['BUNDLE_FROZEN'] = 'true' if lockfile_path.exist? env['BUNDLE_SSL_CA_CERT'] = shell.custom_certificate_path.to_s if shell.custom_certificate_installed? end end def with_clean_bundler Dir.chdir(project_path) do ::Gem.clear_paths ::Bundler.reset! if ::Bundler.respond_to?(:with_unbundled_env) ::Bundler.with_unbundled_env { yield } else ::Bundler.with_clean_env { yield } end end end def ruby_version @ruby_version ||= gemfile_ruby_version || tool_box.version_of(:ruby) end def map_from(gem) Dependency.new( 'Bundler', gem[:name], gem[:version], description: gem[:description], detection_path: lockfile_path, homepage: gem[:homepage], install_path: gem[:full_gem_path] || '/dev/null', spec_licenses: gem[:licenses], summary: gem[:summary] ) end def gemfile_ruby_version with_clean_bundler do stdout, _stderr, status = shell.execute([:embedded_bundle, :platform, '--ruby']) return unless status.success? match = stdout.chomp.match(/\Aruby (?\d+\.\d+.\d+).*\z/) match[:version] if match end end end end