require 'fileutils' module Origen # Provides methods for setting up, booting and # archiving an Origen application module Boot # Gem executables that Origen depends on [bin name, gem name] BIN_DEPS = [%w(rspec rspec-core), %w(nanoc nanoc), %w(yard yard), %w(rubocop rubocop), %w(rake rake)] BUNDLER_WARNING = ' From Origen 0.40.0 onwards, a new way of launching Origen is supported and you are seeing this message because your application is still setup to run the old way. The main difference is that Origen is now launched via an Origen-owned binstub (./lbin/origen) rather than a Bundler-owned binstub. This means that Origen can no longer be prevented from running due to a Bundler configuration issue within your workspace and it should mean that Origen invocation becomes more reliable. It is recommended that you follow these instructions to upgrade your application to the new system. If have already done this and you are seeing this message again, then Bundler has overwritten the binstub at ./lbin/origen and you should perform the upgrade again. To upgrade, run the following command: origen setup If you ever run the `bundle` or `bundle install` commands manually, never use the --binstubs option or it will roll you back to the old system. Under the new system, you should check the `./lbin` directory into your source control system, so remove it from your `.gitignore` (or equivalent) and check it in. When you install a new gem whose executable you want to use in your app, generate a binstub for it via the following command: origen new binstub some-gem-name ______________________________________________________________________________________ ' BUNDLER_SETUP = %q( if Origen.site_config.gem_manage_bundler FileUtils.mkdir_p(File.join(origen_root, '.bundle')) File.open(File.join(origen_root, '.bundle', 'config'), 'w') do |f| f.puts '# Origen is managing this file, any local edits will be overwritten' f.puts '# IT SHOULD NOT BE CHECKED INTO REVISION CONTROL!' f.puts '---' f.puts 'BUNDLE_BIN: false' # If gems have been installed to the app, always use them bundle_path = File.join(origen_root, 'vendor', 'gems') if File.exist?(bundle_path) # Only keep the gems we actually need when installing to the application, but # don't do this when installing outside since other apps might use them f.puts 'BUNDLE_CLEAN: true' else bundle_path = File.expand_path(Origen.site_config.gem_install_dir) end f.puts "BUNDLE_PATH: \"#{bundle_path}\"" Array(Origen.site_config.gem_build_switches).each do |build_switches| switches = build_switches.strip.split(' ') gem = switches.shift f.puts "BUNDLE_BUILD__#{gem.upcase}: \"#{switches.join(' ')}\"" end end end ) UPDATER_WARNING = ' The bin/fix_my_workspace script is not compatible with the new way that Origen is launched and you should remove it from your application. Do this by deleting bin/fix_my_workspace and also remove the origen_updater gem from your application. The command `origen setup` can be used in place of fix_my_workspace under the new system, however the new system should be more robust and such workspace repairs should no longer be required. ______________________________________________________________________________________ ' BINSTUB = "#!/usr/bin/env ruby # # This file was generated by Origen. # require 'rubygems' origen_lib = File.expand_path('../../lib/origen', Gem.bin_path('origen', 'origen')) boot = File.join(origen_lib, 'boot.rb') ORIGEN_ROOT = File.expand_path('..', __dir__) origen_root = ORIGEN_ROOT # If the Origen version supports the new boot system then use it if File.exist?(boot) load boot # Otherwise fall back to an (improved) old-style invocation via Bundler else require 'pathname' require 'fileutils' $_origen_invocation_pwd = Pathname.pwd require File.join(origen_lib, 'site_config') " + BUNDLER_SETUP + %q( bundle_binstub = File.expand_path('../bundle', __FILE__) if File.file?(bundle_binstub) if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ load(bundle_binstub) else abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") end end require 'bundler/setup' load Gem.bin_path('origen', 'origen') end ) class << self # Boot the application at the given root def app!(origen_root) # This will be used to collect warnings about the user's application environment, however showing them # will be deferred until it has been determined that the application is using Origen >= 0.40.0 - i.e. we # don't want to start complaining to the user about existing apps until they have intentionally upgraded # their Origen version. warnings = [] exec_remote = ARGV.include?('--exec_remote') ? true : false lbin_dir = File.join(origen_root, 'lbin') origen_binstub = File.join(lbin_dir, 'origen') unless exec_remote if !File.exist?(origen_binstub) || (File.exist?(origen_binstub) && File.read(origen_binstub) !~ /This file was generated by Origen/) warnings << BUNDLER_WARNING elsif File.exist?(File.join(origen_root, 'bin', 'fix_my_workspace')) warnings << UPDATER_WARNING end setup_bundler(origen_root) end boot_app = true Dir.chdir origen_root do # Overriding bundler here so that bundle install can be automated as required, otherwise if just call # require 'bundler/setup' then it will exit in the event of errors require 'bundler' begin Bundler.setup rescue Gem::LoadError, Bundler::BundlerError => e puts e puts if exec_remote puts 'App failed to boot, run it locally so that this can be resolved before re-submitting to the LSF' exit 1 end puts 'Attempting to resolve this...' puts passed = false Bundler.with_clean_env do cmd = 'bundle install' cmd += ' --local' if File.exist?('.origen_archive') passed = system(cmd) end if passed Bundler.with_clean_env do exec "origen #{ARGV.join(' ')}" end exit 0 else puts puts "If you have just updated a gem version and are now getting an error that Bundler cannot find compatible versions for it then first try running 'bundle update '." puts "For example if you have just changed the version of origen run 'bundle update origen'." exit 1 end end end unless exec_remote # The application's bundle is safely loaded, do a final check to make sure that Origen's # required bin dependencies have binstubs if BIN_DEPS.any? { |bin, gem| !File.exist?(File.join(lbin_dir, bin)) } system "bundle binstubs #{BIN_DEPS.map { |bin, gem| gem }.join(' ')} --path #{lbin_dir} --force" end end require 'origen' warnings end def setup(origen_root) create_origen_binstub(origen_root) bundle_path = setup_bundler(origen_root) unless File.exist?(File.join(origen_root, '.origen_archive')) copy_system_gems(origen_root, bundle_path) end end def create_origen_binstub(origen_root) lbin_dir = File.join(origen_root, 'lbin') FileUtils.mkdir_p(lbin_dir) File.open(File.join(lbin_dir, 'origen'), 'w') do |f| f.puts BINSTUB end FileUtils.chmod('+x', File.join(lbin_dir, 'origen')) if Origen.os.windows? Dir.glob("#{origen_root}/lbin/*").each do |bin| unless bin =~ /.bat$/ bat = "#{bin}.bat" unless File.exist?(bat) File.open(bat, 'w') { |f| f.write('@"ruby.exe" "%~dpn0" %*') } end end end end end def setup_bundler(origen_root) bundle_path = nil eval BUNDLER_SETUP # Will update bundle_path bundle_path end def copy_system_gems(origen_root, bundle_path) if Origen.site_config.gem_use_from_system local_gem_dir = "#{bundle_path}/ruby/#{Pathname.new(Gem.dir).basename}" gem_dir = Pathname.new(Gem.dir) Origen.site_config.gem_use_from_system.each do |gem, version| begin # This will raise an error if the system doesn't have this gem installed, that # will be rescued below spec = Gem::Specification.find_by_name(gem, version) # If the spec has returned a handle to a system installed gem. If this script has been invoked through # Bundler then it could point to some other gem dir. The only time this should occur is when switching # from the old system to the new system, but can't work out how to fix it so just disabling in that case. if spec.gem_dir =~ /#{gem_dir}/ local_dir = File.join(local_gem_dir, Pathname.new(spec.gem_dir).relative_path_from(gem_dir)) FileUtils.mkdir_p local_dir FileUtils.cp_r("#{spec.gem_dir}/.", local_dir) local_file = Pathname.new(File.join(local_gem_dir, Pathname.new(spec.cache_file).relative_path_from(gem_dir))) FileUtils.mkdir_p local_file.dirname FileUtils.cp(spec.cache_file, local_file) if spec.extension_dir && File.exist?(spec.extension_dir) local_dir = File.join(local_gem_dir, Pathname.new(spec.extension_dir).relative_path_from(gem_dir)) FileUtils.mkdir_p local_dir FileUtils.cp_r("#{spec.extension_dir}/.", local_dir) end local_file = Pathname.new(File.join(local_gem_dir, Pathname.new(spec.spec_file).relative_path_from(gem_dir))) FileUtils.mkdir_p local_file.dirname FileUtils.cp(spec.spec_file, local_file) puts "Copied #{gem} #{version} from the system into #{bundle_path}" end rescue Exception # Gem::LoadError # Rescue everything here, this is a try-our-best operation, better to # continue and try and install the gem if this fails rather than crash # This just means that one of the gems that should be copied from the system # was not actually installed in the system, so nothing we can do about that here end end end end end end end