<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/semantic_attributes/locale/en.yml</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -6,9 +6,4 @@ ActiveRecord::Base.class_eval do
   include ActiveRecord::ValidationRecursionControl
 end
 
-# localization mock
-ActiveRecord::Base.class_eval do
-  unless respond_to? :_
-    def _(s); s; end
-  end
-end
+I18n.load_path &lt;&lt; File.dirname(__FILE__) + '/lib/semantic_attributes/locale/en.yml'</diff>
      <filename>init.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,7 +15,7 @@ class Predicates::Association &lt; Predicates::Base
   attr_accessor :max
 
   def error_message
-    @error_message || 'is required.'
+    @error_message || :required
   end
 
   def validate(value, record)</diff>
      <filename>lib/predicates/association.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,9 +13,21 @@ module Predicates
     ##
 
     # the error string when validation fails
-    attr_accessor :error_message
+    def error_message
+      @error_message || :invalid
+    end
+    attr_writer :error_message
     alias_accessor :message, :error_message
 
+    # available interpolation variables for the error message (see I18n.translate)
+    def error_binds
+      {}
+    end
+    
+    def error
+      I18n.t(error_message, error_binds.merge(:scope =&gt; 'semantic-attributes.errors.messages'))
+    end
+
     # a condition to restrict when validation should occur. if it returns false, the validation will not happen.
     # if the value is a proc, then the proc will be called and the record object passed as the argument
     # if the value is a symbol, then a method by that name will be called on the record</diff>
      <filename>lib/predicates/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,7 @@ class Predicates::Blacklisted &lt; Predicates::Base
   attr_accessor :restricted
 
   def error_message
-    @error_message || &quot;is not an allowed option.&quot;
+    @error_message || :exclusion
   end
 
   def validate(val, record)</diff>
      <filename>lib/predicates/blacklisted.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@ require 'uri'
 # Defines a field as a simple domain (not URL).
 class Predicates::Domain &lt; Predicates::Base
   def error_message
-    @error_message || &quot;must be a simple domain.&quot;
+    @error_message || :domain
   end
 
   def validate(value, record)</diff>
      <filename>lib/predicates/domain.rb</filename>
    </modified>
    <modified>
      <diff>@@ -27,7 +27,7 @@ class Predicates::Email &lt; Predicates::Base
   end
 
   def error_message
-    @error_message || 'must be an email address.'
+    @error_message || :email
   end
 
   EmailAddressPattern = begin
@@ -39,4 +39,4 @@ class Predicates::Email &lt; Predicates::Base
       Regexp::EXTENDED | Regexp::IGNORECASE
     )
   end
-end
\ No newline at end of file
+end</diff>
      <filename>lib/predicates/email.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,7 +14,7 @@ class Predicates::Enumerated &lt; Predicates::Base
   end
 
   def error_message
-    @error_message || &quot;is not an allowed option.&quot;
+    @error_message || :inclusion
   end
 
   def validate(value, record)</diff>
      <filename>lib/predicates/enumerated.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,7 @@ class Predicates::HexColor &lt; Predicates::Pattern
   end
 
   def error_message
-    @error_message ||= &quot;must be a hex color.&quot;
+    @error_message ||= :hex
   end
 
   def normalize(value)</diff>
      <filename>lib/predicates/hex_color.rb</filename>
    </modified>
    <modified>
      <diff>@@ -24,7 +24,13 @@ class Predicates::Length &lt; Predicates::Base
   attr_accessor :exactly
 
   def error_message
-    @error_message || &quot;must be #{range_description} characters long.&quot;
+    @error_message || range_description
+  end
+  
+  def error_binds
+    self.range ?
+      {:min =&gt; self.range.first, :max =&gt; self.range.last} :
+      {:min =&gt; self.above, :max =&gt; self.below, :count =&gt; self.exactly}
   end
 
   def validate(value, record)
@@ -52,10 +58,10 @@ class Predicates::Length &lt; Predicates::Base
   end
   
   def range_description
