<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/jake/helper.rb</filename>
    </added>
    <added>
      <filename>lib/jake/observer.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,4 @@
 README.txt
 pkg
+doc
 test/output</diff>
      <filename>.gitignore</filename>
    </modified>
    <modified>
      <diff>@@ -4,6 +4,8 @@ README.txt
 Rakefile
 bin/jake
 lib/jake.rb
+lib/jake/helper.rb
+lib/jake/observer.rb
 lib/jake/build.rb
 lib/jake/buildable.rb
 lib/jake/package.rb</diff>
      <filename>Manifest.txt</filename>
    </modified>
    <modified>
      <diff>@@ -137,6 +137,8 @@ The full list of package options is as follows:
   for the current build. If a build listed above uses &lt;tt&gt;packer: false&lt;/tt&gt;,
   this takes precedence over package-specific instructions. Typically used
   to override options for the minified build.
+* +meta+ - should be a YAML dictionary containing arbitrary data useful to
+  user-defined build events. May be omitted. See 'Event hooks' below.
 
 For example, here's a package listing that uses all the options:
 
@@ -211,6 +213,35 @@ name. When built, the output would contain the following:
   MyJavaScriptLib.VERSION = &quot;1.0-src&quot;;    // or &quot;1.0-min&quot; for the 'min' build
 
 
+=== Event hooks
+
+The +Jakefile+ may also define event hooks that are fired during a build when
+interesting things happen. This allows you to extend your build process using
+configuration data from Jake. We currently have two events:
+
++file_created+ is fired whenever a new build file is created. The callback is
+passed the +Buildable+ package object, the current build name (+src+ or +min+
+using the above examples), and the full path to the newly created file.
+The package object may contain metadata (set using the +meta+ option, see
+above) which you can use for further code generation.
+
++build_complete+ is fired after a build has finished running, that is after
+all sets of minification options have been run. At this point you can use any
+metadata you've gathered to generate more code, copy files to your distribution
+directory, etc.
+
+  $register = {}
+  
+  jake_hook :file_created do |pkg, build_name, path|
+    $register[path] = pkg.meta
+  end
+  
+  jake_hook :build_complete do |build|
+    FileUtils.cp 'README', build.build_directory + '/README'
+    # generate code from $register
+  end
+
+
 == License
 
 (The MIT License)</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -1,24 +1,39 @@
+require 'erb'
+require 'fileutils'
+require 'observer'
+require 'yaml'
+require 'rubygems'
+require 'packr'
+
 module Jake
   VERSION = '0.9.4'
   
   CONFIG_FILE = 'jake.yml'
   HELPER_FILE = 'Jakefile'
+  EXTENSION   = '.js'
   
+  # Runs a build in the given directory. The directory must contain a jake.yml
+  # file, and may contain a Jakefile. See README for example YAML configurations.
   def self.build!(path, options = {})
-    build = Build.new(path, nil, options)
+    build = Build.new(path, options)
     build.run!
   end
   
+  # Removes all registered build event hooks.
   def self.clear_hooks!
     Build.delete_observers
   end
   
+  # Returns the contents of the given path, which may be missing a .js extension.
   def self.read(path)
     path = File.expand_path(path)
