<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,4 @@
 makedepot.html
+checkdepot.html
 work
 snapshot</diff>
      <filename>.gitignore</filename>
    </modified>
    <modified>
      <diff>@@ -12,7 +12,6 @@ class DepotTest &lt; ActiveSupport::TestCase
 
   # micro DSL allowing the definition of optional tests
   def self.section number, title, &amp;tests
-    @@sections ||= self.sections
     return if ARGV.include? 'partial' and !@@sections.has_key? number.to_s
     test &quot;#{number} #{title}&quot; do
       instance_eval {select number}
@@ -20,32 +19,32 @@ class DepotTest &lt; ActiveSupport::TestCase
     end
   end
 
-  # read and pre-process makedepot.html (only needs to be done once)
-  def self.sections
+  # read and pre-process makedepot.html (only done once, and cached)
+  class &lt;&lt; self
     # read makedepot output; remove front matter and footer
-    output = open('makedepot.html').read
-    output.sub! /.*&lt;body&gt;\s+/m, ''
-    output.sub! /\s+&lt;\/body&gt;.*/m, ''
+    makedepot = open('makedepot.html').read
+    head, body, tail = makedepot.split /&lt;body&gt;\s+|\s+&lt;\/body&gt;/m
 
     # split into sections
-    @@sections = output.split(/&lt;a class=&quot;toc&quot; name=&quot;section-(.*?)&quot;&gt;/)
+    @@sections = body.split(/&lt;a class=&quot;toc&quot; name=&quot;section-(.*?)&quot;&gt;/)
 
     # convert to a Hash
-    @@sections = Hash[*@@sections.unshift('head')]
+    @@sections = Hash[*@@sections.unshift(:contents)]
+    @@sections[:head] = head
+    @@sections[:tail] = tail
 
     # reattach anchors
     @@sections.each do |key,value|
-      @@sections[key] = &quot;&lt;a class='toc' name='#{key}'&gt;#{value}&quot;
+      next unless key =~ /^\d/
+      @@sections[key] = &quot;&lt;a class=\&quot;toc\&quot; name=\&quot;section-#{key}\&quot;&gt;#{value}&quot;
     end
 
     # report version
-    output =~ /rails .*?-v&lt;\/pre&gt;\s+.*?&gt;(.*)&lt;\/pre&gt;/
+    body =~ /rails .*?-v&lt;\/pre&gt;\s+.*?&gt;(.*)&lt;\/pre&gt;/
     @@version = $1
-    @@version += ' (git)' if output =~ /ln -s.*vendor.rails/
-    @@version += ' (edge)' if output =~ /rails:freeze:edge/
+    @@version += ' (git)' if body =~ /ln -s.*vendor.rails/
+    @@version += ' (edge)' if body =~ /rails:freeze:edge/
     STDERR.puts @@version
-
-    @@sections
   end
 
   # select an individual section from the HTML
@@ -1058,7 +1057,7 @@ class DepotTest &lt; ActiveSupport::TestCase
     assert_select &quot;hr&quot;
   end
 
-  section 23.10, 'Caching, Part Two' do
+  section '23.10', 'Caching, Part Two' do
     # not exactly a good test of the function in question...
     assert_select &quot;p&quot;, 'There are a total of 4 articles.'
   end
@@ -1090,4 +1089,57 @@ class DepotTest &lt; ActiveSupport::TestCase
     assert_select '.stdout', /&quot;product_id&quot;=&amp;gt;3/
     assert_select '.stdout', /=&amp;gt; 22.8/
   end
+
+  def self.sections
+    @@sections
+  end
+end
+
+# insert failure indicators into checkdepot.html
+require 'test/unit/ui/console/testrunner'
+class HTMLRunner &lt; Test::Unit::UI::Console::TestRunner
+  def attach_to_mediator
+    super
+    @html_tests = []
+    @mediator.add_listener(Test::Unit::TestResult::FAULT,
+      &amp;method(:html_fault))
+    @mediator.add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED,
+      &amp;method(:html_summary))
+  end
+
+  def html_fault fault
+    if fault.test_name =~ /^test_([\d.]+)_.*\(\w+\)$/
+      name = $1
+      sections = DepotTest.sections
+      return unless sections.has_key? name
+
+      # indicate failure in the toc
+      sections[:contents][/&lt;a href=&quot;#section-#{name}&quot;()&gt;/,1] = 
+        ' style=&quot;color:red; font-weight:bold&quot;'
+
+      # provide details in the section itself
+      x = Builder::XmlMarkup.new(:indent =&gt; 2)
+      x.pre fault.message.sub(&quot;.\n&lt;false&gt; is not true&quot;,'') +
+        &quot;\n\nTraceback:\n  &quot; + fault.location.join(&quot;\n  &quot;),
+        :class=&gt;'traceback'
+      sections[name][/&lt;\/a&gt;()/,1] = x.target!
+    end
+  end
+
+  def html_summary elapsed
+    open('checkdepot.html','w') do |checkdepot|
+      sections = DepotTest.sections
+      checkdepot.write(sections.delete(:head))
+      checkdepot.write(&quot;&lt;body&gt;\n&quot;)
+      checkdepot.write(sections.delete(:contents))
+      tail = sections.delete(:tail)
+      sections.keys.sort_by {|key| key.split('.').map {|n| n.to_i}}.each do |n|
+        checkdepot.write(sections[n])
+      end
+      checkdepot.write(&quot;\n  &lt;/body&gt;&quot;)
+      checkdepot.write(tail)
+    end
+  end
 end
+
+HTMLRunner.run(DepotTest)</diff>
      <filename>checkdepot.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1765,7 +1765,7 @@ section 23.9, 'Layouts and Components' do
   get '/partial/list'
 end
 
-section 23.10, 'Caching, Part Two' do
+section '23.10', 'Caching, Part Two' do
   cmd 'ruby script/generate model article body:text'
   cmd &quot;cp -v #{$CODE}/e1/views/app/models/article.rb app/models&quot;
   cmd &quot;cp -vr #{$CODE}/e1/views/app/views/blog app/views&quot;</diff>
      <filename>makedepot.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,6 +13,7 @@ task :clean do
   rm_rf 'work'
   rm_rf 'snapshot'
   rm_rf 'makedepot.html'
+  rm_rf 'checkdepot.html'
 end
 
 def serialize(args)</diff>
      <filename>rakefile</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>caff0923742dea24d19eea6451afb0690a183795</id>
    </parent>
  </parents>
  <author>
    <name>Sam Ruby</name>
    <email>rubys@intertwingly.net</email>
  </author>
  <url>http://github.com/rubys/awdwr/commit/d586f6bb55f4ba0399ca2bf4578d1712264483f2</url>
  <id>d586f6bb55f4ba0399ca2bf4578d1712264483f2</id>
  <committed-date>2009-05-17T12:54:58-07:00</committed-date>
  <authored-date>2009-05-17T12:54:58-07:00</authored-date>
  <message>makedepot.html + failure messages =&gt; checkdepot.html</message>
  <tree>3efc998304c6c99186313b99ad156cfb21f7770d</tree>
  <committer>
    <name>Sam Ruby</name>
    <email>rubys@intertwingly.net</email>
  </committer>
</commit>
