Start creating the plugin middleware sequences

This commit is contained in:
Mitchell Hashimoto 2013-02-02 18:42:04 -08:00
parent db2e27bab6
commit a2ef7790de
10 changed files with 167 additions and 1 deletions

View File

@ -411,6 +411,7 @@ module Vagrant
:box_collection => boxes, :box_collection => boxes,
:global_config => config_global, :global_config => config_global,
:host => host, :host => host,
:gems_path => gems_path,
:root_path => root_path, :root_path => root_path,
:tmp_path => tmp_path, :tmp_path => tmp_path,
:ui => @ui :ui => @ui

View File

@ -15,7 +15,7 @@ module VagrantPlugins
if defined?(Bundler) if defined?(Bundler)
require 'bundler/shared_helpers' require 'bundler/shared_helpers'
if Bundler::SharedHelpers.in_bundle? if Bundler::SharedHelpers.in_bundle?
raise Errors::GemCommandInBundler raise Vagrant::Errors::GemCommandInBundler
end end
end end

View File

@ -0,0 +1,22 @@
require "pathname"
require "vagrant/action/builder"
module VagrantPlugins
module CommandPlugin
module Action
# This middleware sequence will install a plugin.
def self.action_install
Vagrant::Action::Builder.new.tap do |b|
b.use BundlerCheck
b.use InstallGem
end
end
# The autoload farm
action_root = Pathname.new(File.expand_path("../action", __FILE__))
autoload :BundlerCheck, action_root.join("bundler_check")
autoload :InstallGem, action_root.join("install_gem")
end
end
end

View File

@ -0,0 +1,25 @@
module VagrantPlugins
module CommandPlugin
module Action
class BundlerCheck
def initialize(app, env)
@app = app
end
def call(env)
# Bundler sets up its own custom gem load paths such that our
# own gems are never loaded. Therefore, give an error if a user
# tries to install gems while within a Bundler-managed environment.
if defined?(Bundler)
require 'bundler/shared_helpers'
if Bundler::SharedHelpers.in_bundle?
raise Vagrant::Errors::GemCommandInBundler
end
end
@app.call(env)
end
end
end
end
end

View File

@ -0,0 +1,47 @@
require "rubygems"
require "rubygems/gem_runner"
require "log4r"
module VagrantPlugins
module CommandPlugin
module Action
# This action takes the `:plugin_name` variable in the environment
# and installs it using the RubyGems API.
class InstallGem
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant::plugins::plugincommand::installgem")
end
def call(env)
plugin_name = env[:plugin_name]
# First, install the gem
begin
# Set the GEM_HOME so that it is installed into our local gems path
old_gem_home = ENV["GEM_HOME"]
ENV["GEM_HOME"] = env[:gems_path].to_s
p ENV["GEM_PATH"]
@logger.debug("Set GEM_HOME to: #{ENV["GEM_HOME"]}")
@logger.info("Installing gem: #{plugin_name}")
env[:ui].info(
I18n.t("vagrant.commands.plugin.installing", :name => plugin_name))
Gem.clear_paths
Gem::GemRunner.new.run(
["install", plugin_name, "--no-ri", "--no-rdoc"])
ensure
ENV["GEM_HOME"] = old_gem_home
end
# Mark that we installed the gem
env[:plugin_state_file].add_plugin(plugin_name)
# Continue
@app.call(env)
end
end
end
end
end

View File

@ -0,0 +1,29 @@
require 'optparse'
module VagrantPlugins
module CommandPlugin
module Command
class Install < Vagrant.plugin("2", :command)
def execute
opts = OptionParser.new do |o|
o.banner = "Usage: vagrant plugin install <name> [-h]"
end
# Parse the options
argv = parse_options(opts)
return if !argv
raise Vagrant::Errors::CLIInvalidUsage, :help => opts.help.chomp if argv.length < 1
# Install the gem
@env.action_runner.run(Action.action_install, {
:plugin_name => argv[0],
:plugin_state_file => StateFile.new(@env.data_dir.join("plugins.json"))
})
# Success, exit status 0
0
end
end
end
end
end

View File

@ -10,6 +10,10 @@ module VagrantPlugins
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv) @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
@subcommands = Vagrant::Registry.new @subcommands = Vagrant::Registry.new
@subcommands.register(:install) do
require_relative "install"
Install
end
end end
def execute def execute

View File

@ -14,5 +14,8 @@ DESC
Command::Root Command::Root
end end
end end
autoload :Action, File.expand_path("../action", __FILE__)
autoload :StateFile, File.expand_path("../state_file", __FILE__)
end end
end end

View File

@ -0,0 +1,32 @@
require "json"
module VagrantPlugins
module CommandPlugin
# This is a helper to deal with the plugin state file that Vagrant
# uses to track what plugins are installed and activated and such.
class StateFile
def initialize(path)
@path = path
@data = {}
@data = JSON.parse(@path.read) if @path.exist?
end
# Add a plugin that is installed to the state file.
#
# @param [String] name The name of the plugin
def add_plugin(name)
@data["installed"] ||= []
@data["installed"] << name
save!
end
# This saves the state back into the state file.
def save!
@path.open("w+") do |f|
f.write(JSON.dump(@data))
end
end
end
end
end

View File

@ -411,6 +411,9 @@ en:
ready to `vagrant up` your first virtual environment! Please read ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant. `vagrantup.com` for more information on using Vagrant.
plugin:
installing: |-
Installing the '%{name}' plugin...
status: status:
aborted: |- aborted: |-
The VM is in an aborted state. This means that it was abruptly The VM is in an aborted state. This means that it was abruptly