tasking 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/README.rdoc +94 -0
 - data/bin/tasking +11 -0
 - data/lib/tasking/namespace.rb +76 -0
 - data/lib/tasking/task.rb +49 -0
 - data/lib/tasking.rb +163 -0
 - metadata +89 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: f3d84bc5f691b364727b241743fb800bf6d571ac3885461124081e959fc6ac78
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: cd7411408417cd0942ba17e66ce38c3f707b4d76ca4f7171027b07bc670ce2cc
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: d4efa63e1c58b9dac0997f1ff46ba067bcb724c052bbba2f221fde224f12e4f83983e3b56fab1e1a4c91759cfd76d5fc64f431fb0d45c671878f01ef5b3d7404
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 7f25bef3273737f3655809b5af02268c88dc57bbbf1f70e67deca30cf21669584ed6161e02634839f6f0b8b23cbd59975da455fca0126341cd29e144b21ce143
         
     | 
    
        data/README.rdoc
    ADDED
    
    | 
         @@ -0,0 +1,94 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            === Running tasks from the command line
         
     | 
| 
      
 2 
     | 
    
         
            +
            tasking <task_name>
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            === The DSL
         
     | 
| 
      
 5 
     | 
    
         
            +
            The DSL has the following commands:
         
     | 
| 
      
 6 
     | 
    
         
            +
              * namespace
         
     | 
| 
      
 7 
     | 
    
         
            +
              * task
         
     | 
| 
      
 8 
     | 
    
         
            +
              * options
         
     | 
| 
      
 9 
     | 
    
         
            +
              * before
         
     | 
| 
      
 10 
     | 
    
         
            +
              * after
         
     | 
| 
      
 11 
     | 
    
         
            +
              * execute
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            ==== Namespaces
         
     | 
| 
      
 14 
     | 
    
         
            +
            Namespaces are used to organize tasks into logical units and isolate options
         
     | 
| 
      
 15 
     | 
    
         
            +
            from each other. Namespaces can be nested. To reference a nested namespace you
         
     | 
| 
      
 16 
     | 
    
         
            +
            can use the format "outer_name::inner_name". To reference a namespace with it's
         
     | 
| 
      
 17 
     | 
    
         
            +
            absolute name, prefix the name with a "::", e.g. "::outer::inner".
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            Namespaces can be re-opened. In that case their content will be merged with the
         
     | 
| 
      
 20 
     | 
    
         
            +
            original content.
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            ==== Tasks
         
     | 
| 
      
 23 
     | 
    
         
            +
            Tasks contain commands to be executed. The execution of a task can be modified
         
     | 
| 
      
 24 
     | 
    
         
            +
            by supplying before- and after-task chains (see the before/after sections
         
     | 
| 
      
 25 
     | 
    
         
            +
            below).
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            Note that each task _must_ be contained in a namespace. Top-Level tasks will
         
     | 
| 
      
 28 
     | 
    
         
            +
            raise an error.
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            Opening a task with a name that already exists within the same namespace will
         
     | 
| 
      
 31 
     | 
    
         
            +
            overwrite the original task.
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            ==== Before/After
         
     | 
| 
      
 34 
     | 
    
         
            +
            The before and after commands modify the execution chain of a task, by giving a
         
     | 
| 
      
 35 
     | 
    
         
            +
            list of other tasks that should be executed before and after the main task is
         
     | 
| 
      
 36 
     | 
    
         
            +
            executed. Note that these filters will be run each time the main task is run.
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            Also, while the main task name can be given relative to the current namespace,
         
     | 
| 
      
 39 
     | 
    
         
            +
            the tasks in the chain are always interpreted in an absolute fashion.
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            Referencing a task that does not exist will raise an error. 
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            Also note that the before and after commands can only be given within the scope
         
     | 
| 
      
 44 
     | 
    
         
            +
            of a namespace, not within a task.
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            ==== Execute
         
     | 
