You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildr.apache.org by as...@apache.org on 2008/01/02 12:07:15 UTC

svn commit: r608079 - in /incubator/buildr/trunk: Rakefile doc/pages/extending.textile doc/pages/more_stuff.textile doc/print.toc.textile doc/web.toc.textile

Author: assaf
Date: Wed Jan  2 03:07:10 2008
New Revision: 608079

URL: http://svn.apache.org/viewvc?rev=608079&view=rev
Log:
Added documentation for layouts

Added:
    incubator/buildr/trunk/doc/pages/extending.textile
Modified:
    incubator/buildr/trunk/Rakefile
    incubator/buildr/trunk/doc/pages/more_stuff.textile
    incubator/buildr/trunk/doc/print.toc.textile
    incubator/buildr/trunk/doc/web.toc.textile

Modified: incubator/buildr/trunk/Rakefile
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/Rakefile?rev=608079&r1=608078&r2=608079&view=diff
==============================================================================
--- incubator/buildr/trunk/Rakefile (original)
+++ incubator/buildr/trunk/Rakefile Wed Jan  2 03:07:10 2008
@@ -82,6 +82,7 @@
 
 desc 'Run all specs and generate reports in html directory'
 Spec::Rake::SpecTask.new('spec:report') do |task|
+  mkpath 'html'
   task.spec_files = FileList['spec/**/*_spec.rb']
   task.spec_opts << '--format' << 'html:html/report.html' << '--backtrace'
   task.rcov = true
@@ -106,7 +107,7 @@
   end
 
   web_collection = Docter.collection.using('doc/web.toc.textile').include('doc/pages', 'CHANGELOG')
-  web_template = Docter.template('doc/web.haml').include('doc/css', 'doc/images')
+  web_template = Docter.template('doc/web.haml').include('doc/css', 'doc/images', 'html/report.html', 'html/coverage')
   print_collection = Docter.collection.using('doc/print.toc.textile').include('doc/pages')
   print_template = Docter.template('doc/print.haml').include('doc/css', 'doc/images')
 

