<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -315,31 +315,28 @@ private
           save_name = Cabar::Plugin.default_name = name
 
           # Observe when plugins are installed.
-          main.plugin_manager.add_observer(self, :plugin_installed, :plugin_installed!)
+          plugin_manager.add_observer(self, :plugin_installed, :plugin_installed!)
 
           plugin.each do | file |
             next unless file
 
             file = Cabar.path_expand(file, directory)
 
-            _logger.debug do
-              &quot;    loading plugin #{file.inspect}&quot;
-            end
-
-            require file
-
-            _logger.debug do
-              &quot;    loading plugin #{file.inspect}: DONE&quot;
-            end
+            plugin_manager.load_plugin! file
           end
         ensure
           Cabar::Plugin.default_name = save_name
-          main.plugin_manager.delete_observer(self, :plugin_installed)
+          plugin_manager.delete_observer(self, :plugin_installed)
         end
       end
     end
 
 
+    def plugin_manager
+      main.plugin_manager
+    end
+
+
     # Observer callback for newly installed plugins.
     def plugin_installed! plugin_manager, plugin
       _logger.debug do</diff>
      <filename>lib/ruby/cabar/loader.rb</filename>
    </modified>
    <modified>
      <diff>@@ -64,7 +64,8 @@ module Cabar
       @commands = [ ]
       super
 
-      @file = $1 if /^(.*):\d+:in / === @file
+      @file = $1 if /^(.*):\d+/ === @file
+      # $stderr.puts &quot;Plugin file #{@file.inspect}&quot;
 
       @name ||= @@default_name
       raise ArgumentError, &quot;Component in #{@file} does not have a name&quot; unless @name
@@ -141,6 +142,7 @@ module Cabar
       def initialize *args
         @plugins = [ ]
         @plugin_by_name = { }
+        @plugin_by_file = { }
         super
       end
 
@@ -151,7 +153,24 @@ module Cabar
       end
 
 