-    return self.exactly.to_s if self.exactly
-    return &quot;#{self.range.first} to #{self.range.last}&quot; if self.range
-    return &quot;more than #{self.above}&quot; if self.above
-    return &quot;less than #{self.below}&quot; if self.below
+    return :inexact_length if self.exactly
+    return :wrong_length if self.range
+    return :too_short if self.above
+    return :too_long if self.below
     raise 'undetermined range'
   end
 end</diff>
      <filename>lib/predicates/length.rb</filename>
    </modified>
    <modified>
      <diff>@@ -42,7 +42,13 @@ class Predicates::Number &lt; Predicates::Base
   end
 
   def error_message
-    @error_message || &quot;must be a number#{range_description}.&quot;
+    @error_message || range_description
+  end
+  
+  def error_binds
+    self.range ?
+      {:min =&gt; self.range.first, :max =&gt; self.range.last} :
+      {:min =&gt; self.above, :max =&gt; self.below}
   end
 
   def validate(value, record)
@@ -80,16 +86,19 @@ class Predicates::Number &lt; Predicates::Base
 
   def range_description
     # if it has two endpoints
-    return &quot; from #{self.range.first} #{self.range.exclude_end? ? 'to' : 'through'} #{self.range.last}&quot; if self.range
+    if self.range
+      return :between
+    end
     # if it only has one inclusive endpoint
     if inclusive
-      return &quot; at least #{self.above}&quot; if self.above
-      return &quot; no more than #{self.below}&quot; if self.below
+      return :greater_than_or_equal_to if self.above
+      return :less_than_or_equal_to if self.below
     # if it only has one exclusive endpoint
     else
-      return &quot; greater than #{self.above}&quot; if self.above
-      return &quot; less than #{self.below}&quot; if self.below
+      return :greater_than if self.above
+      return :less_than if self.below
     end
     # if it has no endpoints
+    :not_a_number
   end
 end</diff>
      <filename>lib/predicates/number.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,12 +15,8 @@
 class Predicates::Pattern &lt; Predicates::Base
   attr_accessor :like
 
-  def error_message
-    @error_message ||= &quot;is invalid.&quot;
-  end
-
   def validate(value, record)
     value = value.to_s if [Symbol, Fixnum].include?(value.class)
     value.match(self.like)
   end
-end
\ No newline at end of file
+end</diff>
      <filename>lib/predicates/pattern.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,7 +14,7 @@ class Predicates::PhoneNumber &lt; Predicates::Base
   end
 
   def error_message
-    @error_message ||= &quot;must be a phone number.&quot;
+    @error_message ||= :phone
   end
 
   def validate(value, record)</diff>
      <filename>lib/predicates/phone_number.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,10 +13,10 @@ class Predicates::Required &lt; Predicates::Base
   end
 
   def error_message
-    @error_message || 'is required.'
+    @error_message || :required
   end
 
   def validate(value, record)
     !value.blank?
   end
-end
\ No newline at end of file
+end</diff>
      <filename>lib/predicates/required.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,10 +8,10 @@ class Predicates::SameAs &lt; Predicates::Base
   attr_accessor :method
 
   def error_message
-    @error_message ||= &quot;must be the same as #{method}.&quot;
+    @error_message ||= :same_as
   end
-
+  
   def validate(value, record)
     value == record.send(self.method)
   end
-end
\ No newline at end of file
+end</diff>
      <filename>lib/predicates/same_as.rb</filename>
    </modified>
    <modified>
      <diff>@@ -24,7 +24,7 @@ class Predicates::Time &lt; Predicates::Base
   attr_accessor :distance
 
   def error_message
-    @error_message || &quot;must be a point in time.&quot;
+    @error_message || :time
   end
 
   def validate(value, record)</diff>
      <filename>lib/predicates/time.rb</filename>
    </modified>
    <modified>
      <diff>@@ -20,7 +20,7 @@ class Predicates::Unique &lt; Predicates::Base
   end
 
   def error_message