Added: incubator/buildr/trunk/doc/pages/extending.textile
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/doc/pages/extending.textile?rev=608079&view=auto
==============================================================================
--- incubator/buildr/trunk/doc/pages/extending.textile (added)
+++ incubator/buildr/trunk/doc/pages/extending.textile Wed Jan  2 03:07:10 2008
@@ -0,0 +1,229 @@
+h1. Extending Buildr
+
+h2. Organizing Tasks
+
+A couple of things we learned while working on Buildr.  Being able to write
+your own Rake tasks is a very powerful feature.  But if you find yourself
+doing the same thing over and over, you might also want to consider functions.
+They give you a lot more power and easy abstractions.
+
+For example, we use OpenJPA in several projects.  It's a very short task, but
+each time I have to go back to the OpenJPA documentation to figure out how to
+set the Ant MappingTool task, tell Ant how to define it.  After the second
+time, you're recognizing a pattern and it's just easier to write a function
+that does all that for you.
+
+Compare this:
+
+{{{!ruby
+file("derby.sql") do
+  requires = [
+    "org.apache.openjpa:openjpa-all:jar:0.9.7-incubating",
+    "commons-collections:commons-collections:jar:3.1",
+    . . . 
+    "net.sourceforge.serp:serp:jar:1.11.0" ]
+  ant("openjpa") do |ant|
+    ant.taskdef :name=>"mapping",
+      :classname=>"org.apache.openjpa.jdbc.ant.MappingToolTask",
+      :classpath=>REQUIRES.join(File::PATH_SEPARATOR)
+      ant.mapping :schemaAction=>"build", :sqlFile=>task.name,
+        :ignoreErrors=>true do
+        ant.config :propertiesFile=>_("src/main/sql/derby.xml")
+        ant.classpath :path=>projects("store", "utils" ).
+          flatten.map(&:to_s).join(File::PATH_SEPARATOR)
+      end
+    end
+  end
+end
+}}}
+
+To this:
+
+{{{!ruby
+file("derby.sql") do
+  mapping_tool :action=>"build", :sql=>task.name,
+    :properties=>_("src/main/sql/derby.xml"),
+    :classpath=>projects("store", "utils" )
+end
+}}}
+
+I prefer the second.  It's easier to look at the Buildfile and understand what
+it does.  It's easier to maintain when you only have to look at the important
+information.
+
+But just using functions is not always enough.  You end up with a Buildfile
+containing a lot of code that clearly doesn't belong there.  For starters, I
+recommend putting it in the @tasks@ directory.  Write it into a file with a
+@.rake@ extension and place that in the @tasks@ directory next to the
+Buildfile.  Buildr will automatically pick it up and load it for you.
+
+If you want to share these pre-canned definitions between projects, you have a
+few more options.  You can share the @tasks@ directory using SVN externals.
+Another mechanism with better version control is to package all these tasks,
+functions and modules into a "Gem":http://rubygems.org/ and require it from
+your Buildfile.  You can run your own internal Gem server for that.
+
+For individual task files, you can also use
+"Sake":http://errtheblog.com/post/6069 for system-wide Rake tasks deployment.
+
+
+h2.  Creating Extensions
+
+The basic mechanism for extending projects in Buildr are Ruby modules.  In
+fact, base features like compiling and testing are all developed in the form
+of modules, and then added to the core Project class.
+  
+A module defines instance methods that are then mixed into the project and
+become instance methods of the project.  There are two general ways for
+extending projects.  You can extend all projects by including the module in
+Project:
+
+{{{!ruby
+class Project
+  include MyExtension
+end
+}}}
+
+You can also extend a given project instance and only that instance by
+extending it with the module:
+
+{{{!ruby
+define 'foo' do
+  extend MyExtension
+end
+}}}
+
+Some extensions require tighter integration with the project, specifically for
+setting up tasks and properties, or for configuring tasks based on the project
+definition.  You can do that by adding callbacks to the process.
+
+The easiest way to add callbacks is by incorporating the Extension module in
+your own extension, and using the various class methods to define callback
+behavior:
+
+* @first_time@ -- This block will be called once for any particular extension.
+You can use this to setup top-level and local tasks.
+* @before_define@ -- This block is called once for the project with the
+project instance, right before running the project definition.  You can use
+this to add tasks and set properties that will be used in the project
+definition.
+* @after_define@ -- This block is called once for the project with the project
+instance, right after running the project definition.  You can use this to do
+any post-processing that depends on the project definition.
+
+This example illustrates how to write a simple extension:
+
+{{{!ruby
+module LinesOfCode
+  include Extension
+
+  first_time do
+    # Define task not specific to any projet.
+    desc 'Count lines of code in current project'
+    Project.local_task('loc')
+  end
+
+  before_define do |project|
+    # Define the loc task for this particular project.
+    define_task 'loc' do |task|
+      lines = task.prerequisites.map { |path| Dir["#{path}/**/*"] }.flatten.uniq.
+        inject(0) { |total, file| total + File.readlines(file).count }
+      puts "Project #{project.name} has #{lines} lines of code"
+    end
+  end
+
+  after_define do |project|
+    # Now that we know all the source directories, add them.
+    task('loc'=>compile.sources + compile.test.sources)
+  end
+
+  # To use this method in your project:
+  #   loc path_1, path_2
+  def loc(*paths)
+    task('loc'=>paths)
+  end
+
+end
+
+class Buildr::Project
+  include LinesOfCode
+end
+}}}
+
+
+h2.  Using Alternative Layouts
+
+Buildr follows a common convention for project layouts: Java source files
+appear in @src/main/java@ and compile to @target/classes@, resources are
+copied over from @src/main/resources@ and so forth.  Not all projects follow
+this convention, so it's now possible to specify an alternative project
+layout.
+
+The default layout is available in @Layout.default@, and all projects inherit
+it.  You can set @Layout.default@ to your own layout, or define a project with
+a given layout (recommended) by setting the @:layout@ property.  Projects
+inherit the layout from their parent projects.  For example:
+
+{{{!ruby
+define 'foo', :layout=>my_layout do
+  ...
+end
+}}}
+
+A layout is an object that implements the @expand@ method.  The easiest way to
+define a custom layout is to create a new @Layout@ object and specify mapping
+between names used by Buildr and actual paths within the project.  For
+example:
+
+{{{!ruby
+my_layout = Layout.new
+my_layout[:source, :main, :java] = 'java'
+my_layout[:source, :main, :resources] = 'resources'
+}}}
+
+Partial expansion also works, so you can specify the above layout using:
+
+{{{!ruby
+my_layout = Layout.new
+my_layout[:source, :main] = ''
+}}}
+
+If you need anything more complex, you can always subclass @Layout@ and add
+special handling in the @expand@ method, you'll find one such example in the
+API documentation.
+
+The built-in tasks expand lists of symbols into relative paths, using the
+following convention:
+
+* @:source, :main, <lang/usage>@ --  Directory containing source files for a
+given language or usage, for example, @:java@, @:resources@, @:webapp@.
+* @:source, :test, <lang/usage>@ -- Directory containing test files for a
+given language or usage, for example, @:java@, @:resources@.
+* @:target, :generated@ -- Target directory for generated code (typically
+source code).
+* @:target, :main, <lang/usage>@ -- Target directory for compiled code, for
+example, @:classes@, @:resources@.
+* @:target, :test, <lang/usage>@ -- Target directory for compile test cases,
+for example, @:classes@, @:resources@.
+* @:reports, <framework/usage>@ -- Target directory for generated reports, for
+example, @:junit@, @:coverage@.
+
+All tasks are encouraged to use the same convention, and whenever possible, we
+recommend using the project's @path_to@ method to expand a list of symbols
+into a path, or use the appropriate path when available.  For example:
+
+{{{!ruby
+define 'bad' do
+  # This may not be the real target.
+  puts 'Compiling to ' + path_to('target/classes')
+  # This will break with different layouts.
+  package(:jar).include 'src/main/etc/*'
+end
+
+define 'good' do
+  # This is always the compiler's target.
+  puts 'Compiling to ' + compile.target.to_s
+  # This will work with different layouts.
+  package(:jar).include path_to(:source, :main, :etc, '*')
+end
+}}}

