vaguerent/bin/vagrant
Chris Roberts 32f4951759 Activate builtin specs during startup
When starting up, and before any loading, find our current
    specification and activate all the internal dependencies
    while also collecting the activated specifications. Store
    these for later use when doing plugin resolutions. We bypass
    the builtin list when running in bundler since they will
    still show up as not activated, but we use the entire list
    regardless.
2021-03-08 16:25:13 -08:00

264 lines
8.0 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# Trap interrupts to quit cleanly. This will be overridden at some point
# by Vagrant. This is made to catch any interrupts while Vagrant is
# initializing which have historically resulted in stack traces.
Signal.trap("INT") { abort }
# Disable exception reporting by default if available
if Thread.respond_to?(:report_on_exception=)
Thread.report_on_exception = false
end
# Split arguments by "--" if its there, we'll recombine them later
argv = ARGV.dup
argv_extra = []
# These will be the options that are passed to initialize the Vagrant
# environment.
opts = {}
if idx = argv.index("--")
argv_extra = argv.slice(idx+1, argv.length-2)
argv = argv.slice(0, idx)
end
require_relative "../lib/vagrant/version"
# Fast path the version of Vagrant
if argv.include?("-v") || argv.include?("--version")
puts "Vagrant #{Vagrant::VERSION}"
exit 0
end
# Disable plugin loading for commands where plugins are not required. This will
# also disable loading of the Vagrantfile if it available as the environment
# is not required for these commands
argv.each_index do |i|
arg = argv[i]
if !arg.start_with?("-")
if arg == "box" && argv[i+1] == "list"
opts[:vagrantfile_name] = ""
ENV['VAGRANT_NO_PLUGINS'] = "1"
end
# Do not load plugins when performing plugin operations
if arg == "plugin"
if argv.none?{|a| a == "--local" } && !ENV["VAGRANT_LOCAL_PLUGINS_LOAD"]
opts[:vagrantfile_name] = ""
end
ENV['VAGRANT_NO_PLUGINS'] = "1"
# Only initialize plugins when listing installed plugins
if argv[i+1] != "list"
ENV['VAGRANT_DISABLE_PLUGIN_INIT'] = "1"
end
end
break
end
end
# Set logging level to `debug`. This is done before loading 'vagrant', as it
# sets up the logging system.
if argv.include?("--debug")
argv.delete("--debug")
ENV["VAGRANT_LOG"] = "debug"
end
# Enable log timestamps if requested
if argv.include?("--timestamp")
argv.delete("--timestamp")
ENV["VAGRANT_LOG_TIMESTAMP"] = "1"
end
# Convenience flag to enable debug with timestamps
if argv.include?("--debug-timestamp")
argv.delete("--debug-timestamp")
ENV["VAGRANT_LOG"] = "debug"
ENV["VAGRANT_LOG_TIMESTAMP"] = "1"
end
# Stdout/stderr should not buffer output
$stdout.sync = true
$stderr.sync = true
# Before we start activate all our dependencies
# so we can provide correct resolutions later
builtin_specs = []
vagrant_spec = Gem::Specification.find_all_by_name("vagrant").detect do |spec|
spec.version == Gem::Version.new(Vagrant::VERSION)
end
dep_activator = proc do |spec|
spec.runtime_dependencies.each do |dep|
gem(dep.name, *dep.requirement.as_list)
dep_spec = Gem::Specification.find_all_by_name(dep.name).detect(&:activated?)
if dep_spec
builtin_specs << dep_spec
dep_activator.call(dep_spec)
end
end
end
if vagrant_spec
dep_activator.call(vagrant_spec)
end
env = nil
begin
require 'log4r'
require 'vagrant'
require 'vagrant/bundler'
require 'vagrant/cli'
require 'vagrant/util/platform'
require 'vagrant/util/experimental'
# Set our list of builtin specs
Vagrant::Bundler.instance.builtin_specs = builtin_specs
# Schedule the cleanup of things
at_exit(&Vagrant::Bundler.instance.method(:deinit))
# If this is not a pre-release disable verbose output
if !Vagrant.prerelease?
$VERBOSE = nil
end
# Add any option flags defined within this file here
# so they are automatically propagated to all commands
Vagrant.add_default_cli_options(proc { |o|
o.on("--[no-]color", "Enable or disable color output")
o.on("--machine-readable", "Enable machine readable output")
o.on("-v", "--version", "Display Vagrant version")
o.on("--debug", "Enable debug output")
o.on("--timestamp", "Enable timestamps on log output")
o.on("--debug-timestamp", "Enable debug output with timestamps")
o.on("--no-tty", "Enable non-interactive output")
})
# Create a logger right away
logger = Log4r::Logger.new("vagrant::bin::vagrant")
logger.info("`vagrant` invoked: #{ARGV.inspect}")
# Disable color in a few cases:
#
# * --no-color is anywhere in our arguments
# * STDOUT is not a TTY
# * The terminal doesn't support colors (Windows)
#
if argv.include?("--no-color") || ENV["VAGRANT_NO_COLOR"]
# Delete the argument from the list so that it doesn't
# cause any invalid arguments down the road.
argv.delete("--no-color")
opts[:ui_class] = Vagrant::UI::Basic
elsif !Vagrant::Util::Platform.terminal_supports_colors?
opts[:ui_class] = Vagrant::UI::Basic
elsif !$stdout.tty? && !Vagrant::Util::Platform.cygwin?
# Cygwin always reports STDOUT is not a TTY, so we only disable
# colors if its not a TTY AND its not Cygwin.
opts[:ui_class] = Vagrant::UI::Basic
end
# Also allow users to force colors.
if argv.include?("--color") || ENV["VAGRANT_FORCE_COLOR"]
argv.delete("--color")
opts[:ui_class] = Vagrant::UI::Colored
end
# Highest precedence is if we have enabled machine-readable output
if argv.include?("--machine-readable")
argv.delete("--machine-readable")
opts[:ui_class] = Vagrant::UI::MachineReadable
end
# Setting to enable/disable showing progress bars
if argv.include?("--no-tty")
argv.delete("--no-tty")
opts[:ui_class] = Vagrant::UI::NonInteractive
end
# Default to colored output
opts[:ui_class] ||= Vagrant::UI::Colored
# Recombine the arguments
if !argv_extra.empty?
argv << "--"
argv += argv_extra
end
# Create the environment, which is the cwd of wherever the
# `vagrant` command was invoked from
logger.debug("Creating Vagrant environment")
env = Vagrant::Environment.new(opts)
# If we are running with the Windows Subsystem for Linux do
# some extra setup to allow access to Vagrant managed machines
# outside the subsystem
if Vagrant::Util::Platform.wsl?
recreate_env = Vagrant::Util::Platform.wsl_init(env, logger)
if recreate_env
logger.info("Re-creating Vagrant environment due to WSL modifications.")
env = Vagrant::Environment.new(opts)
end
end
if !Vagrant.in_installer? && !Vagrant.very_quiet?
# If we're not in the installer, warn.
env.ui.warn(I18n.t("vagrant.general.not_in_installer") + "\n", prefix: false)
end
# Acceptable experimental flag values include:
#
# Unset - Disables experimental features
# 0 - Disables experimental features
# 1 - Enables all features
# String - Enables one or more features, separated by commas
if Vagrant::Util::Experimental.enabled?
experimental = Vagrant::Util::Experimental.features_requested
ui = Vagrant::UI::Prefixed.new(env.ui, "vagrant")
logger.debug("Experimental flag is enabled")
if Vagrant::Util::Experimental.global_enabled?
ui.warn(I18n.t("vagrant.general.experimental.all"), bold: true, prefix: true, channel: :error)
else
ui.warn(I18n.t("vagrant.general.experimental.features", features: experimental.join(", ")), bold: true, prefix: true, channel: :error)
end
end
begin
# Execute the CLI interface, and exit with the proper error code
exit_status = env.cli(argv)
ensure
# Unload the environment so cleanup can be done
env.unload
end
# Exit with the exit status from our CLI command
exit(exit_status)
rescue Exception => e
# It is possible for errors to happen in Vagrant's initialization. In
# this case, we don't have access to this class yet, so we check for it.
raise if !defined?(Vagrant) || !defined?(Vagrant::Errors)
raise if !e.is_a?(Vagrant::Errors::VagrantError)
require 'log4r'
logger = Log4r::Logger.new("vagrant::bin::vagrant")
logger.error("Vagrant experienced an error! Details:")
logger.error(e.inspect)
logger.error(e.message)
logger.error(e.backtrace.join("\n"))
if env
opts = { prefix: false }
env.ui.error e.message, opts if e.message
env.ui.machine("error-exit", e.class.to_s, e.message.to_s)
else
$stderr.puts "Vagrant failed to initialize at a very early stage:\n\n"
$stderr.puts e.message
end
exit e.status_code if e.respond_to?(:status_code)
exit 255 # An error occurred with no status code defined
end