-    @error_message || &quot;has already been taken.&quot;
+    @error_message || :taken
   end
 
   def validate(value, record)  </diff>
      <filename>lib/predicates/unique.rb</filename>
    </modified>
    <modified>
      <diff>@@ -33,7 +33,7 @@ class Predicates::Url &lt; Predicates::Base
   end
 
   def error_message
-    @error_message || 'must be a valid URL.'
+    @error_message || :url
   end
 
   def validate(value, record)</diff>
      <filename>lib/predicates/url.rb</filename>
    </modified>
    <modified>
      <diff>@@ -17,7 +17,7 @@ class Predicates::UsaState &lt; Predicates::Aliased
   undef_method :options=
 
   def error_message
-    @error_message || &quot;must be a US state#{' or territory' if with_territories?}.&quot;
+    @error_message || with_territories? ? :us_state_or_territory : :us_state
   end
 
   TERRITORIES = {
@@ -84,4 +84,4 @@ class Predicates::UsaState &lt; Predicates::Aliased
     'Wisconsin' =&gt; 'WI',
     'Wyoming' =&gt; 'WY'
   }
-end
\ No newline at end of file
+end</diff>
      <filename>lib/predicates/usa_state.rb</filename>
    </modified>
    <modified>
      <diff>@@ -20,6 +20,6 @@ class Predicates::UsaZipCode &lt; Predicates::Pattern
   undef_method :like=
 
   def error_message
-    @error_message || 'must be a US zip code.'
+    @error_message || :us_zip_code
   end
-end
\ No newline at end of file
+end</diff>
      <filename>lib/predicates/usa_zip_code.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,12 +26,12 @@ module SemanticAttributes
         applicable_predicates.each do |predicate|
           if value.blank?
             # it's empty, so add an error or not but either way move along
-            self.errors.add(attribute.field, _(predicate.error_message)) unless predicate.allow_empty?
+            self.errors.add(attribute.field, predicate.error) unless predicate.allow_empty?
             next
           end
 
           unless predicate.validate(value, self)
-            self.errors.add(attribute.field, _(predicate.error_message))
+            self.errors.add(attribute.field, predicate.error)
           end
         end
       end</diff>
      <filename>lib/semantic_attributes/predicates.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,6 +26,8 @@ class BasePredicateTest &lt; SemanticAttributes::TestCase
   def test_default_values
     assert @predicate.allow_empty?, &quot;allow empty/nil values by default&quot;
     assert_equal :both, @predicate.validate_on, &quot;validate on create and update by default&quot;
+    assert_equal :invalid, @predicate.error_message, &quot;error message is a bland :invalid by default&quot;
+    assert_equal Hash.new, @predicate.error_binds, &quot;there are no binds by default&quot;
   end
 
   def test_or_empty</diff>
      <filename>test/unit/predicates/base_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -25,10 +25,4 @@ class BlacklistedPredicateTest &lt; SemanticAttributes::TestCase
     assert !@predicate.validate('3', nil)
     assert @predicate.validate(6, nil)
   end
-  
-  def test_error_message
-    assert_equal &quot;is not an allowed option.&quot;, @predicate.error_message
-    @predicate.error_message = 'foo'
-    assert_equal 'foo', @predicate.error_message
-  end
 end</diff>
      <filename>test/unit/predicates/blacklisted_predicate_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,12 +5,6 @@ class DomainPredicateTest &lt; SemanticAttributes::TestCase
     @predicate = Predicates::Domain.new(:foo)
   end
 
-  def test_error_message
-    assert_equal 'must be a simple domain.', @predicate.error_message
-    @predicate.error_message = 'foo'
-    assert_equal 'foo', @predicate.error_message
-  end
-
   def test_valid_domains
     %w(example.com www.example.com).each do |domain|
       assert @predicate.validate(domain, nil), &quot;#{domain} is a valid domain&quot;