| 
      
 47 
     | 
    
         
            +
            aka run, invoke. Used to execute another task from within a task. The only
         
     | 
| 
      
 48 
     | 
    
         
            +
            command that may be supplied within a task (and only from within a task). 
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            The supplied task name will first be looked up in a fashion relative to the
         
     | 
| 
      
 51 
     | 
    
         
            +
            current tasks parent namespace. If no task is found there, an absolute lookup
         
     | 
| 
      
 52 
     | 
    
         
            +
            is performed. Will raise an error if a non-existant task is referenced.
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            ==== Options
         
     | 
| 
      
 55 
     | 
    
         
            +
            Supplies a hash of options that can accessed from within a task. Supplying
         
     | 
| 
      
 56 
     | 
    
         
            +
            options within nested namespaces will result in the inner namespace merging its
         
     | 
| 
      
 57 
     | 
    
         
            +
            set of options with the outer namespaces options.
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            Note that the namespace, task and execute commands can also supply an explicit
         
     | 
| 
      
 60 
     | 
    
         
            +
            hash of options.
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            At the time being, explicitly invoking a task from another task does not 
         
     | 
| 
      
 63 
     | 
    
         
            +
            automatically supply the invoking tasks options to the invoked task.
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            Options that have a value that responds to #call (procs, lambdas, methods) will
         
     | 
| 
      
 66 
     | 
    
         
            +
            be resolved to the return value of that #call invocation right before a task
         
     | 
| 
      
 67 
     | 
    
         
            +
            is executed. During the resolving of the options, the original set of 
         
     | 
| 
      
 68 
     | 
    
         
            +
            (unresolved) options is passed as an argument.
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            Option resolution happens every time a task is executed, and the results are
         
     | 
| 
      
 71 
     | 
    
         
            +
            not persisted or memoized. The resolution happens independently for before
         
     | 
| 
      
 72 
     | 
    
         
            +
            and after hook tasks from the main task being executed.
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            For example:
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                namespace "outer", :foo => :bar do
         
     | 
| 
      
 77 
     | 
    
         
            +
                  options :bar => :baz
         
     | 
| 
      
 78 
     | 
    
         
            +
                  namespace "inner", :baz => :quux do
         
     | 
| 
      
 79 
     | 
    
         
            +
                    options :quux => :narf
         
     | 
| 
      
 80 
     | 
    
         
            +
                    task "some task" do
         
     | 
| 
      
 81 
     | 
    
         
            +
                      execute "my task", :bla => :blubb
         
     | 
| 
      
 82 
     | 
    
         
            +
                    end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                    task "my task", :narf => :bla do |options|
         
     | 
| 
      
 85 
     | 
    
         
            +
                      # options now has the contents: { :foo => :bar,
         
     | 
| 
      
 86 
     | 
    
         
            +
                                                        :bar => :baz,
         
     | 
| 
      
 87 
     | 
    
         
            +
                                                        :baz => :quux,
         
     | 
| 
      
 88 
     | 
    
         
            +
                                                        :quux => :narf,
         
     | 
| 
      
 89 
     | 
    
         
            +
                                                        :narf => :bla,
         
     | 
| 
      
 90 
     | 
    
         
            +
                                                        :bla  => :blubb }
         
     | 
| 
      
 91 
     | 
    
         
            +
                    end
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
    
        data/bin/tasking
    ADDED
    
    
| 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Tasking
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Namespace
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :name, :options
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def self.namespaces
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @namespaces ||= {}
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
                private_class_method :namespaces
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def self.all
         
     | 
| 
      
 11 
     | 
    
         
            +
                  namespaces.values
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def self.add_namespace( ns )
         
     | 
| 
      
 15 
     | 
    
         
            +
                  namespaces[ns.name] = ns
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def self.find_namespace( name )
         
     | 
| 
      
 19 
     | 
    
         
            +
                  namespaces[name]
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def self.find_task_in_namespace( ns_name, task_name )
         
     | 
