diff --git a/bin/vagrant b/bin/vagrant index 272b4ea68..5f6725b50 100755 --- a/bin/vagrant +++ b/bin/vagrant @@ -99,6 +99,17 @@ begin $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") + }) + # Create a logger right away logger = Log4r::Logger.new("vagrant::bin::vagrant") logger.info("`vagrant` invoked: #{ARGV.inspect}") diff --git a/lib/vagrant.rb b/lib/vagrant.rb index 66840226f..98dcac650 100644 --- a/lib/vagrant.rb +++ b/lib/vagrant.rb @@ -9,6 +9,31 @@ class Log4r::BasicFormatter end end + +require "optparse" + +module Vagrant + # This is a customized OptionParser for Vagrant plugins. It + # will automatically add any default CLI options defined + # outside of command implementations to the local option + # parser instances in use + class OptionParser < ::OptionParser + def initialize(*_) + super + Vagrant.default_cli_options.each do |opt_proc| + opt_proc.call(self) + end + end + end +end + +# Inject the option parser into the vagrant plugins +# module so it is automatically used when defining +# command options +module VagrantPlugins + OptionParser = Vagrant::OptionParser +end + require "vagrant/shared_helpers" require "rubygems" require "vagrant/util" diff --git a/lib/vagrant/plugin/v2/command.rb b/lib/vagrant/plugin/v2/command.rb index 5b39ef49f..967dbda0f 100644 --- a/lib/vagrant/plugin/v2/command.rb +++ b/lib/vagrant/plugin/v2/command.rb @@ -51,7 +51,7 @@ module Vagrant argv = @argv.dup # Default opts to a blank optionparser if none is given - opts ||= OptionParser.new + opts ||= Vagrant::OptionParser.new # Add the help option, which must be on every command. opts.on_tail("-h", "--help", "Print this help") do diff --git a/lib/vagrant/shared_helpers.rb b/lib/vagrant/shared_helpers.rb index 5cab18f39..4bcfaadf0 100644 --- a/lib/vagrant/shared_helpers.rb +++ b/lib/vagrant/shared_helpers.rb @@ -186,4 +186,32 @@ module Vagrant end @_global_logger end + + # Add a new block of default CLI options which + # should be automatically added to all commands + # + # @param [Proc] block Proc instance containing OptParser configuration + # @return [nil] + def self.add_default_cli_options(block) + if !block.is_a?(Proc) + raise TypeError, + "Expecting type `Proc` but received `#{block.class}`" + end + if block.arity != 1 && block.arity != -1 + raise ArgumentError, + "Proc must accept OptionParser argument" + end + @_default_cli_options = [] if !@_default_cli_options + @_default_cli_options << block + nil + end + + # Array of default CLI options to automatically + # add to commands. + # + # @return [Array] Default optparse options + def self.default_cli_options + @_default_cli_options = [] if !@_default_cli_options + @_default_cli_options.dup + end end diff --git a/test/unit/bin/vagrant_test.rb b/test/unit/bin/vagrant_test.rb index 08edcb20e..d3f0b19ca 100644 --- a/test/unit/bin/vagrant_test.rb +++ b/test/unit/bin/vagrant_test.rb @@ -93,6 +93,22 @@ describe "vagrant bin" do end end + context "default CLI flags" do + let(:argv) { ["--help"] } + + before do + allow(env).to receive(:ui).and_return(ui) + allow(ARGV).to receive(:dup).and_return(argv) + allow(Kernel).to receive(:at_exit) + allow(Kernel).to receive(:exit) + allow(Vagrant::Environment).to receive(:new).and_call_original + end + + it "should include default CLI flags in command help output" do + expect($stdout).to receive(:puts).with(/--debug/) + end + end + context "when not in installer" do let(:warning) { "INSTALLER WARNING" } diff --git a/test/unit/vagrant/shared_helpers_test.rb b/test/unit/vagrant/shared_helpers_test.rb index 7ff41e6a6..fda3bc073 100644 --- a/test/unit/vagrant/shared_helpers_test.rb +++ b/test/unit/vagrant/shared_helpers_test.rb @@ -8,14 +8,14 @@ describe Vagrant do subject { described_class } - describe "#global_lock" do + describe ".global_lock" do it "yields to the block" do result = subject.global_lock { 42 } expect(result).to eq(42) end end - describe "#in_installer?" do + describe ".in_installer?" do it "is not if env is not set" do with_temp_env("VAGRANT_INSTALLER_ENV" => nil) do expect(subject.in_installer?).to be(false) @@ -29,7 +29,7 @@ describe Vagrant do end end - describe "#installer_embedded_dir" do + describe ".installer_embedded_dir" do it "returns nil if not in an installer" do allow(Vagrant).to receive(:in_installer?).and_return(false) expect(subject.installer_embedded_dir).to be_nil @@ -44,7 +44,7 @@ describe Vagrant do end end - describe "#plugins_enabled?" do + describe ".plugins_enabled?" do it "returns true if the env is not set" do with_temp_env("VAGRANT_NO_PLUGINS" => nil) do expect(subject.plugins_enabled?).to be(true) @@ -58,7 +58,7 @@ describe Vagrant do end end - describe "#server_url" do + describe ".server_url" do it "defaults to the default value" do with_temp_env("VAGRANT_SERVER_URL" => nil) do expect(subject.server_url).to eq( @@ -92,7 +92,7 @@ describe Vagrant do end end - describe "#user_data_path" do + describe ".user_data_path" do around do |example| env = { "USERPROFILE" => nil, @@ -132,7 +132,7 @@ describe Vagrant do end end - describe "#prerelease?" do + describe ".prerelease?" do it "should return true when Vagrant version is development" do stub_const("Vagrant::VERSION", "1.0.0.dev") expect(subject.prerelease?).to be(true) @@ -144,7 +144,7 @@ describe Vagrant do end end - describe "#enable_resolv_replace" do + describe ".enable_resolv_replace" do it "should not attempt to require resolv-replace by default" do expect(subject).not_to receive(:require).with("resolv-replace") subject.enable_resolv_replace @@ -163,7 +163,7 @@ describe Vagrant do end end - describe "#global_logger" do + describe ".global_logger" do after{ subject.global_logger = nil } it "should return a logger when none have been provided" do @@ -176,4 +176,26 @@ describe Vagrant do expect(subject.global_logger).to eq(logger) end end + + describe ".add_default_cli_options" do + it "should raise a type error when no provided with proc" do + expect { subject.add_default_cli_options(true) }. + to raise_error(TypeError) + end + + it "should raise an argument error when proc does not accept argument" do + expect { subject.add_default_cli_options(proc{}) }. + to raise_error(ArgumentError) + end + + it "should accept a proc type argument" do + expect(subject.add_default_cli_options(proc{|o|})).to be_nil + end + end + + describe ".default_cli_options" do + it "should return array of items" do + expect(subject.default_cli_options).to be_a(Array) + end + end end