@@ -30,4 +24,4 @@ class DomainPredicateTest &lt; SemanticAttributes::TestCase
     assert_equal &quot;&quot;, @predicate.normalize(&quot;&quot;)
     assert_equal &quot;example.com&quot;, @predicate.normalize(&quot;example.com&quot;)
   end
-end
\ No newline at end of file
+end</diff>
      <filename>test/unit/predicates/domain_predicate_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -80,10 +80,4 @@ class EmailPredicateTest &lt; SemanticAttributes::TestCase
     assert !@predicate.validate('test@example.com', nil), 'syntax and mx check'
     assert @predicate.validate('test@gmail.com', nil)
   end
-
-  def test_error_message
-    assert_equal 'must be an email address.', @predicate.error_message
-    @predicate.error_message = 'foo'
-    assert_equal 'foo', @predicate.error_message
-  end
-end
\ No newline at end of file
+end</diff>
      <filename>test/unit/predicates/email_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,12 +15,6 @@ class EnumeratedPredicateTest &lt; SemanticAttributes::TestCase
     assert !@predicate.validate(6, nil)
   end
 
-  def test_error_message
-    assert_equal &quot;is not an allowed option.&quot;, @predicate.error_message
-    @predicate.error_message = 'foo'
-    assert_equal 'foo', @predicate.error_message
-  end
-  
   def test_or_empty
     assert !Predicates::Enumerated.new(:foo).allow_empty?
     assert Predicates::Enumerated.new(:foo, :or_empty =&gt; true).allow_empty?</diff>
      <filename>test/unit/predicates/enumerated_predicate_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,10 +5,6 @@ class HexColorPredicateTest &lt; SemanticAttributes::TestCase
     @predicate = Predicates::HexColor.new(:foo)
   end
 
-  def test_default_error_message
-    assert_equal @predicate.error_message, &quot;must be a hex color.&quot;
-  end
-
   def test_normalize_conversions
     assert_equal &quot;&quot;, @predicate.normalize(&quot;&quot;)
     assert_equal nil, @predicate.normalize(nil)
@@ -30,4 +26,4 @@ class HexColorPredicateTest &lt; SemanticAttributes::TestCase
     end
   end
 
-end
\ No newline at end of file
+end</diff>
      <filename>test/unit/predicates/hex_color_predicate_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,7 @@ class LengthPredicateTest &lt; SemanticAttributes::TestCase
 
   def test_range
     @predicate.range = 1..5
-    assert_equal 'must be 1 to 5 characters long.', @predicate.error_message
+    assert_equal :wrong_length, @predicate.error_message
 
     assert !@predicate.validate('', nil)
     assert @predicate.validate('1', nil)
@@ -15,13 +15,13 @@ class LengthPredicateTest &lt; SemanticAttributes::TestCase
     assert !@predicate.validate('123456', nil)
 
     @predicate.range = 1...5
-    assert_equal 'must be 1 to 5 characters long.', @predicate.error_message, 'same message for inclusive range'
+    assert_equal :wrong_length, @predicate.error_message, 'same message for inclusive range'
     assert !@predicate.validate('12345', nil)
   end
 
   def test_min
     @predicate.above = 5
-    assert_equal 'must be more than 5 characters long.', @predicate.error_message
+    assert_equal :too_short, @predicate.error_message
 
     assert !@predicate.validate('', nil)
     assert !@predicate.validate('12345', nil)
@@ -30,7 +30,7 @@ class LengthPredicateTest &lt; SemanticAttributes::TestCase
 
   def test_max
     @predicate.below = 5
-    assert_equal 'must be less than 5 characters long.', @predicate.error_message
+    assert_equal :too_long, @predicate.error_message
 
     assert @predicate.validate('', nil)
     assert @predicate.validate('1234', nil)
@@ -39,7 +39,7 @@ class LengthPredicateTest &lt; SemanticAttributes::TestCase
 
   def test_exact
     @predicate.exactly = 5
