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

hens[R]

The global container for all loaded hens.

verbose[R]

The verbosity concerning errors and warnings.

block[R]

The hen's definition block.

dependencies[R]

The list of the hen's dependencies.

name[R]

The hen's name.

Public Class Methods

Hen[hen] → aHen click to toggle source

Get hen by name.

# File lib/hen.rb, line 138
def [](hen)
  @hens[hen]
end
add_hen(hen, overwrite = false) click to toggle source

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
config → aHash click to toggle source
config(key) → anObject

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
default_henrc → aString click to toggle source

The path to a suitable default .henrc location.

# File lib/hen.rb, line 154
def default_henrc
  find_henrc(false).first
end
henrc → anArray click to toggle source

The paths to the user's .henrc files.

# File lib/hen.rb, line 146
def henrc
  @henrc ||= find_henrc
end
lay! click to toggle source
lay!(:some_hen, :some_other_hen)
lay!(exclude: [:some_hen, :some_other_hen])

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
new(args, overwrite = false) { ... } click to toggle source

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

find_henrc(must_exist = true) → anArray click to toggle source

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_config → aHash click to toggle source

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
load_hens(*hens) click to toggle source
load_hens(*hens) { |hen_name| ... }

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

lay! click to toggle source

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

laid? → true or false click to toggle source

Keeps track of whether the block has already been executed.

# File lib/hen.rb, line 313
def laid?
  @laid
end
resolve_args(args) → [name, dependencies] click to toggle source

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
verbose → true or false click to toggle source

Delegates to #verbose.

# File lib/hen.rb, line 282
def verbose
  self.class.verbose
end