lib/mattock/task.rb in mattock-0.3.4 vs lib/mattock/task.rb in mattock-0.4.0

- old
+ new

@@ -7,116 +7,109 @@ module Mattock # A configurable subclass of Rake::Task, such that you can use a # configuration block to change how a common task behaves, while still # overriding Rake API methods like Task#needed? and Task#timestamp - - module TaskMixin + module ConfigurableTask + include Configurable include CascadingDefinition include DeferredDefinition - setting :task_name - setting :task_args - module ClassMethods def default_taskname(name) setting(:task_name, name) end - end - def self.included(mod) - super - mod.class_eval do - extend ClassMethods - DeferredDefinition.add_settings(self) + def define_task(*args) + configs = args.take_while{|arg| Configurable === arg} + extracted_task_args = args[configs.length..-1] + if extracted_task_args.any?{|arg| Configurable === arg} + raise "Mattock::Task classes should be created with parent configs, then Rake task args" + end + + if extracted_task_args.empty? + extracted_task_args = [default_value_for(:task_name)] + end + + task = ::Rake.application.define_task(self, *extracted_task_args) do |task, args| + task.finalize_configuration + task.action(args) + end + + unless self === task + raise "Task already defined for #{task.name} - attempted to redefine with #{self.name}" + end + + task.setup_deferred + task.setup_cascade(*configs) do |t| + t.task_name = task.name + t.task_args = extracted_task_args + + yield(t) if block_given? + end end end - def initialize(*args) - configs = args.take_while{|arg| Configurable === arg} - @extracted_task_args = args[configs.length..-1] - if @extracted_task_args.any?{|arg| Configurable === arg} - raise "Mattock::Task classes should be created with parent configs, then Rake task args" - end - super(*configs) + def self.included(sub) + sub.extend ClassMethods + Configurable.included(sub) + DeferredDefinition.add_settings(sub) end + setting :task_name + setting :task_args + + attr_accessor :base_task + def resolve_configuration super - if @extracted_task_args.empty? - self.task_args = [task_name] - else - self.task_args = @extracted_task_args - end end - def action + def action(*task_args) end + def inspect + "#{self.class.name}: #{self.task_args.inspect}\nConfiguration:\n#{self.class.inspect_instance(self, " ")}" + end + end - module ChildTask - attr_accessor :source_task - - def unset_defaults_guard - source_task.unset_defaults_guard + class DeprecatedTaskAPI + def self.deprecated(message) + @deprecations ||= {} + unless @deprecations.has_key?(message) + warn message + @deprecations[message] = :delivered end + end - def inspect - "From: " + source_task.inspect - end + def initialize(*args, &block) + self.class.deprecated "#{self.class.name}.new(...) is deprecated - instead use #{target_class.name}.define_task(...)\n (from #{caller[0]})" + target_class.define_task(*args, &block) end + end -=begin - # I continue to look for an alternative here. - # The trouble is that deep inside of define_task, Rake actually - # instantiates the Task - so in wanting to be able to override members of - # Task, it's hard to get the virtues of CascadingDefinition as well (maybe - # the virtues could be had without the actual mixin?) - # - # So, what we're doing is to dynamically create a child class and then - # carry forward the Rake::Task#initialize -=end - def task_class - return @task_class if @task_class - @task_class = Class.new(self.class) do - define_method :initialize, Rake::Task.instance_method(:initialize) - include ChildTask - end + module Rake + class Task < ::Rake::Task + include ConfigurableTask end - def inspect - "#{self.class.name}: #{self.task_args.inspect}" + class FileTask < ::Rake::FileTask + include ConfigurableTask end - attr_accessor :rake_task - def define - self.rake_task = task_class.define_task(*task_args) do - finalize_configuration - copy_settings_to(rake_task) - rake_task.action - end - copy_settings_to(rake_task) - rake_task.source_task = self + class FileCreationTask < ::Rake::FileCreationTask + include ConfigurableTask end - end - #I'm having misgivings about this design choice. Rightly, this is probably a - #"Task Definer" that knows what class to ::define_task and then mixin a - #module to handle the original purpose of being able to override e.g. - ##needed? There's a lot of client code that relies on this pattern now, - #though. - class Task < Rake::Task - include TaskMixin + class MultiTask < ::Rake::MultiTask + include ConfigurableTask + end end - class FileTask < Rake::FileTask - include TaskMixin + class Task < DeprecatedTaskAPI + def target_class; Rake::Task; end end - class FileCreationTask < Rake::FileCreationTask - include TaskMixin - end - - class MultiTask < Rake::MultiTask - include TaskMixin + class FileTask < DeprecatedTaskAPI + def target_class; Rake::FileTask; end end end