| 
      
 23 
     | 
    
         
            +
                  ns = find_namespace( ns_name )
         
     | 
| 
      
 24 
     | 
    
         
            +
                  ns&.find_task( task_name )
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def self.find_task( full_name )
         
     | 
| 
      
 28 
     | 
    
         
            +
                  namespace_name, _, task_name = full_name.rpartition( '::' )
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  self.find_task_in_namespace( namespace_name, task_name )
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def self.find_or_create( name, options = {} )
         
     | 
| 
      
 34 
     | 
    
         
            +
                  find_namespace( name ) || new( name, options )
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def initialize( name, options = {} )
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @tasks = {}
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @options = options
         
     | 
| 
      
 41 
     | 
    
         
            +
                  
         
     | 
| 
      
 42 
     | 
    
         
            +
                  self.class.add_namespace( self )
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def tasks
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @tasks.values
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def parent_namespace
         
     | 
| 
      
 50 
     | 
    
         
            +
                  parent_name, _, _ = @name.rpartition( '::' )
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  parent_name.empty? ? nil : self.class.find_namespace( parent_name )
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                def execute( options = {}, &block )
         
     | 
| 
      
 56 
     | 
    
         
            +
                  @options.merge!( options )
         
     | 
| 
      
 57 
     | 
    
         
            +
                  block.call if block
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def merge_options( options )
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @options.merge!( options )
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def register_task( task )
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @tasks[task.name] = task
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def unregister_task( task )
         
     | 
| 
      
 69 
     | 
    
         
            +
                  @tasks.delete( task.name )
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def find_task( name )
         
     | 
| 
      
 73 
     | 
    
         
            +
                  @tasks[name]
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/tasking/task.rb
    ADDED
    
    | 
         @@ -0,0 +1,49 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Tasking
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Task
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :name, :options, :block, :before_filters, :after_filters,
         
     | 
| 
      
 4 
     | 
    
         
            +
                            :parent_namespace
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize( name, parent_namespace, options = {}, &block )
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @name             = name
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @parent_namespace = parent_namespace
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @options          = options
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @block            = block
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @before_filters   = []
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @after_filters    = []
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def add_before_filters( *filters )
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @before_filters.concat( filters.flatten )
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def add_after_filters( *filters )
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @after_filters.concat( filters.flatten )
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def execute( options = {} )
         
     | 
| 
      
 24 
     | 
    
         
            +
                  total_options = @options.merge( options )
         
     | 
| 
      
 25 
     | 
    
         
            +
                  execute_task_chain( before_filters, total_options, "Unknown before task '%s' for task '#{@name}'" )
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @block.call( resolve_options( total_options ) ) if @block
         
     | 
| 
      
 27 
     | 
    
         
            +
                  execute_task_chain( after_filters, total_options, "Unknown after task '%s' for task '#{@name}'" )
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                private
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def resolve_options(options)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  options.transform_values { |v| v.respond_to?(:call) ? v.call(options) : v }
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def execute_task_chain( tasks, options, fail_message )
         
     | 
| 
      
 37 
     | 
    
         
            +
                  tasks.each do |t|
         
     | 
| 
      
 38 
     | 
    
         
            +
                    task = task_lookup( t )
         
     | 
| 
      
 39 
     | 
    
         
            +
                    abort( fail_message % t ) unless task
         
     | 
| 
      
 40 
     | 
    
         
            +
                    task.execute(options)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def task_lookup( name )
         
     | 
| 
      
 45 
     | 
    
         
            +
                  name.slice!( 0, 2 ) if name.start_with?( '::' ) 
         
     | 
| 
      
 46 
     | 
    
         
            +
                  Tasking::Namespace.find_task( name )
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/tasking.rb
    ADDED
    
    | 
         @@ -0,0 +1,163 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Tasking
         
     | 
| 
      
 4 
     | 
    
         
            +
              def task( name, options = {}, &block )
         
     | 
