1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
require "json"
require "fileutils"
require "tempfile"
module Vagrant
module Plugin
# 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
# @return [Pathname] path to file
attr_reader :path
def initialize(path, system = false)
@path = path
@system = system
@data = {}
if @path.exist?
begin
@data = JSON.parse(@path.read)
rescue JSON::ParserError => e
raise Vagrant::Errors::PluginStateFileParseError,
path: path, message: e.message
end
upgrade_v0! if !@data["version"]
end
@data["version"] ||= "1"
@data["installed"] ||= {}
load_extra_plugins
end
def load_extra_plugins
extra_plugins = Dir.glob(@path.dirname.join('plugins.d', '*.json'))
extra_plugins.each do |filename|
json = File.read(filename)
begin
plugin_data = JSON.parse(json)
@data["installed"].merge!(plugin_data)
rescue JSON::ParserError => e
raise Vagrant::Errors::PluginStateFileParseError,
path: filename, message: e.message
end
end
end
# Add a plugin that is installed to the state file.
#
# @param [String] name The name of the plugin
def add_plugin(name, **opts)
@data["installed"][name] = {
"ruby_version" => RUBY_VERSION,
"vagrant_version" => Vagrant::VERSION,
"gem_version" => opts[:version] || "",
"require" => opts[:require] || "",
"sources" => opts[:sources] || [],
"installed_gem_version" => opts[:installed_gem_version],
"env_local" => !!opts[:env_local]
}
save!
end
# Adds a RubyGems index source to look up gems.
#
# @param [String] url URL of the source.
def add_source(url)
@data["sources"] ||= []
@data["sources"] << url if !@data["sources"].include?(url)
save!
end
# This returns a hash of installed plugins according to the state
# file. Note that this may _not_ directly match over to actually
# installed gems.
#
# @return [Hash]
def installed_plugins
@data["installed"]
end
# Returns true/false if the plugin is present in this state file.
#
# @return [Boolean]
def has_plugin?(name)
@data["installed"].key?(name)
end
# Remove a plugin that is installed from the state file.
#
# @param [String] name The name of the plugin.
def remove_plugin(name)
@data["installed"].delete(name)
save!
end
# Remove a source for RubyGems.
#
# @param [String] url URL of the source
def remove_source(url)
@data["sources"] ||= []
@data["sources"].delete(url)
save!
end
# Returns the list of RubyGems sources that will be searched for
# plugins.
#
# @return [Array<String>]
def sources
@data["sources"] || []
end
# This saves the state back into the state file.
def save!
Tempfile.open(@path.basename.to_s, @path.dirname.to_s) do |f|
f.binmode
f.write(JSON.dump(@data))
f.fsync
f.chmod(0644)
f.close
FileUtils.mv(f.path, @path)
end
rescue Errno::EACCES
# Ignore permission denied against system-installed plugins; regular
# users are not supposed to write there.
raise unless @system
end
protected
# This upgrades the internal data representation from V0 (the initial
# version) to V1.
def upgrade_v0!
@data["version"] = "1"
new_installed = {}
(@data["installed"] || []).each do |plugin|
new_installed[plugin] = {
"ruby_version" => "0",
"vagrant_version" => "0",
}
end
@data["installed"] = new_installed
save!
end
end
end
end
|