Add command deprecation helper module

This commit is contained in:
Chris Roberts 2017-02-24 06:22:39 -08:00
parent 899fc7fb82
commit e2acb5250a
5 changed files with 173 additions and 0 deletions

View File

@ -292,6 +292,10 @@ module Vagrant
error_key(:clone_machine_not_found) error_key(:clone_machine_not_found)
end end
class CommandDeprecated < VagrantError
error_key(:command_deprecated)
end
class CommandUnavailable < VagrantError class CommandUnavailable < VagrantError
error_key(:command_unavailable) error_key(:command_unavailable)
end end

View File

@ -1,6 +1,7 @@
module Vagrant module Vagrant
module Util module Util
autoload :Busy, 'vagrant/util/busy' autoload :Busy, 'vagrant/util/busy'
autoload :CommandDeprecation, 'vagrant/util/command_deprecation'
autoload :Counter, 'vagrant/util/counter' autoload :Counter, 'vagrant/util/counter'
autoload :CredentialScrubber, 'vagrant/util/credential_scrubber' autoload :CredentialScrubber, 'vagrant/util/credential_scrubber'
autoload :Env, 'vagrant/util/env' autoload :Env, 'vagrant/util/env'

View File

@ -0,0 +1,56 @@
module Vagrant
module Util
# Automatically add deprecation notices to commands
module CommandDeprecation
# @return [String] generated name of command
def deprecation_command_name
name_parts = self.class.name.split("::")
[
name_parts[1].sub('Command', ''),
name_parts[3]
].compact.map(&:downcase).join(" ")
end
def self.included(klass)
klass.class_eval do
class << self
if method_defined?(:synopsis)
alias_method :non_deprecated_synopsis, :synopsis
def synopsis
if !non_deprecated_synopsis.to_s.empty?
"#{non_deprecated_synopsis} [DEPRECATED]"
else
non_deprecated_synopsis
end
end
end
end
alias_method :non_deprecated_execute, :execute
def execute
@env[:ui].warn(I18n.t("vagrant.commands.deprecated",
name: deprecation_command_name
) + "\n")
non_deprecated_execute
end
end
end
# Mark command deprecation complete and fully disable
# the command's functionality
module Complete
def self.included(klass)
klass.include(CommandDeprecation)
klass.class_eval do
def execute
raise Vagrant::Errors::CommandDeprecated,
name: deprecation_command_name
end
end
end
end
end
end
end

View File

@ -664,6 +664,9 @@ en:
Additionally, the created environment must be started with a provider Additionally, the created environment must be started with a provider
matching this provider. For example, if you're using VirtualBox, matching this provider. For example, if you're using VirtualBox,
the clone environment must also be using VirtualBox. the clone environment must also be using VirtualBox.
command_deprecated: |-
The command 'vagrant %{name}' has been deprecated and is no longer functional
within Vagrant.
command_unavailable: |- command_unavailable: |-
The executable '%{file}' Vagrant is trying to run was not The executable '%{file}' Vagrant is trying to run was not
found in the PATH variable. This is an error. Please verify found in the PATH variable. This is an error. Please verify
@ -1568,6 +1571,9 @@ en:
# Translations for commands. e.g. `vagrant x` # Translations for commands. e.g. `vagrant x`
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
commands: commands:
deprecated: |-
[DEPRECATION WARNING]: The Vagrant command 'vagrant %{name}' is scheduled be
deprecated in an upcoming Vagrant release.
common: common:
vm_already_running: |- vm_already_running: |-
VirtualBox VM is already running. VirtualBox VM is already running.

View File

@ -0,0 +1,106 @@
require File.expand_path("../../../base", __FILE__)
require "vagrant/util/command_deprecation"
describe Vagrant::Util do
include_context "unit"
let(:app){ lambda{|env|} }
let(:argv){[]}
let(:env){ {ui: Vagrant::UI::Silent.new} }
let(:command_class) do
Class.new(Vagrant.plugin("2", :command)) do
def self.synopsis
"base synopsis"
end
def self.name
"VagrantPlugins::CommandTest::Command"
end
def execute
@env[:ui].info("COMMAND CONTENT")
0
end
end
end
let(:command){ command_class.new(app, env) }
describe Vagrant::Util::CommandDeprecation do
before{ command_class.include(Vagrant::Util::CommandDeprecation) }
it "should add deprecation warning to synopsis" do
expect(command_class.synopsis).to include('[DEPRECATED]')
command.class.synopsis
end
it "should add deprecation warning to #execute" do
expect(env[:ui]).to receive(:warn).with(/DEPRECATION WARNING/)
command.execute
end
it "should execute original command" do
expect(env[:ui]).to receive(:info).with("COMMAND CONTENT")
command.execute
end
it "should return with a 0 value" do
expect(command.execute).to eq(0)
end
context "with custom name defined" do
before do
command_class.class_eval do
def deprecation_command_name
"custom-name"
end
end
end
it "should use custom name within warning message" do
expect(env[:ui]).to receive(:warn).with(/custom-name/)
command.execute
end
end
context "with deprecated subcommand" do
let(:command_class) do
Class.new(Vagrant.plugin("2", :command)) do
def self.name
"VagrantPlugins::CommandTest::Command::Action"
end
def execute
@env[:ui].info("COMMAND CONTENT")
0
end
end
end
it "should not modify empty synopsis" do
expect(command_class.synopsis.to_s).to be_empty
end
it "should extract command name and subname" do
expect(command.deprecation_command_name).to eq("test action")
end
end
end
describe Vagrant::Util::CommandDeprecation::Complete do
before{ command_class.include(Vagrant::Util::CommandDeprecation::Complete) }
it "should add deprecation warning to synopsis" do
expect(command_class.synopsis).to include('[DEPRECATED]')
command.class.synopsis
end
it "should raise a deprecation error when executed" do
expect{ command.execute }.to raise_error(Vagrant::Errors::CommandDeprecated)
end
it "should not run original command" do
expect(env[:ui]).not_to receive(:info).with("COMMAND CONTENT")
expect{ command.execute }.to raise_error(Vagrant::Errors::CommandDeprecated)
end
end
end