class Hen
The class handling the program logic. This is what you use in your Rakefile. See the README for more information.
Constants
- HENDIRS
The directories to search for hen files. Set environment variable
HENPATH
to add more.- HENRC_NAME
The name of the
.henrc
file.- HENS
All hens found, mapped by their name.
- RCDIRS
Directories to search for
.henrc
files.- VERSION
Attributes
The global container for all loaded hens.
The verbosity concerning errors and warnings.
The hen's definition block.
The list of the hen's dependencies.
The hen's name.
Public Class Methods
Get hen
by name.
# File lib/hen.rb, line 138 def [](hen) @hens[hen] end
Adds hen
to the global container. Overwrites an existing hen
only if overwrite
is true.
# File lib/hen.rb, line 126 def add_hen(hen, overwrite = false) if overwrite @hens[hen.name] = hen else @hens[hen.name] ||= hen end end
The configuration resulting from the user's .henrc
. Takes
optional key
argument as “path” into the config hash,
returning the thusly retrieved value.
Example:
config('a/b/c') #=> @config[:a][:b][:c]
# File lib/hen.rb, line 168 def config(key = nil) @config ||= load_config return @config unless key key.split('/').inject(@config) { |value, k| value.fetch(k.to_sym) } rescue IndexError, NoMethodError end
The path to a suitable default .henrc
location.
# File lib/hen.rb, line 154 def default_henrc find_henrc(false).first end
The paths to the user's .henrc
files.
# File lib/hen.rb, line 146 def henrc @henrc ||= find_henrc end
Loads the hens, causing them to lay their eggs^H^H^Htasks. Either all, if
no restrictions are specified, or the given hens, or all but those given in
the :exclude
option.
# File lib/hen.rb, line 87 def lay!(*args) # Extract potential options hash options = args.last.is_a?(Hash) ? args.pop : {} @verbose = options[:verbose] if options.key?(:verbose) yield.each { |key, value| config[key].update(value) } if block_given? # Handle include/exclude requirements excl = options[:exclude] args, default = args.empty? ? [Array(excl), true] : [args, false] inclexcl = Hash.new(default) args.each { |arg| inclexcl[arg.to_s] = !default } # Load all available hens (as far as the # include/exclude conditions are met) load_hens { |hen| inclexcl[hen] } # Execute each hen definition hens.each { |name, hen| # Load any dependencies, in case they're not included yet begin load_hens(*hen.dependencies) rescue LoadError => err warn "#{name}: Required dependency missing: " << File.basename(err.to_s, '.rake') if verbose next end hen.lay! } end
Creates a new Hen instance of a certain name and
optional dependencies; see resolve_args for details on the
args
argument. Requires a definition block; see lay! for details.
Adds itself to the global hen container via add_hen.
# File lib/hen.rb, line 243 def initialize(args, overwrite = false, &block) @name, @dependencies = resolve_args(args) @laid = false unless @block = block raise LocalJumpError, "#{@name}: no block given" if verbose return end self.class.add_hen(self, overwrite) end
Private Class Methods
Returns all readable .henrc
files found in the (optional)
environment variable HENRC
and in each directory named in RCDIRS. If must_exist
is false, no
readability checks will be performed.
# File lib/hen.rb, line 199 def find_henrc(must_exist = true) RCDIRS.map { |dir| File.join(dir, HENRC_NAME) }.unshift(ENV['HENRC']).compact.map { |file| File.expand_path(file) if !must_exist || File.readable?(file) }.compact.uniq end
Load the configuration from the user's .henrc
files.
# File lib/hen.rb, line 182 def load_config hash = Hash.new { |h, k| h[k] = {} } henrc.each { |path| yaml = Psych.safe_load(File.read(path), symbolize_names: true) hash.deep_update(yaml) if yaml.is_a?(Hash) } hash end
Actually loads the hen files for hens
, or all available if
none are specified. If a block is given, only those hen files are loaded
for which the block evaluates to true.
# File lib/hen.rb, line 214 def load_hens(*hens, &block) # By default, include all block ||= lambda { |_| true } (hens.empty? ? HENS.keys : hens).each { |hen| hen = hen.to_s HENS[hen].each { |h| load h } if block[hen] } end
Public Instance Methods
Runs the definition block, exposing helper methods from the DSL.
# File lib/hen.rb, line 260 def lay! return if laid? @laid = true # Call dependencies first dependencies.each { |hen| self.class[hen].lay! } block.bind(DSL).call rescue => err trace = $DEBUG || Rake.application.options.trace warn "#{name}: #{err} (#{err.class})" if trace || verbose warn err.backtrace.join("\n ") if trace end
Private Instance Methods
Keeps track of whether the block has already been executed.
# File lib/hen.rb, line 313 def laid? @laid end
Splits into hen name and optional dependencies: args
may be a
single symbol (or string), or a hash with a single key pointing to a list
of hens this one depends upon.
# File lib/hen.rb, line 292 def resolve_args(args) name, dependencies = case args when Hash if args.empty? raise ArgumentError, 'No hen name given' elsif args.size > 1 raise ArgumentError, "Too many hen names: #{args.keys.join(' ')}" end [args.keys.first, [*args.values.first]] else [args, []] end [name.to_sym, dependencies.map { |dependency| dependency.to_sym }] end
Delegates to #verbose.
# File lib/hen.rb, line 282 def verbose self.class.verbose end