| 
      
 5 
     | 
    
         
            +
                abort( "Tasks with empty names are not allowed" ) if name.to_s.empty?
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                full_name = fully_qualified_name( name )
         
     | 
| 
      
 8 
     | 
    
         
            +
                namespace_name, task_name = split_task_from_namespace( full_name )
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                abort( "Task '#{name}' is not in a namespace" ) if namespace_name.empty?
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                build_namespace_hierarchy( namespace_name )
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                parent_namespace = Tasking::Namespace.find_namespace( namespace_name )
         
     | 
| 
      
 15 
     | 
    
         
            +
                task = Tasking::Task.new( task_name, parent_namespace, options, &block )
         
     | 
| 
      
 16 
     | 
    
         
            +
                parent_namespace.register_task( task )
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              def namespace( name, options = {}, &block ) 
         
     | 
| 
      
 20 
     | 
    
         
            +
                abort( "Namespaces with empty names are not allowed" ) if name.to_s.empty?
         
     | 
| 
      
 21 
     | 
    
         
            +
                @__parent_namespace ||= []
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                full_name = fully_qualified_name( name )
         
     | 
| 
      
 24 
     | 
    
         
            +
                parent_namespace_names, _ = split_task_from_namespace( full_name )
         
     | 
| 
      
 25 
     | 
    
         
            +
                build_namespace_hierarchy( parent_namespace_names )
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                next_namespace = Tasking::Namespace.find_or_create( full_name, options )
         
     | 
| 
      
 28 
     | 
    
         
            +
                @__parent_namespace.push( next_namespace )
         
     | 
| 
      
 29 
     | 
    
         
            +
                next_namespace.execute( options, &block )
         
     | 
| 
      
 30 
     | 
    
         
            +
                @__parent_namespace.pop
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              def options( options ) 
         
     | 
| 
      
 34 
     | 
    
         
            +
                @__parent_namespace.last.merge_options( options )
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              def late_before( task_name, parent_namespace_name, *before_task_names )
         
     | 
| 
      
 38 
     | 
    
         
            +
                task = Tasking::Namespace.find_task_in_namespace( parent_namespace_name, task_name ) ||
         
     | 
| 
      
 39 
     | 
    
         
            +
                       Tasking::Namespace.find_task( task_name ) 
         
     | 
| 
      
 40 
     | 
    
         
            +
                abort( "Unknown task '#{task_name}' in before filter" ) unless task
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                task.add_before_filters( *before_task_names )
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              def late_after( task_name, parent_namespace_name, *after_task_names )
         
     | 
| 
      
 46 
     | 
    
         
            +
                task = Tasking::Namespace.find_task_in_namespace( parent_namespace_name, task_name ) ||
         
     | 
| 
      
 47 
     | 
    
         
            +
                       Tasking::Namespace.find_task( task_name ) 
         
     | 
| 
      
 48 
     | 
    
         
            +
                abort( "Unknown task '#{task_name}' in after filter" ) unless task
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                task.add_after_filters( *after_task_names )
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              def before( task_name, *before_task_names )
         
     | 
| 
      
 54 
     | 
    
         
            +
                @__late_evaluations ||= {}
         
     | 
| 
      
 55 
     | 
    
         
            +
                @__late_evaluations[:before] ||= []
         
     | 
| 
      
 56 
     | 
    
         
            +
                parent_namespace_name = @__parent_namespace.last&.name.to_s
         
     | 
| 
      
 57 
     | 
    
         
            +
                @__late_evaluations[:before] << [ task_name, parent_namespace_name, before_task_names.flatten ]
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              def after( task_name, *after_task_names )
         
     | 
| 
      
 61 
     | 
    
         
            +
                @__late_evaluations ||= {}
         
     | 
| 
      
 62 
     | 
    
         
            +
                @__late_evaluations[:after] ||= []
         
     | 
| 
      
 63 
     | 
    
         
            +
                parent_namespace_name = @__parent_namespace.last&.name.to_s
         
     | 
