require 'rake' require 'chrysalis/loader' # Intercept Rake's methods for declaring tasks. # # Task interception is used to construct internal tables, and synthesize # tasks in the all: namespace. # # Tasks declared in the course of loading a dependency are intercepted # completely, and are unknown to Rake. This prevents dependencies from # polluting the task space of their dependents. # # Tasks declared by the main rakefile are forwarded to Rake's original methods, # ensuring that the system remains consistent. class Object alias_method :rake_task, :task def task(args, &block) task_name, deps = Rake.application.resolve_args(args) Chrysalis::Loader.instance.task_intercept(task_name) { rake_task(args, &block) } end alias_method :rake_file, :file def file(args, &block) task_name, deps = Rake.application.resolve_args(args) Chrysalis::Loader.instance.file_task_intercept(task_name) { rake_file(args, &block) } end alias_method :rake_file_create, :file_create def file_create(args, &block) task_name, deps = Rake.application.resolve_args(args) Chrysalis::Loader.instance.file_task_intercept(task_name) { rake_file_create(args, &block) } end #-- # NOTE: Intercepting directory tasks is unnecessary, because Rake itself # implements them as a set of file_create tasks. Thus, the interception # of file_create is sufficient. #alias_method :rake_directory, :directory #def directory(dir) #end alias_method :rake_multitask, :multitask def multitask(args, &block) task_name, deps = Rake.application.resolve_args(args) Chrysalis::Loader.instance.task_intercept(task_name) { rake_multitask(args, &block) } end alias_method :rake_namespace, :namespace def namespace(name=nil, &block) Chrysalis::Loader.instance.namespace_intercept(name, block) { rake_namespace(name, &block) } end alias_method :rake_rule, :rule def rule(args, &block) Chrysalis::Loader.instance.rule_intercept { rake_rule(args, &block) } end alias_method :rake_desc, :desc def desc(comment) Chrysalis::Loader.instance.desc_intercept(comment) { rake_desc(comment) } end end module Rake class Application alias_method :rake_top_level, :top_level # Invoked after the main rakefile has been loaded, but before any tasks are # executed. # # Chrysalis reimplements this method for the purpose of hooking into the # loader and seeding the all: namespace with tasks, prior to # retrieval of dependencies. # # After invoking the hook, execution proceeds with Rake's original method. def top_level Chrysalis.post :rakefile_loaded rake_top_level end end end