module Grably::Core::ProductExpand

Product expansion rules. Expand is mapping from anything(almost) to list of products

We have following expansion rules:

Constants

METHOD_TABLE

We define method table for expand rules. Key is object class, value is method.

Initially we just define set of Class to Symbol mappings. Then calling ProductExpand.singleton_method on each method name. As bonus following this technique we will get NameError immediately after module load.

Public Class Methods

check_dependencies(target_task, context_task) click to toggle source

Ensure that target task is among context_task dependencies

# File lib/grably/core/product.rb, line 211
def check_dependencies(target_task, context_task)
  return true if target_task == context_task
  context_task.all_prerequisite_tasks.include?(target_task)
end
expand(srcs, task = nil) click to toggle source
# File lib/grably/core/product.rb, line 110
def expand(srcs, task = nil)
  # Wrap o in Array to simplify processing flow
  srcs = [srcs] unless srcs.is_a? Array
  # First typed expand will be array expand. So we will get array as
  # result
  typed_expand(srcs, task)
end
expand_array(elements, task) click to toggle source
# File lib/grably/core/product.rb, line 137
def expand_array(elements, task)
  elements.flat_map { |e| typed_expand(e, task) }
end
expand_hash(hash, task) click to toggle source
# File lib/grably/core/product.rb, line 128
def expand_hash(hash, task)
  hash.flat_map do |expr, filter|
    # If got string generate lambda representing filter operation
    filter = generate_string_filter(filter) if filter.is_a? String
    raise 'Filter is not a proc %s'.format(filter) unless filter.is_a?(Proc)
    filter.call(typed_expand(expr, task), ->(o) { expand(o, task) })
  end
end
expand_proc(proc, task) click to toggle source
# File lib/grably/core/product.rb, line 154
def expand_proc(proc, task)
  proc.call(->(o) { expand(o, task) })
end
expand_product(product, _) click to toggle source
# File lib/grably/core/product.rb, line 170
def expand_product(product, _)
  product
end
expand_string(expr, _task) click to toggle source
# File lib/grably/core/product.rb, line 141
def expand_string(expr, _task)
  unless File.exist?(expr)
    warn "'#{expr}' does not exist. Can't expand path"
    return []
  end
  # Will expand recursively over directory content.
  if File.directory?(expr)
    expand_dir(expr)
  else
    Product.new(expr)
  end
end
expand_symbol(symbol, task) click to toggle source
# File lib/grably/core/product.rb, line 118
def expand_symbol(symbol, task)
  case symbol
  when :task_deps
    typed_expand(task.prerequisites.map(&:to_sym), task)
  else
    task_ref = Task[symbol]
    typed_expand(task_ref, task)
  end
end
expand_task(target_task, context_task) click to toggle source
# File lib/grably/core/product.rb, line 158
def expand_task(target_task, context_task)
  # Behaving strictly we can only get task backet of
  # self, i.e. target_task == context_task, or if target_task is
  # context_task prerequisite (direct or indirect).
  unless check_dependencies(target_task, context_task)
    raise(ArgumentError,
          'Target task [%s] is not in context task [%s] prerequisites'
              .format(target_task.name, context_task.name))
  end
  target_task.bucket
end
typed_expand(element, task) click to toggle source
# File lib/grably/core/product.rb, line 194
def typed_expand(element, task)
  # Fetching expand rule for element type
  method_refs = METHOD_TABLE.select { |c, _| element.is_a?(c) }
  raise 'Multiple expands found for %s. Expands %s'.format(element, method_refs.keys) if method_refs.size > 1
  method_ref = method_refs.values.first
  unless method_ref
    err = 'No expand for type: %s. Element is \'%s\''
    raise err.format(element.class, element)
  end
  # Every expand_%something% method follows same contract, so we just
  # passing standard set of arguments
  method_ref.call(element, task)
end

Private Class Methods

expand_dir(expr) click to toggle source
# File lib/grably/core/product.rb, line 218
def expand_dir(expr)
  glob = File.join(expr, '**/*')
  Dir[glob]
    .select { |entry| File.file?(entry) }
    .map { |file| Product.new(file, file.sub(expr + File::SEPARATOR, '')) }
end