| 
      
 64 
     | 
    
         
            +
                @__late_evaluations[:after] << [ task_name, parent_namespace_name, after_task_names.flatten ]
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              def late_evaluations
         
     | 
| 
      
 68 
     | 
    
         
            +
                return unless @__late_evaluations
         
     | 
| 
      
 69 
     | 
    
         
            +
                @__late_evaluations.each_pair do |type, task_parameters|
         
     | 
| 
      
 70 
     | 
    
         
            +
                  task_parameters.each do |( task_name, parent_namespace_name, args )|
         
     | 
| 
      
 71 
     | 
    
         
            +
                    self.send( :"late_#{type}", task_name, parent_namespace_name, *args )
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              def execute( name, options = {} )
         
     | 
| 
      
 77 
     | 
    
         
            +
                if !@__subsequent_executions
         
     | 
| 
      
 78 
     | 
    
         
            +
                  @__subsequent_executions = true
         
     | 
| 
      
 79 
     | 
    
         
            +
                  late_evaluations
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
                task = task_lookup( name )
         
     | 
| 
      
 82 
     | 
    
         
            +
              
         
     | 
| 
      
 83 
     | 
    
         
            +
                if !task
         
     | 
| 
      
 84 
     | 
    
         
            +
                  msg = "Unknown task '#{name}'"
         
     | 
| 
      
 85 
     | 
    
         
            +
                  msg << " or #{fully_qualified_name( name )}" if @__parent_namespace.size > 0
         
     | 
| 
      
 86 
     | 
    
         
            +
                  abort( msg )
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                namespace_hierarchy_options = gather_options_for( name, task )
         
     | 
| 
      
 90 
     | 
    
         
            +
                namespace_hierarchy_options.merge!( options )
         
     | 
| 
      
 91 
     | 
    
         
            +
                @__parent_namespace.push( task.parent_namespace )
         
     | 
| 
      
 92 
     | 
    
         
            +
                task.execute( namespace_hierarchy_options )
         
     | 
| 
      
 93 
     | 
    
         
            +
                @__parent_namespace.pop
         
     | 
| 
      
 94 
     | 
    
         
            +
              end
         
     | 
| 
      
 95 
     | 
    
         
            +
              alias_method :invoke, :execute
         
     | 
| 
      
 96 
     | 
    
         
            +
              alias_method :run, :execute
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
              private
         
     | 
| 
      
 99 
     | 
    
         
            +
              def task_lookup( name )
         
     | 
| 
      
 100 
     | 
    
         
            +
                @__parent_namespace ||= []
         
     | 
| 
      
 101 
     | 
    
         
            +
                task = nil
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                if name.start_with?( '::' ) 
         
     | 
| 
      
 104 
     | 
    
         
            +
                  name.slice!( 0, 2 )
         
     | 
| 
      
 105 
     | 
    
         
            +
                  return Tasking::Namespace.find_task( name )
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                if @__parent_namespace.last 
         
     | 
| 
      
 109 
     | 
    
         
            +
                  full_name = "#{@__parent_namespace.last.name}::#{name}"
         
     | 
| 
      
 110 
     | 
    
         
            +
                  task = Tasking::Namespace.find_task( full_name )
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                task || Tasking::Namespace.find_task( name )
         
     | 
| 
      
 114 
     | 
    
         
            +
              end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
              def walk_namespace_tree_to( namespace_name, type = :namespace, &block )
         
     | 
| 
      
 117 
     | 
    
         
            +
                ns_segments = namespace_name.split( '::' )
         
     | 
| 
      
 118 
     | 
    
         
            +
                ns_segments.pop if type != :namespace
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                current_ns_hierarchy_level = nil
         
     | 
| 
      
 121 
     | 
    
         
            +
                ns_segments.each do |segment|
         
     | 
| 
      
 122 
     | 
    
         
            +
                  if current_ns_hierarchy_level == nil
         
     | 
| 
      
 123 
     | 
    
         
            +
                    current_ns_hierarchy_level = segment
         
     | 
