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 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
require "pathname"
require "librarian/config/file_source"
require "librarian/config/hash_source"
module Librarian
module Config
class Database
class << self
def library
name.split("::").first.downcase
end
end
attr_accessor :adapter_name
private :adapter_name=
attr_accessor :root, :assigned_specfile_name
private :root=, :assigned_specfile_name=
attr_accessor :underlying_env, :underlying_pwd, :underlying_home
private :underlying_env=, :underlying_pwd=, :underlying_home=
def initialize(adapter_name, options = { })
self.adapter_name = adapter_name or raise ArgumentError, "must provide adapter_name"
options[:project_path] || options[:pwd] or raise ArgumentError, "must provide project_path or pwd"
self.root = options[:project_path] && Pathname(options[:project_path])
self.assigned_specfile_name = options[:specfile_name]
self.underlying_env = options[:env] or raise ArgumentError, "must provide env"
self.underlying_pwd = options[:pwd] && Pathname(options[:pwd])
self.underlying_home = options[:home] && Pathname(options[:home])
end
def global
memo(__method__) { new_file_source(global_config_path) }
end
def env
memo(__method__) { HashSource.new(adapter_name, :name => "environment", :raw => env_source_data) }
end
def local
memo(__method__) { new_file_source(local_config_path) }
end
def [](key, scope = nil)
case scope
when "local", :local then local[key]
when "env", :env then env[key]
when "global", :global then global[key]
when nil then local[key] || env[key] || global[key]
else raise Error, "bad scope"
end
end
def []=(key, scope, value)
case scope
when "local", :local then local[key] = value
when "global", :global then global[key] = value
else raise Error, "bad scope"
end
end
def keys
[local, env, global].inject([]){|a, e| a.concat(e.keys) ; a}.sort.uniq
end
def project_path
root || specfile_path.dirname
end
def specfile_path
if root
root + (assigned_specfile_name || default_specfile_name)
else
env_specfile_path || default_specfile_path
end
end
def specfile_name
specfile_path.basename.to_s
end
def lockfile_path
project_path + lockfile_name
end
def lockfile_name
"#{specfile_name}.lock"
end
private
def new_file_source(config_path)
return unless config_path
FileSource.new(adapter_name,
:config_path => config_path,
:forbidden_keys => [config_key, specfile_key]
)
end
def global_config_path
env_global_config_path || default_global_config_path
end
def env_global_config_path
memo(__method__) { env[config_key] }
end
def default_global_config_path
underlying_home && underlying_home + config_name
end
def local_config_path
root_local_config_path || env_local_config_path || default_local_config_path
end
def root_local_config_path
root && root + config_name
end
def env_specfile_path
memo(__method__) do
path = env[specfile_key]
path && Pathname(path)
end
end
def default_specfile_path
default_project_root_path + (assigned_specfile_name || default_specfile_name)
end
def env_local_config_path
return unless env_specfile_path
env_specfile_path.dirname + config_name
end
def default_local_config_path
default_project_root_path + config_name
end
def default_project_root_path
if root
root
else
path = underlying_pwd
path = path.dirname until project_root_path?(path) || path.dirname == path
project_root_path?(path) ? path : underlying_pwd
end
end
def project_root_path?(path)
File.file?(path + default_specfile_name)
end
def config_key
"config"
end
def specfile_key
"#{adapter_name}file"
end
def default_specfile_name
"#{adapter_name.capitalize}file"
end
def library
self.class.library
end
def config_name_prefix
".#{library}"
end
def config_name
File.join(*[config_name_prefix, adapter_name, "config"])
end
def raw_key_prefix
"#{library.upcase}_#{adapter_name.upcase}_"
end
def env_source_data
prefix = raw_key_prefix
data = underlying_env.dup
data.reject!{|k, _| !k.start_with?(prefix) || k.size <= prefix.size}
data
end
def memo(key)
key = "@#{key}"
instance_variable_set(key, yield) unless instance_variable_defined?(key)
instance_variable_get(key)
end
end
end
end
|