-    assert_equal 'must be 5 characters long.', @predicate.error_message
+    assert_equal :inexact_length, @predicate.error_message
 
     assert !@predicate.validate('', nil)
     assert !@predicate.validate('1234', nil)</diff>
      <filename>test/unit/predicates/length_predicate_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,9 +6,7 @@ class NumberPredicateTest &lt; SemanticAttributes::TestCase
   end
 
   def test_basic_error_message
-    assert_equal 'must be a number.', @predicate.error_message
-    @predicate.error_message = 'foo'
-    assert_equal 'foo', @predicate.error_message
+    assert_equal :not_a_number, @predicate.error_message
   end
 
   def test_integers
@@ -38,7 +36,7 @@ class NumberPredicateTest &lt; SemanticAttributes::TestCase
 
   def test_min
     @predicate.above = 5
-    assert_equal 'must be a number greater than 5.', @predicate.error_message
+    assert_equal :greater_than, @predicate.error_message
 
     assert !@predicate.validate(-10, nil)
     assert !@predicate.validate(-5, nil)
@@ -55,7 +53,7 @@ class NumberPredicateTest &lt; SemanticAttributes::TestCase
     @predicate.at_least = 5
     assert_equal 5, @predicate.above
     assert @predicate.inclusive
-    assert_equal 'must be a number at least 5.', @predicate.error_message
+    assert_equal :greater_than_or_equal_to, @predicate.error_message
 
     assert !@predicate.validate(4, nil)
     assert @predicate.validate(5, nil)
@@ -63,7 +61,7 @@ class NumberPredicateTest &lt; SemanticAttributes::TestCase
 
   def test_max
     @predicate.below = 5
-    assert_equal 'must be a number less than 5.', @predicate.error_message
+    assert_equal :less_than, @predicate.error_message
 
     assert @predicate.validate(-10, nil)
     assert @predicate.validate(-5, nil)
@@ -80,7 +78,7 @@ class NumberPredicateTest &lt; SemanticAttributes::TestCase
     @predicate.no_more_than = 5
     assert_equal 5, @predicate.below
     assert @predicate.inclusive
-    assert_equal 'must be a number no more than 5.', @predicate.error_message
+    assert_equal :less_than_or_equal_to, @predicate.error_message
 
     assert @predicate.validate(5, nil)
     assert !@predicate.validate(6, nil)
@@ -88,7 +86,7 @@ class NumberPredicateTest &lt; SemanticAttributes::TestCase
 
   def test_range
     @predicate.range = -5...5
-    assert_equal 'must be a number from -5 to 5.', @predicate.error_message
+    assert_equal :between, @predicate.error_message
 
     assert !@predicate.validate(-10, nil)
     assert @predicate.validate(-5, nil)
@@ -103,7 +101,7 @@ class NumberPredicateTest &lt; SemanticAttributes::TestCase
 
   def test_range_inclusive
     @predicate.range = -5..5
-    assert_equal 'must be a number from -5 through 5.', @predicate.error_message
+    assert_equal :between, @predicate.error_message
 
     assert @predicate.validate(5, nil)
     assert !@predicate.validate(6, nil)</diff>
      <filename>test/unit/predicates/number_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,12 +5,6 @@ class TimePredicateTest &lt; SemanticAttributes::TestCase
     @predicate = Predicates::Time.new(:foo)
   end
 
-  def test_error_message
-    assert_equal 'must be a point in time.', @predicate.error_message
-    @predicate.error_message = 'foo'
-    assert_equal 'foo', @predicate.error_message
-  end
-
   def test_default_validation
     assert !@predicate.validate('2007-07-19 00:00:00', nil), 'value may not be a string, even if string parses'
     assert !@predicate.validate(1184817600, nil), 'value must not be a timestamp'</diff>
      <filename>test/unit/predicates/time_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,6 @@ class UniquePredicateTest &lt; SemanticAttributes::TestCase
   def test_defaults
     assert_equal false, @predicate.case_sensitive, 'case insensitive by default'
     assert_equal [], @predicate.scope, 'default scope is empty array'
