# = TITLE: # # Task DSL # # = COPYING: # # Copyright (c) 2007 Psi T Corp. # # This file is part of the ProUtils' Ratch program. # # Ratch is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ratch is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ratch. If not, see . module Ratch module Dsl module Tasks # Define main task. def main(name, &block) name, deps, block = *parse_task_dependencies(name, &block) define_main(name, *deps, &block) end # Define a task. def task(name, &block) name, deps, block = *parse_task_dependencies(name, &block) define_task(name, *deps, &block) end # Run a task. def run(name, arguments=nil) task_plan(name).each{ |name| tasks[name].call } end private def tasks ; @tasks ||= {} ; end def main_task ; @main ; end # def parse_task_dependencies(name_deps, &block) if Hash===name_deps name = name_deps.keys[0] deps = name_deps.values[0] else name = name_deps deps = [] end [name, deps, block] end def define_main(name=nil, *depend, &block) @main = define_task(name, *depend, &block) #@main = Task.new(name, *depend, &block) #tasks[@main.name] = @main end def define_task(name, *depend, &block) task = Task.new(name, *depend, &block) tasks[task.name] = task end # Call main task. #-- # TODO If @main is nil try task by same name a file (?) # If so, be careful of infinite loop via method_missing. #++ def run_main return unless main_task run(main_task.name) end # Prepare plan, checking for circular dependencies. def task_plan(name, list=[]) if list.include?(name) raise "Circular dependency #{name}." end if task = tasks[name] task.needs.each do |need| need = need.to_s next if list.include?(need) #@tasks[need].task_plan(need, list) task_plan(need, list) end list << task.name else # TODO THIS TIES TASKS INTO BATCH, BETTER WAY? if name != main_task && fname = batch?(name) task = Task.new(name) do batch(fname) end tasks[name] = task list << task.name else abort "no task -- #{name}" end end return list end end # Task is a very simple store for defined actions # and their prerequisites. class Task attr_reader :name, :needs, :action def initialize(name, *needs, &action) @name = name.to_s @needs = needs @action = action end def call @action.call if @action end end end end