| 
      
 124 
     | 
    
         
            +
                  else
         
     | 
| 
      
 125 
     | 
    
         
            +
                    current_ns_hierarchy_level += "::#{segment}"
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end 
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                  block.call( current_ns_hierarchy_level )
         
     | 
| 
      
 129 
     | 
    
         
            +
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
              end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
              def gather_options_for( full_task_name, task )
         
     | 
| 
      
 133 
     | 
    
         
            +
                final_options = {}
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                walk_namespace_tree_to( full_task_name, :task ) do |ns_name|
         
     | 
| 
      
 136 
     | 
    
         
            +
                  namespace = Tasking::Namespace.find_namespace( ns_name )
         
     | 
| 
      
 137 
     | 
    
         
            +
                  final_options.merge!( namespace.options )
         
     | 
| 
      
 138 
     | 
    
         
            +
                end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                final_options.merge!( task.options )
         
     | 
| 
      
 141 
     | 
    
         
            +
              end
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
              def fully_qualified_name( name )
         
     | 
| 
      
 144 
     | 
    
         
            +
                @__parent_namespace&.last ? 
         
     | 
| 
      
 145 
     | 
    
         
            +
                  "#{@__parent_namespace.last.name}::#{name}" : 
         
     | 
| 
      
 146 
     | 
    
         
            +
                  name
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
              def build_namespace_hierarchy( full_name ) 
         
     | 
| 
      
 150 
     | 
    
         
            +
                walk_namespace_tree_to( full_name ) do |ns_name|
         
     | 
| 
      
 151 
     | 
    
         
            +
                  Tasking::Namespace.find_or_create( ns_name ) 
         
     | 
| 
      
 152 
     | 
    
         
            +
                end
         
     | 
| 
      
 153 
     | 
    
         
            +
              end
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
              def split_task_from_namespace( full_name )
         
     | 
| 
      
 156 
     | 
    
         
            +
                namespace_name, _, task_name = full_name.rpartition( '::' )
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                [ namespace_name, task_name ]
         
     | 
| 
      
 159 
     | 
    
         
            +
              end
         
     | 
| 
      
 160 
     | 
    
         
            +
            end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
            require_relative 'tasking/namespace'
         
     | 
| 
      
 163 
     | 
    
         
            +
            require_relative 'tasking/task'
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,89 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: tasking
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.2.0
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Sven Riedel
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2019-08-01 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: rspec-its
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: byebug
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 55 
     | 
    
         
            +
            description: A lightweight DSL for task definition and execution
         
     | 
| 
      
 56 
     | 
    
         
            +
            email: sr@gimp.org
         
     | 
| 
      
 57 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 58 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 59 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 60 
     | 
    
         
            +
            files:
         
     | 
| 
      
 61 
     | 
    
         
            +
            - README.rdoc
         
     | 
| 
      
 62 
     | 
    
         
            +
            - bin/tasking
         
     | 
| 
      
 63 
     | 
    
         
            +
            - lib/tasking.rb
         
     | 
| 
      
 64 
     | 
    
         
            +
            - lib/tasking/namespace.rb
         
     | 
| 
      
 65 
     | 
    
         
            +
            - lib/tasking/task.rb
         
     | 
| 
      
 66 
     | 
    
         
            +
            homepage: https://github.com/sriedel/tasking
         
     | 
| 
      
 67 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 68 
     | 
    
         
            +
            - GPL-2.0
         
     | 
| 
      
 69 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 70 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 71 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 72 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 73 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 74 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 75 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 76 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 77 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 78 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 79 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 80 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 81 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 82 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 83 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 84 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 85 
     | 
    
         
            +
            rubygems_version: 3.0.3
         
     | 
| 
      
 86 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 87 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 88 
     | 
    
         
            +
            summary: A lightweight task runner DSL
         
     | 
| 
      
 89 
     | 
    
         
            +
            test_files: []
         
     |