Class: Tap::Env
- Includes:
- Configurable, Enumerable, Support::Minimap
- Defined in:
- lib/tap/env.rb
Overview
– Note that gems and env_paths reset envs – custom modifications to envs will be lost whenever these configs are reset.
Direct Known Subclasses
Defined Under Namespace
Classes: ConfigError
Constant Summary collapse
- DEFAULT_CONFIG_FILE =
The default config file path
"tap.yml"
- TEMPLATES =
{}
- @@instance =
nil
- @@instances =
{}
Instance Attribute Summary collapse
-
#logger ⇒ Object
Gets or sets the logger for self.
-
#root ⇒ Object
readonly
The Root directory structure for self.
Class Method Summary collapse
-
.gemspecs(latest = true) ⇒ Object
Returns the gemspecs for all installed gems with a DEFAULT_CONFIG_FILE.
-
.instance ⇒ Object
Returns the active instance of Env.
- .instance_for(path) ⇒ Object
-
.instances ⇒ Object
A hash of (path, Env instance) pairs, generated by Env#instantiate.
-
.instantiate(path_or_root, default_config = {}, logger = nil, &block) ⇒ Object
Creates a new Env for the specified path and adds it to Env#instances, or returns the existing instance for the path.
-
.manifest(name, &block) ⇒ Object
:yields: env (returns manifest).
- .pathify(path) ⇒ Object
Instance Method Summary collapse
-
#activate ⇒ Object
Activates self by unshifting load_paths for self to the load_path_targets.
-
#active? ⇒ Boolean
Return true if self has been activated.
-
#count ⇒ Object
Returns the total number of unique envs nested in self (including self).
-
#deactivate ⇒ Object
Deactivates self by clearing manifests and deleting load_paths for self from the load_path_targets.
-
#each ⇒ Object
Passes each nested env to the block in order, starting with self.
-
#env_path ⇒ Object
Returns the path for self in Env.instances.
-
#envs(flat = false) ⇒ Object
An array of nested Envs, by default comprised of the env_path + gem environments (in that order).
-
#envs=(envs) ⇒ Object
Sets envs removing duplicates and instances of self.
-
#initialize(config = {}, root = Tap::Root.new, logger = nil) ⇒ Env
constructor
A new instance of Env.
-
#inspect(template = nil) ⇒ Object
:yields: templater, attrs.
-
#log(action, msg = "", level = Logger::INFO) ⇒ Object
Logs the action and message at the input level (default INFO).
-
#push(env) ⇒ Object
Pushes env onto envs, removing duplicates.
-
#reconfigure(overrides = {}) ⇒ Object
Processes and resets the input configurations for both root and self.
-
#recursive_each(*args, &block) ⇒ Object
Visits each nested env in order, starting with self, and passing to the block the env and any arguments generated by the parent of the env.
-
#recursive_inspect(template = nil, *args) ⇒ Object
:yields: templater, attrs.
-
#reverse_each ⇒ Object
Passes each nested env to the block in reverse order, ending with self.
-
#search_path(dir, path) ⇒ Object
Searches each env for the first existing file or directory at env.root.filepath(dir, path).
- #summarize(name, template = ) ⇒ Object
-
#unshift(env) ⇒ Object
Unshifts env onto envs, removing duplicates.
Methods included from Support::Minimap
Constructor Details
#initialize(config = {}, root = Tap::Root.new, logger = nil) ⇒ Env
Returns a new instance of Env.
214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/tap/env.rb', line 214 def initialize(config={}, root=Tap::Root.new, logger=nil) @root = root @logger = logger @envs = [] @active = false @manifests = {} # initialize these for reset_env @gems = [] @env_paths = [] initialize_config(config) end |
Instance Attribute Details
#logger ⇒ Object
Gets or sets the logger for self
124 125 126 |
# File 'lib/tap/env.rb', line 124 def logger @logger end |
Class Method Details
.gemspecs(latest = true) ⇒ Object
Returns the gemspecs for all installed gems with a DEFAULT_CONFIG_FILE. If latest==true, then only the specs for the most current gems will be returned.
83 84 85 86 87 |
# File 'lib/tap/env.rb', line 83 def gemspecs(latest=true) Support::Gems.select_gems(latest) do |spec| File.exists?(File.join(spec.full_gem_path, DEFAULT_CONFIG_FILE)) end end |
.instance ⇒ Object
Returns the active instance of Env.
17 18 19 |
# File 'lib/tap/env.rb', line 17 def instance @@instance end |
.instance_for(path) ⇒ Object
61 62 63 64 |
# File 'lib/tap/env.rb', line 61 def instance_for(path) path = pathify(path) instances.has_key?(path) ? instances[path] : instantiate(path) end |
.instances ⇒ Object
A hash of (path, Env instance) pairs, generated by Env#instantiate. Used to prevent infinite loops of Env dependencies by assigning a single Env to a given path.
24 25 26 |
# File 'lib/tap/env.rb', line 24 def instances @@instances end |
.instantiate(path_or_root, default_config = {}, logger = nil, &block) ⇒ Object
Creates a new Env for the specified path and adds it to Env#instances, or returns the existing instance for the path. Paths can point to an env config file, or to a directory. If a directory is provided, instantiate treats path as the DEFAULT_CONFIG_FILE in that directory. All paths are expanded.
e1 = Env.instantiate("./path/to/config.yml")
e2 = Env.instantiate("./path/to/dir")
Env.instances
# => {
# File.expand_path("./path/to/config.yml") => e1,
# File.expand_path("./path/to/dir/#{Tap::Env::DEFAULT_CONFIG_FILE}") => e2 }
The Env is initialized using configurations read from the env config file, and a Root initialized to the config file directory. An instance will be initialized regardless of whether the config file or directory exists.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/tap/env.rb', line 45 def instantiate(path_or_root, default_config={}, logger=nil, &block) path = path_or_root.kind_of?(Root) ? path_or_root.root : path_or_root path = pathify(path) begin root = path_or_root.kind_of?(Root) ? path_or_root : Root.new(File.dirname(path)) config = default_config.merge(load_file(path)) # note the assignment of env to instances MUST occur before # reconfigure to prevent infinite looping (instances[path] = new({}, root, logger)).reconfigure(config, &block) rescue(Exception) raise Env::ConfigError.new($!, path) end end |
.manifest(name, &block) ⇒ Object
:yields: env (returns manifest)
73 74 75 76 77 78 |
# File 'lib/tap/env.rb', line 73 def manifest(name, &block) # :yields: env (returns manifest) name = name.to_sym define_method(name) do self.manifests[name] ||= block.call(self).bind(self, name) end end |
.pathify(path) ⇒ Object
66 67 68 69 70 71 |
# File 'lib/tap/env.rb', line 66 def pathify(path) if File.directory?(path) || (!File.exists?(path) && File.extname(path) == "") path = File.join(path, DEFAULT_CONFIG_FILE) end File.(path) end |
Instance Method Details
#activate ⇒ Object
Activates self by unshifting load_paths for self to the load_path_targets. Once active, self can be referenced from Env.instance and the current configurations are frozen. Env.instance is deactivated, if set, before self is activated. Returns true if activate succeeded, or false if self is already active.
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 |
# File 'lib/tap/env.rb', line 377 def activate return false if active? @active = true @@instance = self if @@instance == nil # freeze array configs like load_paths config.each_pair do |key, value| next unless value.kind_of?(Array) value.freeze end # activate nested envs envs.reverse_each do |env| env.activate end # add load paths load_paths.reverse_each do |path| $LOAD_PATH.unshift(path) end $LOAD_PATH.uniq! # perform requires requires.each do |path| require path end # perform loads loads.each do |path| load path end true end |
#active? ⇒ Boolean
Return true if self has been activated.
446 447 448 |
# File 'lib/tap/env.rb', line 446 def active? @active end |
#count ⇒ Object
Returns the total number of unique envs nested in self (including self).
304 305 306 |
# File 'lib/tap/env.rb', line 304 def count envs(true).length end |
#deactivate ⇒ Object
Deactivates self by clearing manifests and deleting load_paths for self from the load_path_targets. Env.instance will no longer reference self and the configurations are unfrozen (using duplication).
Returns true if deactivate succeeded, or false if self is not active.
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
# File 'lib/tap/env.rb', line 419 def deactivate return false unless active? # remove load paths load_paths.each do |path| $LOAD_PATH.delete(path) end @active = false @manifests.clear @@instance = nil if @@instance == self # unfreeze array configs by duplicating config.each_pair do |key, value| next unless value.kind_of?(Array) instance_variable_set("@#{key}", value.dup) end # dectivate nested envs envs.reverse_each do |env| env.deactivate end true end |
#each ⇒ Object
Passes each nested env to the block in order, starting with self.
265 266 267 |
# File 'lib/tap/env.rb', line 265 def each envs(true).each {|e| yield(e) } end |
#env_path ⇒ Object
Returns the path for self in Env.instances.
361 362 363 364 |
# File 'lib/tap/env.rb', line 361 def env_path Env.instances.each_pair {|path, env| return path if env == self } nil end |
#envs(flat = false) ⇒ Object
An array of nested Envs, by default comprised of the env_path + gem environments (in that order). These nested Envs are activated/deactivated with self.
Returns a flattened array of the unique nested envs when flat == true.
241 242 243 |
# File 'lib/tap/env.rb', line 241 def envs(flat=false) flat ? (@flat_envs ||= self.flatten_envs.freeze) : @envs end |
#envs=(envs) ⇒ Object
Sets envs removing duplicates and instances of self.
229 230 231 232 233 |
# File 'lib/tap/env.rb', line 229 def envs=(envs) @envs = envs.uniq.delete_if {|e| e == self } @envs.freeze @flat_envs = nil end |
#inspect(template = nil) ⇒ Object
:yields: templater, attrs
532 533 534 535 536 537 538 539 540 541 542 |
# File 'lib/tap/env.rb', line 532 def inspect(template=nil) # :yields: templater, attrs return "#<#{self.class}:#{object_id} root='#{root.root}'>" if template == nil attrs = {} collect do |env| templater = Support::Templater.new(template, :env => env) block_given? ? (yield(templater, attrs) ? templater : nil) : templater end.compact.collect do |templater| templater.build(attrs) end.join end |
#log(action, msg = "", level = Logger::INFO) ⇒ Object
Logs the action and message at the input level (default INFO). Logging is suppressed if no logger is set.
368 369 370 |
# File 'lib/tap/env.rb', line 368 def log(action, msg="", level=Logger::INFO) logger.add(level, msg, action.to_s) if logger end |
#push(env) ⇒ Object
Pushes env onto envs, removing duplicates.
Self cannot be pushed onto self.
256 257 258 259 260 261 262 |
# File 'lib/tap/env.rb', line 256 def push(env) unless env == self || envs[-1] == env envs = self.envs.reject {|e| e == env } self.envs = envs.push(env) end self end |
#reconfigure(overrides = {}) ⇒ Object
Processes and resets the input configurations for both root and self. Reconfiguration consists of the following steps:
-
partition overrides into env, root, and other configs
-
reconfigure root with the root configs
-
reconfigure self with the env configs
-
yield other configs to the block (if given)
Reconfigure will always yields to the block, even if there are no non-root, non-env configurations. Unspecified configurations are NOT reconfigured. (Note this means that existing path configurations like load_paths will not automatically be reset using reconfigured root.)
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'lib/tap/env.rb', line 321 def reconfigure(overrides={}) check_configurable # partiton config into its parts env_configs = {} root_configs = {} other_configs = {} env_configurations = self.class.configurations root_configurations = root.class.configurations overrides.each_pair do |key, value| key = key.to_sym partition = case when env_configurations.key?(key) then env_configs when root_configurations.key?(key) then root_configs else other_configs end partition[key] = value end # reconfigure root so it can resolve path_configs root.reconfigure(root_configs) # reconfigure self super(env_configs) # handle other configs case when block_given? yield(other_configs) when !other_configs.empty? log(:warn, "ignoring non-env configs: #{other_configs.keys.join(',')}", Logger::DEBUG) end self end |
#recursive_each(*args, &block) ⇒ Object
Visits each nested env in order, starting with self, and passing to the block the env and any arguments generated by the parent of the env. The initial arguments are set when recursive_each is first called; subsequent arguements are the return values of the block.
e0, e1, e2, e3, e4 = ('a'..'e').collect {|name| Tap::Env.new(:name => name) }
e0.push(e1).push(e2)
e1.push(e3).push(e4)
lines = []
e0.recursive_each(0) do |env, nesting_depth|
lines << "\n#{'..' * nesting_depth}#{env.config[:name]} (#{nesting_depth})"
nesting_depth + 1
end
lines.join
# => %Q{
# a (0)
# ..b (1)
# ....d (2)
# ....e (2)
# ..c (1)}
299 300 301 |
# File 'lib/tap/env.rb', line 299 def recursive_each(*args, &block) # :yields: env, *parent_args each_nested_env(self, [], args, &block) end |
#recursive_inspect(template = nil, *args) ⇒ Object
:yields: templater, attrs
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 |
# File 'lib/tap/env.rb', line 544 def recursive_inspect(template=nil, *args) # :yields: templater, attrs return "#<#{self.class}:#{object_id} root='#{root.root}'>" if template == nil attrs = {} templaters = [] recursive_each(*args) do |env, *argv| templater = Support::Templater.new(template, :env => env) next_args = block_given? ? yield(templater, attrs, *argv) : argv templaters << templater if next_args next_args end templaters.collect do |templater| templater.build(attrs) end.join end |
#reverse_each ⇒ Object
Passes each nested env to the block in reverse order, ending with self.
270 271 272 |
# File 'lib/tap/env.rb', line 270 def reverse_each envs(true).reverse_each {|e| yield(e) } end |
#search_path(dir, path) ⇒ Object
Searches each env for the first existing file or directory at env.root.filepath(dir, path). Paths are expanded, and search_path checks to make sure the file is, in fact, relative to env.root. An optional block may be used to check the file; the file will only be returned if the block returns true.
Returns nil if no file can be found.
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 |
# File 'lib/tap/env.rb', line 457 def search_path(dir, path) each do |env| directory = env.root.filepath(dir) file = env.root.filepath(dir, path) # check the file is relative to the # directory, and that the file exists. if file.rindex(directory, 0) == 0 && File.exists?(file) && (!block_given? || yield(file)) return file end end nil end |
#summarize(name, template = ) ⇒ Object
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
# File 'lib/tap/env.rb', line 504 def summarize(name, template=TEMPLATES[name]) count = 0 width = 10 env_names = {} minimap.each do |env_name, env| env_names[env] = env_name end inspect(template) do |templater, share| env = templater.env entries = env.send(name).minimap next(false) if entries.empty? templater.env_name = env_names[env] templater.entries = entries count += 1 entries.each do |entry_name, entry| width = entry_name.length if width < entry_name.length end share[:count] = count share[:width] = width true end end |