Modified: incubator/buildr/trunk/doc/pages/more_stuff.textile
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/doc/pages/more_stuff.textile?rev=608079&r1=608078&r2=608079&view=diff
==============================================================================
--- incubator/buildr/trunk/doc/pages/more_stuff.textile (original)
+++ incubator/buildr/trunk/doc/pages/more_stuff.textile Wed Jan  2 03:07:10 2008
@@ -2,7 +2,8 @@
 
 h2. Help Tasks
 
-Buildr includes a number of informative tasks.  Currently that number stands at two, but we'll be adding more tasks in future releases.
+Buildr includes a number of informative tasks.  Currently that number stands
+at two, but we'll be adding more tasks in future releases.
 
 To start with, type:
 
@@ -10,7 +11,8 @@
 $ buildr help
 }}}
 
-You can list the name and description of all your projects using the @help:projects@ task.  For example:
+You can list the name and description of all your projects using the
+@help:projects@ task.  For example:
 
 {{{!sh
 $ buildr help:projects
@@ -20,14 +22,24 @@
 killer-app:la-web          # What our users see
 }}}
 
-You are, of course, describing your projects for the sake of those who will maintain your code, right?  To describe a project, or a task, call the @desc@ method before the project or task definition.
+You are, of course, describing your projects for the sake of those who will
+maintain your code, right?  To describe a project, or a task, call the @desc@
+method before the project or task definition.
 
 
 h2. Personal Settings and Environment Variables
 
-Some things clearly do not belong in the Buildfile.  For example, the username/password you use to upload releases.  If you're working in a team or making the source code available, you'd want to keep these in a separate place.  You may want to pick a different location for the local repository, or use a different remote repository than everyone else, etc.
-
-Besides loading the Buildfile, Buildr will also attempt to load two @buildr.rb@ files.  It looks for the first @buildr.rb@ file in your home directory.  That's the file you would use to define personal settings.  It then looks for the second @buildr.rb@ file in the project directory.  You can use that one to over-ride settings specific to that project.
+Some things clearly do not belong in the Buildfile.  For example, the
+username/password you use to upload releases.  If you're working in a team or
+making the source code available, you'd want to keep these in a separate
+place.  You may want to pick a different location for the local repository, or
+use a different remote repository than everyone else, etc.
+
+Besides loading the Buildfile, Buildr will also attempt to load two
+@buildr.rb@ files.  It looks for the first @buildr.rb@ file in your home
+directory.  That's the file you would use to define personal settings.  It
+then looks for the second @buildr.rb@ file in the project directory.  You can
+use that one to over-ride settings specific to that project.
 
 Here's an example @buildr.rb@, not one I actually use, but close enough:
 