-    path = File.file?(path) ? path : ( File.file?(&quot;#{path}.js&quot;) ? &quot;#{path}.js&quot; : nil )
-    path and File.read(path).strip
+    [path, &quot;#{path}#{EXTENSION}&quot;].each do |p|
+      return File.read(p).strip if File.file?(p)
+    end
+    return nil
   end
   
+  # Returns a copy of the given hash with the keys cast to symbols.
   def self.symbolize_hash(hash, deep = true)
     hash.inject({}) do |output, (key, value)|
       value = Jake.symbolize_hash(value) if deep and value.is_a?(Hash)
@@ -27,35 +42,13 @@ module Jake
     end
   end
   
-  class Helper
-    attr_accessor :build
-    attr_reader :options
-    
-    def initialize(options = {})
-      @options = options
-    end
-    
-    def scope; binding; end
-  end
-  
-  class Observer
-    def initialize(type, &amp;block)
-      @type, @block = type, block
-      Build.add_observer(self)
-    end
-    
-    def update(*args)
-      @block[*args[1..-1]] if args.first == @type
-    end
-  end
 end
 
-require 'erb'
-
-%w(build buildable package bundle).each do |file|
+%w(helper observer build buildable package bundle).each do |file|
   require File.dirname(__FILE__) + '/jake/' + file
 end
 
+# Adds a helper method that can be called from ERB.
 def jake_helper(name, &amp;block)
   Jake::Helper.class_eval do
     define_method(name, &amp;block)
@@ -63,6 +56,7 @@ def jake_helper(name, &amp;block)
 end
 alias :jake :jake_helper
 
+# Registers an event listener that will fire whenever a build is run.
 def jake_hook(type, &amp;block)
   Jake::Observer.new(type, &amp;block)
 end</diff>
      <filename>lib/jake.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,12 @@
-require 'yaml'
-require 'fileutils'
-require 'observer'
-
 module Jake
+  # A +Build+ encapsulates a single instance of running &lt;tt&gt;Jake.build!&lt;/tt&gt;. It
+  # is responsible for running the build and provides access to any configuration
+  # data used to set up the build.
   class Build
     extend Observable
+    
+    # Calls all registered +Observer+ instances with any arguments passed in. Note
+    # that it is the +Build+ class that is +Observable+, not its instances.
     def self.notify_observers(*args)
       self.changed(true)
       super
@@ -15,7 +17,10 @@ module Jake
     include Enumerable
     attr_reader :helper
     
-    def initialize(dir, config = nil, options = {})
+    # Builds are initialized using a directory in which to run the build, and an
+    # options hash. Options are passed through to helper methods in the +options+
+    # object.
+    def initialize(dir, options = {})
       @dir    = File.expand_path(dir)
       @helper = Helper.new(options)
       force! if options[:force]
@@ -23,7 +28,7 @@ module Jake
       path    = &quot;#{dir}/#{CONFIG_FILE}&quot;
       yaml    = File.read(path)
       
-      @config = Jake.symbolize_hash( config || YAML.load(ERB.new(yaml).result(@helper.scope)) )
+      @config = Jake.symbolize_hash( YAML.load(ERB.new(yaml).result(@helper.scope)) )
       
       helpers = &quot;#{dir}/#{HELPER_FILE}&quot;
       load helpers if File.file?(helpers)
@@ -41,22 +46,27 @@ module Jake
       end
     end
     
+    # Yields to the block for each build in the group.
     def each(&amp;block)
       @builds.each(&amp;block)
     end
     
+    # Forces the build to generate new files even if target files appear up-to-date.
     def force!
       @forced = true
     end
     
+    # Returns +true+ iff this is a forced build.
     def forced?
       defined?(@forced)
     end
     
+    # Returns the +Buildable+ with the given name.
     def package(name)
       @packages[name.to_sym] || @bundles[name.to_sym]
     end
     
+    # Runs the build, generating new files in +build_directory+.
     def run!
       FileUtils.cd(@dir) do
         @packages.each { |name, pkg| pkg.write! }
@@ -65,34 +75,44 @@ module Jake
       end
     end
     
+    # Returns the path to the build directory, where generated files appear.
     def build_directory
       &quot;#{ @dir }/#{ @config[:build_directory] || '.' }&quot;
     end
     alias :build_dir :build_directory
     
+    # Returns the path to the source directory, where source code is read from.
     def source_directory
       &quot;#{ @dir }/#{ @config[:source_directory] || '.' }&quot;
     end
     alias :source_dir :source_directory
     
+    # Returns the header string used for the build, or an empty string if no
+    # header file has been set.
     def header
       @config[:header] ?
           Jake.read(&quot;#{ source_directory }/#{ @config[:header] }&quot;) :
           &quot;&quot;
     end
     
+    # Returns the minification settings for PackR for the given build name. Each
+    # +Build+ object can build all its packages multiple times with different
+    # minification settings in each run.
     def packer_settings(build_name)
       build = @builds[build_name.to_sym]
       return false unless build
       build[:packer].nil? ? build : build[:packer]
     end
     
+    # Returns +true+ iff filename suffixes based on build name should be added
+    # to generated files for the given build name.
     def use_suffix?(build_name)
       build = @builds[build_name.to_sym]
       return true unless build
       build[:suffix] != false
     end
     
+    # Returns the name of the layout being used, either +together+ or +apart+.
     def layout
       @config[:layout] || DEFAULT_LAYOUT
     end</diff>
      <filename>lib/jake/build.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,11 +1,15 @@
-require 'fileutils'
-require 'packr'
-
 module Jake
+  # A +Buildable+ represents a group of files that may be merged to form a single
+  # build file. There are two subtypes of +Buildable+; a +Package+ takes several
+  # source files and produces a build file, and a +Bundle+ takes several +Package+
+  # build files to produce another build file. This class should be considered
+  # abstract as some of its method must be filled in by subtypes.
   class Buildable
     
     attr_reader :name
     
+    # Create a new +Buildable+ using a +Build+ container, a name and a configuration
+    # hash, typically a subsection of jake.yml.
     def initialize(build, name, config)
       @build, @name = build, name
       @config = case config
@@ -16,17 +20,21 @@ module Jake
       @code = {}
     end
     
+    # Returns the parent +Buildable+ set using the +extends+ option, or +nil+ if
+    # there is no parent.
     def parent
       return nil unless @config[:extends]
       @parent ||= @build.package(@config[:extends])
     end
     
+    # Returns the source directory for this package.
     def directory
       dir = @config[:directory]
       return parent.directory if parent &amp;&amp; !dir
       &quot;#{ @build.source_directory }/#{ @config[:directory] }&quot;
     end
     
+    # Returns the path to the output file from this package for the given build name.
     def build_path(build_name)
       suffix = @build.use_suffix?(build_name) ? &quot;-#{ build_name }&quot; : &quot;&quot;
       @build.layout == 'together' ?
@@ -34,6 +42,8 @@ module Jake
           &quot;#{ @build.build_directory }/#{ build_name }/#{ @name }.js&quot;
     end
     
+    # Returns +true+ if the build file for the given build name is out of date and
+    # should be regenerated.
     def build_needed?(name)
       return true if @build.forced?
       path = build_path(name)
@@ -42,6 +52,7 @@ module Jake
       files.any? { |path| File.mtime(path) &gt; build_time }
     end
     
+    # Returns the header string being used for this package.
     def header
       content = @config[:header] ?
           Jake.read(&quot;#{ directory }/#{ @config[:header] }&quot;) :
@@ -49,6 +60,7 @@ module Jake
       ERB.new(content).result(@build.helper.scope).strip
     end
     
+    # Returns the PackR settings to use for this package during the given build.
     def packer_settings(build_name)
       global = @build.packer_settings(build_name)
       local  = @config[:packer]
@@ -57,10 +69,15 @@ module Jake
       {}.merge(global || {}).merge(local || {})
     end
     
+    # Returns a hash containing any metadata attached to the package in the config.
     def meta
       @config[:meta] || {}
     end
     
+    # Generates all the build files for this package by looping over all the
+    # required builds and compressing the source code using each set of minification
+    # options. Files are only generated if they are out of date or the build has
+    # been forced.
     def write!
       puts &quot;Package #{@name}...&quot;
       </diff>
      <filename>lib/jake/buildable.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,15 +1,22 @@
 module Jake
   class Bundle &lt; Buildable
     
+    # Returns a list of paths to all the files used to build this package.
     def files
       base = parent ? parent.files : []
       base + @config[:files].map { |pkg| @build.package(pkg).files }.flatten
     end
     
+    # Returns the full uncompressed source code of this package, before
+    # ERB processing. ERB output will be build-dependent; this method
+    # simply builds the raw template for further processing by other
+    # methods.
     def source
       @source ||= @config[:files].map { |pkg| @build.package(pkg).source }.join(&quot;\n\n\n&quot;)
     end
     
+    # Returns the result of building the source template and minifying
+    # the output using the given named set of PackR settings.
     def code(name)
       joiner = (packer_settings(name) == false) ? &quot;\n\n\n&quot; : &quot;\n&quot;
       @code[name] ||= @config[:files].map { |pkg| @build.package(pkg).code(name) }.join(joiner)</diff>
      <filename>lib/jake/bundle.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,7 @@
 module Jake
   class Package &lt; Buildable
     
+    # Returns a list of paths to all the files used to build this package.
     def files
       base = parent ? parent.files : []
       base + @config[:files].map do |path|
@@ -9,10 +10,16 @@ module Jake
       end
     end
     
+    # Returns the full uncompressed source code of this package, before
+    # ERB processing. ERB output will be build-dependent; this method
+    # simply builds the raw template for further processing by other
+    # methods.
     def source
       @source ||= files.map { |path| Jake.read(path) }.join(&quot;\n\n\n&quot;)
     end
     
+    # Returns the result of building the source template and minifying
+    # the output using the given named set of PackR settings.
     def code(name)
       return @code[name] if @code[name]
       settings = packer_settings(name)</diff>
      <filename>lib/jake/package.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>fca9e451331678704dbe2a1c5c27007d7f8f4ad7</id>
    </parent>
  </parents>
  <author>
    <name>James Coglan</name>
    <email>jcoglan@googlemail.com</email>
  </author>
  <url>http://github.com/jcoglan/jake/commit/06b143089d8b6607240cd4e3797ee153115eebf7</url>
  <id>06b143089d8b6607240cd4e3797ee153115eebf7</id>
  <committed-date>2009-06-17T06:33:08-07:00</committed-date>
  <authored-date>2009-06-17T06:33:08-07:00</authored-date>
  <message>Adding documentation for event hooks, inline method docs, and making a few small tweaks.</message>
  <tree>f9b8f652b68cc2044a7ccb756d0dbfdfb9ee0c0d</tree>
  <committer>
    <name>James Coglan</name>
    <email>jcoglan@googlemail.com</email>
  </committer>
</commit>
