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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
require 'buff/config'
module OldInspect
if defined? Hashie::Array
refine Hashie::Array do
alias inspect array_inspect
end
end
end
using OldInspect
module Buff
module Config
class Ruby < Config::Base
class Evaluator
class << self
# Parse the contents of the Ruby file into a Hash.
#
# @param [String] contents
# @param [String] path file that should be used as __FILE__
# during eval
# @param [Object] context the parent Config object
#
# @return [Hash]
def parse(contents, path=nil, context=nil)
self.new(contents, path, context).send(:attributes)
end
end
# @param [String] contents
# @param [String] path
# @param [Object] context
def initialize(contents, path=nil, context=nil)
path ||= "(buff-config)"
@context = context
@attributes = Hash.new
instance_eval(contents, path)
rescue Exception => ex
raise Errors::InvalidConfig, ex
end
# @see {Buff::Config::Ruby.platform_specific_path}
def platform_specific_path(path)
Buff::Config::Ruby.platform_specific_path(path)
end
private
attr_reader :attributes
def method_missing(m, *args, &block)
if args.size > 0
attributes[m.to_sym] = (args.length == 1) ? args[0] : args
elsif @context && @context.respond_to?(m)
@context.send(m, *args, &block)
else
Proxy.new
end
end
class Proxy
def method_missing(m, *args, &block)
self
end
end
end
class << self
# @param [String] contents
# @param [String] path
#
# @return [Buff::Config::Ruby]
def from_ruby(contents, path=nil)
new.from_ruby(contents, path)
end
# @param [String] path
#
# @raise [Buff::Errors::ConfigNotFound]
#
# @return [Buff::Config::Ruby]
def from_file(path)
path = File.expand_path(path)
contents = File.read(path)
new(path).from_ruby(contents, path)
rescue TypeError, Errno::ENOENT, Errno::EISDIR
raise Errors::ConfigNotFound, "No configuration found at: '#{path}'"
end
# Converts a path to a path usable for your current platform
#
# @param [String] path
#
# @return [String]
def platform_specific_path(path)
if RUBY_PLATFORM =~ /mswin|mingw|windows/
system_drive = ENV['SYSTEMDRIVE'] ? ENV['SYSTEMDRIVE'] : ""
path = win_slashify File.join(system_drive, path.split('/')[2..-1])
end
path
end
private
# Convert a unixy filepath to a windowsy filepath. Swaps forward slashes for
# double backslashes
#
# @param [String] path
# filepath to convert
#
# @return [String]
# converted filepath
def win_slashify(path)
path.gsub(File::SEPARATOR, (File::ALT_SEPARATOR || '\\'))
end
end
def initialize(path = nil, options = {})
super
from_ruby(File.read(path), path) if path && File.exists?(path)
end
# @raise [Buff::Errors::InvalidConfig]
#
# @return [Buff::Config::Ruby]
def from_ruby(contents, path=nil)
hash = Buff::Config::Ruby::Evaluator.parse(contents, path, self)
mass_assign(hash)
self
end
# Convert the result to Ruby.
#
# @return [String]
def to_ruby
self.to_hash.map do |k,v|
value = if const = find_constant(v)
const
else
v.inspect
end
"#{k.to_s}(#{value})"
end.join("\n")
end
alias_method :to_rb, :to_ruby
def save(destination = self.path)
if destination.nil?
raise Errors::ConfigSaveError, "Cannot save configuration without a destination. " +
"Provide one to save or set one on the object."
end
FileUtils.mkdir_p(File.dirname(destination))
File.open(destination, 'w+') do |f|
f.write(to_ruby)
end
end
# Reload the current configuration file from disk
#
# @return [Buff::Config::Ruby]
def reload
mass_assign(self.class.from_file(path).to_hash)
self
end
private
def find_constant(name)
Module.constants.find do |const|
begin
Module.const_get(const) == name
rescue NameError; end
end
end
end
end
end
|