module Taskable def self.define_task(base, target_and_requisite, &function) case base when Class, Module else #Object end end module ClassDSL # Without an argument, returns list of tasks defined for this class. # # If a task's target name is given, will return the first # task mathing the name found in the class' inheritance chain. # This is important ot ensure task are inherited in the same manner # that methods are. def tasks(target=nil) if target target = target.to_sym anc = ancestors.select{|a| a < DSL} t = nil; anc.find{|a| t = a.tasks[target]} return t else @tasks ||= {} end end # Set a description to be used by then next defined task in this class. def desc(description) @desc = description end # Define a task. def task(target_and_requisite, &function) target, requisite, function = *Task.parse_arguments(target_and_requisite, &function) task = tasks[target.to_sym] ||= ( tdesc = @desc @desc = nil Task.new(self, target, tdesc) #, reqs, actions) ) task.update(requisite, &function) define_method("#{target}Trigger"){ task.run(self) } define_method("#{target}:task", &function) end end # module ObjectDSL # Without an argument, returns list of tasks defined for this class. # # If a task's target name is given, will return the first # task mathing the name found in the class' inheritance chain. # This is important ot ensure task are inherited in the same manner # that methods are. def tasks(target=nil) if target target = target.to_sym anc = ancestors.select{|a| a < DSL} t = nil; anc.find{|a| t = a.tasks[target]} return t else @tasks ||= {} end end # Set a description to be used by then next defined task in this class. def desc(description) @desc = description end # Define a task. def task(target_and_requisite, &function) target, requisite, function = *Task.parse_arguments(target_and_requisite, &function) task = tasks[target.to_sym] ||= ( tdesc = @desc @desc = nil Task.new(self, target, tdesc) #, reqs, actions) ) task.update(requisite, &function) define_method("#{target}Trigger"){ task.run(self) } define_method("#{target}:task", &function) end end # Run a task. #def run(target) # t = self.class.tasks(target) # t.run(self) #end # = Task Class # class Task attr :base attr :target attr :requisite attr :function attr :description def initialize(base, target, description=nil, requisite=nil, &function) @base = base @target = target.to_sym @description = description @requisite = requisite || [] @function = function end # def update(requisite, &function) @requisite.concat(requisite).uniq! @function = function if function end # def prerequisite base.ancestors.select{ |a| a < DSL }.collect{ |a| a.tasks[target].requisite }.flatten.uniq end # invoke target def run(object) rd = rule_dag rd.each do |t| object.send("#{t}:task") end end # def call(object) object.instance_eval(&function) end # Collect task dependencies for running. def rule_dag(cache=[]) prerequisite.each do |r| next if cache.include?(r) t = base.tasks[r] t.rule_dag(cache) #cache << dep end cache << target.to_s cache end # def self.parse_arguments(name_and_reqs, &action) if Hash===name_and_reqs target = name_and_reqs.keys.first.to_s reqs = [name_and_reqs.values.first].flatten else target = name_and_reqs.to_s reqs = [] end return target, reqs, action end end # = File Task Class # class FileTask < Task def needed? if prerequisite.empty? dated = true elsif File.exist?(target) mtime = File.mtime(target) dated = prerequisite.find do |file| !File.exist?(file) || File.mtime(file) > mtime end else dated = true end return dated end # def call(object) object.instance_eval(&function) if needed? end end end =begin # turn yaml file into tasks def parse(file) script = YAML.load(File.new(file.to_s)) imports = script.delete('import') || [] #plugins = script.delete('plugin') || [] srvs = script.delete('services') || {} tgts = script.delete('targets') || {} imports.each do |import| path = Reap::Domain::LIB_DIRECTORY + 'systems' + (import + '.reap').to_s parse(path) end srvs.each do |label, options| type = options.delete('type') @services[label] = domain.send("#{type}_service") # FIXME end tgts.each do |target, options| @targets[target] = Task.new(self, target, options) end end =end =begin # Collect task dependencies for running. def self.rule_dag(target, cache=[]) t = tasks[target.to_sym] d = t.prerequisite d.each do |r| next if cache.include?(r) rule_dag(r, cache) #cache << dep end # file requirements #q = self.class.ann(name, :reqs) || [] #q.each do |req| # path = Pathname.new(req) # next if r.include?(path) # mat = annotations.select{ |n, a| File.fnmatch?(a[:file].first, req) if a[:file] }.compact # mat.each do |n, a| # rule_dag(n, r) # end # r << path #end cache << target.to_s return cache end # invoke target def run(target) target = target.to_sym rd = self.class.rule_dag(target) rd.each do |t| send("#{t}:task") end end =end =begin if target == name.to_s tasks[target].call else case action when Pathname raise unless action.exist? else run_rec(action) end end end end def run_rec(action) # creates a file? dated = true if creates = self.class.ann(action, :file) if self.class.ann(name, :reqs).empty? dated = true elsif File.exist?(creates) mtime = File.mtime(creates) dated = self.class.ann(name, :reqs).find do |file| !File.exist?(file) || File.mtime(file) > mtime end else dated = true end end return unless dated send(action) end =end