@@ -39,32 +51,47 @@
 repositories.remote << "http://inside-the-firewall"
 }}} 
 
-Environment variables are another way to set personal settings.  Here's an example for a Buildfile that will read the username/password from environment variables:
+Environment variables are another way to set personal settings.  Here's an
+example for a Buildfile that will read the username/password from environment
+variables:
 
 {{{!ruby
 repositories.upload_to[:username] = ENV["USERNAME"]
 repositories.upload_to[:password] = ENV["PASSWORD"]
 }}}
 
-Build itself uses several environment variables, some more common, some specific to Buildr:
+Build itself uses several environment variables, some more common, some
+specific to Buildr:
 
 *JAVA_HOME* -- Points to your JDK, required for running Buildr.
 
-*JAVA_OPTS/JAVA_OPTIONS* -- Command line options to pass to the JDK (e.g. @"-Xms1g"@)[1].
+*JAVA_OPTS/JAVA_OPTIONS* -- Command line options to pass to the JDK (e.g.
+@"-Xms1g"@)[1].
 
-*HTTP_PROXY* -- URL for HTTP proxy server (see "Specifying Repositories":artifacts.html#specifying_repositories).
+*HTTP_PROXY* -- URL for HTTP proxy server (see "Specifying
+Repositories":artifacts.html#specifying_repositories).
 
-*NO_PROXY* -- Comma separated list of hosts and domain that should not be proxied (see "Specifying Repositories":artifacts.html#specifying_repositories).
+*NO_PROXY* -- Comma separated list of hosts and domain that should not be
+proxied (see "Specifying
+Repositories":artifacts.html#specifying_repositories).
 
-*DEBUG* -- Set to @off@ if you want Buildr to compile without debugging information (default when running @release@, see "Compiling":building.html#compiling).
+*DEBUG* -- Set to @off@ if you want Buildr to compile without debugging
+information (default when running @release@, see
+"Compiling":building.html#compiling).
 
-*TEST* -- Set to @off@ to tell Buildr to skip tests, or @all@ to tell Buildr to run all tests and ignore failures (see "Running Tests":testing.html#running_tests).
+*TEST* -- Set to @off@ to tell Buildr to skip tests, or @all@ to tell Buildr
+to run all tests and ignore failures (see "Running
+Tests":testing.html#running_tests).
 
-*BUILDR_ENV* -- Environment name that you can also set using the @-e@ command line option.
+*BUILDR_ENV* -- Environment name that you can also set using the @-e@ command
+line option.
 
-Some Buildfiles depend on the environment in which they are running, and may work differently in development, QA, production, etc.  Setting the environment name is a simple mechanism to control the Buildfile behavior.
+Some Buildfiles depend on the environment in which they are running, and may
+work differently in development, QA, production, etc.  Setting the environment
+name is a simple mechanism to control the Buildfile behavior.
 
-You set the environment name either using the @BUILDR_ENV@ environment variable, or the @-e@ command line option.  For example:
+You set the environment name either using the @BUILDR_ENV@ environment
+variable, or the @-e@ command line option.  For example:
 
 {{{!sh
 $ export BUILDR_ENV=development
@@ -76,7 +103,9 @@
 . . .
 }}}
 
-From the Buildfile, you can access the environment name using @Buildr.environment@, and in some contexts, simply by calling @environment@.  For example:
+From the Buildfile, you can access the environment name using
+@Buildr.environment@, and in some contexts, simply by calling @environment@.
+For example:
 
 {{{!ruby
 project 'db-module' do
@@ -88,15 +117,21 @@
 
 h2. Eclipse, IDEA
 
-If you're using Eclipse, you can generate @.classpath@ and @.project@ from your Buildfile and use them to create a project in your workspace:
+If you're using Eclipse, you can generate @.classpath@ and @.project@ from
+your Buildfile and use them to create a project in your workspace:
 
 {{{!sh
 $ buildr eclipse
 }}}
 
-The @eclipse@ task will generate a @.classpath@ and @.project@ file for each of projects (and sub-project) that compiles source code.  It will not generate files for other projects, for examples, projects you use strictly for packaging a distribution, or creating command line scripts, etc.
-
-If you add a new project, change the dependencies, or make any other change to your Buildfile, just run the @eclipse@ task again to re-generate the Eclipse project files.
+The @eclipse@ task will generate a @.classpath@ and @.project@ file for each
+of projects (and sub-project) that compiles source code.  It will not generate
+files for other projects, for examples, projects you use strictly for
+packaging a distribution, or creating command line scripts, etc.
+
+If you add a new project, change the dependencies, or make any other change to
+your Buildfile, just run the @eclipse@ task again to re-generate the Eclipse
+project files.
 
 If you prefer IntelliJ IDEA, you can always:
 
@@ -104,14 +139,21 @@
 $ buildr idea
 }}}
 
-It will generate a @.iml@ file for every project (or subproject) and a @.ipr@ that you can directly open for the root project.  To allow IntelliJ Idea to resolve external dependencies properly, you will need to add a @M2_REPO@ variable pointing to your Maven2 repository directory (@Settings / Path Variables@).
+It will generate a @.iml@ file for every project (or subproject) and a @.ipr@
+that you can directly open for the root project.  To allow IntelliJ Idea to
+resolve external dependencies properly, you will need to add a @M2_REPO@
+variable pointing to your Maven2 repository directory (@Settings / Path
+Variables@).
 
 
 h2. Cobertura, JDepend
 
-You can use "Cobertura":http://cobertura.sourceforge.net/ to instrument your code, run the tests and create a test coverage report in either HTML or XML format.
+You can use "Cobertura":http://cobertura.sourceforge.net/ to instrument your
+code, run the tests and create a test coverage report in either HTML or XML
+format.
 
-There are two tasks, both of which generate a test coverage report in the @reports/cobertura@ directory.  For example:
+There are two tasks, both of which generate a test coverage report in the
+@reports/cobertura@ directory.  For example:
 
 {{{!sh
 $ buildr test cobertura:html
@@ -119,7 +161,9 @@
 
 As you can guess, the other task is @cobertura:xml@.
 
-You can use "JDepend":http://clarkware.com/software/JDepend.html on to generate design quality metrics.  There are three tasks this time, the eye candy one:
+You can use "JDepend":http://clarkware.com/software/JDepend.html on to
+generate design quality metrics.  There are three tasks this time, the eye
+candy one:
 
 {{{!sh
 $ buildr jdepend:swing
@@ -127,16 +171,22 @@
 
 The other two tasks are @jdepend:text@ and @jdepend:xml@.
 
-We want Buildr to load fast, and not everyone cares for these tasks, so we don't include them by default.  If you want to use either one, you need to require it explicitly.  The proper way to do it in Ruby:
+We want Buildr to load fast, and not everyone cares for these tasks, so we
+don't include them by default.  If you want to use either one, you need to
+require it explicitly.  The proper way to do it in Ruby:
 
 {{{!ruby
 require "buildr/cobertura"
 require "buildr/jdepend"
 }}}
 
-You may want to add those to the Buildfile.  Alternatively, you can use these tasks for all your projects without modifying the Buildfile.  One convenient method is to add these two likes to the @buildr.rb@ file in your home directory.
+You may want to add those to the Buildfile.  Alternatively, you can use these
+tasks for all your projects without modifying the Buildfile.  One convenient
+method is to add these two likes to the @buildr.rb@ file in your home
+directory.
 
-Another option is to require it from the command line (@--require@ or @-r@), for example:
+Another option is to require it from the command line (@--require@ or @-r@),
+for example:
 
 {{{!sh
 $ buildr --require buildr/jdepend jdepend:swing
@@ -144,62 +194,20 @@
 }}}
 
 
-h2. Organizing Tasks
-
-A couple of things we learned while working on Buildr.  Being able to write your own Rake tasks is a very powerful feature.  But if you find yourself doing the same thing over and over, you might also want to consider functions.  They give you a lot more power and easy abstractions.
-
-For example, we use OpenJPA in several projects.  It's a very short task, but each time I have to go back to the OpenJPA documentation to figure out how to set the Ant MappingTool task, tell Ant how to define it.  After the second time, you're recognizing a pattern and it's just easier to write a function that does all that for you.
-
-Compare this:
-
-{{{!ruby
-file("derby.sql") do
-  requires = [
-    "org.apache.openjpa:openjpa-all:jar:0.9.7-incubating",
-    "commons-collections:commons-collections:jar:3.1",
-    . . . 
-    "net.sourceforge.serp:serp:jar:1.11.0" ]
-  ant("openjpa") do |ant|
-    ant.taskdef :name=>"mapping",
-      :classname=>"org.apache.openjpa.jdbc.ant.MappingToolTask",
-      :classpath=>REQUIRES.join(File::PATH_SEPARATOR)
-      ant.mapping :schemaAction=>"build", :sqlFile=>task.name,
-        :ignoreErrors=>true do
-        ant.config :propertiesFile=>_("src/main/sql/derby.xml")
-        ant.classpath :path=>projects("store", "utils" ).
-          flatten.map(&:to_s).join(File::PATH_SEPARATOR)
-      end
-    end
-  end
-end
-}}}
-
-To this:
-
-{{{!ruby
-file("derby.sql") do
-  mapping_tool :action=>"build", :sql=>task.name,
-    :properties=>_("src/main/sql/derby.xml"),
-    :classpath=>projects("store", "utils" )
-end
-}}}
-
-I prefer the second.  It's easier to look at the Buildfile and understand what it does.  It's easier to maintain when you only have to look at the important information.
-
-But just using functions is not always enough.  You end up with a Buildfile containing a lot of code that clearly doesn't belong there.  For starters, I recommend putting it in the @tasks@ directory.  Write it into a file with a @.rake@ extension and place that in the @tasks@ directory next to the Buildfile.  Buildr will automatically pick it up and load it for you.
-
-If you want to share these pre-canned definitions between projects, you have a few more options.  You can share the @tasks@ directory using SVN externals.  Another mechanism with better version control is to package all these tasks, functions and modules into a "Gem":http://rubygems.org/ and require it from your Buildfile.  You can run your own internal Gem server for that.
-
-For individual task files, you can also use "Sake":http://errtheblog.com/post/6069 for system-wide Rake tasks deployment.
-
-
 h2. Anything Ruby Can Do
 
-Buildr is Ruby code.  That's an implementation detail for some, but a useful features for others.  You can use Ruby to keep your build scripts simple and DRY, tackle ad hoc tasks and write reusable features without the complexity of "plugins".
-
-We already showed you one example where Ruby could help.  You can use Ruby to manage dependency by setting constants and reusing them, grouping related dependencies into arrays and structures.
-
-You can use Ruby to perform ad hoc tasks.  For example, Buildr doesn't have any pre-canned task for setting file permissions.  But Ruby has a method for just, so it's just a matter of writing a task:
+Buildr is Ruby code.  That's an implementation detail for some, but a useful
+features for others.  You can use Ruby to keep your build scripts simple and
+DRY, tackle ad hoc tasks and write reusable features without the complexity of
+"plugins".
+
+We already showed you one example where Ruby could help.  You can use Ruby to
+manage dependency by setting constants and reusing them, grouping related
+dependencies into arrays and structures.
+
+You can use Ruby to perform ad hoc tasks.  For example, Buildr doesn't have
+any pre-canned task for setting file permissions.  But Ruby has a method for
+just, so it's just a matter of writing a task:
 
 {{{!ruby
 bins = file("target/bin"=>FileList[_("src/main/dist/bin/*")]) do |task|
@@ -209,7 +217,10 @@
 end
 }}}
 
-You can use functions to keep your code simple.  For example, in the ODE project we create two binary distributions, both of which contain a common set of files, and one additional file unique to each distribution.  We use a method to define the common distribution:
+You can use functions to keep your code simple.  For example, in the ODE
+project we create two binary distributions, both of which contain a common set
+of files, and one additional file unique to each distribution.  We use a
+method to define the common distribution:
 
 {{{!ruby
 def distro(project, id)
@@ -238,7 +249,9 @@
 end
 }}}
 
-Ruby's functional style and blocks make some task extremely easy.  For example, let's say we wanted to count how many source files we have, and total number of lines:
+Ruby's functional style and blocks make some task extremely easy.  For
+example, let's say we wanted to count how many source files we have, and total
+number of lines:
 
 {{{!ruby
 sources = projects.map { |prj| prj.compile.sources.
@@ -249,74 +262,4 @@
 }}}
 
 
-h2.  Creating Extensions
-
-The basic mechanism for extending projects in Buildr are Ruby modules.  In fact, base features like compiling and testing are all developed in the form of modules, and then added to the core Project class.
-  
-A module defines instance methods that are then mixed into the project and become instance methods of the project.  There are two general ways for extending projects.  You can extend all projects by including the module in Project:
-
-{{{!ruby
-class Project
-  include MyExtension
-end
-}}}
-
-You can also extend a given project instance and only that instance by extending it with the module:
-
-{{{!ruby
-define 'foo' do
-  extend MyExtension
-end
-}}}
-
-Some extensions require tighter integration with the project, specifically for setting up tasks and properties, or for configuring tasks based on the project definition.  You can do that by adding callbacks to the process.
-
-The easiest way to add callbacks is by incorporating the Extension module in your own extension, and using the various class methods to define callback behavior:
-
-* @first_time@ -- This block will be called once for any particular extension.  You can use this to setup top-level and local tasks.
-
-* @before_define@ -- This block is called once for the project with the project instance, right before running the project definition.  You can use this to add tasks and set properties that will be used in the project definition.
-
-* @after_define@ -- This block is called once for the project with the project instance, right after running the project definition.  You can use this to do any post-processing that depends on the project definition.
-
-This example illustrates how to write a simple extension:
-
-{{{!ruby
-module LinesOfCode
-  include Extension
-
-  first_time do
-    # Define task not specific to any projet.
-    desc 'Count lines of code in current project'
-    Project.local_task('loc')
-  end
-
-  before_define do |project|
-    # Define the loc task for this particular project.
-    define_task 'loc' do |task|
-      lines = task.prerequisites.map { |path| Dir["#{path}/**/*"] }.flatten.uniq.
-        inject(0) { |total, file| total + File.readlines(file).count }
-      puts "Project #{project.name} has #{lines} lines of code"
-    end
-  end
-
-  after_define do |project|
-    # Now that we know all the source directories, add them.
-    task('loc'=>compile.sources + compile.test.sources)
-  end
-
-  # To use this method in your project:
-  #   loc path_1, path_2
-  def loc(*paths)
-    task('loc'=>paths)
-  end
-
-end
-
-class Buildr::Project
-  include LinesOfCode
-end
-}}}
-
-
-fn1. Unfortunately, Buildr does not check any of the arguments in @JAVA_OPTS@.  A common mistake is to pass an option like @mx512mb@, where it should be @Xmx512mb@.  Make sure to double check @JAVA_OPTS@.
+fn1. Buildr does not check any of the arguments in @JAVA_OPTS@.  A common mistake is to pass an option like @mx512mb@, where it should be @Xmx512mb@.  Make sure to double check @JAVA_OPTS@.

Modified: incubator/buildr/trunk/doc/print.toc.textile
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/doc/print.toc.textile?rev=608079&r1=608078&r2=608079&view=diff
==============================================================================
--- incubator/buildr/trunk/doc/print.toc.textile (original)
+++ incubator/buildr/trunk/doc/print.toc.textile Wed Jan  2 03:07:10 2008
@@ -8,4 +8,5 @@
 # packaging
 # testing
 # more_stuff
+# extending
 # contributing

Modified: incubator/buildr/trunk/doc/web.toc.textile
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/doc/web.toc.textile?rev=608079&r1=608078&r2=608079&view=diff
==============================================================================
--- incubator/buildr/trunk/doc/web.toc.textile (original)
+++ incubator/buildr/trunk/doc/web.toc.textile Wed Jan  2 03:07:10 2008
@@ -8,6 +8,7 @@
 # packaging
 # testing
 # more_stuff
+# extending
 # "API":rdoc/index.html
 # "Printable PDF":buildr.pdf
 # mailing_lists
@@ -15,3 +16,5 @@
 # contributing
 # "License":http://apache.org/licenses/LICENSE-2.0.html
 # "Change Log":changelog.html
+# "Test Report":report.html
+# "Test Coverage":coverage/index.html