<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -97,8 +97,6 @@ class Merb::Controller &lt; Merb::AbstractController
     params
   end
 
-  private
-
   # All methods that are callable as actions.
   #
   # ==== Returns</diff>
      <filename>lib/merb-core/controller/merb_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,16 @@
 # Merb::Logger = Extlib::Logger
 
+class Merb::Logger &lt; Extlib::Logger
+  def verbose!(message, level = :warn)
+    send(&quot;#{level}!&quot;, message) if Merb::Config[:verbose]
+  end
+
+  def verbose(message, level = :warn)
+    send(level, message) if Merb::Config[:verbose]
+  end
+end
+
+# require &quot;time&quot; # httpdate
 # ==== Public Merb Logger API
 #
 # To replace an existing logger with a new one:
@@ -34,37 +45,168 @@
 #   Merb::Logger.new(log{String, IO},level{Symbol, String})
 module Merb
 
-  class Logger &lt; Extlib::Logger
+  class Logger
+
+    attr_accessor :level
+    attr_accessor :delimiter
+    attr_accessor :auto_flush
+    attr_reader   :buffer
+    attr_reader   :log
+    attr_reader   :init_args
+
+    # ==== Notes
+    # Ruby (standard) logger levels:
+    # :fatal:: An unhandleable error that results in a program crash
+    # :error:: A handleable error condition
+    # :warn:: A warning
+    # :info:: generic (useful) information about system operation
+    # :debug:: low-level information for developers
+    Levels = Mash.new({
+      :fatal =&gt; 7,
+      :error =&gt; 6,
+      :warn  =&gt; 4,
+      :info  =&gt; 3,
+      :debug =&gt; 0
+    }) unless const_defined?(:Levels)
+
+    @@mutex = {}
 
-    # Appends a message to the log if the specified log level is at least as high as
-    # the log level of the logger if Merb::Config[:verbose]. Then flushes the log 
-    # buffer to disk.
+    private
+
+    # Readies a log for writing.
     #
     # ==== Parameters
-    # message&lt;String&gt;:: The message to be logged.
-    # level&lt;Symbol&gt;:: The level at which to log. Default is :warn.
+    # log&lt;IO, String&gt;:: Either an IO object or a name of a logfile.
+    def initialize_log(log)
+      close if @log # be sure that we don't leave open files laying around.
+
+      if log.respond_to?(:write)
+        @log = log
+      elsif File.exist?(log)
+        @log = open(log, (File::WRONLY | File::APPEND))
+        @log.sync = true
+      else
+        FileUtils.mkdir_p(File.dirname(log)) unless File.directory?(File.dirname(log))
+        @log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
+        @log.sync = true
+        @log.write(&quot;#{Time.now.httpdate} #{delimiter} info #{delimiter} Logfile created\n&quot;)
+      end
+    end
+
+    public
+
+    # To initialize the logger you create a new object, proxies to set_log.
     #
-    # ==== Returns
-    # self:: The logger object for chaining.
+    # ==== Parameters
+    # *args:: Arguments to create the log from. See set_logs for specifics.
+    def initialize(*args)
+      set_log(*args)
+    end
+
+    # Replaces an existing logger with a new one.
     #
-    # @api plugin
-    def verbose!(message, level = :warn)
-      send(&quot;#{level}!&quot;, message) if Merb::Config[:verbose]
+    # ==== Parameters
+    # log&lt;IO, String&gt;:: Either an IO object or a name of a logfile.
+    # log_level&lt;~to_sym&gt;::
+    #   The log level from, e.g. :fatal or :info. Defaults to :error in the
+    #   production environment and :debug otherwise.
+    # delimiter&lt;String&gt;::
+    #   Delimiter to use between message sections. Defaults to &quot; ~ &quot;.
+    # auto_flush&lt;Boolean&gt;::
+    #   Whether the log should automatically flush after new messages are
+    #   added. Defaults to false.
+    def set_log(stream = Merb::Config[:log_stream],
+      log_level = Merb::Config[:log_level],
+      delimiter = Merb::Config[:log_delimiter],
+      auto_flush = Merb::Config[:log_auto_flush])
+
+      @buffer                   = []
+      @delimiter                = delimiter
+      @auto_flush               = auto_flush
+
+      if Levels[log_level]
+        @level                  = Levels[log_level]
+      else
+        @level                  = log_level
+      end
+
+      @log                      = stream
+      @mutex = (@@mutex[@log] ||= Mutex.new)
+    end
+
+    # Flush the entire buffer to the log object.
+    def flush
+      return unless @buffer.size &gt; 0
+      @mutex.synchronize do
+        @log.write(@buffer.slice!(0..-1).to_s)
+      end
+    end
+
+    # Close and remove the current log object.
+    def close
+      flush
+      @log.close if @log.respond_to?(:close) &amp;&amp; !@log.tty?
+      @log = nil
     end
 
-    # Appends a message to the log if the specified log level is at least as high as
-    # the log level of the logger if Merb::Config[:verbose].
+    # Appends a message to the log. The methods yield to an optional block and
+    # the output of this block will be appended to the message.
     #
     # ==== Parameters
-    # message&lt;String&gt;:: The message to be logged.
-    # level&lt;Symbol&gt;:: The level at which to log. Default is :warn.
+    # string&lt;String&gt;:: The message to be logged. Defaults to nil.
     #
     # ==== Returns
-    # self:: The logger object for chaining.
-    #
-    # @api plugin
-    def verbose(message, level = :warn)
-      send(level, message) if Merb::Config[:verbose]
+    # String:: The resulting message added to the log file.
+    def &lt;&lt;(string = nil)
+      message = &quot;&quot;
+      message &lt;&lt; delimiter
+      message &lt;&lt; string if string
+      message &lt;&lt; &quot;\n&quot; unless message[-1] == ?\n
+      @buffer &lt;&lt; message
+      flush if @auto_flush
+
+      message
+    end
+    alias :push :&lt;&lt;
+
+    # Generate the logging methods for Merb.logger for each log level.
+    Levels.each_pair do |name, number|
+      class_eval &lt;&lt;-LEVELMETHODS, __FILE__, __LINE__
+
+      # Appends a message to the log if the log level is at least as high as
+      # the log level of the logger.
+      #
+      # ==== Parameters
+      # string&lt;String&gt;:: The message to be logged. Defaults to nil.
+      #
+      # ==== Returns
+      # self:: The logger object for chaining.
+      def #{name}(message = nil)
+        self &lt;&lt; message if #{number} &gt;= level
+        self
+      end
+
+      # Appends a message to the log if the log level is at least as high as
+      # the log level of the logger. The bang! version of the method also auto
+      # flushes the log buffer to disk.
+      #
+      # ==== Parameters
+      # string&lt;String&gt;:: The message to be logged. Defaults to nil.
+      #
+      # ==== Returns
+      # self:: The logger object for chaining.
+      def #{name}!(message = nil)
+        self &lt;&lt; message if #{number} &gt;= level
+        flush if #{number} &gt;= level
+        self
+      end
+
+      # ==== Returns
+      # Boolean:: True if this level will be logged by this logger.
+      def #{name}?
+        #{number} &gt;= level
+      end
+      LEVELMETHODS
     end
 
   end</diff>
      <filename>lib/merb-core/logger.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,14 +21,6 @@ end
 
 describe Merb::Logger do
 
-  describe &quot;Levels&quot; do
-    it &quot;should have the same entries as Extlib::Logger::Levels&quot; do
-      Extlib::Logger::Levels.each do |level, value|
-        Merb::Logger::Levels[level].should == value
-      end
-    end
-  end
-
   describe &quot;#new&quot; do
     it &quot;should call set_log with the arguments it was passed.&quot; do
       logger = Merb::Logger.allocate # create an object sans initialization
@@ -49,12 +41,6 @@ describe Merb::Logger do
       Merb.logger.level.should == 4
     end
 
-    it &quot;should set the log level to a specific numeric value when that value is set into Mer&quot; do
-      Merb::Config[:log_level] = 5
-      Merb.reset_logger!
-      Merb.logger.level.should == 5
-    end
-
     it &quot;should set the log level to :debug (0) when Merb.environment is development&quot; do
       Merb.environment = &quot;development&quot;
       Merb::Config.delete(:log_level)
@@ -294,81 +280,4 @@ describe Merb::Logger do
       Merb.logger.should log_with_method(:fatal)
     end
   end # #fatal
-  
-  describe &quot;#verbose&quot; do
-    before do
-      @stream = Merb::Config[:log_stream] = StringIO.new
-      Merb.reset_logger!
-    end
-    
-    describe &quot;when Merb::Config[:verbose] is false&quot; do
-      it &quot;should not log any messages&quot; do
-        Merb::Config[:verbose] = false
-        Merb::Config[:log_level] = :debug
-        Merb.logger.verbose(&quot;message&quot;, :fatal)
-        Merb.logger.flush
-        
-        Merb.logger.log.string.should_not include(&quot;message&quot;)
-      end
-    end
-    
-    describe &quot;when Merb::Config[:verbose] is true&quot; do
-      before do
-        Merb::Config[:verbose] = true
-        Merb::Config[:log_level] = :debug
-      end
-
-      it &quot;adds to the buffer with error level&quot; do
-        set_level(:error)
-        Merb.logger.verbose(&quot;message&quot;, :error)
-        Merb.logger.flush
-        Merb.logger.log.string.should include(&quot;message&quot;)
-      end
-
-      it &quot;adds to the buffer with fatal level&quot; do
-        set_level(:fatal)
-        Merb.logger.verbose(&quot;message&quot;, :error)
-        Merb.logger.flush
-        Merb.logger.log.string.should_not include(&quot;message&quot;)
-      end
-      
-    end
-  end
-  
-  describe &quot;#verbose!&quot; do
-    before do
-      @stream = Merb::Config[:log_stream] = StringIO.new
-      Merb.reset_logger!
-    end
-    
-    describe &quot;when Merb::Config[:verbose] is false&quot; do
-      it &quot;should not log any messages&quot; do
-        Merb::Config[:verbose] = false
-        Merb::Config[:log_level] = :debug
-        Merb.logger.verbose!(&quot;message&quot;, :fatal)
-        Merb.logger.log.string.should_not include(&quot;message&quot;)
-      end
-    end
-    
-    describe &quot;when Merb::Config[:verbose] is true&quot; do
-      before do
-        Merb::Config[:verbose] = true
-        Merb::Config[:log_level] = :debug
-      end
-
-      it &quot;adds to the buffer with error level&quot; do
-        set_level(:error)
-        Merb.logger.verbose!(&quot;message&quot;, :error)
-        Merb.logger.log.string.should include(&quot;message&quot;)
-      end
-
-      it &quot;adds to the buffer with fatal level&quot; do
-        set_level(:fatal)
-        Merb.logger.verbose!(&quot;message&quot;, :error)
-        Merb.logger.log.string.should_not include(&quot;message&quot;)
-      end
-      
-    end
-  end
-  
 end # Merb::Logger</diff>
      <filename>spec/public/logger/logger_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,7 @@ describe &quot;Recognizing requests for deferred routes&quot; do
     before :each do
       Merb::Router.prepare do      
         match(&quot;/deferred/:zoo&quot;).defer_to do |request, params|
-          route params.merge(:controller =&gt; &quot;w00t&quot;) if params[:zoo]
+          params.merge(:controller =&gt; &quot;w00t&quot;) if params[:zoo]
         end
       end    
     end
@@ -22,7 +22,7 @@ describe &quot;Recognizing requests for deferred routes&quot; do
     it &quot;should return the param hash returned by the block&quot; do
       Merb::Router.prepare do
         match(&quot;/deferred&quot;).defer_to do |request, params|
-          route :hello =&gt; &quot;world&quot;
+          :hello =&gt; &quot;world&quot;
         end
       end
 
@@ -32,7 +32,7 @@ describe &quot;Recognizing requests for deferred routes&quot; do
     it &quot;should accept params&quot; do
       Merb::Router.prepare do
         match(&quot;/&quot;).defer_to(:controller =&gt; &quot;accounts&quot;) do |request, params|
-          route params.update(:action =&gt; &quot;hello&quot;)
+          params.update(:action =&gt; &quot;hello&quot;)
         end
       end
 
@@ -42,7 +42,7 @@ describe &quot;Recognizing requests for deferred routes&quot; do
     it &quot;should be able to define routes after the deferred route&quot; do
       Merb::Router.prepare do
         match(&quot;/deferred&quot;).defer_to do
-          route :hello =&gt; &quot;world&quot;
+          :hello =&gt; &quot;world&quot;
         end
 
         match(&quot;/&quot;).to(:foo =&gt; &quot;bar&quot;)</diff>
      <filename>spec/public/router/recognition/deferred_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>5e4a862e856bd0a5b90deebbf2be3340a8955b6a</id>
    </parent>
    <parent>
      <id>d425060afd09ba313ae5fba3568029106009abf8</id>
    </parent>
  </parents>
  <author>
    <name>Yehuda Katz</name>
    <email>wycats@gmail.com</email>
  </author>
  <url>http://github.com/wycats/merb-core/commit/a7fb18c7f3cf24321ccd8a8e03f6ddafcb6be651</url>
  <id>a7fb18c7f3cf24321ccd8a8e03f6ddafcb6be651</id>
  <committed-date>2008-10-11T00:06:01-07:00</committed-date>
  <authored-date>2008-10-11T00:06:01-07:00</authored-date>
  <message>Merge commit 'adelcambre/sprint' into sprint</message>
  <tree>daf87dba7c130400dbf16edcb8313bc2125537c1</tree>
  <committer>
    <name>Yehuda Katz</name>
    <email>wycats@gmail.com</email>
  </committer>
</commit>
