the attached update to the patch fixes recursive_task to work when the subprojects have not already being invoked. it is not the best way to implement it, but the quickest. note that it also makes 'recursive_task' actually recursive, meaning you can call it on a specific project so it will call the children of that project (the original implementation would just make the parent task depend on it).

ittay

Ittay Dror wrote:

Hi,


The attached patch to buildr works for me (invoking without arguments, with local task and with specific project tasks). What do you think? Can this be included in Buildr?


The reason I'm requesting this is that I have a buildfile with 150 projects and the current way Buildr works, by invoking all projects takes too much time when I want to build just a single project (and its dependencies of course). On developer windows machine this "warmup" time is ~15 seconds and is increasing as more modules are added. From my tests, this patch can lower it to just a few seconds.


Ittay

--
--
Ittay Dror <[EMAIL PROTECTED]>

--
--
Ittay Dror <[EMAIL PROTECTED]>

>From f2604a0f035a3f8534e8b917219a8720206b76aa Mon Sep 17 00:00:00 2001
From: Ittay Dror <[EMAIL PROTECTED]>
Date: Wed, 5 Nov 2008 00:19:39 +0200
Subject: [PATCH] lazily invoking for more performance

---
 lib/buildr/core/application.rb |   19 ++++++++++++++++++-
 lib/buildr/core/project.rb     |   34 +++++++++++++++++++++++++---------
 2 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/lib/buildr/core/application.rb b/lib/buildr/core/application.rb
index 9898e3c..74cf7a3 100644
--- a/lib/buildr/core/application.rb
+++ b/lib/buildr/core/application.rb
@@ -404,7 +404,24 @@ module Buildr
         end
       end
       load_imports
-      Buildr.projects
+      #Buildr.projects
+      top_level_tasks.each do |task_name|
+        if task_name.index(':')
+          parts = []
+          task_name.split(':').each do |part|
+            parts << part
+            begin
+              Buildr.project(parts.join(':')).invoke
+            rescue
+              nil
+            end
+          end
+        else
+          Buildr.projects.each do |project|
+            project.invoke
+          end
+        end
+      end
     end
 
     # Load/install all Gems specified in build.yaml file.
diff --git a/lib/buildr/core/project.rb b/lib/buildr/core/project.rb
index 959e863..c6cb3d2 100644
--- a/lib/buildr/core/project.rb
+++ b/lib/buildr/core/project.rb
@@ -222,12 +222,12 @@ module Buildr
             @on_define.each { |callback| callback[project] }
           end if @on_define
           # Enhance the project using the definition block.
-          project.enhance { project.instance_eval &block } if block
+          project.enhance {|project| project.instance_eval &block } if block
 
           # Top-level project? Invoke the project definition. Sub-project? We don't invoke
           # the project definiton yet (allow project calls to establish order of evaluation),
-          # but must do so before the parent project's definition is done. 
-          project.parent.enhance { project.invoke } if project.parent
+          # but must do so before the parent project's definition is done.
+          ### project.parent.enhance { project.invoke } if project.parent
         end
       end
 
@@ -242,14 +242,18 @@ module Buildr
         @projects ||= {}
         name = args.first
         if options && options[:scope]
-          # We assume parent project is evaluated.
-          project = options[:scope].split(':').inject([[]]) { |scopes, scope| scopes << (scopes.last + [scope]) }.
-            map { |scope| @projects[(scope + [name]).join(':')] }.
-            select { |project| project }.last
+          scope = options[:scope].split(':').inject([[]]) { |scopes, scope| scopes << (scopes.last + [scope]) }.
+            reverse. # get all prefixes to name from longest to shortest
+            find do |scope|
+              name.split(':').inject([[]]) {|parts, part| parts << (parts.last + [part])}.
+                all? {|names| @projects[(scope + names).join(':')].tap {|project| project.invoke if project}}
+            end
+          project = @projects[(scope + [name]).join(':')] if scope
         end
         unless project
           # Parent project not evaluated.
-          name.split(':').tap { |parts| @projects[parts.first].invoke if parts.size > 1 }
+        name.split(':').inject([[]]) { |parts, part| parts << (parts.last + [part])}.
+            each {|scope| @projects[scope.join(':')].tap {|project| project.invoke if project}}
           project = @projects[name]
         end
         raise "No such project #{name}" unless project
@@ -391,6 +395,11 @@ module Buildr
     # The parent project if this is a sub-project.
     attr_reader :parent
 
+    def invoke(*args)
+      return if @already_invoked
+      super
+    end
+
     def initialize(*args) #:nodoc:
       super
       split = name.split(':')
@@ -537,9 +546,16 @@ module Buildr
     def recursive_task(*args, &block)
       task_name, arg_names, deps = Buildr.application.resolve_args(args)
       task = Buildr.options.parallel ? multitask(task_name) : task(task_name)
-      parent.task(task_name).enhance [task] if parent
       task.set_arg_names(arg_names) unless arg_names.empty?
       task.enhance Array(deps), &block
+
+
+      task.instance_variable_set :@project, self
+      def task.invoke_prerequisites(*args)
+        task_name = name.sub(@project.name + ':', '')
+        @prerequisites |= @project.projects.map {|project| project.task(task_name)}
+        super
+      end
     end
 
     # :call-seq:
-- 
1.6.0.3.640.g6331a

Reply via email to