require 'rbconfig' require 'fileutils' require 'facet/fileutils/safe_ln' require 'facet/string/tabto' require 'facet/module/basename' require 'facet/module/attr_setter' require 'facet/filelist' unless defined?( FileList ) require 'facet/openobject' require 'reap/projectinfo' # _____ _ ___ ___ _ # |_ _|_ _ __| |__ | _ ) __ _ ___ ___ / __| |__ _ ______ # | |/ _` (_-< / / | _ \/ _` (_- Hello! # puts master.default #=> Yo! # puts mytask.default #=> Yo! (inherited from master) # end # end # # With the corresponding settings in the ProjectInfo file as: # # default: Yo! # # mytask: # message: Hello! # module Reap def self.registry Task.registry end # Task base class. class Task #include ::Config include ::FileUtils RUBY = ::Config::CONFIG['ruby_install_name'] class << self # When this class is inherited the new task is registered. def inherited( base ) registry << base YAML.add_private_type( base.basename.downcase ) do |type, val| base.new( val ) end end # List of task classes. def registry @registry ||= [] end # Task DSL # Provides tasks type. def task_class basename.downcase end # Short one-line description of the task. def task_desc( text=nil, &block ) return @task_desc = proc { text } if text return @task_desc = block if block_given? return @task_desc.call end alias_method :desc, :task_desc # Takes a string or a block the evaluates to a string # providing detailed help information about the task. def task_help( text=nil, &block ) return @task_help = proc { text } if text return @task_help = block if block_given? return @task_help.call end alias_method :help, :task_help # Set alias for 'task' attribute, which provides # inherited (from master) access to section data. # (Deprecate? You can use "alias_method name, :task") def task_attr( name ) define_method(name) { @task } end # How to determine if a task is available for use. # By default a taks is only available if the Project # file exists and the task's section also exists. # Common was to loosen this resriction are to # only require the file, not the seciton: # # task_available { Reap.projectfile? } # # Or have no restrictions: # # task_available true # def task_available( bool=false, &block ) if bool (class << self; self; end).class_eval { define_method( :available? ){ |app| true } } else (class << self; self; end).class_eval { define_method( :available?, &block ) } end end # Is the task available for use? By default # a task is only made available if the # ProjectInfo file has a task for it. def available?(app) false end # Class-level access to Project file's master data # provided via a CascadingOpenObject. def master @master ||= ProjectInfo.instance.to_cascading_open_object end end #<< class # instance methods attr_accessor :task_name def name ; task_name ; end def task_desc ; @section[:desc] || self.class.task_desc ; end def task_help ; self.class.task_help ; end def master ; self.class.master ; end def setting ; @task ; end attr :section def initialize( section ) case section when Hash, nil @section = CascadingOpenObject.new( section || {} ) else @section = section end end # Run task. def execute( *args ) #@section = CascadingOpenObject.new( section ) task = section.dup if task.respond_to?(:__parent__) task.__parent__ = master end @task = task # deprecate init ? if respond_to?( :init ) if method(:init).arity == 0 init else init( *args ) end end if method(:run).arity == 0 run else run( *args ) end end # interface #def init # raise "not implemented for '#{name}' task" #end def run raise "no action defined for task #{task_name}" end # delegate to section hash def method_missing( *args, &block ) @section.send( *args, &block ) end # Task support methods def use_subsection( name ) subsection = @section.__send__(task_name) if subsection subsection.__parent__ = @section @task = subsection end end def sh( arg ) puts arg system arg unless $PRETEND end def ask( question, answers=nil ) print "#{question}" print " [#{answers}] " if answers until inp = $stdin.gets[0,1] ; sleep 1 ; end ; puts inp end def tell( statement ) puts statement end def provide_setup_rb return true if File.exists?( 'setup.rb') # copy from data dir to current directory (Won't work with Gem!) f = File.join( Config::CONFIG['datadir'], 'reap', 'setup_rb', 'setup.rb' ) if File.exists?(f) File.cp( f, '.' ) true else nil end end end #class Task end #module Reap