+      def load_plugin! file
+        file += &quot;.rb&quot; unless /\.rb$/ === file
+        file = File.expand_path(file)
+        return :already if @plugin_by_file[file]
+
+        @plugin_by_file[file] = [ ]
+        _logger.info { &quot;plugin: loading plugin #{file.inspect}&quot; }
+        require file
+        _logger.info { &quot;plugin: loading plugin #{file.inspect}: DONE&quot; }
+        self
+      end
+
+
       def register_plugin! plugin
+        unless @plugin_by_file[plugin.file]
+          raise Error, &quot;Plugin not loaded via Plugin::Manager#load_plugin!&quot;
+        end
+
         # Overlay configuration options.
         config_opts = main.configuration.config['plugin']
         config_opts &amp;&amp;= config_opts[plugin.name]
@@ -186,6 +205,7 @@ module Cabar
         plugin.manager = self
         @plugins &lt;&lt; plugin
         @plugin_by_name[name] = plugin
+        @plugin_by_file[plugin.file] &lt;&lt; plugin
 
         notify_observers(:plugin_installed, plugin)
         
@@ -210,6 +230,7 @@ module Cabar
       # The default documentation.
       attr_accessor :default_doc
 
+
       def initialize *args, &amp;blk
         @target = nil
         @target_stack = [ ]
@@ -224,6 +245,18 @@ module Cabar
         @_logger ||=
           @plugin._logger
       end
+      
+
+      # Returns the Plugin Manager.
+      def manager
+        @plugin.manager
+      end
+
+
+      # Returns the current Main objects.
+      def main
+        Cabar::Main.current
+      end
 
 
       # Define :documentation for the next item.</diff>
      <filename>lib/ruby/cabar/plugin.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,13 +13,12 @@ DOC
   $:.map { | dir | Dir[&quot;#{dir}/cabar/plugin/*.rb&quot;] }.
     flatten.
     reject { | fn | fn == __FILE__ }.
-    map { | fn | %r{/(cabar/plugin/[a-z0-9_-]+)\.rb$}i =~ fn ? $1 : nil }.
     compact.
     sort.
     uniq.
     each do | n |
       # $stderr.puts &quot;loading #{n}&quot;
-      require n
+      manager.load_plugin! n
     end
 
   doc &quot;Internals and introspection.&quot;</diff>
      <filename>lib/ruby/cabar/plugin/cabar.rb</filename>
    </modified>
    <modified>
      <diff>@@ -86,33 +86,61 @@ module Cabar
 
 
       def match_output generated, expected
+
+        if Array === expected and (Regexp === expected[0] or String === expected[0])
+          g = generated
+          expected.each do | e |
+            case e
+            when String
+              e.split(&quot;\n&quot;).each do | e |
+                e_rx = match_output_rx(e, :eol)
+                unless e_rx === g
+                  $stderr.puts &quot;expected:\n#{e}\n----&quot;
+                  case e
+                  when /^([a-z0-9_]+=)/i
+                    g_rx = /^(#{$1}.*)^/
+                    # $stderr.puts &quot;g_rx = #{g_rx.inspect}&quot;
+                    
+                    $stderr.puts &quot;generated:\n#{g_rx === g ? $1 : generated}\n----&quot;
+                  else
+                    $stderr.puts &quot;generated:\n#{generated}\n----&quot;
+                  end
+                end
+                g.should match(e_rx)
+              end
+            when Regexp
+              g.should match(e)
+            end
+          end
+        else
 #        require 'rubygems'
 #        gem 'diff-lcs'
 #        require 'diff-lcs'
 
-        e = match_output_rx expected
-        g = generated
-        g = g.gsub(/(:|&quot;)test\/ruby:/) { $1 }
-
-        unless e === g
-          e = expected.split(&quot;\n&quot;)
-          g = generated.split(&quot;\n&quot;)
-          e.zip(g) do | (el, gl) |
-            el_rx = match_output_rx el, :eol
-            unless el_rx === gl
-              $stderr.puts &quot;- #{el_rx.inspect}&quot;
-              $stderr.puts &quot;+  #{gl.inspect}&quot;
+          e = match_output_rx expected
+          g = generated
+          g = g.gsub(/(:|&quot;)test\/ruby:/) { $1 }
+          
+          unless e === g
+            e = expected.split(&quot;\n&quot;)
+            g = generated.split(&quot;\n&quot;)
+            e.zip(g) do | (el, gl) |
+              el_rx = match_output_rx el, :eol
+              unless el_rx === gl
+                $stderr.puts &quot;- #{el_rx.inspect}&quot;
+                $stderr.puts &quot;+  #{gl.inspect}&quot;
+              end
             end
           end
+          
+          g.should match(e)
         end
-
-        g.should match(e)
-
       rescue Exception =&gt; err
         $stderr.puts &quot;generated:\n#{generated}\n----&quot;
         raise err.class.new(err.message + &quot;\n#{err.backtrace * &quot;\n&quot;}&quot;)
       end
 
+
       def match_output_rx expected, eol = false
         e = expected.gsub('&lt;&lt;CABAR_BASE_DIR&gt;&gt;', Cabar::CABAR_BASE_DIR)
         e = Regexp.escape(e)</diff>
      <filename>lib/ruby/cabar/test/main_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,9 +6,10 @@ describe 'cbr env' do
 
   it 'cbr env # no args' do
     example_main(:args =&gt; 'env', 
-                 :match_stdout =&gt; &lt;&lt;'EOF')
+                 :match_stdout =&gt; [ 
+&lt;&lt;&quot;EOF&quot;
 CABAR_TOP_LEVEL_COMPONENTS=&quot;boc&quot;; export CABAR_TOP_LEVEL_COMPONENTS;
-CABAR_REQUIRED_COMPONENTS=&quot;boc todo c1 boc_customer gems c3 c2 boc_locale boc_config rubygems cabar ruby&quot;; export CABAR_REQUIRED_COMPONENTS;
+CABAR_REQUIRED_COMPONENTS=&quot;boc todo c1 boc_customer gems c3 c2 boc_locale boc_config rubygems cabar ruby derby cabar_core&quot;; export CABAR_REQUIRED_COMPONENTS;
 CABAR_boc_NAME=&quot;boc&quot;; export CABAR_boc_NAME;
 CABAR_boc_VERSION=&quot;1.1&quot;; export CABAR_boc_VERSION;
 CABAR_boc_DIRECTORY=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc&quot;; export CABAR_boc_DIRECTORY;
@@ -81,7 +82,7 @@ CABAR_ruby_NAME=&quot;ruby&quot;; export CABAR_ruby_NAME;
 CABAR_ruby_VERSION=&quot;&lt;&lt;ANY&gt;&gt;&quot;; export CABAR_ruby_VERSION;
 CABAR_ruby_DIRECTORY=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/ruby/std&quot;; export CABAR_ruby_DIRECTORY;
 CABAR_ruby_BASE_DIRECTORY=&quot;/usr&quot;; export CABAR_ruby_BASE_DIRECTORY;
-CABAR_ruby_RUBYLIB=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/lib/ruby:&lt;&lt;ANY&gt;&gt;:.&quot;; export CABAR_ruby_RUBYLIB;
+CABAR_ruby_RUBYLIB=&quot;&lt;&lt;ANY&gt;&gt;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/lib/ruby:&lt;&lt;ANY&gt;&gt;:.&quot;; export CABAR_ruby_RUBYLIB;
 CABAR_ruby_PATH=&quot;/usr/bin&quot;; export CABAR_ruby_PATH;
 CABAR_ENV_PERL5LIB=&quot;&lt;&lt;ANY&gt;&gt;&quot;; export CABAR_ENV_PERL5LIB;
 PERL5LIB=&quot;&lt;&lt;ANY&gt;&gt;&quot;; export PERL5LIB;
@@ -93,10 +94,11 @@ CABAR_ENV_BOC_LOCALE_PATH=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_customer/1.2
 BOC_LOCALE_PATH=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_customer/1.2/locale&quot;; export BOC_LOCALE_PATH;
 CABAR_ENV_INCLUDE_PATH=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/c3/include&quot;; export CABAR_ENV_INCLUDE_PATH;
 INCLUDE_PATH=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/c3/include&quot;; export INCLUDE_PATH;
-CABAR_ENV_RUBYLIB=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_customer/1.2/lib:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c2/1.2/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_locale/1.1/lib:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/lib:test/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/lib/ruby:&lt;&lt;ANY&gt;&gt;:.&quot;; export CABAR_ENV_RUBYLIB;
-RUBYLIB=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_customer/1.2/lib:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c2/1.2/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_locale/1.1/lib:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/lib:test/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/lib/ruby:&lt;&lt;ANY&gt;&gt;:.&quot;; export RUBYLIB;
-CABAR_ENV_CABAR_RAKE_FILE=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc/Rakefile!boc:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/Rakefile!c1:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/Rakefile!boc_config:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/Rakefile!cabar&quot;; export CABAR_ENV_CABAR_RAKE_FILE;
-CABAR_RAKE_FILE=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc/Rakefile!boc:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/Rakefile!c1:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/Rakefile!boc_config:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/Rakefile!cabar&quot;; export CABAR_RAKE_FILE;
+CABAR_ENV_RUBYLIB=&quot;&lt;&lt;ANY&gt;&gt;:.&quot;; export CABAR_ENV_RUBYLIB;
+RUBYLIB=&quot;test/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_customer/1.2/lib:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c2/1.2/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_locale/1.1/lib:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/lib:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/derby/1.0/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/cabar_core/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/lib/ruby:&lt;&lt;ANY&gt;&gt;:.&quot;; export RUBYLIB;
+RUBYLIB=&quot;test/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_customer/1.2/lib:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c2/1.2/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_locale/1.1/lib:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/lib:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/derby/1.0/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/cabar_core/lib/ruby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/lib/ruby:&lt;&lt;ANY&gt;&gt;:.&quot;; export RUBYLIB;
+CABAR_ENV_CABAR_RAKE_FILE=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc/Rakefile!boc:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/Rakefile!c1:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/Rakefile!boc_config:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/Rakefile!cabar:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/derby/1.0/Rakefile!derby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc/Rakefile!boc!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/Rakefile!c1!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/Rakefile!boc_config!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/Rakefile!cabar!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/derby/1.0/Rakefile!derby!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc/Rakefile!boc!!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/Rakefile!c1!!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/Rakefile!boc_config!!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/Rakefile!cabar!!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/derby/1.0/Rakefile!derby!!&quot;; export CABAR_ENV_CABAR_RAKE_FILE;
+CABAR_RAKE_FILE=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc/Rakefile!boc:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/Rakefile!c1:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/Rakefile!boc_config:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/Rakefile!cabar:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/derby/1.0/Rakefile!derby:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc/Rakefile!boc!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/Rakefile!c1!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/Rakefile!boc_config!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/Rakefile!cabar!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/derby/1.0/Rakefile!derby!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc/Rakefile!boc!!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/Rakefile!c1!!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/boc_config/1.0/Rakefile!boc_config!!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/Rakefile!cabar!!:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/comp/derby/1.0/Rakefile!derby!!&quot;; export CABAR_RAKE_FILE;
 CABAR_ENV_PATH=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc/bin:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/bin:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/c3/bin:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c2/1.2/bin:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/bin:&lt;&lt;ANY&gt;&gt;&quot;; export CABAR_ENV_PATH;
 PATH=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/boc/bin:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c1/bin:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/prod/c3/bin:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/dev/c2/1.2/bin:&lt;&lt;CABAR_BASE_DIR&gt;&gt;/bin:&lt;&lt;ANY&gt;&gt;&quot;; export PATH;
 CABAR_ENV_GEM_PATH=&quot;&lt;&lt;CABAR_BASE_DIR&gt;&gt;/example/repo/plat/gems/1.0/gems-&lt;&lt;ANY&gt;&gt;&quot;; export CABAR_ENV_GEM_PATH;
@@ -108,6 +110,8 @@ TEST2=&quot;test2&quot;; export TEST2;
 unset CABAR_ENV_TEST3;
 unset TEST3;
 EOF
+]
+)
   end
 
 </diff>
      <filename>test/ruby/cabar/env.spec</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>b7067d25fb8f7b84d9993ff05d689cf16187bcb4</id>
    </parent>
  </parents>
  <author>
    <name>Kurt Stephens</name>
    <login>kstephens</login>
    <email>ks.github@kurtstephens.com</email>
  </author>
  <url>http://github.com/kstephens/cabar/commit/163c85450faa16e6abec24df49c64931dcb44fb1</url>
  <id>163c85450faa16e6abec24df49c64931dcb44fb1</id>
  <committed-date>2009-06-30T10:37:21-07:00</committed-date>
  <authored-date>2009-06-30T10:37:21-07:00</authored-date>
  <message>Use Plugin::Manager#load_plugin!; Fixed env.spec.</message>
  <tree>2f58a5cecd844af6a39ac563df32efcda3a459d5</tree>
  <committer>
    <name>Kurt Stephens</name>
    <login>kstephens</login>
    <email>ks.github@kurtstephens.com</email>
  </committer>
</commit>