-    assert_equal &quot;has already been taken.&quot;, @predicate.error_message
   end
 
   def test_uniqueness_validation_scoping
@@ -56,4 +55,4 @@ class UniquePredicateTest &lt; SemanticAttributes::TestCase
     @predicate.validate(@fred.login, @fred)
     assert_equal &quot;Fred&quot;, @fred.login, &quot;attribute value was not changed by validate()&quot;
   end
-end
\ No newline at end of file
+end</diff>
      <filename>test/unit/predicates/unique_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -83,10 +83,4 @@ class UrlPredicateTest &lt; SemanticAttributes::TestCase
     assert_equal 'example.com', @predicate.normalize('example.com')
     assert_equal 'example.com:80', @predicate.normalize('example.com:80')
   end
-
-  def test_error_message
-    assert_equal 'must be a valid URL.', @predicate.error_message
-    @predicate.error_message = 'foo  bar'
-    assert_equal 'foo  bar', @predicate.error_message
-  end
-end
\ No newline at end of file
+end</diff>
      <filename>test/unit/predicates/url_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,7 @@ class UsaStatePredicateTest &lt; SemanticAttributes::TestCase
 
   def test_with_territories
     @predicate.with_territories = true
-    assert_equal 'must be a US state or territory.', @predicate.error_message
+    assert_equal :us_state_or_territory, @predicate.error_message
 
     assert @predicate.options.include?('Guam')
     assert @predicate.options.include?('Minnesota')
@@ -19,7 +19,7 @@ class UsaStatePredicateTest &lt; SemanticAttributes::TestCase
 
   def test_without_territories
     @predicate.with_territories = false
-    assert_equal 'must be a US state.', @predicate.error_message
+    assert_equal :us_state, @predicate.error_message
 
     assert !@predicate.options.include?('Guam')
     assert @predicate.options.include?('Minnesota')</diff>
      <filename>test/unit/predicates/usa_state_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -38,6 +38,5 @@ class UsaZipCodePredicateTest &lt; SemanticAttributes::TestCase
 
   def test_defaults
     assert !@predicate.extended
-    assert_equal 'must be a US zip code.', @predicate.error_message
   end
-end
\ No newline at end of file
+end</diff>
      <filename>test/unit/predicates/usa_zip_code_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,12 +18,6 @@ class ValidationsTest &lt; SemanticAttributes::TestCase
     assert_equal 'is required.', @record.errors[:login]
   end
 
-  def test_that_errors_are_localized
-    @record.expects(:_).returns(&quot;translated!&quot;)
-    @record.valid?
-    assert_equal &quot;translated!&quot;, @record.errors[:login]
-  end
-
   def test_validate_on_default
     assert_equal :both, @record.semantic_attributes['login'].get('required').validate_on
   end
@@ -124,4 +118,4 @@ class ValidationsTest &lt; SemanticAttributes::TestCase
       assert @record.errors.on(:login)
     end
   end
-end
\ No newline at end of file
+end</diff>
      <filename>test/unit/validations_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>7544ae92006f36be86354b35277314ac8e2bcf27</id>
    </parent>
  </parents>
  <author>
    <name>Lance Ivy</name>
    <email>lance@cainlevy.net</email>
  </author>
  <url>http://github.com/cainlevy/semantic-attributes/commit/c235618b92e845de6b45f809c817e8ec1d2d8677</url>
  <id>c235618b92e845de6b45f809c817e8ec1d2d8677</id>
  <committed-date>2009-02-23T22:57:15-08:00</committed-date>
  <authored-date>2009-02-23T22:57:15-08:00</authored-date>
  <message>using Rails' I18n.translate() backend for semantic attribute error messages. attempting to mimic activerecord's message names where possible.</message>
  <tree>2a2072667eba9435ade70ae16740d32371da8e09</tree>
  <committer>
    <name>Lance Ivy</name>
    <email>lance@cainlevy.net</email>
  </committer>
</commit>
