[DRE-commits] r3862 - in packages-wip/merb/trunk: . debian debian/patches lib merb-assets merb-core merb-core/bin merb-core/debian merb-core/debian/libmerb-core-ruby1.8 merb-core/debian/libmerb-core-ruby1.8/usr merb-core/debian/libmerb-core-ruby1.8/usr/bin merb-core/debian/libmerb-core-ruby1.8/usr/lib merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8 merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/gem_ext merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/handler merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/tasks merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext merb-gen merb-gen/bin merb-haml merb-helpers merb-slices merb-slices/bin patches

Joshua Timberman jtimberman-guest at alioth.debian.org
Thu Jul 30 20:20:09 UTC 2009


Author: jtimberman-guest
Date: 2009-07-30 20:20:09 +0000 (Thu, 30 Jul 2009)
New Revision: 3862

Added:
   packages-wip/merb/trunk/debian/
   packages-wip/merb/trunk/debian/README.Debian
   packages-wip/merb/trunk/debian/changelog
   packages-wip/merb/trunk/debian/compat
   packages-wip/merb/trunk/debian/control
   packages-wip/merb/trunk/debian/copyright
   packages-wip/merb/trunk/debian/dirs
   packages-wip/merb/trunk/debian/docs
   packages-wip/merb/trunk/debian/merb-core.dirs
   packages-wip/merb/trunk/debian/merb-core.manpages
   packages-wip/merb/trunk/debian/merb-slices.dirs
   packages-wip/merb/trunk/debian/merb-slices.manpages
   packages-wip/merb/trunk/debian/merb.1
   packages-wip/merb/trunk/debian/merb.dirs
   packages-wip/merb/trunk/debian/patches/
   packages-wip/merb/trunk/debian/patches/load_dependencies_uses_require
   packages-wip/merb/trunk/debian/patches/series
   packages-wip/merb/trunk/debian/rules
   packages-wip/merb/trunk/debian/slice.1
   packages-wip/merb/trunk/debian/watch
   packages-wip/merb/trunk/lib/
   packages-wip/merb/trunk/lib/merb-more.rb
   packages-wip/merb/trunk/merb-assets/
   packages-wip/merb/trunk/merb-assets/.config
   packages-wip/merb/trunk/merb-assets/InstalledFiles
   packages-wip/merb/trunk/merb-core/.config
   packages-wip/merb/trunk/merb-core/InstalledFiles
   packages-wip/merb/trunk/merb-core/debian/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/bin/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/bin/merb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/autoload.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/bootloader.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/config.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/constants.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/abstract_controller.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/exceptions.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/merb_controller.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mime.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/authentication.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/conditional_get.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/controller.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/render.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/responder.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/template.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/class.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/hash.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/kernel.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/cookies.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/default_exception.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/_css.html.erb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/_javascript.html.erb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/index.html.erb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/dispatcher.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/request.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/request_parsers.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/behavior.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/cached_proc.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/resources.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/route.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/container.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/cookie.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/memcached.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/memory.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/store_container.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/worker.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/gem_ext/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/gem_ext/erubis.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/logger.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/plugins.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/abstract.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/ebb.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/evented_mongrel.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/fcgi.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/irb.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/mongrel.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/runner.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/swiftiplied_mongrel.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/thin.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/thin_turbo.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/webrick.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/application.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/handler/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/handler/mongrel.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/helpers.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/conditional_get.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/content_length.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/path_prefix.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/profiler.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/static.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/tracer.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/stream_wrapper.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/server.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/audit.rake
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/gem_management.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/merb.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/merb_rake_helper.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/stats.rake
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/controller_helper.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/cookie_jar.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/mock_request_helper.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/multipart_request_helper.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/request_helper.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/route_helper.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/controller_matchers.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/request_matchers.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/route_matchers.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/run_spec.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/run_specs.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/tasks/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/tasks/spectasks.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/hpricot.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/object.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/rspec.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/string.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/two-oh.rb
   packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/version.rb
   packages-wip/merb/trunk/merb-gen/.config
   packages-wip/merb/trunk/merb-gen/InstalledFiles
   packages-wip/merb/trunk/merb-haml/
   packages-wip/merb/trunk/merb-haml/.config
   packages-wip/merb/trunk/merb-haml/InstalledFiles
   packages-wip/merb/trunk/merb-helpers/
   packages-wip/merb/trunk/merb-helpers/.config
   packages-wip/merb/trunk/merb-helpers/InstalledFiles
   packages-wip/merb/trunk/merb-slices/.config
   packages-wip/merb/trunk/merb-slices/InstalledFiles
   packages-wip/merb/trunk/patches/
   packages-wip/merb/trunk/patches/load_dependencies_uses_require
Modified:
   packages-wip/merb/trunk/merb-core/bin/merb
   packages-wip/merb/trunk/merb-core/bin/merb-specs
   packages-wip/merb/trunk/merb-gen/bin/merb-gen
   packages-wip/merb/trunk/merb-slices/bin/slice
Log:
[svn-inject] Applying Debian modifications to trunk


Property changes on: packages-wip/merb/trunk/debian
___________________________________________________________________
Added: mergeWithUpstream
   + 1

Added: packages-wip/merb/trunk/debian/README.Debian
===================================================================
--- packages-wip/merb/trunk/debian/README.Debian	                        (rev 0)
+++ packages-wip/merb/trunk/debian/README.Debian	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,18 @@
+merb for Debian
+---------------
+
+The Merb packages provide just enough of Merb to run an existing application
+but not the components required to generate a new application for development.
+
+This package patches merb-core to allow load_dependency to 'require' other 
+libraries, rather than trying to load them with Gem. This resolves ticket
+# 1281, on the Merb ticket system.
+
+  https://merb.lighthouseapp.com/projects/7433-merb/tickets/1281
+
+For more information about the libraries provided, see the RDoc documentation
+in libmerb-ruby-doc. For more information about Merb, visit its homepage at:
+
+  http://www.merbivore.com/
+
+ -- Joshua Timberman <joshua at opscode.com>  Mon, 27 Jul 2009 23:38:37 -0600

Added: packages-wip/merb/trunk/debian/changelog
===================================================================
--- packages-wip/merb/trunk/debian/changelog	                        (rev 0)
+++ packages-wip/merb/trunk/debian/changelog	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,5 @@
+merb (1.0.12-1) unstable; urgency=low
+
+   * Initial release (Closes: #538928)
+
+ -- Joshua Timberman <joshua at opscode.com>  Mon, 27 Jul 2009 23:38:37 -0600

Added: packages-wip/merb/trunk/debian/compat
===================================================================
--- packages-wip/merb/trunk/debian/compat	                        (rev 0)
+++ packages-wip/merb/trunk/debian/compat	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1 @@
+7

Added: packages-wip/merb/trunk/debian/control
===================================================================
--- packages-wip/merb/trunk/debian/control	                        (rev 0)
+++ packages-wip/merb/trunk/debian/control	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,189 @@
+Source: merb
+Section: ruby
+Priority: extra
+Maintainer: Joshua Timberman <joshua at opscode.com>
+Build-Depends: cdbs, debhelper (>= 7), ruby-pkg-tools (>= 0.14), quilt
+Build-Depends-Indep: ruby1.8, rake
+Standards-Version: 3.8.2
+Homepage: http://merbivore.com
+
+Package: merb-core
+Architecture: all
+Depends: ${misc:Depends}, ${shlibs:Depends}, ruby1.8, libmerb-core-ruby1.8
+Suggests: libmerb-ruby-doc
+Description: Lightweight Ruby-based MVC framework for web development
+ Ruby-based MVC framework that is agnostic to ORM, JavaScript library,
+ and template languages. Merb is plugin-based, so the core is small and
+ well organized.
+ .
+ The Merb packages provide just enough to run a basic Merb application.
+ .
+ This package contains the merb binary and associated files.
+
+Package: merb-slices
+Architecture: all
+Depends: ${misc:Depends}, ruby1.8, libmerb-slices-ruby1.8
+Suggests: libmerb-ruby-doc
+Description: Merb plugin to modularize an application by creating 'slices'
+ Usually these slices are reusable extractions from the main application.
+ A module is set up to serve as a namespace for controller, models, helpers,
+ etc.
+ .
+ Installing this package will provide the capability to run a Merb application
+ slice.
+ .
+ This package contains the slice binary and associated files.
+
+Package: libmerb-core-ruby
+Architecture: all
+Depends: ${misc:Depends}, libmerb-core-ruby1.8
+Suggests: libmerb-ruby-doc
+Description: Core libraries for the Merb MVC framework
+ Ruby-based MVC framework that is agnostic to ORM, JavaScript library,
+ and template languages. Merb is plugin-based, so the core is small and
+ well organized.
+ .
+ This package is a dependency package, which depends on the package
+ containing actual Ruby merb-core libraries for the default Ruby version
+ (currently 1.8).
+
+Package: libmerb-core-ruby1.8
+Architecture: all
+Depends: ${misc:Depends}, ruby1.8, libextlib-ruby (>=0.9.8), liberubis-ruby (>=2.6.2), rake, libjson-ruby, librack-ruby, libmime-types-ruby
+Suggests: libmerb-ruby-doc
+Description: Core Ruby 1.8 libraries for the Merb MVC framework
+ Ruby-based MVC framework that is agnostic to ORM, JavaScript library,
+ and template languages. Merb is plugin-based, so the core is small and
+ well organized.
+ .
+ This package provides the core libraries that provide enough of Merb 
+ to run an application.
+ .
+ This package contains merb-core libraries for Ruby 1.8.
+
+Package: libmerb-assets-ruby
+Architecture: all
+Depends: ${misc:Depends}, libmerb-assets-ruby1.8
+Suggests: libmerb-ruby-doc
+Description: Plugin library for Merb that provides helpers for assets
+ Provides extra functionality related to assets:
+  * Assets bundling.
+  * Assets hosts.
+  * Helpers to add asset links to views.
+  * Deployment-time assets processing (for instance, with YUI Compressor).
+ .
+ This package is a dependency package, which depends on the package
+ containing actual Ruby merb-assets libraries for the default Ruby version
+ (currently 1.8).
+
+Package: libmerb-assets-ruby1.8
+Architecture: all
+Depends: ${misc:Depends}, libmerb-core-ruby1.8
+Suggests: libmerb-ruby-doc
+Description: Ruby 1.8 plugin library for Merb that provides helpers for assets
+ Provides extra functionality related to assets:
+  * Assets bundling.
+  * Assets hosts.
+  * Helpers to add asset links to views.
+  * Deployment-time assets processing (for instance, with YUI Compressor).
+ .
+ This package contains the merb-assets libraries for Ruby 1.8.
+
+Package: libmerb-haml-ruby
+Architecture: all
+Depends: ${misc:Depends}, libmerb-haml-ruby1.8
+Suggests: libmerb-ruby-doc, libhaml-ruby-doc
+Description: Plugin library for Merb that provides access to libhaml-ruby
+ Haml (HTML Abstraction Markup Language) is a layer on top of XHTML or 
+ XML that's designed to express the structure of XHTML or XML documents 
+ in a non-repetitive, elegant, easy way, using indentation rather than
+ closing tags and allowing Ruby to be embedded with ease. It was originally
+ envisioned as a plugin for Ruby on Rails, but it can function as a 
+ stand-alone templating engine. 
+ .
+ This package is a dependency package, which depends on the package
+ containing actual Ruby merb-haml libraries for the default Ruby version
+ (currently 1.8).
+
+Package: libmerb-haml-ruby1.8
+Architecture: all
+Depends: ${misc:Depends}, libmerb-core-ruby1.8, libhaml-ruby1.8
+Suggests: libmerb-ruby-doc, libhaml-ruby-doc
+Description: Ruby 1.8 library for Merb that provides access to libhaml-ruby
+ Haml (HTML Abstraction Markup Language) is a layer on top of XHTML or 
+ XML that's designed to express the structure of XHTML or XML documents 
+ in a non-repetitive, elegant, easy way, using indentation rather than
+ closing tags and allowing Ruby to be embedded with ease. It was originally
+ envisioned as a plugin for Ruby on Rails, but it can function as a 
+ stand-alone templating engine. 
+ .
+ This package contains the merb-haml libraries for Ruby 1.8.
+
+Package: libmerb-helpers-ruby
+Architecture: all
+Depends: ${misc:Depends}, libmerb-helpers-ruby1.8
+Suggests: libmerb-ruby-doc
+Description: Plugin library for Merb that provides view helpers
+ This plugin provides the following helpers for your views:
+  * form_helpers
+  * date_time_helpers
+  * tag_helpers
+  * text_helpers
+ See the RDOC documentation and the package README for more information.
+ .
+ This package is a dependency package, which depends on the package
+ containing actual Ruby merb-helpers libraries for the default Ruby version
+ (currently 1.8).
+
+Package: libmerb-helpers-ruby1.8
+Architecture: all
+Depends: ${misc:Depends}, libmerb-core-ruby1.8
+Suggests: libmerb-ruby-doc
+Description: Ruby 1.8 library for Merb that provides view helpers
+ This plugin provides the following helpers for your views:
+  * form_helpers
+  * date_time_helpers
+  * tag_helpers
+  * text_helpers
+ See the RDOC documentation and the package README for more information.
+ .
+ This package contains the merb-helpers libraries for Ruby 1.8.
+
+Package: libmerb-slices-ruby
+Architecture: all
+Depends: ${misc:Depends}, libmerb-slices-ruby1.8
+Suggests: libmerb-ruby-doc
+Description: Library to support merb-slices application modularization
+ Usually these slices are reusable extractions from the main application.
+ A module is set up to serve as a namespace for controller, models, helpers,
+ etc.
+ .
+ This package is a dependency package, which depends on the package
+ containing actual Ruby merb-slices libraries for the default Ruby version
+ (currently 1.8).
+
+Package: libmerb-slices-ruby1.8
+Architecture: all
+Depends: ${misc:Depends}, libmerb-core-ruby1.8
+Suggests: libmerb-ruby-doc
+Description: Ruby 1.8 library to support merb-slices application modularization
+ Usually these slices are reusable extractions from the main application.
+ A module is set up to serve as a namespace for controller, models, helpers,
+ etc.
+ .
+ Installing this package will provide the capability to run a Merb application
+ slice.
+ .
+ This package contains the merb-slices libraries for Ruby 1.8.
+
+Package: libmerb-ruby-doc
+Section: doc
+Architecture: all
+Depends: ${misc:Depends}
+Suggests: ruby1.8
+Description: Documentation for Merb
+ Ruby-based MVC framework that is agnostic to ORM, JavaScript library,
+ and template languages. Merb is plugin-based, so the core is small and
+ well organized.
+ .
+ This package provides generated HTML documentation (rdoc) for Merb.

Added: packages-wip/merb/trunk/debian/copyright
===================================================================
--- packages-wip/merb/trunk/debian/copyright	                        (rev 0)
+++ packages-wip/merb/trunk/debian/copyright	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,28 @@
+This package was debianized by Joshua Timberman <joshua at opscode.com> on
+Mon, 27 Jul 2009 23:38:37 -0600.
+
+It was downloaded from <http://github.com/wycats/merb>
+
+Upstream Authors: Yehuda Katz <ykatz at engineyard.com>
+
+Copyright (c) 2008 Engine Yard Inc.
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+    
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+    
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+

Added: packages-wip/merb/trunk/debian/dirs
===================================================================
--- packages-wip/merb/trunk/debian/dirs	                        (rev 0)
+++ packages-wip/merb/trunk/debian/dirs	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1 @@
+usr/bin

Added: packages-wip/merb/trunk/debian/docs
===================================================================
--- packages-wip/merb/trunk/debian/docs	                        (rev 0)
+++ packages-wip/merb/trunk/debian/docs	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,2 @@
+README
+TODO

Added: packages-wip/merb/trunk/debian/merb-core.dirs
===================================================================
--- packages-wip/merb/trunk/debian/merb-core.dirs	                        (rev 0)
+++ packages-wip/merb/trunk/debian/merb-core.dirs	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1 @@
+usr/bin

Added: packages-wip/merb/trunk/debian/merb-core.manpages
===================================================================
--- packages-wip/merb/trunk/debian/merb-core.manpages	                        (rev 0)
+++ packages-wip/merb/trunk/debian/merb-core.manpages	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1 @@
+debian/merb.1

Added: packages-wip/merb/trunk/debian/merb-slices.dirs
===================================================================
--- packages-wip/merb/trunk/debian/merb-slices.dirs	                        (rev 0)
+++ packages-wip/merb/trunk/debian/merb-slices.dirs	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1 @@
+usr/bin

Added: packages-wip/merb/trunk/debian/merb-slices.manpages
===================================================================
--- packages-wip/merb/trunk/debian/merb-slices.manpages	                        (rev 0)
+++ packages-wip/merb/trunk/debian/merb-slices.manpages	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1 @@
+debian/slice.1

Added: packages-wip/merb/trunk/debian/merb.1
===================================================================
--- packages-wip/merb/trunk/debian/merb.1	                        (rev 0)
+++ packages-wip/merb/trunk/debian/merb.1	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,104 @@
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
+.TH MERB "1" "July 2009" "merb 1.0.12" "User Commands"
+.SH NAME
+merb \- Start a merb application.
+.SH SYNOPSIS
+.B merb
+[\fIuGdcIpPhmailLerkKX\fR] [\fIargument\fR]
+.SH DESCRIPTION
+If no flags are given, Merb starts in the foreground on port 4000.
+.TP
+\fB\-u\fR, \fB\-\-user\fR USER
+This flag is for having merb run as a user other than the one currently logged in. Note: if you set this you must also provide a \fB\-\-group\fR option for it to take effect.
+.TP
+\fB\-G\fR, \fB\-\-group\fR GROUP
+This flag is for having merb run as a group other than the one currently logged in. Note: if you set this you must also provide a \fB\-\-user\fR option for it to take effect.
+.TP
+\fB\-d\fR, \fB\-\-daemonize\fR
+This will run a single merb in the background.
+.TP
+\fB\-N\fR, \fB\-\-no\-daemonize\fR
+This will allow you to run a cluster in console mode
+.TP
+\fB\-c\fR, \fB\-\-cluster\-nodes\fR NUM_MERBS
+Number of merb daemons to run.
+.TP
+\fB\-I\fR, \fB\-\-init\-file\fR FILE
+File to use for initialization on load, defaults to config/init.rb
+.TP
+\fB\-p\fR, \fB\-\-port\fR PORTNUM
+Port to run merb on, defaults to 4000.
+.TP
+\fB\-o\fR, \fB\-\-socket\-file\fR FILE
+Socket file to run merb on, defaults to [Merb.root]/log/merb.sock. This is for web servers, like thin, that use sockets.Specify this *only* if you *must*.
+.TP
+\fB\-s\fR, \fB\-\-socket\fR SOCKNUM
+Socket number to run merb on, defaults to 0.
+.TP
+\fB\-n\fR, \fB\-\-name\fR NAME
+Set the name of the application. This is used in the process title and log file names.
+.TP
+\fB\-P\fR, \fB\-\-pid\fR PIDFILE
+PID file, defaults to [Merb.root]/log/merb.main.pid for the master process and[Merb.root]/log/merb.[port number].pid for worker processes. For clusters, use %s to specify where in the file merb should place the port number. For instance: \fB\-P\fR myapp.%s.pid
+.TP
+\fB\-h\fR, \fB\-\-host\fR HOSTNAME
+Host to bind to (default is 0.0.0.0).
+.HP
+\fB\-m\fR, \fB\-\-merb\-root\fR /path/to/approot The path to the Merb.root for the app you want to run (default is current working directory).
+.TP
+\fB\-a\fR, \fB\-\-adapter\fR ADAPTER
+The rack adapter to use to run merb (default is mongrel)[mongrel, emongrel, thin, ebb, fastcgi, webrick]
+.TP
+\fB\-R\fR, \fB\-\-rackup\fR FILE
+Load an alternate Rack config file (default is config/rack.rb)
+.TP
+\fB\-i\fR, \fB\-\-irb\-console\fR
+This flag will start merb in irb console mode. All your models and other classes will be available for you in an irb session.
+.TP
+\fB\-S\fR, \fB\-\-sandbox\fR
+This flag will enable a sandboxed irb console. If your ORM supports transactions, all edits will be rolled back on exit.
+.TP
+\fB\-l\fR, \fB\-\-log\-level\fR LEVEL
+Log levels can be set to any of these options: debug < info < warn < error < fatal (default is info)
+.TP
+\fB\-L\fR, \fB\-\-log\fR LOGFILE
+A string representing the logfile to use. Defaults to [Merb.root]/log/merb.[main].log for the master process and [Merb.root]/log/merb[port number].logfor worker processes
+.TP
+\fB\-e\fR, \fB\-\-environment\fR STRING
+Environment to run Merb under [development, production, testing] (default is development)
+.HP
+\fB\-r\fR ['RUBY CODE'| FULL_SCRIPT_PATH]
+.TP
+\fB\-\-script\-runner\fR
+Command\-line option to run scripts and/or code in the merb app.
+.TP
+\fB\-K\fR, \fB\-\-graceful\fR PORT or all
+Gracefully kill one merb proceses by port number.  Use merb \fB\-K\fR all to gracefully kill all merbs.
+.TP
+\fB\-k\fR, \fB\-\-kill\fR PORT
+Force kill one merb worker by port number. This will cause the worker tobe respawned.
+.TP
+\fB\-\-fast\-deploy\fR
+Reload the code, but not yourinit.rb or gems
+.TP
+\fB\-X\fR, \fB\-\-mutex\fR on/off
+This flag is for turning the mutex lock on and off.
+.TP
+\fB\-D\fR, \fB\-\-debugger\fR
+Run merb using rDebug.
+.TP
+\fB\-V\fR, \fB\-\-verbose\fR
+Print extra information
+.TP
+\fB\-C\fR, \fB\-\-console\-trap\fR
+Enter an irb console on ^C
+.TP
+\-?, \fB\-H\fR, \fB\-\-help\fR
+Show this help message
+.SH "SEE ALSO"
+Full documentation for merb is available after the Merb packages are installed.
+For getting started instructions, see /usr/share/doc/merb/README.Debian.
+.SH AUTHOR
+The upstream author of Merb is Yehuda Katz <ykatz at engineyard.com>. 
+This manual page was written by Joshua Timberman <joshua at opscode.com> with help2man
+for the Debian project (but may be used by others).

Added: packages-wip/merb/trunk/debian/merb.dirs
===================================================================
--- packages-wip/merb/trunk/debian/merb.dirs	                        (rev 0)
+++ packages-wip/merb/trunk/debian/merb.dirs	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1 @@
+usr/bin

Added: packages-wip/merb/trunk/debian/patches/load_dependencies_uses_require
===================================================================
--- packages-wip/merb/trunk/debian/patches/load_dependencies_uses_require	                        (rev 0)
+++ packages-wip/merb/trunk/debian/patches/load_dependencies_uses_require	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,26 @@
+# Merb's dependency method, which calls load_dependency needs to have
+# a fallback to simply use require if a gem is not found.
+Index: merb-1.0.12/merb-core/lib/merb-core/core_ext/kernel.rb
+===================================================================
+--- merb-1.0.12.orig/merb-core/lib/merb-core/core_ext/kernel.rb	2009-07-29 16:20:14.000000000 -0600
++++ merb-1.0.12/merb-core/lib/merb-core/core_ext/kernel.rb	2009-07-29 16:20:51.000000000 -0600
+@@ -141,8 +141,17 @@
+       return unless dep.require_as
+       Gem.activate(dep)
+     rescue Gem::LoadError => e
+-      e.set_backtrace dep.original_caller
+-      Merb.fatal! "The gem #{name}, #{ver.inspect} was not found", e
++      begin
++        Merb.logger.debug "Falling back to a regular require"
++        if name.kind_of?(Gem::Dependency)
++          require name.name
++        else
++          require name
++        end 
++      rescue LoadError => le
++        e.set_backtrace dep.original_caller
++        Merb.fatal! "The gem #{name}, #{ver.inspect} was not found and we could not require it"
++      end 
+     end
+   
+     begin

Added: packages-wip/merb/trunk/debian/patches/series
===================================================================
--- packages-wip/merb/trunk/debian/patches/series	                        (rev 0)
+++ packages-wip/merb/trunk/debian/patches/series	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1 @@
+load_dependencies_uses_require

Added: packages-wip/merb/trunk/debian/rules
===================================================================
--- packages-wip/merb/trunk/debian/rules	                        (rev 0)
+++ packages-wip/merb/trunk/debian/rules	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,172 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/rules/patchsys-quilt.mk
+include /usr/share/ruby-pkg-tools/1/class/ruby-common.mk
+
+CDBS_NO_DOC_SYMLINKING = ""
+
+PACKAGED_RUBY_SETUP_CMD = /usr/lib/ruby/1.8/setup.rb
+DEB_RUBY_SETUP_CMD = debian-setup.rb
+DEB_RUBY_CONFIG_ARGS = --installdirs=std
+
+# command to install symlink to packaged setup.rb: used in both build and clean
+# targets
+DEB_RUBY_INSTALL_SETUP_CMD = \
+  if [ ! -L $(DEB_RUBY_SETUP_CMD) ] ; then \
+    if [ -f $(DEB_RUBY_SETUP_CMD) ] ; then \
+      mv $(DEB_RUBY_SETUP_CMD) $(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ;\
+    fi ; \
+    ln -s $(PACKAGED_RUBY_SETUP_CMD) $(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+DEB_RUBY_REMOVE_SETUP_CMD = \
+  if [ -L $(DEB_RUBY_SETUP_CMD) ] ; then \
+    rm $(DEB_RUBY_SETUP_CMD) ; \
+  fi ; \
+  if [ -f $(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ] ; then \
+    mv $(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build $(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+MERB_CORE_INSTALL_SETUP_CMD = \
+  if [ ! -L merb-core/$(DEB_RUBY_SETUP_CMD) ] ; then \
+    if [ -f merb-core/$(DEB_RUBY_SETUP_CMD) ] ; then \
+      mv merb-core/$(DEB_RUBY_SETUP_CMD) merb-core/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ;\
+    fi ; \
+    ln -s $(PACKAGED_RUBY_SETUP_CMD) merb-core/$(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+MERB_CORE_REMOVE_SETUP_CMD = \
+  if [ -L merb-core/$(DEB_RUBY_SETUP_CMD) ] ; then \
+    rm merb-core/$(DEB_RUBY_SETUP_CMD) ; \
+  fi ; \
+  if [ -f merb-core/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ] ; then \
+    mv merb-core/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build merb-core/$(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+MERB_HAML_INSTALL_SETUP_CMD = \
+  if [ ! -L merb-haml/$(DEB_RUBY_SETUP_CMD) ] ; then \
+    if [ -f merb-haml/$(DEB_RUBY_SETUP_CMD) ] ; then \
+      mv merb-haml/$(DEB_RUBY_SETUP_CMD) merb-haml/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ;\
+    fi ; \
+    ln -s $(PACKAGED_RUBY_SETUP_CMD) merb-haml/$(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+MERB_HAML_REMOVE_SETUP_CMD = \
+  if [ -L merb-haml/$(DEB_RUBY_SETUP_CMD) ] ; then \
+    rm merb-haml/$(DEB_RUBY_SETUP_CMD) ; \
+  fi ; \
+  if [ -f merb-haml/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ] ; then \
+    mv merb-haml/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build merb-haml/$(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+MERB_SLICES_INSTALL_SETUP_CMD = \
+  if [ ! -L merb-slices/$(DEB_RUBY_SETUP_CMD) ] ; then \
+    if [ -f merb-slices/$(DEB_RUBY_SETUP_CMD) ] ; then \
+      mv merb-slices/$(DEB_RUBY_SETUP_CMD) merb-slices/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ;\
+    fi ; \
+    ln -s $(PACKAGED_RUBY_SETUP_CMD) merb-slices/$(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+MERB_SLICES_REMOVE_SETUP_CMD = \
+  if [ -L merb-slices/$(DEB_RUBY_SETUP_CMD) ] ; then \
+    rm merb-slices/$(DEB_RUBY_SETUP_CMD) ; \
+  fi ; \
+  if [ -f merb-slices/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ] ; then \
+    mv merb-slices/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build merb-slices/$(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+MERB_ASSETS_INSTALL_SETUP_CMD = \
+  if [ ! -L merb-assets/$(DEB_RUBY_SETUP_CMD) ] ; then \
+    if [ -f merb-assets/$(DEB_RUBY_SETUP_CMD) ] ; then \
+      mv merb-assets/$(DEB_RUBY_SETUP_CMD) merb-assets/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ;\
+    fi ; \
+    ln -s $(PACKAGED_RUBY_SETUP_CMD) merb-assets/$(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+MERB_ASSETS_REMOVE_SETUP_CMD = \
+  if [ -L merb-assets/$(DEB_RUBY_SETUP_CMD) ] ; then \
+    rm merb-assets/$(DEB_RUBY_SETUP_CMD) ; \
+  fi ; \
+  if [ -f merb-assets/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ] ; then \
+    mv merb-assets/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build merb-assets/$(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+MERB_HELPERS_INSTALL_SETUP_CMD = \
+  if [ ! -L merb-helpers/$(DEB_RUBY_SETUP_CMD) ] ; then \
+    if [ -f merb-helpers/$(DEB_RUBY_SETUP_CMD) ] ; then \
+      mv merb-helpers/$(DEB_RUBY_SETUP_CMD) merb-helpers/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ;\
+    fi ; \
+    ln -s $(PACKAGED_RUBY_SETUP_CMD) merb-helpers/$(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+MERB_HELPERS_REMOVE_SETUP_CMD = \
+  if [ -L merb-helpers/$(DEB_RUBY_SETUP_CMD) ] ; then \
+    rm merb-helpers/$(DEB_RUBY_SETUP_CMD) ; \
+  fi ; \
+  if [ -f merb-helpers/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build ] ; then \
+    mv merb-helpers/$(DEB_RUBY_SETUP_CMD).moved_away_by_debian_build merb-helpers/$(DEB_RUBY_SETUP_CMD) ; \
+  fi
+
+install/merb-core::
+	dh_installchangelogs
+	dh_installdirs
+
+install/merb-slices::
+	dh_installchangelogs
+	dh_installdirs
+
+install/libmerb-core-ruby1.8::
+	$(MERB_CORE_INSTALL_SETUP_CMD)
+	(cd merb-core && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) config $(DEB_RUBY_CONFIG_ARGS))
+	(cd merb-core && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) setup)
+	(cd merb-core && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) install --prefix=../debian/libmerb-core-ruby1.8)
+	mv $(CURDIR)/debian/libmerb-core-ruby1.8/usr/bin/merb $(CURDIR)/debian/merb-core/usr/bin/
+	rm $(CURDIR)/debian/libmerb-core-ruby1.8/usr/bin/merb-specs
+	rmdir $(CURDIR)/debian/libmerb-core-ruby1.8/usr/bin/
+
+install/libmerb-haml-ruby1.8::
+	$(MERB_HAML_INSTALL_SETUP_CMD)
+	(cd merb-haml && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) config $(DEB_RUBY_CONFIG_ARGS))
+	(cd merb-haml && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) setup)
+	(cd merb-haml && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) install --prefix=../debian/libmerb-haml-ruby1.8)
+
+install/libmerb-slices-ruby1.8::
+	$(MERB_SLICES_INSTALL_SETUP_CMD)
+	(cd merb-slices && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) config $(DEB_RUBY_CONFIG_ARGS))
+	(cd merb-slices && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) setup)
+	(cd merb-slices && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) install --prefix=../debian/libmerb-slices-ruby1.8)
+	mv $(CURDIR)/debian/libmerb-slices-ruby1.8/usr/bin/slice $(CURDIR)/debian/merb-slices/usr/bin/
+	rmdir $(CURDIR)/debian/libmerb-slices-ruby1.8/usr/bin/
+
+install/libmerb-assets-ruby1.8::
+	$(MERB_ASSETS_INSTALL_SETUP_CMD)
+	(cd merb-assets && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) config $(DEB_RUBY_CONFIG_ARGS))
+	(cd merb-assets && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) setup)
+	(cd merb-assets && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) install --prefix=../debian/libmerb-assets-ruby1.8)
+
+install/libmerb-helpers-ruby1.8::
+	$(MERB_HELPERS_INSTALL_SETUP_CMD)
+	(cd merb-helpers && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) config $(DEB_RUBY_CONFIG_ARGS))
+	(cd merb-helpers && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) setup)
+	(cd merb-helpers && /usr/bin/ruby $(DEB_RUBY_SETUP_CMD) install --prefix=../debian/libmerb-helpers-ruby1.8)
+
+install/libmerb-ruby-doc::
+	rdoc --all --inline-source --fileboxes --line-numbers --fmt=html -o debian/$(cdbs_curpkg)/usr/share/doc/libmerb-ruby-doc/rdoc merb-core/lib merb-haml/lib merb-helpers/lib merb-assets/lib merb-slices/lib lib
+
+clean::
+	$(DEB_RUBY_INSTALL_SETUP_CMD)
+	$(MERB_CORE_INSTALL_SETUP_CMD)
+	$(MERB_HAML_INSTALL_SETUP_CMD)
+	$(MERB_SLICES_INSTALL_SETUP_CMD)
+	$(MERB_ASSETS_INSTALL_SETUP_CMD)
+	$(MERB_HELPERS_INSTALL_SETUP_CMD)
+	/usr/bin/ruby $(DEB_RUBY_SETUP_CMD) distclean
+	$(DEB_RUBY_REMOVE_SETUP_CMD)
+	$(MERB_CORE_REMOVE_SETUP_CMD)
+	$(MERB_HAML_REMOVE_SETUP_CMD)
+	$(MERB_SLICES_REMOVE_SETUP_CMD)
+	$(MERB_ASSETS_REMOVE_SETUP_CMD)
+	$(MERB_HELPERS_REMOVE_SETUP_CMD)
+	rm -f $(DEB_SRCDIR)/.config
+	rm -f $(DEB_SRCDIR)/InstalledFiles


Property changes on: packages-wip/merb/trunk/debian/rules
___________________________________________________________________
Added: svn:executable
   + *

Added: packages-wip/merb/trunk/debian/slice.1
===================================================================
--- packages-wip/merb/trunk/debian/slice.1	                        (rev 0)
+++ packages-wip/merb/trunk/debian/slice.1	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,16 @@
+.TH SLICE "1" "July 2009"
+.SH NAME
+slice \- Start a Merb slice.
+.SH SYNOPSIS
+.B slice
+.SH DESCRIPTION
+The slice command starts a Merb application as a slice.
+.SH SEE ALSO
+.br
+Full documentation of merb is available after the Merb packages are installed.
+.SH AUTHOR
+Merb was written by Yehuda Katz <ykatz at engineyard.com>.
+.PP
+This manual page was written by Joshua Timberman <joshua at opscode.com>,
+for the Debian project (and may be used by others).
+

Added: packages-wip/merb/trunk/debian/watch
===================================================================
--- packages-wip/merb/trunk/debian/watch	                        (rev 0)
+++ packages-wip/merb/trunk/debian/watch	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,2 @@
+version=3
+http://githubredir.debian.net/github/wycats/merb /(.*).tar.gz

Added: packages-wip/merb/trunk/lib/merb-more.rb
===================================================================
--- packages-wip/merb/trunk/lib/merb-more.rb	                        (rev 0)
+++ packages-wip/merb/trunk/lib/merb-more.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,11 @@
+### AUTOMATICALLY GENERATED. DO NOT EDIT!
+require "merb-action-args"
+require "merb-assets"
+require "merb-slices"
+require "merb-auth"
+require "merb-cache"
+require "merb-exceptions"
+require "merb-haml"
+require "merb-helpers"
+require "merb-mailer"
+require "merb-param-protection"

Added: packages-wip/merb/trunk/merb-assets/.config
===================================================================
--- packages-wip/merb/trunk/merb-assets/.config	                        (rev 0)
+++ packages-wip/merb/trunk/merb-assets/.config	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,20 @@
+prefix=/usr
+bindir=$prefix/bin
+libdir=$prefix/lib
+datadir=$prefix/share
+mandir=$prefix/share/man
+sysconfdir=/etc
+localstatedir=/var
+libruby=/usr/lib/ruby
+librubyver=/usr/lib/ruby/1.8
+librubyverarch=/usr/lib/ruby/1.8/i486-linux
+siteruby=/usr/local/lib/site_ruby
+siterubyver=/usr/local/lib/site_ruby/1.8
+siterubyverarch=/usr/local/lib/site_ruby/1.8/i486-linux
+rbdir=$librubyver
+sodir=$librubyverarch
+rubypath=/usr/bin/ruby1.8
+rubyprog=/usr/bin/ruby1.8
+makeprog=make
+shebang=ruby
+without-ext=no

Added: packages-wip/merb/trunk/merb-assets/InstalledFiles
===================================================================
--- packages-wip/merb/trunk/merb-assets/InstalledFiles	                        (rev 0)
+++ packages-wip/merb/trunk/merb-assets/InstalledFiles	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,3 @@
+/usr/lib/ruby/1.8/merb-assets.rb
+/usr/lib/ruby/1.8/merb-assets/assets.rb
+/usr/lib/ruby/1.8/merb-assets/assets_mixin.rb

Added: packages-wip/merb/trunk/merb-core/.config
===================================================================
--- packages-wip/merb/trunk/merb-core/.config	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/.config	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,20 @@
+prefix=/usr
+bindir=$prefix/bin
+libdir=$prefix/lib
+datadir=$prefix/share
+mandir=$prefix/share/man
+sysconfdir=/etc
+localstatedir=/var
+libruby=/usr/lib/ruby
+librubyver=/usr/lib/ruby/1.8
+librubyverarch=/usr/lib/ruby/1.8/i486-linux
+siteruby=/usr/local/lib/site_ruby
+siterubyver=/usr/local/lib/site_ruby/1.8
+siterubyverarch=/usr/local/lib/site_ruby/1.8/i486-linux
+rbdir=$librubyver
+sodir=$librubyverarch
+rubypath=/usr/bin/ruby1.8
+rubyprog=/usr/bin/ruby1.8
+makeprog=make
+shebang=ruby
+without-ext=no

Added: packages-wip/merb/trunk/merb-core/InstalledFiles
===================================================================
--- packages-wip/merb/trunk/merb-core/InstalledFiles	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/InstalledFiles	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,95 @@
+/usr/bin/merb-specs
+/usr/bin/merb
+/usr/lib/ruby/1.8/merb-core.rb
+/usr/lib/ruby/1.8/merb-core/core_ext.rb
+/usr/lib/ruby/1.8/merb-core/config.rb
+/usr/lib/ruby/1.8/merb-core/bootloader.rb
+/usr/lib/ruby/1.8/merb-core/logger.rb
+/usr/lib/ruby/1.8/merb-core/server.rb
+/usr/lib/ruby/1.8/merb-core/constants.rb
+/usr/lib/ruby/1.8/merb-core/test.rb
+/usr/lib/ruby/1.8/merb-core/version.rb
+/usr/lib/ruby/1.8/merb-core/rack.rb
+/usr/lib/ruby/1.8/merb-core/autoload.rb
+/usr/lib/ruby/1.8/merb-core/two-oh.rb
+/usr/lib/ruby/1.8/merb-core/plugins.rb
+/usr/lib/ruby/1.8/merb-core/rack/stream_wrapper.rb
+/usr/lib/ruby/1.8/merb-core/rack/middleware.rb
+/usr/lib/ruby/1.8/merb-core/rack/helpers.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter.rb
+/usr/lib/ruby/1.8/merb-core/rack/application.rb
+/usr/lib/ruby/1.8/merb-core/rack/handler/mongrel.rb
+/usr/lib/ruby/1.8/merb-core/rack/middleware/profiler.rb
+/usr/lib/ruby/1.8/merb-core/rack/middleware/content_length.rb
+/usr/lib/ruby/1.8/merb-core/rack/middleware/tracer.rb
+/usr/lib/ruby/1.8/merb-core/rack/middleware/conditional_get.rb
+/usr/lib/ruby/1.8/merb-core/rack/middleware/path_prefix.rb
+/usr/lib/ruby/1.8/merb-core/rack/middleware/static.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/runner.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/thin_turbo.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/fcgi.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/swiftiplied_mongrel.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/webrick.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/thin.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/mongrel.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/ebb.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/irb.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/evented_mongrel.rb
+/usr/lib/ruby/1.8/merb-core/rack/adapter/abstract.rb
+/usr/lib/ruby/1.8/merb-core/gem_ext/erubis.rb
+/usr/lib/ruby/1.8/merb-core/test/run_spec.rb
+/usr/lib/ruby/1.8/merb-core/test/helpers.rb
+/usr/lib/ruby/1.8/merb-core/test/run_specs.rb
+/usr/lib/ruby/1.8/merb-core/test/matchers.rb
+/usr/lib/ruby/1.8/merb-core/test/test_ext/object.rb
+/usr/lib/ruby/1.8/merb-core/test/test_ext/hpricot.rb
+/usr/lib/ruby/1.8/merb-core/test/test_ext/rspec.rb
+/usr/lib/ruby/1.8/merb-core/test/test_ext/string.rb
+/usr/lib/ruby/1.8/merb-core/test/helpers/cookie_jar.rb
+/usr/lib/ruby/1.8/merb-core/test/helpers/controller_helper.rb
+/usr/lib/ruby/1.8/merb-core/test/helpers/mock_request_helper.rb
+/usr/lib/ruby/1.8/merb-core/test/helpers/request_helper.rb
+/usr/lib/ruby/1.8/merb-core/test/helpers/route_helper.rb
+/usr/lib/ruby/1.8/merb-core/test/helpers/multipart_request_helper.rb
+/usr/lib/ruby/1.8/merb-core/test/matchers/request_matchers.rb
+/usr/lib/ruby/1.8/merb-core/test/matchers/route_matchers.rb
+/usr/lib/ruby/1.8/merb-core/test/matchers/controller_matchers.rb
+/usr/lib/ruby/1.8/merb-core/test/tasks/spectasks.rb
+/usr/lib/ruby/1.8/merb-core/controller/mime.rb
+/usr/lib/ruby/1.8/merb-core/controller/abstract_controller.rb
+/usr/lib/ruby/1.8/merb-core/controller/template.rb
+/usr/lib/ruby/1.8/merb-core/controller/merb_controller.rb
+/usr/lib/ruby/1.8/merb-core/controller/exceptions.rb
+/usr/lib/ruby/1.8/merb-core/controller/mixins/responder.rb
+/usr/lib/ruby/1.8/merb-core/controller/mixins/conditional_get.rb
+/usr/lib/ruby/1.8/merb-core/controller/mixins/render.rb
+/usr/lib/ruby/1.8/merb-core/controller/mixins/authentication.rb
+/usr/lib/ruby/1.8/merb-core/controller/mixins/controller.rb
+/usr/lib/ruby/1.8/merb-core/tasks/stats.rake
+/usr/lib/ruby/1.8/merb-core/tasks/gem_management.rb
+/usr/lib/ruby/1.8/merb-core/tasks/merb.rb
+/usr/lib/ruby/1.8/merb-core/tasks/audit.rake
+/usr/lib/ruby/1.8/merb-core/tasks/merb_rake_helper.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/router.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/session.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/cookies.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/request.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/request_parsers.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/worker.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/dispatcher.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/router/route.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/router/behavior.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/router/resources.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/router/cached_proc.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/default_exception.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/index.html.erb
+/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/_css.html.erb
+/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/_javascript.html.erb
+/usr/lib/ruby/1.8/merb-core/dispatch/session/container.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/session/store_container.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/session/cookie.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/session/memcached.rb
+/usr/lib/ruby/1.8/merb-core/dispatch/session/memory.rb
+/usr/lib/ruby/1.8/merb-core/core_ext/class.rb
+/usr/lib/ruby/1.8/merb-core/core_ext/kernel.rb
+/usr/lib/ruby/1.8/merb-core/core_ext/hash.rb

Modified: packages-wip/merb/trunk/merb-core/bin/merb
===================================================================
--- packages-wip/merb/trunk/merb-core/bin/merb	2009-07-30 20:19:53 UTC (rev 3861)
+++ packages-wip/merb/trunk/merb-core/bin/merb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -1,4 +1,4 @@
-#!/usr/bin/env ruby
+#! /usr/bin/ruby1.8
 
 require 'rubygems'
 require 'merb-core'

Modified: packages-wip/merb/trunk/merb-core/bin/merb-specs
===================================================================
--- packages-wip/merb/trunk/merb-core/bin/merb-specs	2009-07-30 20:19:53 UTC (rev 3861)
+++ packages-wip/merb/trunk/merb-core/bin/merb-specs	2009-07-30 20:20:09 UTC (rev 3862)
@@ -1,4 +1,4 @@
-#!/usr/bin/env ruby
+#! /usr/bin/ruby1.8
 
 require File.join(File.dirname(__FILE__),"..","lib","merb-core","test","run_specs")
 

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/bin/merb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/bin/merb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/bin/merb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,11 @@
+#! /usr/bin/ruby1.8
+
+require 'rubygems'
+require 'merb-core'
+
+ARGV.push '-H' if ARGV[0] && ARGV[0] =~ /^[^-]/
+unless %w[-a --adapter -i --irb-console -r --script-runner].any? { |o| ARGV.index(o) }
+  ARGV.push *%w[-a mongrel]
+end
+
+Merb.start
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/autoload.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/autoload.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/autoload.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,31 @@
+require 'merb-core/core_ext'
+require "merb-core/controller/exceptions"
+require "merb-core/controller/mixins/responder"
+require "merb-core/controller/mixins/render"
+require "merb-core/controller/mixins/authentication"
+require "merb-core/controller/mixins/conditional_get"
+require "merb-core/controller/mixins/controller"
+require "merb-core/controller/abstract_controller"
+require "merb-core/controller/template"
+require "merb-core/controller/merb_controller"
+require "merb-core/bootloader"
+require "merb-core/config"
+require "merb-core/constants"
+require "merb-core/dispatch/dispatcher"
+require "merb-core/plugins"
+require "merb-core/rack"
+require "merb-core/dispatch/request"
+require "merb-core/dispatch/request_parsers.rb"
+require "merb-core/dispatch/router"
+require "merb-core/dispatch/worker"
+
+module Merb
+  autoload :Test, "merb-core/test"
+end
+
+# Require this rather than autoloading it so we can be sure the default template
+# gets registered
+
+module Merb
+  module InlineTemplates; end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/bootloader.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/bootloader.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/bootloader.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,1381 @@
+module Merb
+
+  class BootLoader
+
+    # def self.subclasses
+    #
+    # :api: plugin
+    cattr_accessor :subclasses, :after_load_callbacks, :before_load_callbacks,
+    :finished, :before_worker_shutdown_callbacks, :before_master_shutdown_callbacks
+
+    self.subclasses, self.after_load_callbacks,
+      self.before_load_callbacks, self.finished, self.before_master_shutdown_callbacks,
+      self.before_worker_shutdown_callbacks = [], [], [], [], [], []
+
+    class << self
+
+      # Adds the inheriting class to the list of subclasses in a position
+      # specified by the before and after methods.
+      #
+      # ==== Parameters
+      # klass<Class>:: The class inheriting from Merb::BootLoader.
+      #
+      # ==== Returns
+      # nil
+      #
+      # :api: plugin
+      def inherited(klass)
+        subclasses << klass.to_s
+        super
+      end
+
+      # Execute this boot loader after the specified boot loader.
+      #
+      # ==== Parameters
+      # klass<~to_s>::
+      #   The boot loader class after which this boot loader should be run.
+      #
+      # ==== Returns
+      # nil
+      #
+      # :api: plugin
+      def after(klass)
+        move_klass(klass, 1)
+        nil
+      end
+
+      # Execute this boot loader before the specified boot loader.
+      #
+      # ==== Parameters
+      # klass<~to_s>::
+      #   The boot loader class before which this boot loader should be run.
+      #
+      # ==== Returns
+      # nil
+      #
+      # :api: plugin
+      def before(klass)
+        move_klass(klass, 0)
+        nil
+      end
+
+      # Move a class that is inside the bootloader to some place in the Array,
+      # relative to another class.
+      #
+      # ==== Parameters
+      # klass<~to_s>::
+      #   The klass to move the bootloader relative to
+      # where<Integer>::
+      #   0 means insert it before; 1 means insert it after
+      #
+      # ==== Returns
+      # nil
+      #
+      # :api: private
+      def move_klass(klass, where)
+        index = Merb::BootLoader.subclasses.index(klass.to_s)
+        if index
+          Merb::BootLoader.subclasses.delete(self.to_s)
+          Merb::BootLoader.subclasses.insert(index + where, self.to_s)
+        end
+        nil
+      end
+
+      # Runs all boot loader classes by calling their run methods.
+      #
+      # ==== Returns
+      # nil
+      #
+      # :api: plugin
+      def run
+        Merb.started = true
+        subklasses = subclasses.dup
+        until subclasses.empty?
+          time = Time.now.to_i
+          bootloader = subclasses.shift
+          if (ENV['DEBUG'] || $DEBUG || Merb::Config[:verbose]) && Merb.logger
+            Merb.logger.debug!("Loading: #{bootloader}")
+          end
+          Object.full_const_get(bootloader).run
+          if (ENV['DEBUG'] || $DEBUG || Merb::Config[:verbose]) && Merb.logger
+            Merb.logger.debug!("It took: #{Time.now.to_i - time}")
+          end
+          self.finished << bootloader
+        end
+        self.subclasses = subklasses
+        nil
+      end
+
+      # Determines whether or not a specific bootloader has finished yet.
+      #
+      # ==== Parameters
+      # bootloader<String, Class>:: The name of the bootloader to check.
+      #
+      # ==== Returns
+      # Boolean:: Whether or not the bootloader has finished.
+      #
+      # :api: private
+      def finished?(bootloader)
+        self.finished.include?(bootloader.to_s)
+      end
+
+      # Set up the default framework
+      #
+      # ==== Returns
+      # nil
+      #
+      # :api: plugin
+      # @overridable
+      def default_framework
+        %w[view model helper controller mailer part].each do |component|
+          Merb.push_path(component.to_sym, Merb.root_path("app/#{component}s"))
+        end
+        Merb.push_path(:application,  Merb.root_path("app" / "controllers" / "application.rb"))
+        Merb.push_path(:config,       Merb.root_path("config"), nil)
+        Merb.push_path(:router,       Merb.dir_for(:config), (Merb::Config[:router_file] || "router.rb"))
+        Merb.push_path(:lib,          Merb.root_path("lib"), nil)
+        Merb.push_path(:merb_session, Merb.root_path("merb" / "session"))
+        Merb.push_path(:log,          Merb.log_path, nil)
+        Merb.push_path(:public,       Merb.root_path("public"), nil)
+        Merb.push_path(:stylesheet,   Merb.dir_for(:public) / "stylesheets", nil)
+        Merb.push_path(:javascript,   Merb.dir_for(:public) / "javascripts", nil)
+        Merb.push_path(:image,        Merb.dir_for(:public) / "images", nil)
+        nil
+      end
+
+      # Execute a block of code after the app loads.
+      #
+      # ==== Parameters
+      # &block::
+      #   A block to be added to the callbacks that will be executed after the
+      #   app loads.
+      #
+      # :api: public
+      def after_app_loads(&block)
+        after_load_callbacks << block
+      end
+
+      # Execute a block of code before the app loads but after dependencies load.
+      #
+      # ==== Parameters
+      # &block::
+      #   A block to be added to the callbacks that will be executed before the
+      #   app loads.
+      #
+      # :api: public
+      def before_app_loads(&block)
+        before_load_callbacks << block
+      end
+
+      # Execute a block of code before master process is shut down.
+      # Only makes sense on platforms where Merb server can use forking.
+      #
+      # ==== Parameters
+      # &block::
+      #   A block to be added to the callbacks that will be executed
+      #   before master process is shut down.
+      #
+      # :api: public
+      def before_master_shutdown(&block)
+        before_master_shutdown_callbacks << block
+      end
+
+      # Execute a block of code before worker process is shut down.
+      # Only makes sense on platforms where Merb server can use forking.
+      #
+      # ==== Parameters
+      # &block::
+      #   A block to be added to the callbacks that will be executed
+      #   before worker process is shut down.
+      #
+      # :api: public
+      def before_worker_shutdown(&block)
+        before_worker_shutdown_callbacks << block
+      end
+    end
+
+  end
+
+end
+
+# Set up the logger.
+#
+# Place the logger inside of the Merb log directory (set up in
+# Merb::BootLoader::BuildFramework)
+class Merb::BootLoader::Logger < Merb::BootLoader
+
+  # Sets Merb.logger to a new logger created based on the config settings.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    Merb::Config[:log_level] ||= begin
+      if Merb.environment == "production"
+        Merb::Logger::Levels[:warn]
+      else
+        Merb::Logger::Levels[:debug]
+      end
+    end
+
+    Merb::Config[:log_stream] = 
+      Merb::Config[:original_log_stream] || Merb.log_stream
+
+    print_warnings
+
+    nil
+  end
+
+  # Print a warning if the installed version of rubygems is not supported
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: private
+  def self.print_warnings
+    if Gem::Version.new(Gem::RubyGemsVersion) < Gem::Version.new("1.1")
+      Merb.fatal! "Merb requires Rubygems 1.1 and later. " \
+        "Please upgrade RubyGems with gem update --system."
+    end
+  end
+end
+
+# Stores pid file.
+#
+# Only run if daemonization or clustering options specified on start.
+# Port is taken from Merb::Config and must be already set at this point.
+class Merb::BootLoader::DropPidFile < Merb::BootLoader
+  class << self
+
+    # Stores a PID file if Merb is running daemonized or clustered.
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: plugin
+    def run
+      Merb::Server.store_pid("main") if Merb::Config[:daemonize] || Merb::Config[:cluster]
+      nil
+    end
+  end
+end
+
+# Setup some useful defaults
+class Merb::BootLoader::Defaults < Merb::BootLoader
+  # Sets up the defaults
+  # 
+  # ==== Returns
+  # nil
+  # 
+  # :api: plugin
+  def self.run
+    Merb::Request.http_method_overrides.concat([
+      proc { |c| c.params[:_method] },
+      proc { |c| c.env['HTTP_X_HTTP_METHOD_OVERRIDE'] }
+    ])
+    nil
+  end
+end
+
+
+# Build the framework paths.
+#
+# By default, the following paths will be used:
+# application:: Merb.root/app/controller/application.rb
+# config:: Merb.root/config
+# lib:: Merb.root/lib
+# log:: Merb.root/log
+# view:: Merb.root/app/views
+# model:: Merb.root/app/models
+# controller:: Merb.root/app/controllers
+# helper:: Merb.root/app/helpers
+# mailer:: Merb.root/app/mailers
+# part:: Merb.root/app/parts
+#
+# To override the default, set Merb::Config[:framework] in your initialization
+# file. Merb::Config[:framework] takes a Hash whose key is the name of the
+# path, and whose values can be passed into Merb.push_path (see Merb.push_path
+# for full details).
+#
+# ==== Notes
+# All paths will default to Merb.root, so you can get a flat-file structure by
+# doing Merb::Config[:framework] = {}.
+#
+# ==== Example
+#   Merb::Config[:framework] = {
+#     :view   => Merb.root / "views",
+#     :model  => Merb.root / "models",
+#     :lib    => Merb.root / "lib",
+#     :public => [Merb.root / "public", nil]
+#     :router => [Merb.root / "config", "router.rb"]
+#   }
+#
+# That will set up a flat directory structure with the config files and
+# controller files under Merb.root, but with models, views, and lib with their
+# own folders off of Merb.root.
+class Merb::BootLoader::BuildFramework < Merb::BootLoader
+  class << self
+
+    # Builds the framework directory structure.
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: plugin
+    def run
+      $:.push Merb.root unless Merb.root == File.expand_path(Dir.pwd)
+      build_framework
+      nil
+    end
+
+    # Sets up merb paths to support the app's file layout. First, config/framework.rb is checked,
+    # next we look for Merb.root/framework.rb, finally we use the default merb layout (Merb::BootLoader.default_framework)
+    #
+    # This method can be overriden to support other application layouts.
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: plugin
+    # @overridable
+    def build_framework
+      if File.exists?(Merb.root / "config" / "framework.rb")
+        require Merb.root / "config" / "framework"
+      elsif File.exists?(Merb.root / "framework.rb")
+        require Merb.root / "framework"
+      else
+        Merb::BootLoader.default_framework
+      end
+      (Merb::Config[:framework] || {}).each do |name, path|
+        path = Array(path)
+        Merb.push_path(name, path.first, path.length == 2 ? path[1] : "**/*.rb")
+      end
+      nil
+    end
+  end
+end
+
+class Merb::BootLoader::Dependencies < Merb::BootLoader
+
+  # ==== Returns
+  # Array[Gem::Dependency]:: The dependencies registered in init.rb.
+  #
+  # :api: plugin
+  cattr_accessor :dependencies
+  self.dependencies = []
+
+  # Load the init_file specified in Merb::Config or if not specified, the
+  # init.rb file from the Merb configuration directory, and any environment
+  # files, which register the list of necessary dependencies and any
+  # after_app_loads hooks.
+  #
+  # Dependencies can hook into the bootloader process itself by using
+  # before or after insertion methods. Since these are loaded from this
+  # bootloader (Dependencies), they can only adapt the bootloaders that
+  # haven't been loaded up until this point.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    set_encoding
+    # this is crucial: load init file with all the preferences
+    # then environment init file, then start enabling specific
+    # components, load dependencies and update logger.
+    unless Merb::disabled?(:initfile)
+      load_initfile
+      load_env_config
+    end
+    expand_ruby_path
+    enable_json_gem unless Merb::disabled?(:json)
+    load_dependencies
+    update_logger
+    nil
+  end
+
+  # Load each dependency that has been declared so far.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: private
+  def self.load_dependencies
+    dependencies.each { |dependency| Kernel.load_dependency(dependency, nil) }
+    nil
+  end
+
+  # Loads json or json_pure and requires it.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: private
+  def self.enable_json_gem
+    gem "json"
+    require "json/ext"
+  rescue LoadError
+    gem "json_pure"
+    require "json/pure"
+  end
+
+  # Resets the logger and sets the log_stream to Merb::Config[:log_file]
+  # if one is specified, falling back to STDOUT.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: private
+  def self.update_logger
+    Merb.reset_logger!
+
+    # If log file is given, use it and not log stream we have.
+    if Merb::Config[:log_file]
+      raise "log file should be a string, got: #{Merb::Config[:log_file].inspect}" unless Merb::Config[:log_file].is_a?(String)
+      STDOUT.puts "Logging to file at #{Merb::Config[:log_file]}" unless Merb.testing?
+      Merb::Config[:log_stream] = File.open(Merb::Config[:log_file], "a")
+    # but if it's not given, fallback to log stream or stdout
+    else
+      Merb::Config[:log_stream] ||= STDOUT
+    end
+
+    nil
+  end
+
+  # Default encoding to UTF8 if it has not already been set to something else.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: private
+  def self.set_encoding
+    unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("1.9")
+      $KCODE = 'UTF8' if $KCODE == 'NONE' || $KCODE.blank?
+    end
+    
+    nil
+  end
+
+  private
+
+    # Determines the path for the environment configuration file
+    #
+    # ==== Returns
+    # String:: The path to the config file for the environment
+    #
+    # :api: private
+    def self.env_config
+      Merb.dir_for(:config) / "environments" / (Merb.environment + ".rb")
+    end
+
+    # Checks to see whether or not an environment configuration exists
+    #
+    # ==== Returns
+    # Boolean:: Whether or not the environment configuration file exists.
+    #
+    # :api: private
+    def self.env_config?
+      Merb.environment && File.exist?(env_config)
+    end
+
+    # Loads the environment configuration file, if it is present
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: private
+    def self.load_env_config
+      if env_config?
+        STDOUT.puts "Loading #{env_config}" unless Merb.testing?
+        load(env_config)
+      end
+      nil
+    end
+
+    # Determines the init file to use, if any.
+    # By default Merb uses init.rb from application config directory.
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: private
+    def self.initfile
+      if Merb::Config[:init_file]
+        Merb::Config[:init_file].chomp(".rb") + ".rb"
+      else
+        Merb.dir_for(:config) / "init.rb"
+      end
+    end
+
+    # Loads the init file, should one exist
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: private
+    def self.load_initfile
+      return nil if Merb.const_defined?("INIT_RB_LOADED")
+      if File.exists?(initfile)
+        STDOUT.puts "Loading init file from #{initfile}" unless Merb.testing?
+        load(initfile)
+        Merb.const_set("INIT_RB_LOADED", true)
+      elsif !Merb.testing?
+        Merb.fatal! "You are not in a Merb application, or you are in " \
+          "a flat application and have not specified the init file. If you " \
+          "are trying to create a new merb application, use merb-gen app."
+      end
+      nil
+    end
+
+    # Expands Ruby path with framework directories (for models, lib, etc). Only run once.
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: private
+    def self.expand_ruby_path
+      # Add models, controllers, helpers and lib to the load path
+      unless @ran
+        Merb.logger.info "Expanding RUBY_PATH..." if Merb::Config[:verbose]
+
+        $LOAD_PATH.unshift Merb.dir_for(:model)
+        $LOAD_PATH.unshift Merb.dir_for(:controller)
+        $LOAD_PATH.unshift Merb.dir_for(:lib)
+        $LOAD_PATH.unshift Merb.dir_for(:helper)
+      end
+
+      @ran = true
+      nil
+    end
+end
+
+class Merb::BootLoader::MixinSession < Merb::BootLoader
+
+  # Mixin the session functionality; this is done before BeforeAppLoads
+  # so that SessionContainer and SessionStoreContainer can be subclassed by
+  # plugin session stores for example - these need to be loaded in a
+  # before_app_loads block or a BootLoader that runs after MixinSession.
+  #
+  # Note: access to Merb::Config is needed, so it needs to run after
+  # Merb::BootLoader::Dependencies is done.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    require 'merb-core/dispatch/session'
+    Merb::Controller.send(:include, ::Merb::SessionMixin)
+    Merb::Request.send(:include, ::Merb::SessionMixin::RequestMixin)
+  end
+
+end
+
+class Merb::BootLoader::BeforeAppLoads < Merb::BootLoader
+
+  # Call any before_app_loads hooks that were registered via before_app_loads
+  # in any plugins.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    Merb::BootLoader.before_load_callbacks.each { |x| x.call }
+    nil
+  end
+end
+
+# Load all classes inside the load paths.
+#
+# This is used in conjunction with Merb::BootLoader::ReloadClasses to track
+# files that need to be reloaded, and which constants need to be removed in
+# order to reload a file.
+#
+# This also adds the model, controller, and lib directories to the load path,
+# so they can be required in order to avoid load-order issues.
+class Merb::BootLoader::LoadClasses < Merb::BootLoader
+  LOADED_CLASSES = {}
+  MTIMES = {}
+  FILES_LOADED = {}
+
+  class << self
+
+    # Load all classes from Merb's native load paths.
+    #
+    # If fork-based loading is used, every time classes are loaded this will return in a new spawner process
+    # and boot loading will continue from this point in the boot loading process.
+    #
+    # If fork-based loading is not in use, this only returns once and does not fork a new
+    # process.
+    #
+    # ==== Returns
+    # Returns at least once:
+    #   nil
+    #
+    # :api: plugin
+    def run
+      # process name you see in ps output
+      $0 = "merb#{" : " + Merb::Config[:name] if Merb::Config[:name]} : master"
+
+      # Log the process configuration user defined signal 1 (SIGUSR1) is received.
+      Merb.trap("USR1") do
+        require "yaml"
+        Merb.logger.fatal! "Configuration:\n#{Merb::Config.to_hash.merge(:pid => $$).to_yaml}\n\n"
+      end
+
+      if Merb::Config[:fork_for_class_load] && !Merb.testing?
+        start_transaction
+      else
+        Merb.trap('INT') do
+          Merb.logger.warn! "Reaping Workers"
+          reap_workers
+        end
+      end
+
+      # Load application file if it exists - for flat applications
+      load_file Merb.dir_for(:application) if File.file?(Merb.dir_for(:application))
+
+      # Load classes and their requirements
+      Merb.load_paths.each do |component, path|
+        next if path.last.blank? || component == :application || component == :router
+        load_classes(path.first / path.last)
+      end
+
+      Merb::Controller.send :include, Merb::GlobalHelpers
+
+      nil
+    end
+
+    # Wait for any children to exit, remove the "main" PID, and
+    # exit.
+    #
+    # ==== Returns
+    # (Does not return.)
+    #
+    # :api: private
+    def exit_gracefully
+      # wait all workers to exit
+      Process.waitall
+      # remove master process pid
+      Merb::Server.remove_pid("main")
+      # terminate, workers remove their own pids
+      # in on exit hook
+
+      Merb::BootLoader.before_master_shutdown_callbacks.each do |cb|
+        begin
+          cb.call
+        rescue Exception => e
+          Merb.logger.fatal "before_master_shutdown callback crashed: #{e.message}"
+        end
+      end
+      exit
+    end
+
+    # Set up the BEGIN point for fork-based loading and sets up
+    # any signals in the parent and child. This is done by forking
+    # the app. The child process continues on to run the app. The parent
+    # process waits for the child process to finish and either forks again
+    #
+    #
+    # ==== Returns
+    # Parent Process:
+    #   (Does not return.)
+    # Child Process returns at least once:
+    #   nil
+    #
+    # :api: private
+    def start_transaction
+      Merb.logger.warn! "Parent pid: #{Process.pid}"
+      reader, writer = nil, nil
+
+      if GC.respond_to?(:copy_on_write_friendly=)
+        GC.copy_on_write_friendly = true
+      end
+
+      loop do
+        # create two connected endpoints
+        # we use them for master/workers communication
+        reader, @writer = IO.pipe
+        pid = Kernel.fork
+
+        # pid means we're in the parent; only stay in the loop if that is case
+        break unless pid
+        # writer must be closed so reader can generate EOF condition
+        @writer.close
+
+        # master process stores pid to merb.main.pid
+        Merb::Server.store_pid("main") if Merb::Config[:daemonize] || Merb::Config[:cluster]
+
+        if Merb::Config[:console_trap]
+          Merb.trap("INT") {}
+        else
+          # send ABRT to worker on INT
+          Merb.trap("INT") do
+            Merb.logger.warn! "Reaping Workers"
+            begin
+              Process.kill(reap_workers_signal, pid)
+            rescue SystemCallError
+            end
+            exit_gracefully
+          end
+        end
+
+        Merb.trap("HUP") do
+          Merb.logger.warn! "Doing a fast deploy\n"
+          Process.kill("HUP", pid)
+        end
+
+        reader_ary = [reader]
+        loop do
+          # wait for worker to exit and capture exit status
+          #
+          #
+          # WNOHANG specifies that wait2 exists without waiting
+          # if no worker processes are ready to be noticed.
+          if exit_status = Process.wait2(pid, Process::WNOHANG)
+            # wait2 returns a 2-tuple of process id and exit
+            # status.
+            #
+            # We do not care about specific pid here.
+            exit_status[1] && exit_status[1].exitstatus == 128 ? break : exit
+          end
+          # wait for data to become available, timeout in 0.25 of a second
+          if select(reader_ary, nil, nil, 0.25)
+            begin
+              # no open writers
+              next if reader.eof?
+              msg = reader.readline
+              if msg =~ /128/
+                Process.detach(pid)
+                break
+              else
+                exit_gracefully
+              end
+            rescue SystemCallError
+              exit_gracefully
+            end
+          end
+        end
+      end
+
+      reader.close
+
+      # add traps to the worker
+      if Merb::Config[:console_trap]
+        Merb::Server.add_irb_trap
+        at_exit { reap_workers }
+      else
+        Merb.trap('INT') do
+          Merb::BootLoader.before_worker_shutdown_callbacks.each { |cb| cb.call }
+        end
+        Merb.trap('ABRT') { reap_workers }
+        Merb.trap('HUP') { reap_workers(128, "ABRT") }
+      end
+    end
+
+    def reap_workers_signal
+      Merb::Config[:reap_workers_quickly] ? "KILL" : "ABRT"
+    end
+
+    # Reap any workers of the spawner process and
+    # exit with an appropriate status code.
+    #
+    # Note that exiting the spawner process with a status code
+    # of 128 when a master process exists will cause the
+    # spawner process to be recreated, and the app code reloaded.
+    #
+    # ==== Parameters
+    # status<Integer>:: The status code to exit with. Defaults to 0.
+    # sig<String>::     The signal to send to workers
+    #
+    # ==== Returns
+    # (Does not return.)
+    #
+    # :api: private    
+    def reap_workers(status = 0, sig = reap_workers_signal)
+      
+      Merb.logger.info "Executed all before worker shutdown callbacks..."
+      Merb::BootLoader.before_worker_shutdown_callbacks.each do |cb|
+        begin
+          cb.call
+        rescue Exception => e
+          Merb.logger.fatal "before worker shutdown callback crashed: #{e.message}"
+        end
+
+      end
+
+      Merb.exiting = true unless status == 128
+
+      begin
+        @writer.puts(status.to_s) if @writer
+      rescue SystemCallError
+      end
+
+      threads = []
+
+      ($WORKERS || []).each do |p|
+        threads << Thread.new do
+          begin
+            Process.kill(sig, p)
+            Process.wait2(p)
+          rescue SystemCallError
+          end
+        end
+      end
+      threads.each {|t| t.join }
+      exit(status)
+    end
+
+    # Loads a file, tracking its modified time and, if necessary, the classes it declared.
+    #
+    # ==== Parameters
+    # file<String>:: The file to load.
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: private
+    def load_file(file, reload = false)
+      Merb.logger.verbose! "#{reload ? "re" : ""}loading #{file}"
+      
+      # If we're going to be reloading via constant remove,
+      # keep track of what constants were loaded and what files
+      # have been added, so that the constants can be removed
+      # and the files can be removed from $LOADED_FEAUTRES
+      if !Merb::Config[:fork_for_class_load]
+        if FILES_LOADED[file]
+          FILES_LOADED[file].each {|lf| $LOADED_FEATURES.delete(lf)}
+        end
+        
+        klasses = ObjectSpace.classes.dup
+        files_loaded = $LOADED_FEATURES.dup
+      end
+
+      # If we're in the midst of a reload, remove the file
+      # itself from $LOADED_FEATURES so it will get reloaded
+      if reload
+        $LOADED_FEATURES.delete(file) if reload
+      end
+
+      # Ignore the file for syntax errors. The next time
+      # the file is changed, it'll be reloaded again
+      begin
+        require file
+      rescue SyntaxError => e
+        Merb.logger.error "Cannot load #{file} because of syntax error: #{e.message}"
+      ensure
+        if Merb::Config[:reload_classes]
+          MTIMES[file] = File.mtime(file)
+        end
+      end
+
+      # If we're reloading via constant remove, store off the details
+      # after the file has been loaded
+      unless Merb::Config[:fork_for_class_load]
+        LOADED_CLASSES[file] = ObjectSpace.classes - klasses
+        FILES_LOADED[file] = $LOADED_FEATURES - files_loaded
+      end
+
+      nil
+    end
+
+    # Load classes from given paths - using path/glob pattern.
+    #
+    # ==== Parameters
+    # *paths<Array>::
+    #   Array of paths to load classes from - may contain glob pattern
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: private
+    def load_classes(*paths)
+      orphaned_classes = []
+      paths.flatten.each do |path|
+        Dir[path].each do |file|
+          begin
+            load_file file
+          rescue NameError => ne
+            orphaned_classes.unshift(file)
+          end
+        end
+      end
+      load_classes_with_requirements(orphaned_classes)
+    end
+
+    # Reloads the classes in the specified file. If fork-based loading is used,
+    # this causes the current processes to be killed and and all classes to be
+    # reloaded. If class-based loading is not in use, the classes declared in that file
+    # are removed and the file is reloaded.
+    #
+    # ==== Parameters
+    # file<String>:: The file to reload.
+    #
+    # ==== Returns
+    # When fork-based loading is used:
+    #   (Does not return.)
+    # When fork-based loading is not in use:
+    #   nil
+    #
+    # :api: private
+    def reload(file)
+      if Merb::Config[:fork_for_class_load]
+        reap_workers(128)
+      else
+        remove_classes_in_file(file) { |f| load_file(f, true) }
+      end
+    end
+
+    # Removes all classes declared in the specified file. Any hashes which use classes as keys
+    # will be protected provided they have been added to Merb.klass_hashes. These hashes have their
+    # keys substituted with placeholders before the file's classes are unloaded. If a block is provided,
+    # it is called before the substituted keys are reconstituted.
+    #
+    # ==== Parameters
+    # file<String>:: The file to remove classes for.
+    # &block:: A block to call with the file that has been removed before klass_hashes are updated
+    # to use the current values of the constants they used as keys.
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: private
+    def remove_classes_in_file(file, &block)
+      Merb.klass_hashes.each { |x| x.protect_keys! }
+      if klasses = LOADED_CLASSES.delete(file)
+        klasses.each { |klass| remove_constant(klass) unless klass.to_s =~ /Router/ }
+      end
+      yield file if block_given?
+      Merb.klass_hashes.each {|x| x.unprotect_keys!}
+      nil
+    end
+
+    # Removes the specified class.
+    #
+    # Additionally, removes the specified class from the subclass list of every superclass that
+    # tracks it's subclasses in an array returned by _subclasses_list. Classes that wish to use this
+    # functionality are required to alias the reader for their list of subclasses
+    # to _subclasses_list. Plugins for ORMs and other libraries should keep this in mind.
+    #
+    # ==== Parameters
+    # const<Class>:: The class to remove.
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: private
+    def remove_constant(const)
+      # This is to support superclasses (like AbstractController) that track
+      # their subclasses in a class variable.
+      superklass = const
+      until (superklass = superklass.superclass).nil?
+        if superklass.respond_to?(:_subclasses_list)
+          superklass.send(:_subclasses_list).delete(klass)
+          superklass.send(:_subclasses_list).delete(klass.to_s)
+        end
+      end
+
+      parts = const.to_s.split("::")
+      base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::"))
+      object = parts[-1].to_s
+      begin
+        base.send(:remove_const, object)
+        Merb.logger.debug("Removed constant #{object} from #{base}")
+      rescue NameError
+        Merb.logger.debug("Failed to remove constant #{object} from #{base}")
+      end
+      nil
+    end
+
+    private
+
+    # "Better loading" of classes.  If a file fails to load due to a NameError
+    # it will be added to the failed_classes and load cycle will be repeated unless
+    # no classes load.
+    #
+    # ==== Parameters
+    # klasses<Array[Class]>:: Classes to load.
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: private
+    def load_classes_with_requirements(klasses)
+      klasses.uniq!
+
+      while klasses.size > 0
+        # Note size to make sure things are loading
+        size_at_start = klasses.size
+
+        # List of failed classes
+        failed_classes = []
+        # Map classes to exceptions
+        error_map = {}
+
+        klasses.each do |klass|
+          klasses.delete(klass)
+          begin
+            load_file klass
+          rescue NameError => ne
+            error_map[klass] = ne
+            failed_classes.push(klass)
+          end
+        end
+
+        # Keep list of classes unique
+        failed_classes.each { |k| klasses.push(k) unless klasses.include?(k) }
+
+        # Stop processing if nothing loads or if everything has loaded
+        if klasses.size == size_at_start && klasses.size != 0
+          # Write all remaining failed classes and their exceptions to the log
+          messages = error_map.only(*failed_classes).map do |klass, e|
+            ["Could not load #{klass}:\n\n#{e.message} - (#{e.class})",
+              "#{(e.backtrace || []).join("\n")}"]
+          end
+          messages.each { |msg, trace| Merb.logger.fatal!("#{msg}\n\n#{trace}") }
+          Merb.fatal! "#{failed_classes.join(", ")} failed to load."
+        end
+        break if(klasses.size == size_at_start || klasses.size == 0)
+      end
+
+      nil
+    end
+
+  end
+
+end
+
+# Loads the router file. This needs to happen after everything else is loaded while merb is starting up to ensure
+# the router has everything it needs to run.
+class Merb::BootLoader::Router < Merb::BootLoader
+  class << self
+
+    # load the router file
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: plugin
+    def run
+      Merb::BootLoader::LoadClasses.load_file(router_file) if router_file
+
+      nil
+    end
+
+    # Tries to find the router file.
+    #
+    # ==== Returns
+    # String:: The path to the router file if it exists, nil otherwise.
+    #
+    # :api: private
+    def router_file
+      @router_file ||= begin
+        if File.file?(router = Merb.dir_for(:router) / Merb.glob_for(:router))
+          router
+        end
+      end
+    end
+
+  end
+end
+
+# Precompiles all non-partial templates.
+class Merb::BootLoader::Templates < Merb::BootLoader
+  class << self
+
+    # Loads all non-partial templates into the Merb::InlineTemplates module.
+    #
+    # ==== Returns
+    # Array[String]:: The list of template files which were loaded.
+    #
+    # :api: plugin
+    def run
+      template_paths.each do |path|
+        Merb::Template.inline_template(File.open(path))
+      end
+    end
+
+    # Finds a list of templates to load.
+    #
+    # ==== Returns
+    # Array[String]:: All found template files whose basename does not begin with "_".
+    #
+    # :api: private
+    def template_paths
+      extension_glob = "{#{Merb::Template.template_extensions.join(',')}}"
+
+      # This gets all templates set in the controllers template roots
+      # We separate the two maps because most of controllers will have
+      # the same _template_root, so it's silly to be globbing the same
+      # path over and over.
+      controller_view_paths = []
+      Merb::AbstractController._abstract_subclasses.each do |klass|
+        next if (const = Object.full_const_get(klass))._template_root.blank?
+        controller_view_paths += const._template_roots.map { |pair| pair.first }
+      end
+      template_paths = controller_view_paths.uniq.compact.map { |path| Dir["#{path}/**/*.#{extension_glob}"] }
+
+      # This gets the templates that might be created outside controllers
+      # template roots.  eg app/views/shared/*
+      template_paths << Dir["#{Merb.dir_for(:view)}/**/*.#{extension_glob}"] if Merb.dir_for(:view)
+
+      # This ignores templates for partials, which need to be compiled at use time to generate
+      # a preamble that assigns local variables
+      template_paths.flatten.compact.uniq.grep(%r{^.*/[^_][^/]*$})
+    end
+  end
+end
+
+# Register the default MIME types:
+#
+# By default, the mime-types include:
+# :all:: no transform, */*
+# :yaml:: to_yaml, application/x-yaml or text/yaml
+# :text:: to_text, text/plain
+# :html:: to_html, text/html or application/xhtml+xml or application/html
+# :xml:: to_xml, application/xml or text/xml or application/x-xml
+# :js:: to_json, text/javascript ot application/javascript or application/x-javascript
+# :json:: to_json, application/json or text/x-json
+class Merb::BootLoader::MimeTypes < Merb::BootLoader
+
+  # Registers the default MIME types.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    Merb.add_mime_type(:all,  nil,      %w[*/*])
+    Merb.add_mime_type(:yaml, :to_yaml, %w[application/x-yaml text/yaml], :charset => "utf-8")
+    Merb.add_mime_type(:text, :to_text, %w[text/plain], :charset => "utf-8")
+    Merb.add_mime_type(:html, :to_html, %w[text/html application/xhtml+xml application/html], :charset => "utf-8")
+    Merb.add_mime_type(:xml,  :to_xml,  %w[application/xml text/xml application/x-xml], {:charset => "utf-8"}, 0.9998)
+    Merb.add_mime_type(:js,   :to_json, %w[text/javascript application/javascript application/x-javascript], :charset => "utf-8")
+    Merb.add_mime_type(:json, :to_json, %w[application/json text/x-json], :charset => "utf-8")
+    nil
+  end
+end
+
+# Set up cookies support in Merb::Controller and Merb::Request
+class Merb::BootLoader::Cookies < Merb::BootLoader
+
+  # Set up cookies support in Merb::Controller and Merb::Request
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    require 'merb-core/dispatch/cookies'
+    Merb::Controller.send(:include, Merb::CookiesMixin)
+    Merb::Request.send(:include, Merb::CookiesMixin::RequestMixin)
+    nil
+  end
+
+end
+
+class Merb::BootLoader::SetupSession < Merb::BootLoader
+
+  # Enable the configured session container(s); any class that inherits from
+  # SessionContainer will be considered by its session_store_type attribute.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    # Require all standard session containers.
+    Dir[Merb.framework_root / "merb-core" / "dispatch" / "session" / "*.rb"].each do |file|
+      base_name = File.basename(file, ".rb")
+      require file unless base_name == "container" || base_name == "store_container"
+    end
+
+    # Set some defaults.
+    Merb::Config[:session_id_key] ||= "_session_id"
+
+    # List of all session_stores from :session_stores and :session_store config options.
+    config_stores = Merb::Config.session_stores
+
+    # Register all configured session stores - any loaded session container class
+    # (subclassed from Merb::SessionContainer) will be available for registration.
+    Merb::SessionContainer.subclasses.each do |class_name|
+      if(store = Object.full_const_get(class_name)) &&
+        config_stores.include?(store.session_store_type)
+          Merb::Request.register_session_type(store.session_store_type, class_name)
+      end
+    end
+
+    # Mixin the Merb::Session module to add app-level functionality to sessions
+    overrides = (Merb::Session.instance_methods & Merb::SessionContainer.instance_methods)
+    overrides.each do |m| 
+      Merb.logger.warn!("Warning: Merb::Session##{m} overrides existing " \
+                        "Merb::SessionContainer##{m}")
+    end    
+    Merb::SessionContainer.send(:include, Merb::Session)
+    nil
+  end
+
+end
+
+# In case someone's running a sparse app, the default exceptions require the
+# Exceptions class.  This must run prior to the AfterAppLoads BootLoader
+# So that plugins may have ensured access in the after_app_loads block
+class Merb::BootLoader::SetupStubClasses < Merb::BootLoader
+  # Declares empty Application and Exception controllers.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    unless defined?(Exceptions)
+      Object.class_eval <<-RUBY
+        class Application < Merb::Controller
+          abstract!
+        end
+
+        class Exceptions < Merb::Controller
+        end
+      RUBY
+    end
+    nil
+  end
+end
+
+class Merb::BootLoader::AfterAppLoads < Merb::BootLoader
+
+  # Call any after_app_loads hooks that were registered via after_app_loads in
+  # init.rb.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    Merb::BootLoader.after_load_callbacks.each {|x| x.call }
+    nil
+  end
+end
+
+class Merb::BootLoader::ChooseAdapter < Merb::BootLoader
+
+  # Choose the Rack adapter/server to use and set Merb.adapter.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    Merb.adapter = Merb::Rack::Adapter.get(Merb::Config[:adapter])
+  end
+end
+
+class Merb::BootLoader::RackUpApplication < Merb::BootLoader
+  # Setup the Merb Rack App or read a rackup file located at
+  # Merb::Config[:rackup] with the same syntax as the
+  # rackup tool that comes with rack. Automatically evals the file in
+  # the context of a Rack::Builder.new { } block. Allows for mounting
+  # additional apps or middleware.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    require 'rack'
+    if File.exists?(Merb.dir_for(:config) / "rack.rb")
+      Merb::Config[:rackup] ||= Merb.dir_for(:config) / "rack.rb"
+    end
+
+    if Merb::Config[:rackup]
+      rackup_code = File.read(Merb::Config[:rackup])
+      Merb::Config[:app] = eval("::Rack::Builder.new {( #{rackup_code}\n )}.to_app", TOPLEVEL_BINDING, Merb::Config[:rackup])
+    else
+      Merb::Config[:app] = ::Rack::Builder.new {
+         if prefix = ::Merb::Config[:path_prefix]
+           use Merb::Rack::PathPrefix, prefix
+         end
+         use Merb::Rack::Static, Merb.dir_for(:public)
+         run Merb::Rack::Application.new
+       }.to_app
+    end
+
+    nil
+  end
+end
+
+class Merb::BootLoader::ReloadClasses < Merb::BootLoader
+
+  class TimedExecutor
+    # Executes the associated block every @seconds@ seconds in a separate thread.
+    #
+    # ==== Parameters
+    # seconds<Integer>:: Number of seconds to sleep in between runs of &block.
+    # &block:: The block to execute periodically.
+    #
+    # ==== Returns
+    # Thread:: The thread executing the block periodically.
+    #
+    # :api: private
+    def self.every(seconds, &block)
+      Thread.new do
+        loop do
+          sleep( seconds )
+          yield
+        end
+        Thread.exit
+      end
+    end
+  end
+
+  # Set up the class reloader if class reloading is enabled. This checks periodically
+  # for modifications to files loaded by the LoadClasses BootLoader and reloads them
+  # when they are modified.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: plugin
+  def self.run
+    return unless Merb::Config[:reload_classes]
+
+    paths = []
+    Merb.load_paths.each do |path_name, file_info|
+      path, glob = file_info
+      next unless glob
+      paths << Dir[path / glob]
+    end
+
+    if Merb.dir_for(:application) && File.file?(Merb.dir_for(:application))
+      paths << Merb.dir_for(:application)
+    end
+
+    paths.flatten!
+
+    TimedExecutor.every(Merb::Config[:reload_time] || 0.5) do
+      GC.start
+      reload(paths)
+    end
+
+    nil
+  end
+
+  # Reloads all files which have been modified since they were last loaded.
+  #
+  # ==== Returns
+  # nil
+  #
+  # :api: private
+  def self.reload(paths)
+    paths.each do |file|
+      next if LoadClasses::MTIMES[file] &&
+        LoadClasses::MTIMES[file] == File.mtime(file)
+
+      LoadClasses.reload(file)
+    end
+
+    nil
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/config.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/config.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/config.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,484 @@
+require "optparse"
+
+module Merb
+
+  class Config
+
+    class << self
+
+      # Returns the hash of default config values for Merb.
+      #
+      # ==== Returns
+      # Hash:: The defaults for the config.
+      #
+      # :api: private
+      def defaults
+        @defaults ||= {
+          :host                   => "0.0.0.0",
+          :port                   => "4000",
+          :adapter                => "runner",
+          :reload_classes         => true,
+          :fork_for_class_load    => Merb.forking_environment?,
+          :environment            => "development",
+          :merb_root              => Dir.pwd,
+          :use_mutex              => true,
+          :log_delimiter          => " ~ ",
+          :log_auto_flush         => false,
+          :log_level              => :info,
+          :log_stream             => STDOUT,
+          :disabled_components    => Merb.on_windows? ? [:signals] : [],
+          :deferred_actions       => [],
+          :verbose                => false,
+          :name                   => "merb"
+        }
+      end
+
+      # Yields the configuration.
+      #
+      # ==== Block parameters
+      # c<Hash>:: The configuration parameters.
+      #
+      # ==== Examples
+      #   Merb::Config.use do |config|
+      #     config[:exception_details] = false
+      #     config[:log_stream]        = STDOUT
+      #   end
+      #
+      # ==== Returns
+      # nil
+      #
+      # :api: public
+      def use
+        @configuration ||= {}
+        yield @configuration
+        nil
+      end
+      
+      # Detects whether the provided key is in the config.
+      #
+      # ==== Parameters
+      # key<Object>:: The key to check.
+      #
+      # ==== Returns
+      # Boolean:: True if the key exists in the config.
+      #
+      # :api: public
+      def key?(key)
+        @configuration.key?(key)
+      end
+
+      # Retrieve the value of a config entry.
+      #
+      # ==== Parameters
+      # key<Object>:: The key to retrieve the parameter for.
+      #
+      # ==== Returns
+      # Object:: The value of the configuration parameter.
+      #
+      # :api: public
+      def [](key)
+        (@configuration ||= setup)[key]
+      end
+
+      # Set the value of a config entry.
+      #
+      # ==== Parameters
+      # key<Object>:: The key to set the parameter for.
+      # val<Object>:: The value of the parameter.
+      #
+      # :api: public
+      def []=(key, val)
+        (@configuration ||= setup)[key] = val
+      end
+
+      # Remove the value of a config entry.
+      #
+      # ==== Parameters
+      # key<Object>:: The key of the parameter to delete.
+      #
+      # ==== Returns
+      # Object:: The value of the removed entry.
+      #
+      # :api: public
+      def delete(key)
+        @configuration.delete(key)
+      end
+
+      # Retrieve the value of a config entry, returning the provided default if the key is not present
+      #
+      # ==== Parameters
+      # key<Object>:: The key to retrieve the parameter for.
+      # default<Object>::
+      #   The default value to return if the parameter is not set.
+      #
+      # ==== Returns
+      # Object:: The value of the configuration parameter or the default.
+      #
+      # :api: public
+      def fetch(key, default)
+        @configuration.fetch(key, default)
+      end
+
+      # Returns the configuration as a hash.
+      #
+      # ==== Returns
+      # Hash:: The config as a hash.
+      #
+      # :api: public
+      def to_hash
+        @configuration
+      end
+
+      # Returns the config as YAML.
+      #
+      # ==== Returns
+      # String:: The config as YAML.
+      #
+      # :api: public
+      def to_yaml
+        require "yaml"
+        @configuration.to_yaml
+      end
+
+      # Sets up the configuration by storing the given settings.
+      #
+      # ==== Parameters
+      # settings<Hash>::
+      #   Configuration settings to use. These are merged with the defaults.
+      #
+      # ==== Returns
+      # The configuration as a hash.
+      #
+      # :api: private
+      def setup(settings = {})
+        config = defaults.merge(settings)
+        
+        unless config[:reload_classes]
+          config[:fork_for_class_load] = false
+        end
+
+        dev_mode = config[:environment] == "development"
+        unless config.key?(:reap_workers_quickly)
+          config[:reap_workers_quickly] = dev_mode & !config[:cluster]
+        end
+        
+        unless config.key?(:bind_fail_fatal)
+          config[:bind_fail_fatal] = dev_mode
+        end
+        
+        @configuration = config
+      end
+
+      # Parses the command line arguments and stores them in the config.
+      #
+      # ==== Parameters
+      # argv<String>:: The command line arguments. Defaults to +ARGV+.
+      #
+      # ==== Returns
+      # The configuration as a hash.
+      #
+      # :api: private
+      def parse_args(argv = ARGV)
+        @configuration ||= {}
+        # Our primary configuration hash for the length of this method
+        options = {}
+
+        # Environment variables always win
+        options[:environment] = ENV["MERB_ENV"] if ENV["MERB_ENV"]
+        
+        # Build a parser for the command line arguments
+        opts = OptionParser.new do |opts|
+          opts.version = Merb::VERSION
+
+          opts.banner = "Usage: merb [uGdcIpPhmailLerkKX] [argument]"
+          opts.define_head "Merb. Pocket rocket web framework"
+          opts.separator '*' * 80
+          opts.separator "If no flags are given, Merb starts in the " \
+            "foreground on port 4000."
+          opts.separator '*' * 80
+
+          opts.on("-u", "--user USER", "This flag is for having merb run " \
+                  "as a user other than the one currently logged in. Note: " \
+                  "if you set this you must also provide a --group option " \
+                  "for it to take effect.") do |user|
+            options[:user] = user
+          end
+
+          opts.on("-G", "--group GROUP", "This flag is for having merb run " \
+                  "as a group other than the one currently logged in. Note: " \
+                  "if you set this you must also provide a --user option " \
+                  "for it to take effect.") do |group|
+            options[:group] = group
+          end
+
+          opts.on("-d", "--daemonize", "This will run a single merb in the " \
+                  "background.") do |daemon|
+            options[:daemonize] = true
+          end
+          
+          opts.on("-N", "--no-daemonize", "This will allow you to run a " \
+                  "cluster in console mode") do |no_daemon|
+            options[:daemonize] = false
+          end
+
+          opts.on("-c", "--cluster-nodes NUM_MERBS", Integer, 
+                  "Number of merb daemons to run.") do |nodes|
+            options[:daemonize] = true unless options.key?(:daemonize)
+            options[:cluster] = nodes
+          end
+
+          opts.on("-I", "--init-file FILE", "File to use for initialization " \
+                  "on load, defaults to config/init.rb") do |init_file|
+            options[:init_file] = init_file
+          end
+
+          opts.on("-p", "--port PORTNUM", Integer, "Port to run merb on, " \
+                  "defaults to 4000.") do |port|
+            options[:port] = port
+          end
+
+          opts.on("-o", "--socket-file FILE", "Socket file to run merb on, " \
+                  "defaults to [Merb.root]/log/merb.sock. This is for " \
+                  "web servers, like thin, that use sockets." \
+                  "Specify this *only* if you *must*.") do |port|
+            options[:socket_file] = port
+          end
+
+          opts.on("-s", "--socket SOCKNUM", Integer, "Socket number to run " \
+                  "merb on, defaults to 0.") do |port|
+            options[:socket] = port
+          end
+
+          opts.on("-n", "--name NAME", String, "Set the name of the application. "\
+                  "This is used in the process title and log file names.") do |name|
+            options[:name] = name
+          end
+
+          opts.on("-P", "--pid PIDFILE", "PID file, defaults to " \
+                  "[Merb.root]/log/merb.main.pid for the master process and" \
+                  "[Merb.root]/log/merb.[port number].pid for worker " \
+                  "processes. For clusters, use %s to specify where " \
+                  "in the file merb should place the port number. For " \
+                  "instance: -P myapp.%s.pid") do |pid_file|
+            options[:pid_file] = pid_file
+          end
+
+          opts.on("-h", "--host HOSTNAME", "Host to bind to " \
+                  "(default is 0.0.0.0).") do |host|
+            options[:host] = host
+          end
+
+          opts.on("-m", "--merb-root /path/to/approot", "The path to the " \
+                  "Merb.root for the app you want to run " \
+                  "(default is current working directory).") do |root|
+            options[:merb_root] = File.expand_path(root)
+          end
+
+          adapters = [:mongrel, :emongrel, :thin, :ebb, :fastcgi, :webrick]
+
+          opts.on("-a", "--adapter ADAPTER",
+                  "The rack adapter to use to run merb (default is mongrel)" \
+                  "[#{adapters.join(', ')}]") do |adapter|
+            options[:adapter] ||= adapter
+          end
+
+          opts.on("-R", "--rackup FILE", "Load an alternate Rack config " \
+                  "file (default is config/rack.rb)") do |rackup|
+            options[:rackup] = rackup
+          end
+
+          opts.on("-i", "--irb-console", "This flag will start merb in " \
+                  "irb console mode. All your models and other classes will " \
+                  "be available for you in an irb session.") do |console|
+            options[:adapter] = 'irb'
+          end
+
+          opts.on("-S", "--sandbox", "This flag will enable a sandboxed irb " \
+                  "console. If your ORM supports transactions, all edits will " \
+                  "be rolled back on exit.") do |sandbox|
+            options[:sandbox] = true
+          end
+
+          opts.on("-l", "--log-level LEVEL", "Log levels can be set to any of " \
+                  "these options: debug < info < warn < error < " \
+                  "fatal (default is info)") do |log_level|
+            options[:log_level] = log_level.to_sym
+            options[:force_logging] = true
+          end
+
+          opts.on("-L", "--log LOGFILE", "A string representing the logfile to " \
+                  "use. Defaults to [Merb.root]/log/merb.[main].log for the " \
+                  "master process and [Merb.root]/log/merb[port number].log" \
+                  "for worker processes") do |log_file|
+            options[:log_file] = log_file
+            options[:force_logging] = true
+          end
+
+          opts.on("-e", "--environment STRING", "Environment to run Merb " \
+                  "under [development, production, testing] " \
+                  "(default is development)") do |env|
+            options[:environment] = env
+          end
+
+          opts.on("-r", "--script-runner ['RUBY CODE'| FULL_SCRIPT_PATH]",
+                  "Command-line option to run scripts and/or code in the " \
+                  "merb app.") do |code_or_file|
+            options[:runner_code] = code_or_file
+            options[:adapter] = 'runner'
+          end
+
+          opts.on("-K", "--graceful PORT or all", "Gracefully kill one " \
+                  "merb proceses by port number.  Use merb -K all to " \
+                  "gracefully kill all merbs.") do |ports|
+            options[:action] = :kill
+            ports = "main" if ports == "all"
+            options[:port] = ports
+          end
+
+          opts.on("-k", "--kill PORT", "Force kill one merb worker " \
+                  "by port number. This will cause the worker to" \
+                  "be respawned.") do |port|
+            options[:action] = :kill_9
+            port = "main" if port == "all"
+            options[:port] = port
+          end
+          
+          opts.on("--fast-deploy", "Reload the code, but not your" \
+            "init.rb or gems") do
+              options[:action] = :fast_deploy
+          end
+
+          # @todo Do we really need this flag? It seems unlikely to want to
+          #   change the mutex from the command-line.
+          opts.on("-X", "--mutex on/off", "This flag is for turning the " \
+                  "mutex lock on and off.") do |mutex|
+            if mutex == "off"
+              options[:use_mutex] = false
+            else
+              options[:use_mutex] = true
+            end
+          end
+
+          opts.on("-D", "--debugger", "Run merb using rDebug.") do
+            begin
+              require "ruby-debug"
+              Debugger.start
+
+              # Load up any .rdebugrc files we find
+              [".", ENV["HOME"], ENV["HOMEPATH"]].each do |script_dir|
+                script_file = "#{script_dir}/.rdebugrc"
+                Debugger.run_script script_file, StringIO.new if File.exists?(script_file)
+              end
+
+              if Debugger.respond_to?(:settings)
+                Debugger.settings[:autoeval] = true
+              end
+              puts "Debugger enabled"
+            rescue LoadError
+              puts "You need to install ruby-debug to run the server in " \
+                "debugging mode. With gems, use `gem install ruby-debug'"
+              exit
+            end
+          end
+
+          opts.on("-V", "--verbose", "Print extra information") do
+            options[:verbose] = true
+          end
+
+          opts.on("-C", "--console-trap", "Enter an irb console on ^C") do
+            options[:console_trap] = true
+          end
+
+          opts.on("-?", "-H", "--help", "Show this help message") do
+            puts opts
+            exit
+          end
+        end
+
+        # Parse what we have on the command line
+        begin
+          opts.parse!(argv)
+        rescue OptionParser::InvalidOption => e
+          Merb.fatal! e.message, e
+        end
+        Merb::Config.setup(options)
+      end
+
+      # :api: private
+      attr_accessor :configuration
+
+      # Set configuration parameters from a code block, where each method
+      # evaluates to a config parameter.
+      #
+      # ==== Parameters
+      # &block:: Configuration parameter block.
+      #
+      # ==== Examples
+      #   # Set environment and log level.
+      #   Merb::Config.configure do
+      #     environment "development"
+      #     log_level   "debug"
+      #     log_file    Merb.root / "log" / "special.log"
+      #   end
+      #
+      # ==== Returns
+      # nil
+      #
+      # :api: public
+      def configure(&block)
+        ConfigBlock.new(self, &block) if block_given?
+        nil
+      end
+
+      # Allows retrieval of single key config values via Merb.config.<key>
+      # Allows single key assignment via Merb.config.<key> = ...
+      #
+      # ==== Parameters
+      # method<~to_s>:: Method name as hash key value.
+      # *args:: Value to set the configuration parameter to.
+      #
+      # ==== Returns
+      # The value of the entry fetched or assigned to.
+      #
+      # :api: public
+      def method_missing(method, *args)
+        if method.to_s[-1,1] == '='
+          @configuration[method.to_s.tr('=','').to_sym] = *args
+        else
+          @configuration[method]
+        end
+      end
+
+    end # class << self
+
+    class ConfigBlock
+
+      # Evaluates the provided block, where any call to a method causes
+      # #[]= to be called on klass with the method name as the key and the arguments
+      # as the value.
+      #
+      # ==== Parameters
+      # klass<Object~[]=>:: The object on which to assign values.
+      # &block:: The block which specifies the config values to set.
+      #
+      # ==== Returns
+      # nil
+      #
+      # :api: private
+      def initialize(klass, &block)
+        @klass = klass
+        instance_eval(&block)
+      end
+
+      # Assign args as the value of the entry keyed by method.
+      #
+      # :api: private
+      def method_missing(method, *args)
+        @klass[method] = *args
+      end
+
+    end # class Configurator
+
+  end # Config
+
+end # Merb

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/constants.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/constants.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/constants.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,100 @@
+# Most of this list is simply constants frozen for efficiency
+# and lowered memory consumption. Every time Ruby VM comes
+# across a string or a number or a regexp literal,
+# new object is created.
+#
+# This means if you refer to the same string 6 times per request
+# and your application takes 100 requests per second, there are
+# 600 objects for weak MRI garbage collector to work on.
+#
+# GC cycles take up to 80% (!) time of request processing in
+# some cases. Eventually Rubinius and maybe MRI 2.0 gonna
+# improve this situation but at the moment, all commonly used
+# strings, regexp and numbers used as constants so no extra
+# objects created and VM just operates pointers.
+module Merb
+  module Const
+
+    DEFAULT_SEND_FILE_OPTIONS = {
+      :type         => 'application/octet-stream'.freeze,
+      :disposition  => 'attachment'.freeze
+    }.freeze
+
+    RACK_INPUT               = 'rack.input'.freeze
+    SET_COOKIE               = " %s=%s; path=/; expires=%s".freeze
+    COOKIE_EXPIRATION_FORMAT = "%a, %d-%b-%Y %H:%M:%S GMT".freeze
+    COOKIE_SPLIT             = /[;,] */n.freeze
+    COOKIE_REGEXP            = /\s*(.+)=(.*)\s*/.freeze
+    COOKIE_EXPIRED_TIME      = Time.at(0).freeze
+    ACCEPT_SPLIT             = /,/.freeze
+    SLASH_SPLIT              = %r{/}.freeze
+    MEDIA_RANGE              = /\s*([^;\s]*)\s*(;\s*q=\s*(.*))?/.freeze
+    HOUR                     = 60 * 60
+    DAY                      = HOUR * 24
+    WEEK                     = DAY * 7
+    MULTIPART_REGEXP         = /\Amultipart\/form-data.*boundary=\"?([^\";,]+)/n.freeze
+    HTTP_COOKIE              = 'HTTP_COOKIE'.freeze
+    QUERY_STRING             = 'QUERY_STRING'.freeze
+    JSON_MIME_TYPE_REGEXP    = %r{^application/json|^text/x-json}.freeze
+    XML_MIME_TYPE_REGEXP     = %r{^application/xml|^text/xml}.freeze
+    FORM_URL_ENCODED_REGEXP  = %r{^application/x-www-form-urlencoded}.freeze
+    LOCAL_IP_REGEXP          = /^unknown$|^(127|10|172\.16|192\.168)\.|^(172\.(1[6-9]|2[0-9]|3[0-1]))\.|^(169\.254)\./i.freeze
+    XML_HTTP_REQUEST_REGEXP  = /XMLHttpRequest/i.freeze
+    UPCASE_CONTENT_TYPE      = 'CONTENT_TYPE'.freeze
+    CONTENT_TYPE             = "Content-Type".freeze
+    DATE                     = 'Date'.freeze
+    UPCASE_HTTPS             = 'HTTPS'.freeze
+    HTTPS                    = 'https'.freeze
+    HTTP                     = 'http'.freeze
+    ETAG                     = 'ETag'.freeze
+    LAST_MODIFIED            = "Last-Modified".freeze
+    GET                      = "GET".freeze
+    POST                     = "POST".freeze
+    HEAD                     = "HEAD".freeze
+    CONTENT_LENGTH           = "CONTENT_LENGTH".freeze
+    HTTP_CLIENT_IP           = "HTTP_CLIENT_IP".freeze
+    HTTP_X_REQUESTED_WITH    = "HTTP_X_REQUESTED_WITH".freeze
+    HTTP_X_FORWARDED_FOR     = "HTTP_X_FORWARDED_FOR".freeze
+    HTTP_X_FORWARDED_PROTO   = "HTTP_X_FORWARDED_PROTO".freeze
+    HTTP_X_FORWARDED_HOST    = "HTTP_X_FORWARDED_HOST".freeze
+    HTTP_IF_MODIFIED_SINCE   = "HTTP_IF_MODIFIED_SINCE".freeze
+    HTTP_IF_NONE_MATCH       = "HTTP_IF_NONE_MATCH".freeze
+    HTTP_CONTENT_TYPE        = "HTTP_CONTENT_TYPE".freeze
+    HTTP_CONTENT_LENGTH      = "HTTP_CONTENT_LENGTH".freeze
+    HTTP_REFERER             = "HTTP_REFERER".freeze
+    HTTP_USER_AGENT          = "HTTP_USER_AGENT".freeze
+    HTTP_HOST                = "HTTP_HOST".freeze
+    HTTP_CONNECTION          = "HTTP_CONNECTION".freeze
+    HTTP_KEEP_ALIVE          = "HTTP_KEEP_ALIVE".freeze
+    HTTP_ACCEPT              = "HTTP_ACCEPT".freeze
+    HTTP_ACCEPT_ENCODING     = "HTTP_ACCEPT_ENCODING".freeze
+    HTTP_ACCEPT_LANGUAGE     = "HTTP_ACCEPT_LANGUAGE".freeze
+    HTTP_ACCEPT_CHARSET      = "HTTP_ACCEPT_CHARSET".freeze
+    HTTP_CACHE_CONTROL       = "HTTP_CACHE_CONTROL".freeze
+    UPLOAD_ID                = "upload_id".freeze
+    PATH_INFO                = "PATH_INFO".freeze
+    HTTP_VERSION             = "HTTP_VERSION".freeze
+    GATEWAY_INTERFACE        = "GATEWAY_INTERFACE".freeze
+    SCRIPT_NAME              = "SCRIPT_NAME".freeze
+    SERVER_NAME              = "SERVER_NAME".freeze
+    SERVER_SOFTWARE          = "SERVER_SOFTWARE".freeze
+    SERVER_PROTOCOL          = "SERVER_PROTOCOL".freeze
+    SERVER_PORT              = "SERVER_PORT".freeze
+    REQUEST_URI              = "REQUEST_URI".freeze
+    REQUEST_PATH             = "REQUEST_PATH".freeze
+    REQUEST_METHOD           = "REQUEST_METHOD".freeze
+    REMOTE_ADDR              = "REMOTE_ADDR".freeze
+    BREAK_TAG                = "<br/>".freeze
+    EMPTY_STRING             = "".freeze
+    NEWLINE                  = "\n".freeze
+    SLASH                    = "/".freeze
+    DOT                      = ".".freeze
+    QUESTION_MARK            = "?".freeze
+    DOUBLE_NEWLINE           = "\n\n".freeze
+    LOCATION                 = "Location".freeze
+    TEXT_SLASH_HTML          = "text/html".freeze
+
+    WIN_PLATFORM_REGEXP      = /(:?mswin|mingw)/.freeze
+    JAVA_PLATFORM_REGEXP     = /java/.freeze
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/abstract_controller.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/abstract_controller.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/abstract_controller.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,718 @@
+# ==== Why do we use Underscores?
+# In Merb, views are actually methods on controllers. This provides
+# not-insignificant speed benefits, as well as preventing us from
+# needing to copy over instance variables, which we think is proof
+# that everything belongs in one class to begin with.
+#
+# Unfortunately, this means that view helpers need to be included
+# into the <strong>Controller</strong> class. To avoid causing confusion
+# when your helpers potentially conflict with our instance methods,
+# we use an _ to disambiguate. As long as you don't begin your helper
+# methods with _, you only need to worry about conflicts with Merb
+# methods that are part of the public API.
+#
+#
+#
+# ==== Filters
+# #before is a class method that allows you to specify before filters in
+# your controllers. Filters can either be a symbol or string that
+# corresponds to a method name to call, or a proc object. if it is a method
+# name that method will be called and if it is a proc it will be called
+# with an argument of self where self is the current controller object.
+# When you use a proc as a filter it needs to take one parameter.
+# 
+# #after is identical, but the filters are run after the action is invoked.
+#
+# ===== Examples
+#   before :some_filter
+#   before :authenticate, :exclude => [:login, :signup]
+#   before :has_role, :with => ["Admin"], :exclude => [:index, :show]
+#   before Proc.new { some_method }, :only => :foo
+#   before :authorize, :unless => :logged_in?  
+#
+# You can use either <code>:only => :actionname</code> or 
+# <code>:exclude => [:this, :that]</code> but not both at once. 
+# <code>:only</code> will only run before the listed actions and 
+# <code>:exclude</code> will run for every action that is not listed.
+#
+# Merb's before filter chain is very flexible. To halt the filter chain you
+# use <code>throw :halt</code>. If <code>throw</code> is called with only one 
+# argument of <code>:halt</code> the return value of the method 
+# <code>filters_halted</code> will be what is rendered to the view. You can 
+# override <code>filters_halted</code> in your own controllers to control what 
+# it outputs. But the <code>throw</code> construct is much more powerful than 
+# just that.
+#
+# <code>throw :halt</code> can also take a second argument. Here is what that 
+# second argument can be and the behavior each type can have:
+#
+# * +String+:
+#   when the second argument is a string then that string will be what
+#   is rendered to the browser. Since merb's <code>#render</code> method returns
+#   a string you can render a template or just use a plain string:
+#
+#     throw :halt, "You don't have permissions to do that!"
+#     throw :halt, render(:action => :access_denied)
+#
+# * +Symbol+:
+#   If the second arg is a symbol, then the method named after that
+#   symbol will be called
+#
+#     throw :halt, :must_click_disclaimer
+#
+# * +Proc+:
+#   If the second arg is a Proc, it will be called and its return
+#   value will be what is rendered to the browser:
+#
+#     throw :halt, proc { access_denied }
+#     throw :halt, proc { Tidy.new(c.index) }
+#
+# ===== Filter Options (.before, .after, .add_filter, .if, .unless)
+# :only<Symbol, Array[Symbol]>::
+#   A list of actions that this filter should apply to
+#
+# :exclude<Symbol, Array[Symbol]::
+#   A list of actions that this filter should *not* apply to
+# 
+# :if<Symbol, Proc>::
+#   Only apply the filter if the method named after the symbol or calling the proc evaluates to true
+# 
+# :unless<Symbol, Proc>::
+#   Only apply the filter if the method named after the symbol or calling the proc evaluates to false
+#
+# :with<Array[Object]>::
+#   Arguments to be passed to the filter. Since we are talking method/proc calls,
+#   filter method or Proc should to have the same arity
+#   as number of elements in Array you pass to this option.
+#
+# ===== Types (shortcuts for use in this file)
+# Filter:: <Array[Symbol, (Symbol, String, Proc)]>
+#
+# ==== params[:action] and params[:controller] deprecated
+# <code>params[:action]</code> and <code>params[:controller]</code> have been deprecated as of
+# the 0.9.0 release. They are no longer set during dispatch, and
+# have been replaced by <code>action_name</code> and <code>controller_name</code> respectively.
+
+module Merb
+  module InlineTemplates; end
+  
+  class AbstractController
+    include Merb::RenderMixin
+    include Merb::InlineTemplates
+
+    class_inheritable_accessor :_layout, :_template_root, :template_roots
+    class_inheritable_accessor :_before_filters, :_after_filters
+    class_inheritable_accessor :_before_dispatch_callbacks, :_after_dispatch_callbacks
+
+    cattr_accessor :_abstract_subclasses
+
+    # :api: plugin
+    attr_accessor :body, :action_name, :_benchmarks
+    # :api: private
+    attr_accessor :_thrown_content  
+
+    # Stub so content-type support in RenderMixin doesn't throw errors
+    # :api: private
+    attr_accessor :content_type
+
+    FILTER_OPTIONS = [:only, :exclude, :if, :unless, :with]
+
+    self._before_filters, self._after_filters = [], []
+    self._before_dispatch_callbacks, self._after_dispatch_callbacks = [], []
+
+    #---
+    # We're using abstract_subclasses so that Merb::Controller can have its
+    # own subclasses. We're using a Set so we don't have to worry about
+    # uniqueness.
+    self._abstract_subclasses = Set.new
+
+    # ==== Returns
+    # String:: The controller name in path form, e.g. "admin/items".
+    # :api: public
+    def self.controller_name() @controller_name ||= self.name.to_const_path end
+
+    # ==== Returns
+    # String:: The controller name in path form, e.g. "admin/items".
+    #
+    # :api: public
+    def controller_name()      self.class.controller_name                   end
+  
+    # This is called after the controller is instantiated to figure out where to
+    # look for templates under the _template_root. Override this to define a new
+    # structure for your app.
+    #
+    # ==== Parameters
+    # context<~to_s>:: The controller context (the action or template name).
+    # type<~to_s>:: The content type. Could be nil. 
+    # controller<~to_s>::
+    #   The name of the controller. Defaults to being called with the controller_name.  Set t
+    #
+    #
+    # ==== Returns
+    # String:: 
+    #   Indicating where to look for the template for the current controller,
+    #   context, and content-type.
+    #
+    # ==== Notes
+    # The type is irrelevant for controller-types that don't support
+    # content-type negotiation, so we default to not include it in the
+    # superclass.
+    #
+    # ==== Examples
+    #   def _template_location
+    #     "#{params[:controller]}.#{params[:action]}.#{content_type}"
+    #   end
+    #
+    # This would look for templates at controller.action.mime.type instead
+    # of controller/action.mime.type
+    #
+    # :api: public
+    # @overridable
+    def _template_location(context, type, controller)
+      controller ? "#{controller}/#{context}" : context
+    end
+
+    # The location to look for a template - override this method for particular behaviour. 
+    #
+    # ==== Parameters
+    # template<String>:: The absolute path to a template - without template extension.
+    # type<~to_s>::
+    #    The mime-type of the template that will be rendered. Defaults to being called with nil.
+    #
+    # :api: public
+    # @overridable
+    def _absolute_template_location(template, type)
+      template
+    end
+
+    # Resets the template roots to the template root passed in.
+    #
+    # ==== Parameters
+    # root<~to_s>:: 
+    #   The new path to set the template root to.  
+    #
+    # :api: public
+    def self._template_root=(root)
+      @_template_root = root
+      _reset_template_roots
+    end
+
+    # Reset the template root based on the @_template_root ivar.
+    #
+    # :api: private
+    def self._reset_template_roots
+      self.template_roots = [[self._template_root, :_template_location]]
+    end
+
+    # ==== Returns
+    # roots<Array[Array]>::
+    #   Template roots as pairs of template root path and template location
+    #   method.
+    #
+    # :api: plugin
+    def self._template_roots
+      self.template_roots || _reset_template_roots
+    end
+
+    # ==== Parameters
+    # roots<Array[Array]>::
+    #   Template roots as pairs of template root path and template location
+    #   method.
+    #
+    # :api: plugin
+    def self._template_roots=(roots)
+      self.template_roots = roots
+    end
+  
+    # Returns the list of classes that have specifically subclassed AbstractController.  
+    # Does not include all decendents.  
+    #
+    # ==== Returns
+    # Set:: The subclasses.
+    #
+    # :api: private
+    def self.subclasses_list() _abstract_subclasses end
+  
+    # ==== Parameters
+    # klass<Merb::AbstractController>::
+    #   The controller that is being inherited from Merb::AbstractController
+    #
+    # :api: private
+    def self.inherited(klass)
+      _abstract_subclasses << klass.to_s
+      helper_module_name = klass.to_s =~ /^(#|Merb::)/ ? "#{klass}Helper" : "Merb::#{klass}Helper"
+      Object.make_module helper_module_name
+      klass.class_eval <<-HERE
+        include Object.full_const_get("#{helper_module_name}") rescue nil
+      HERE
+      super
+    end    
+  
+    # This will initialize the controller, it is designed to be overridden in subclasses (like MerbController)
+    # ==== Parameters
+    # *args:: The args are ignored in this class, but we need this so that subclassed initializes can have parameters
+    #
+    # :api: private
+    def initialize(*args)
+      @_benchmarks = {}
+      @_caught_content = {}
+    end
+  
+    # This will dispatch the request, calling internal before/after dispatch callbacks.  
+    # If the return value of _call_filters is not :filter_chain_completed the action is not called, and the return from the filters is used instead. 
+    # 
+    # ==== Parameters
+    # action<~to_s>::
+    #   The action to dispatch to. This will be #send'ed in _call_action.
+    #   Defaults to :to_s.
+    #
+    # ==== Returns
+    # <~to_s>::
+    #   Returns the string that was returned from the action. 
+    #
+    # ==== Raises
+    # ArgumentError:: Invalid result caught from before filters.
+    #
+    # :api: plugin
+    def _dispatch(action)
+      self.action_name = action
+      self._before_dispatch_callbacks.each { |cb| cb.call(self) }
+
+      caught = catch(:halt) do
+        start = Time.now
+        result = _call_filters(_before_filters)
+        @_benchmarks[:before_filters_time] = Time.now - start if _before_filters
+        result
+      end
+  
+      @body = case caught
+      when :filter_chain_completed  then _call_action(action_name)
+      when String                   then caught
+      # return *something* if you throw halt with nothing
+      when nil                      then "<html><body><h1>Filter Chain Halted!</h1></body></html>"
+      when Symbol                   then __send__(caught)
+      when Proc                     then self.instance_eval(&caught)
+      else
+        raise ArgumentError, "Threw :halt, #{caught}. Expected String, nil, Symbol, Proc."
+      end
+      start = Time.now
+      _call_filters(_after_filters)
+      @_benchmarks[:after_filters_time] = Time.now - start if _after_filters
+    
+      self._after_dispatch_callbacks.each { |cb| cb.call(self) }
+    
+      @body
+    end
+  
+    # This method exists to provide an overridable hook for ActionArgs.  It uses #send to call the action method.
+    #
+    # ==== Parameters
+    # action<~to_s>:: the action method to dispatch to
+    #
+    # :api: plugin
+    # @overridable
+    def _call_action(action)
+      send(action)
+    end
+  
+    # Calls a filter chain. 
+    #
+    # ==== Parameters
+    # filter_set<Array[Filter]>::
+    #   A set of filters in the form [[:filter, rule], [:filter, rule]]
+    #
+    # ==== Returns
+    # Symbol:: :filter_chain_completed.
+    #
+    # ==== Notes
+    # Filter rules can be Symbols, Strings, or Procs.
+    #
+    # Symbols or Strings::
+    #   Call the method represented by the +Symbol+ or +String+.
+    # Procs::
+    #   Execute the +Proc+, in the context of the controller (self will be the
+    #   controller)
+    #
+    # :api: private
+    def _call_filters(filter_set)
+      (filter_set || []).each do |filter, rule|
+        if _call_filter_for_action?(rule, action_name) && _filter_condition_met?(rule)
+          case filter
+          when Symbol, String
+            if rule.key?(:with)
+              args = rule[:with]
+              send(filter, *args)
+            else
+              send(filter)
+            end
+          when Proc then self.instance_eval(&filter)
+          end
+        end
+      end
+      return :filter_chain_completed
+    end
+
+    # Determine whether the filter should be called for the current action using :only and :exclude.
+    #
+    # ==== Parameters
+    # rule<Hash>:: Rules for the filter (see below).
+    # action_name<~to_s>:: The name of the action to be called.
+    #
+    # ==== Options (rule)
+    # :only<Array>::
+    #   Optional list of actions to fire. If given, action_name must be a part of
+    #   it for this function to return true.
+    # :exclude<Array>::
+    #   Optional list of actions not to fire. If given, action_name must not be a
+    #   part of it for this function to return true.
+    #
+    # ==== Returns
+    # Boolean:: True if the action should be called.
+    #
+    # :api: private
+    def _call_filter_for_action?(rule, action_name)
+      # Both:
+      # * no :only or the current action is in the :only list
+      # * no :exclude or the current action is not in the :exclude list
+      (!rule.key?(:only) || rule[:only].include?(action_name)) &&
+      (!rule.key?(:exclude) || !rule[:exclude].include?(action_name))
+    end
+
+    # Determines whether the filter should be run based on the conditions passed (:if and :unless)
+    #
+    # ==== Parameters
+    # rule<Hash>:: Rules for the filter (see below).
+    #
+    # ==== Options (rule)
+    # :if<Array>:: Optional conditions that must be met for the filter to fire.
+    # :unless<Array>::
+    #   Optional conditions that must not be met for the filter to fire.
+    #
+    # ==== Returns
+    # Boolean:: True if the conditions are met.
+    #
+    # :api: private
+    def _filter_condition_met?(rule)
+      # Both:
+      # * no :if or the if condition evaluates to true
+      # * no :unless or the unless condition evaluates to false
+      (!rule.key?(:if) || _evaluate_condition(rule[:if])) &&
+      (!rule.key?(:unless) || ! _evaluate_condition(rule[:unless]))
+    end
+
+    # Evaluates a filter condition (:if or :unless)
+    #
+    # ==== Parameters
+    # condition<Symbol, Proc>:: The condition to evaluate.
+    #
+    # ==== Raises
+    # ArgumentError:: condition not a Symbol or Proc.
+    #
+    # ==== Returns
+    # Boolean:: True if the condition is met.
+    #
+    # ==== Alternatives
+    # If condition is a symbol, it will be send'ed. If it is a Proc it will be
+    # called directly with self as an argument.
+    #
+    # :api: private
+    def _evaluate_condition(condition)
+      case condition
+      when Symbol then self.send(condition)
+      when Proc then self.instance_eval(&condition)
+      else
+        raise ArgumentError,
+              'Filter condtions need to be either a Symbol or a Proc'
+      end
+    end
+
+    # Adds a filter to the after filter chain
+    # ==== Parameters
+    # filter<Symbol, Proc>:: The filter to add. Defaults to nil.
+    # opts<Hash>::
+    #   Filter options (see class documentation under <tt>Filter Options</tt>).
+    # &block:: A block to use as a filter if filter is nil.
+    #
+    # ==== Notes
+    # If the filter already exists, its options will be replaced with opts.;
+    #
+    # :api: public
+    def self.after(filter = nil, opts = {}, &block)
+      add_filter(self._after_filters, filter || block, opts)
+    end
+
+    # Adds a filter to the before filter chain.  
+    #
+    # ==== Parameters
+    # filter<Symbol, Proc>:: The filter to add. Defaults to nil.
+    # opts<Hash>::
+    #   Filter options (see class documentation under <tt>Filter Options</tt>).
+    # &block:: A block to use as a filter if filter is nil.
+    #
+    # ==== Notes
+    # If the filter already exists, its options will be replaced with opts.
+    #
+    # :api: public
+    def self.before(filter = nil, opts = {}, &block)
+      add_filter(self._before_filters, filter || block, opts)
+    end
+     
+    # Removes a filter from the after filter chain.  This removes the 
+    # filter from the filter chain for the whole controller and does not 
+    # take any options. 
+    #
+    # ==== Parameters
+    # filter<Symbol, String>:: A filter name to skip.
+    #
+    # :api: public
+    def self.skip_after(filter)
+      skip_filter(self._after_filters, filter)
+    end
+  
+    # Removes a filter from the before filter chain.  This removes the 
+    # filter from the filter chain for the whole controller and does not 
+    # take any options.
+    #
+    # ==== Parameters
+    # filter<Symbol, String>:: A filter name to skip.
+    #
+    # :api: public
+    def self.skip_before(filter)
+      skip_filter(self._before_filters , filter)
+    end  
+
+    # There are three possible ways to use this method.  First, if you have a named route, 
+    # you can specify the route as the first parameter as a symbol and any paramters in a 
+    # hash.  Second, you can generate the default route by just passing the params hash, 
+    # just passing the params hash.  Finally, you can use the anonymous parameters.  This 
+    # allows you to specify the parameters to a named route in the order they appear in the 
+    # router.  
+    #
+    # ==== Parameters(Named Route)
+    # name<Symbol>:: 
+    #   The name of the route. 
+    # args<Hash>:: 
+    #   Parameters for the route generation.
+    #
+    # ==== Parameters(Default Route)
+    # args<Hash>:: 
+    #   Parameters for the route generation.  This route will use the default route. 
+    #
+    # ==== Parameters(Anonymous Parameters)
+    # name<Symbol>::
+    #   The name of the route.  
+    # args<Array>:: 
+    #   An array of anonymous parameters to generate the route
+    #   with. These parameters are assigned to the route parameters
+    #   in the order that they are passed.
+    #
+    # ==== Returns
+    # String:: The generated URL.
+    #
+    # ==== Examples
+    # Named Route
+    #
+    # Merb::Router.prepare do
+    #   match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+    # end
+    #
+    # url(:articles, :title => "new_article")
+    #
+    # Default Route
+    #
+    # Merb::Router.prepare do
+    #   default_routes
+    # end
+    #
+    # url(:controller => "articles", :action => "new")
+    #
+    # Anonymous Paramters
+    #
+    # Merb::Router.prepare do
+    #   match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+    # end
+    #
+    # url(:articles, 2008, 10, "test_article")
+    #
+    # :api: public
+    def url(name, *args)
+      args << {}
+      Merb::Router.url(name, *args)
+    end
+  
+    alias_method :relative_url, :url
+
+    # Returns the absolute url including the passed protocol and host.  
+    # 
+    # This uses the same arguments as the url method, with added requirements 
+    # of protocol and host options. 
+    #
+    # :api: public
+    def absolute_url(*args)
+      # FIXME: arrgh, why request.protocol returns http://?
+      # :// is not part of protocol name
+      options  = extract_options_from_args!(args) || {}
+      protocol = options.delete(:protocol)
+      host     = options.delete(:host)
+    
+      raise ArgumentError, "The :protocol option must be specified" unless protocol
+      raise ArgumentError, "The :host option must be specified"     unless host
+    
+      args << options
+    
+      protocol + "://" + host + url(*args)
+    end
+  
+    # Generates a URL for a single or nested resource.
+    #
+    # ==== Parameters
+    # resources<Symbol,Object>:: The resources for which the URL
+    #   should be generated. These resources should be specified
+    #   in the router.rb file using #resources and #resource.
+    #
+    # options<Hash>:: Any extra parameters that are needed to
+    #   generate the URL.
+    #
+    # ==== Returns
+    # String:: The generated URL.
+    #
+    # ==== Examples
+    #
+    # Merb::Router.prepare do
+    #   resources :users do
+    #     resources :comments
+    #   end
+    # end
+    #
+    # resource(:users)            # => /users
+    # resource(@user)             # => /users/10
+    # resource(@user, :comments)  # => /users/10/comments
+    # resource(@user, @comment)   # => /users/10/comments/15
+    # resource(:users, :new)      # => /users/new
+    # resource(:@user, :edit)     # => /users/10/edit
+    #
+    # :api: public
+    def resource(*args)
+      args << {}
+      Merb::Router.resource(*args)
+    end
+
+    # Calls the capture method for the selected template engine.
+    #
+    # ==== Parameters
+    # *args:: Arguments to pass to the block.
+    # &block:: The block to call.
+    #
+    # ==== Returns
+    # String:: The output of a template block or the return value of a non-template block converted to a string.
+    #
+    # :api: public
+    def capture(*args, &block)
+      ret = nil
+
+      captured = send("capture_#{@_engine}", *args) do |*args|
+        ret = yield *args
+      end
+
+      # return captured value only if it is not empty
+      captured.empty? ? ret.to_s : captured
+    end
+
+    # Calls the concatenate method for the selected template engine.
+    #
+    # ==== Parameters
+    # str<String>:: The string to concatenate to the buffer.
+    # binding<Binding>:: The binding to use for the buffer.
+    #
+    # :api: public
+    def concat(str, binding)
+      send("concat_#{@_engine}", str, binding)
+    end
+
+    private
+    # adds a filter to the specified filter chain
+    # ==== Parameters
+    # filters<Array[Filter]>:: The filter chain that this should be added to.
+    # filter<Filter>:: A filter that should be added.
+    # opts<Hash>::
+    #   Filter options (see class documentation under <tt>Filter Options</tt>).
+    #
+    # ==== Raises
+    # ArgumentError::
+    #   Both :only and :exclude, or :if and :unless given, if filter is not a
+    #   Symbol, String or Proc, or if an unknown option is passed.
+    #
+    # :api: private
+    def self.add_filter(filters, filter, opts={})
+      raise(ArgumentError,
+        "You can specify either :only or :exclude but 
+         not both at the same time for the same filter.") if opts.key?(:only) && opts.key?(:exclude)
+       
+       raise(ArgumentError,
+         "You can specify either :if or :unless but 
+          not both at the same time for the same filter.") if opts.key?(:if) && opts.key?(:unless)
+        
+      opts.each_key do |key| raise(ArgumentError,
+        "You can only specify known filter options, #{key} is invalid.") unless FILTER_OPTIONS.include?(key)
+      end
+
+      opts = normalize_filters!(opts)
+    
+      case filter
+      when Proc
+        # filters with procs created via class methods have identical signature
+        # regardless if they handle content differently or not. So procs just
+        # get appended
+        filters << [filter, opts]
+      when Symbol, String
+        if existing_filter = filters.find {|f| f.first.to_s == filter.to_s}
+          filters[ filters.index(existing_filter) ] = [filter, opts]
+        else
+          filters << [filter, opts]
+        end
+      else
+        raise(ArgumentError, 
+          'Filters need to be either a Symbol, String or a Proc'
+        )        
+      end
+    end  
+
+    # Skip a filter that was previously added to the filter chain. Useful in
+    # inheritence hierarchies.
+    #
+    # ==== Parameters
+    # filters<Array[Filter]>:: The filter chain that this should be removed from.
+    # filter<Filter>:: A filter that should be removed.
+    #
+    # ==== Raises
+    # ArgumentError:: filter not Symbol or String.
+    #
+    # :api: private
+    def self.skip_filter(filters, filter)
+      raise(ArgumentError, 'You can only skip filters that have a String or Symbol name.') unless
+        [Symbol, String].include? filter.class
+
+      Merb.logger.warn("Filter #{filter} was not found in your filter chain.") unless
+        filters.reject! {|f| f.first.to_s[filter.to_s] }
+    end
+
+    # Ensures that the passed in hash values are always arrays.
+    #
+    # ==== Parameters
+    # opts<Hash>:: Options for the filters (see below).
+    #
+    # ==== Options (opts)
+    # :only<Symbol, Array[Symbol]>:: A list of actions.
+    # :exclude<Symbol, Array[Symbol]>:: A list of actions.
+    #
+    # ==== Examples
+    #   normalize_filters!(:only => :new) #=> {:only => [:new]}
+    #
+    # :api: public
+    def self.normalize_filters!(opts={})
+      opts[:only]     = Array(opts[:only]).map {|x| x.to_s} if opts[:only]
+      opts[:exclude]  = Array(opts[:exclude]).map {|x| x.to_s} if opts[:exclude]
+      return opts
+    end
+  end
+end
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/exceptions.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/exceptions.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/exceptions.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,351 @@
+class Exception
+  # Returns the action_name that will be invoked on your Exceptions controller when this
+  # exception is raised. Override this method to force a different action to be invoked.
+  #
+  # ==== Returns
+  # String:: The name of the action in the Exceptions controller which will get invoked
+  #   when this exception is raised during a request.
+  # 
+  # :api: public
+  # @overridable
+  def action_name() self.class.action_name end
+  
+  
+  # ==== Returns
+  # Boolean:: Whether or not this exception is the same as another.
+  #
+  # :api: public
+  def same?(other)
+    self.class == other.class &&
+    self.message == other.message &&
+    self.backtrace == other.backtrace
+  end
+  
+  # Returns the action_name that will be invoked on your Exceptions controller when an instance
+  # is raised during a request.
+  #
+  # ==== Returns
+  # String:: The name of the action in the Exceptions controller which will get invoked
+  #   when an instance of this Exception sub/class is raised by an action.
+  # 
+  # :api: public
+  # @overridable
+  def self.action_name
+    if self == Exception
+      return nil unless Object.const_defined?(:Exceptions) && 
+        Exceptions.method_defined?(:exception)
+    end
+    name = self.to_s.split('::').last.snake_case
+    Object.const_defined?(:Exceptions) && 
+      Exceptions.method_defined?(name) ? name : superclass.action_name
+  end
+  
+  # The status that will be sent in the response when an instance is
+  # raised during a request. Override this to send a different status.
+  #
+  # ==== Returns
+  # Integer:: The status code to send in the response. Defaults to 500.
+  #
+  # :api: public
+  # @overridable
+  def self.status
+    500
+  end
+end
+
+module Merb
+  # ControllerExceptions are a way of simplifying controller code by placing
+  # exception logic back into the MVC pattern.
+  #
+  # When a ControllerException is raised within your application merb will
+  # attempt to re-route the request to your Exceptions controller to render
+  # the error in a friendly manor.
+  #
+  # For example you might have an action in your app that raises NotFound
+  # if a resource was not available
+  #
+
+  #   def show
+  #     product = Product.find(params[:id])
+  #     raise NotFound if product.nil?
+  #     [...]
+  #   end
+  #
+  # This would halt execution of your action and re-route it over to your
+  # Exceptions controller which might look something like:
+  #
+  # class Exceptions < Merb::Controller
+
+  #   def not_found
+  #     render :layout => :none
+  #   end
+  # end
+  #
+  # As usual, the not_found action will look for a template in
+  #   app/views/exceptions/not_found.html.erb
+  #
+  # Note: All standard ControllerExceptions have an HTTP status code associated 
+  # with them which is sent to the browser when the action is rendered.
+  #
+  # Note: If you do not specifiy how to handle raised ControllerExceptions 
+  # or an unhandlable exception occurs within your customised exception action
+  # then they will be rendered using the built-in error template.
+  # In development mode this "built in" template will show stack-traces for
+  # any of the ServerError family of exceptions (you can force the stack-trace
+  # to display in production mode using the :exception_details config option in 
+  # merb.yml)
+  #
+  #
+  # ==== Internal Exceptions 
+  #
+  # Any other rogue errors (not ControllerExceptions) that occur during the 
+  # execution of your app will be converted into the ControllerException 
+  # InternalServerError. And like all other exceptions, the ControllerExceptions  
+  # can be caught on your Exceptions controller.
+  #
+  # InternalServerErrors return status 500, a common use for customizing this
+  # action might be to send emails to the development team, warning that their
+  # application has exploded. Mock example:
+  #
+
+  #   def internal_server_error
+  #     MySpecialMailer.deliver(
+  #       "team at cowboys.com", 
+  #       "Exception occured at #{Time.now}", 
+  #       self.request.exceptions.first)
+  #     render 'Something is wrong, but the team is on it!'
+  #   end
+  #
+  # Note: The special method +exceptions+ is available on Merb::Request instances 
+  # and contains the exceptions that was raised (this is handy if
+  # you want to display the associated message or display more detailed info).
+  #
+  #
+  # ==== Extending ControllerExceptions
+  #
+  # To extend the use of the ControllerExceptions one may extend any of the 
+  # HTTPError classes.
+  #
+  # As an example we can create an exception called AdminAccessRequired.
+  #
+  #   class AdminAccessRequired < Merb::ControllerExceptions::Unauthorized; end
+  #
+  # Add the required action to our Exceptions controller
+  #
+  #   class Exceptions < Merb::Controller
+
+  #     def admin_access_required
+  #       render
+  #     end
+  #   end
+  #
+  # In app/views/exceptions/admin_access_required.rhtml
+  # 
+  #   <h1>You're not an administrator!</h1>
+  #   <p>You tried to access <%= @tried_to_access %> but that URL is 
+  #   restricted to administrators.</p>
+  #
+  module ControllerExceptions
+    
+    # Mapping of status code names to their numeric value.
+    STATUS_CODES = {}
+
+    class Base < StandardError #:doc:
+
+      # === Returns
+      # Integer:: The status-code of the error.
+      # 
+      # @overridable
+      # :api: plugin
+      def status; self.class.status; end
+      alias :to_i :status
+
+      class << self
+
+        # Get the actual status-code for an Exception class.
+        #
+        # As usual, this can come from a constant upwards in
+        # the inheritance chain.
+        #
+        # ==== Returns
+        # Fixnum:: The status code of this exception.
+        #
+        # :api: public
+        def status
+          const_get(:STATUS) rescue 0
+        end
+        alias :to_i :status
+        
+        # Set the actual status-code for an Exception class.
+        #
+        # If possible, set the STATUS constant, and update
+        # any previously registered (inherited) status-code.
+        #
+        # ==== Parameters
+        # num<~to_i>:: The status code
+        #
+        # ==== Returns
+        # (Integer, nil):: The status set on this exception, or nil if a status was already set.
+        #
+        # :api: private
+        def status=(num)
+          unless self.status?
+            register_status_code(self, num)
+            self.const_set(:STATUS, num.to_i)
+          end
+        end
+      
+        # See if a status-code has been defined (on self explicitly).
+        #
+        # ==== Returns
+        # Boolean:: Whether a status code has been set
+        #
+        # :api: private
+        def status?
+          self.const_defined?(:STATUS)
+        end
+      
+        # Registers any subclasses with status codes for easy lookup by
+        # set_status in Merb::Controller.
+        #
+        # Inheritance ensures this method gets inherited by any subclasses, so
+        # it goes all the way down the chain of inheritance.
+        #
+        # ==== Parameters
+        # 
+        # subclass<Merb::ControllerExceptions::Base>::
+        #   The Exception class that is inheriting from Merb::ControllerExceptions::Base
+        #
+        # :api: public
+        def inherited(subclass)
+          # don't set the constant yet - any class methods will be called after self.inherited
+          # unless self.status = ... is set explicitly, the status code will be inherited
+          register_status_code(subclass, self.status) if self.status?
+        end
+        
+        private
+        
+        # Register the status-code for an Exception class.
+        #
+        # ==== Parameters
+        # num<~to_i>:: The status code
+        #
+        # :api: privaate
+        def register_status_code(klass, code)
+          name = self.to_s.split('::').last.snake_case
+          STATUS_CODES[name.to_sym] = code.to_i
+        end
+        
+      end
+    end
+
+    class Informational                 < Merb::ControllerExceptions::Base; end
+
+      class Continue                    < Merb::ControllerExceptions::Informational; self.status = 100; end
+
+      class SwitchingProtocols          < Merb::ControllerExceptions::Informational; self.status = 101; end
+
+    class Successful                    < Merb::ControllerExceptions::Base; end
+
+      class OK                          < Merb::ControllerExceptions::Successful; self.status = 200; end
+
+      class Created                     < Merb::ControllerExceptions::Successful; self.status = 201; end
+
+      class Accepted                    < Merb::ControllerExceptions::Successful; self.status = 202; end
+
+      class NonAuthoritativeInformation < Merb::ControllerExceptions::Successful; self.status = 203; end
+
+      class NoContent                   < Merb::ControllerExceptions::Successful; self.status = 204; end
+
+      class ResetContent                < Merb::ControllerExceptions::Successful; self.status = 205; end
+
+      class PartialContent              < Merb::ControllerExceptions::Successful; self.status = 206; end
+
+    class Redirection                   < Merb::ControllerExceptions::Base; end
+
+      class MultipleChoices             < Merb::ControllerExceptions::Redirection; self.status = 300; end
+
+      class MovedPermanently            < Merb::ControllerExceptions::Redirection; self.status = 301; end
+
+      class MovedTemporarily            < Merb::ControllerExceptions::Redirection; self.status = 302; end
+
+      class SeeOther                    < Merb::ControllerExceptions::Redirection; self.status = 303; end
+
+      class NotModified                 < Merb::ControllerExceptions::Redirection; self.status = 304; end
+
+      class UseProxy                    < Merb::ControllerExceptions::Redirection; self.status = 305; end
+
+      class TemporaryRedirect           < Merb::ControllerExceptions::Redirection; self.status = 307; end
+
+    class ClientError                   < Merb::ControllerExceptions::Base; end
+
+      class BadRequest                  < Merb::ControllerExceptions::ClientError; self.status = 400; end
+
+      class MultiPartParseError         < Merb::ControllerExceptions::BadRequest; end
+
+      class Unauthorized                < Merb::ControllerExceptions::ClientError; self.status = 401; end
+
+      class PaymentRequired             < Merb::ControllerExceptions::ClientError; self.status = 402; end
+
+      class Forbidden                   < Merb::ControllerExceptions::ClientError; self.status = 403; end
+
+      class NotFound                    < Merb::ControllerExceptions::ClientError; self.status = 404; end
+
+      class ActionNotFound              < Merb::ControllerExceptions::NotFound; end
+
+      class TemplateNotFound            < Merb::ControllerExceptions::NotFound; end
+
+      class LayoutNotFound              < Merb::ControllerExceptions::NotFound; end
+
+      class MethodNotAllowed            < Merb::ControllerExceptions::ClientError; self.status = 405; end
+
+      class NotAcceptable               < Merb::ControllerExceptions::ClientError; self.status = 406; end
+
+      class ProxyAuthenticationRequired < Merb::ControllerExceptions::ClientError; self.status = 407; end
+
+      class RequestTimeout              < Merb::ControllerExceptions::ClientError; self.status = 408; end
+
+      class Conflict                    < Merb::ControllerExceptions::ClientError; self.status = 409; end
+
+      class Gone                        < Merb::ControllerExceptions::ClientError; self.status = 410; end
+
+      class LengthRequired              < Merb::ControllerExceptions::ClientError; self.status = 411; end
+
+      class PreconditionFailed          < Merb::ControllerExceptions::ClientError; self.status = 412; end
+
+      class RequestEntityTooLarge       < Merb::ControllerExceptions::ClientError; self.status = 413; end
+
+      class RequestURITooLarge          < Merb::ControllerExceptions::ClientError; self.status = 414; end
+
+      class UnsupportedMediaType        < Merb::ControllerExceptions::ClientError; self.status = 415; end
+
+      class RequestRangeNotSatisfiable  < Merb::ControllerExceptions::ClientError; self.status = 416; end
+
+      class ExpectationFailed           < Merb::ControllerExceptions::ClientError; self.status = 417; end
+
+    class ServerError                   < Merb::ControllerExceptions::Base; end
+
+      class InternalServerError         < Merb::ControllerExceptions::ServerError; self.status = 500; end
+
+      class NotImplemented              < Merb::ControllerExceptions::ServerError; self.status = 501; end
+
+      class BadGateway                  < Merb::ControllerExceptions::ServerError; self.status = 502; end
+
+      class ServiceUnavailable          < Merb::ControllerExceptions::ServerError; self.status = 503; end
+
+      class GatewayTimeout              < Merb::ControllerExceptions::ServerError; self.status = 504; end
+
+      class HTTPVersionNotSupported     < Merb::ControllerExceptions::ServerError; self.status = 505; end
+  end
+  
+  # Required to show exceptions in the log file
+  #
+  # e<Exception>:: The exception that a message is being generated for
+  #
+  # :api: plugin
+  def self.exception(e)
+    "#{ e.message } - (#{ e.class })\n" <<  
+    "#{(e.backtrace or []).join("\n")}" 
+  end
+
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/merb_controller.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/merb_controller.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/merb_controller.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,484 @@
+class Merb::Controller < Merb::AbstractController
+
+  class_inheritable_accessor :_hidden_actions, :_shown_actions, 
+                             :_overridable, :_override_bang
+
+  self._hidden_actions ||= []
+  self._shown_actions  ||= []
+  self._overridable    ||= []
+  self._override_bang  ||= []
+
+  cattr_accessor :_subclasses
+  self._subclasses = Set.new
+
+  # :api: private
+  def self.subclasses_list() _subclasses end
+
+  include Merb::ResponderMixin
+  include Merb::ControllerMixin
+  include Merb::AuthenticationMixin
+  include Merb::ConditionalGetMixin
+
+  # ==== Parameters
+  # klass<Merb::Controller>::
+  #   The Merb::Controller inheriting from the base class.
+  #
+  # :api: private
+  def self.inherited(klass)
+    _subclasses << klass.to_s
+    super
+    klass._template_root = Merb.dir_for(:view) unless self._template_root
+  end
+
+  # ==== Parameters
+  # *names<Array[Symbol]>::
+  #   an Array of method names that should be overridable in application
+  #   controllers.
+  # 
+  # ==== Returns
+  # Array:: The list of methods that are overridable
+  #
+  # :api: plugin
+  def self.overridable(*names)
+    self._overridable.push(*names)
+  end
+  
+  # In an application controller, call override! before a method to indicate
+  # that you want to override a method in Merb::Controller that is not
+  # normally overridable.
+  #
+  # Doing this may potentially break your app in a future release of Merb,
+  # and this is provided for users who are willing to take that risk.
+  # Without using override!, Merb will raise an error if you attempt to
+  # override a method defined on Merb::Controller.
+  #
+  # This is to help users avoid a common mistake of defining an action
+  # that overrides a core method on Merb::Controller.
+  #
+  # ==== Parameters
+  # *names<Array[Symbol]>:: 
+  #   An Array of methods that will override Merb core classes on purpose
+  #
+  # ==== Example
+  #     
+  #     class Kontroller < Application
+  #       def status
+  #         render
+  #       end
+  #     end
+  # 
+  # will raise a Merb::ReservedError, because #status is a method on
+  # Merb::Controller.
+  # 
+  #     class Kontroller < Application
+  #       override! :status
+  #       def status
+  #         some_code || super
+  #       end
+  #     end
+  #
+  # will not raise a Merb::ReservedError, because the user specifically
+  # decided to override the status method.
+  #
+  # :api: public
+  def self.override!(*names)
+    self._override_bang.push(*names)
+  end
+
+  # Hide each of the given methods from being callable as actions.
+  #
+  # ==== Parameters
+  # *names<~to-s>:: Actions that should be added to the list.
+  #
+  # ==== Returns
+  # Array[String]::
+  #   An array of actions that should not be possible to dispatch to.
+  #
+  # :api: public
+  def self.hide_action(*names)
+    self._hidden_actions = self._hidden_actions | names.map { |n| n.to_s }
+  end
+
+  # Makes each of the given methods being callable as actions. You can use
+  # this to make methods included from modules callable as actions.
+  #
+  # ==== Parameters
+  # *names<~to-s>:: Actions that should be added to the list.
+  #
+  # ==== Returns
+  # Array[String]::
+  #   An array of actions that should be dispatched to even if they would not
+  #   otherwise be.
+  #
+  # ==== Example
+  #   module Foo
+  #     def self.included(base)
+  #       base.show_action(:foo)
+  #     end
+  #
+  #     def foo
+  #       # some actiony stuff
+  #     end
+  #
+  #     def foo_helper
+  #       # this should not be an action
+  #     end
+  #   end
+  #
+  # :api: public
+  def self.show_action(*names)
+    self._shown_actions = self._shown_actions | names.map {|n| n.to_s}
+  end
+
+  # The list of actions that are callable, after taking defaults,
+  # _hidden_actions and _shown_actions into consideration. It is calculated
+  # once, the first time an action is dispatched for this controller.
+  #
+  # ==== Returns
+  # SimpleSet[String]:: A set of actions that should be callable.
+  #
+  # :api: public
+  def self.callable_actions
+    @callable_actions ||= Extlib::SimpleSet.new(_callable_methods)
+  end
+
+  # This is a stub method so plugins can implement param filtering if they want.
+  #
+  # ==== Parameters
+  # params<Hash{Symbol => String}>:: A list of params
+  #
+  # ==== Returns
+  # Hash{Symbol => String}:: A new list of params, filtered as desired
+  # 
+  # :api: plugin
+  # @overridable
+  def self._filter_params(params)
+    params
+  end
+  overridable :_filter_params
+
+  # All methods that are callable as actions.
+  #
+  # ==== Returns
+  # Array:: A list of method names that are also actions
+  #
+  # :api: private
+  def self._callable_methods
+    callables = []
+    klass = self
+    begin
+      callables << (klass.public_instance_methods(false) + klass._shown_actions) - klass._hidden_actions
+      klass = klass.superclass
+    end until klass == Merb::AbstractController || klass == Object
+    callables.flatten.reject{|action| action =~ /^_.*/}.map {|x| x.to_s}
+  end
+
+  # The location to look for a template for a particular controller, context,
+  # and mime-type. This is overridden from AbstractController, which defines a
+  # version of this that does not involve mime-types.
+  #
+  # ==== Parameters
+  # context<~to_s>:: The name of the action or template basename that will be rendered.
+  # type<~to_s>::
+  #    The mime-type of the template that will be rendered. Defaults to nil.
+  # controller<~to_s>::
+  #   The name of the controller that will be rendered. Defaults to
+  #   controller_name.  This will be "layout" for rendering a layout.  
+  #
+  # ==== Notes
+  # By default, this renders ":controller/:action.:type". To change this,
+  # override it in your application class or in individual controllers.
+  #
+  # :api: public
+  # @overridable
+  def _template_location(context, type, controller)
+    _conditionally_append_extension(controller ? "#{controller}/#{context}" : "#{context}", type)
+  end
+  overridable :_template_location
+
+  # The location to look for a template and mime-type. This is overridden
+  # from AbstractController, which defines a version of this that does not
+  # involve mime-types.
+  #
+  # ==== Parameters
+  # template<String>::
+  #    The absolute path to a template - without mime and template extension.
+  #    The mime-type extension is optional - it will be appended from the
+  #    current content type if it hasn't been added already.
+  # type<~to_s>::
+  #    The mime-type of the template that will be rendered. Defaults to nil.
+  #
+  # :api: public
+  def _absolute_template_location(template, type)
+    _conditionally_append_extension(template, type)
+  end
+
+  # Build a new controller.
+  #
+  # Sets the variables that came in through the dispatch as available to
+  # the controller.
+  #
+  # ==== Parameters
+  # request<Merb::Request>:: The Merb::Request that came in from Rack.
+  # status<Integer>:: An integer code for the status. Defaults to 200.
+  # headers<Hash{header => value}>::
+  #   A hash of headers to start the controller with. These headers can be
+  #   overridden later by the #headers method.
+  # 
+  # :api: plugin
+  # @overridable
+  def initialize(request, status=200, headers={'Content-Type' => 'text/html; charset=utf-8'})
+    super()
+    @request, @_status, @headers = request, status, headers
+  end
+  overridable :initialize
+
+  # Dispatch the action.
+  #
+  # ==== Parameters
+  # action<~to_s>:: An action to dispatch to. Defaults to :index.
+  #
+  # ==== Returns
+  # String:: The string sent to the logger for time spent.
+  #
+  # ==== Raises
+  # ActionNotFound:: The requested action was not found in class.
+  #
+  # :api: plugin
+  def _dispatch(action=:index)
+    Merb.logger.info { "Params: #{self.class._filter_params(request.params).inspect}" }
+    start = Time.now
+    if self.class.callable_actions.include?(action.to_s)
+      super(action)
+    else
+      raise ActionNotFound, "Action '#{action}' was not found in #{self.class}"
+    end
+    @_benchmarks[:action_time] = Time.now - start
+    self
+  end
+
+  # :api: public
+  attr_reader :request, :headers
+
+  # ==== Returns
+  # Fixnum:: The response status code
+  #
+  # :api: public
+  def status
+    @_status
+  end
+
+  # Set the response status code.
+  #
+  # ==== Parameters
+  # s<Fixnum, Symbol>:: A status-code or named http-status
+  #
+  # :api: public
+  def status=(s)
+    if s.is_a?(Symbol) && STATUS_CODES.key?(s)
+      @_status = STATUS_CODES[s]
+    elsif s.is_a?(Fixnum)
+      @_status = s
+    else
+      raise ArgumentError, "Status should be of type Fixnum or Symbol, was #{s.class}"
+    end
+  end
+
+  # ==== Returns
+  # Hash:: The parameters from the request object
+  # 
+  # :api: public
+  def params()  request.params  end
+    
+  # There are three possible ways to use this method.  First, if you have a named route, 
+  # you can specify the route as the first parameter as a symbol and any paramters in a 
+  # hash.  Second, you can generate the default route by just passing the params hash, 
+  # just passing the params hash.  Finally, you can use the anonymous parameters.  This 
+  # allows you to specify the parameters to a named route in the order they appear in the 
+  # router.  
+  #
+  # ==== Parameters(Named Route)
+  # name<Symbol>:: 
+  #   The name of the route. 
+  # args<Hash>:: 
+  #   Parameters for the route generation.
+  #
+  # ==== Parameters(Default Route)
+  # args<Hash>:: 
+  #   Parameters for the route generation.  This route will use the default route. 
+  #
+  # ==== Parameters(Anonymous Parameters)
+  # name<Symbol>::
+  #   The name of the route.  
+  # args<Array>:: 
+  #   An array of anonymous parameters to generate the route
+  #   with. These parameters are assigned to the route parameters
+  #   in the order that they are passed.
+  #
+  # ==== Returns
+  # String:: The generated URL.
+  #
+  # ==== Examples
+  # Named Route
+  #
+  # Merb::Router.prepare do
+  #   match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+  # end
+  #
+  # url(:articles, :title => "new_article")
+  #
+  # Default Route
+  #
+  # Merb::Router.prepare do
+  #   default_routes
+  # end
+  #
+  # url(:controller => "articles", :action => "new")
+  #
+  # Anonymous Paramters
+  #
+  # Merb::Router.prepare do
+  #   match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+  # end
+  #
+  # url(:articles, 2008, 10, "test_article")
+  #
+  # :api: public
+  def url(name, *args)
+    args << params
+    name = request.route if name == :this
+    Merb::Router.url(name, *args)
+  end
+  
+  # Generates a URL for a single or nested resource.
+  #
+  # ==== Parameters
+  # resources<Symbol,Object>:: The resources for which the URL
+  #   should be generated. These resources should be specified
+  #   in the router.rb file using #resources and #resource.
+  #
+  # options<Hash>:: Any extra parameters that are needed to
+  #   generate the URL.
+  #
+  # ==== Returns
+  # String:: The generated URL.
+  #
+  # ==== Examples
+  #
+  # Merb::Router.prepare do
+  #   resources :users do
+  #     resources :comments
+  #   end
+  # end
+  #
+  # resource(:users)            # => /users
+  # resource(@user)             # => /users/10
+  # resource(@user, :comments)  # => /users/10/comments
+  # resource(@user, @comment)   # => /users/10/comments/15
+  # resource(:users, :new)      # => /users/new
+  # resource(:@user, :edit)     # => /users/10/edit
+  #
+  # :api: public
+  def resource(*args)
+    args << params
+    Merb::Router.resource(*args)
+  end
+  
+
+  alias_method :relative_url, :url
+  
+  # Returns the absolute url including the passed protocol and host.  
+  # 
+  # This uses the same arguments as the url method, with added requirements 
+  # of protocol and host options. 
+  #
+  # :api: public
+  def absolute_url(*args)
+    options  = extract_options_from_args!(args) || {}
+    options[:protocol] ||= request.protocol
+    options[:host] ||= request.host
+    args << options
+    super(*args)
+  end
+
+  # The results of the controller's render, to be returned to Rack.
+  #
+  # ==== Returns
+  # Array[Integer, Hash, String]::
+  #   The controller's status code, headers, and body
+  #
+  # :api: private
+  def rack_response
+    [status, headers, Merb::Rack::StreamWrapper.new(body)]
+  end
+
+  # Sets a controller to be "abstract" 
+  # This controller will not be able to be routed to
+  # and is used for super classing only
+  #
+  # :api: public
+  def self.abstract!
+    @_abstract = true
+  end
+  
+  # Asks a controller if it is abstract
+  #
+  # === Returns
+  # Boolean
+  #  true if the controller has been set as abstract
+  #
+  # :api: public
+  def self.abstract?
+    !!@_abstract 
+  end
+
+  # Hide any methods that may have been exposed as actions before.
+  hide_action(*_callable_methods)
+
+  private
+
+  # If not already added, add the proper mime extension to the template path.
+  #
+  # ==== Parameters
+  #
+  # template<~to_s> ::
+  #   The template path to append the mime type to.
+  # type<~to_s> ::
+  #   The extension to append to the template path conditionally
+  #
+  # :api: private
+  def _conditionally_append_extension(template, type)
+    type && !template.match(/\.#{type.to_s.escape_regexp}$/) ? "#{template}.#{type}" : template
+  end
+  
+  # When a method is added to a subclass of Merb::Controller (i.e. an app controller) that
+  # is defined on Merb::Controller, raise a Merb::ReservedError. An error will not be raised
+  # if the method is defined as overridable in the Merb API.
+  #
+  # This behavior can be overridden by using override! method_name before attempting to
+  # override the method.
+  #
+  # ==== Parameters
+  # meth<~to_sym> The method that is being added
+  #
+  # ==== Raises
+  # Merb::ReservedError::
+  #   If the method being added is in a subclass of Merb::Controller,
+  #   the method is defined on Merb::Controller, it is not defined
+  #   as overridable in the Merb API, and the user has not specified
+  #   that it can be overridden.
+  #
+  # ==== Returns
+  # nil
+  # 
+  # :api: private
+  def self.method_added(meth)
+    if self < Merb::Controller && Merb::Controller.method_defined?(meth) && 
+      !self._overridable.include?(meth.to_sym) && !self._override_bang.include?(meth.to_sym)
+
+      raise Merb::ReservedError, "You tried to define #{meth} on " \
+        "#{self.name} but it was already defined on Merb::Controller. " \
+        "If you meant to override a core method, use override!"
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mime.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mime.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mime.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,135 @@
+module Merb
+  class << self
+
+    
+    # Returns a hash of the available mime types. 
+    #
+    # ==== Returns
+    # Hash{Symbol => Hash{Symbol => Object}}:: The available mime types.
+    #
+    # ==== Notes
+    # Each entry corresponds to a call to add_mime_type, having the mime type key (:html, :xml, :json, etc.)
+    # as the key and a hash containing the following entries:
+    #   :accepts           # the mime types that will be recognized by this entry
+    #   :transform_method  # the method called on an object to convert it to content of this type (such as to_json)
+    #   :content_type      # the value set to the "Content-Type" HTTP header when this mime is sent in a response
+    #   :response_headers  # sent in a response using this content type
+    #   :default_quality   # the scale factor used in describing content type preference
+    #   :response_block    # the block to be called with the controller when a request responds to this mime type
+    #
+    # :api: public
+    def available_mime_types
+      ResponderMixin::TYPES
+    end
+
+    # ==== Returns
+    # Hash{String => Symbol}:: 
+    #   A hash mapping Content-Type values to the mime type key of the appropriate entry in #available_mime_types
+    #
+    # :api: public
+    def available_accepts
+      ResponderMixin::MIMES
+    end
+
+    # Any specific outgoing headers should be included here.  These are not
+    # the content-type header but anything in addition to it.
+    # +transform_method+ should be set to a symbol of the method used to
+    # transform a resource into this mime type.
+    # For example for the :xml mime type an object might be transformed by
+    # calling :to_xml, or for the :js mime type, :to_json.
+    # If there is no transform method, use nil.
+    #
+    # ==== Autogenerated Methods
+    # Adding a mime-type adds a render_type method that sets the content
+    # type and calls render.
+    # 
+    # By default this does: def render_all, def render_yaml, def render_text,
+    # def render_html, def render_xml, def render_js, and def render_yaml
+    #
+    # ==== Parameters
+    # key<Symbol>:: The name of the mime-type. This is used by the provides API
+    # transform_method<~to_s>:: 
+    #   The associated method to call on objects to convert them to the
+    #   appropriate mime-type. For instance, :json would use :to_json as its
+    #   transform_method.
+    # mimes<Array[String]>::
+    #   A list of possible values sent in the Accept header, such as text/html,
+    #   that should be associated with this content-type.
+    # new_response_headers<Hash>::
+    #   The response headers to set for the the mime type. For example: 
+    #   'Content-Type' => 'application/json; charset=utf-8'; As a shortcut for
+    #   the common charset option, use :charset => 'utf-8', which will be
+    #   correctly appended to the mimetype itself.
+    # &block:: a block which recieves the current controller when the format
+    #   is set (in the controller's #content_type method)
+    #
+    # ==== Returns
+    # nil
+    #
+    # :api: public
+    def add_mime_type(key, transform_method, mimes, new_response_headers = {}, default_quality = 1, &block) 
+      enforce!(key => Symbol, mimes => Array)
+      
+      content_type = new_response_headers["Content-Type"] || mimes.first
+      
+      if charset = new_response_headers.delete(:charset)
+        content_type += "; charset=#{charset}"
+      end
+      
+      ResponderMixin::TYPES.update(key => 
+        {:accepts           => mimes, 
+         :transform_method  => transform_method,
+         :content_type      => content_type,
+         :response_headers  => new_response_headers,
+         :default_quality   => default_quality,
+         :response_block    => block })
+
+      mimes.each do |mime|
+        ResponderMixin::MIMES.update(mime => key)
+      end
+
+      Merb::RenderMixin.class_eval <<-EOS, __FILE__, __LINE__
+        def render_#{key}(thing = nil, opts = {})
+          self.content_type = :#{key}
+          render thing, opts
+        end
+      EOS
+      
+      nil
+    end
+
+    # Removes a MIME-type from the mime-type list.
+    #
+    # ==== Parameters
+    # key<Symbol>:: The key that represents the mime-type to remove.
+    #
+    # ==== Returns
+    # (Boolean, Hash{Symbol => Object}):: If it was present, the old specification of the MIME-type. Same structure
+    #   as a value in Merb.available_mime_types. False if the key was not present.
+    #
+    # ==== Notes
+    # :all is the key for */*; It can't be removed.
+    #
+    # :api: public
+    def remove_mime_type(key)
+      return false if key == :all
+      ResponderMixin::TYPES.delete(key)
+    end
+
+    # ==== Parameters
+    # key<Symbol>:: The key that represents the mime-type.
+    #
+    # ==== Returns
+    # Symbol:: The transform method for the mime type, e.g. :to_json.
+    #
+    # ==== Raises
+    # ArgumentError:: The requested mime type is not valid.
+    #
+    # :api: private
+    def mime_transform_method(key)
+      raise ArgumentError, ":#{key} is not a valid MIME-type" unless ResponderMixin::TYPES.key?(key)
+      ResponderMixin::TYPES[key][:transform_method]
+    end
+
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/authentication.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/authentication.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/authentication.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,171 @@
+module Merb::AuthenticationMixin
+  
+  # Attempts to authenticate the user via HTTP Basic authentication. Takes a
+  # block with the username and password, if the block yields false the
+  # authentication is not accepted and :halt is thrown.
+  #
+  # If no block is passed, +basic_authentication+, the +request+ and +authenticate+
+  # methods can be chained. These can be used to independently request authentication
+  # or confirm it, if more control is desired.
+  #
+  # ==== Parameters
+  # realm<~to_s>:: The realm to authenticate against. Defaults to 'Application'.
+  # &authenticator:: A block to check if the authentication is valid.
+  #
+  # ==== Returns
+  # Merb::AuthenticationMixin::BasicAuthentication
+  #
+  # ==== Examples
+  #     class Application < Merb::Controller
+  #     
+  #       before :authenticate
+  #     
+  #       protected
+  #     
+  #       def authenticate
+  #         basic_authentication("My App") do |username, password|
+  #           password == "secret"
+  #         end
+  #       end
+  #     
+  #     end
+  #
+  #     class Application < Merb::Controller
+  #     
+  #       before :authenticate
+  #     
+  #       def authenticate
+  #         user = basic_authentication.authenticate do |username, password|
+  #           User.authenticate(username, password)
+  #         end
+  #     
+  #         if user
+  #           @current_user = user
+  #         else
+  #           basic_authentication.request
+  #         end
+  #       end
+  #     
+  #     end
+  #
+  # If you need to request basic authentication inside an action you need to use the request! method.
+  #
+  # ==== Example
+  #
+  #    class Sessions < Application
+  #  
+  #      def new
+  #        case content_type
+  #        when :html
+  #          render
+  #
+  #        else
+  #         user = basic_authentication.authenticate do |username, password|
+  #           User.authenticate(username, password)
+  #         end
+  #
+  #         if user
+  #           display(user)
+  #         else
+  #           basic_authentication.request
+  #         end
+  #        end
+  #      end
+  # 
+  #    end 
+  #
+  #
+  # :api: public
+  def basic_authentication(realm = "Application", &authenticator)
+    @_basic_authentication ||= BasicAuthentication.new(self, realm, &authenticator)
+  end
+  
+  class BasicAuthentication
+    # So we can have access to the status codes
+    include Merb::ControllerExceptions
+
+    # :api: private
+    def initialize(controller, realm = "Application", &authenticator)
+      @controller = controller
+      @realm = realm
+      @auth = Rack::Auth::Basic::Request.new(@controller.request.env)
+      authenticate_or_request(&authenticator) if authenticator
+    end
+
+    # Determines whether or not the user is authenticated using the criteria
+    # in the provided authenticator block.
+    #
+    # ==== Parameters
+    # &authenticator:: A block that decides whether the provided username and password
+    #   are valid.
+    #
+    # ==== Returns
+    # Object:: False if basic auth is not provided, otherwise the return value of the authenticator block.
+    # 
+    # @overridable
+    # :api: public
+    def authenticate(&authenticator)
+      if @auth.provided? and @auth.basic?
+        authenticator.call(*@auth.credentials)
+      else
+        false
+      end
+    end
+
+    # Request basic authentication and halt the filter chain. This is for use in a before filter.
+    #
+    # ==== Throws
+    # :halt with an "HTTP Basic: Access denied." message with no layout, and sets the status to Unauthorized.
+    #
+    # :api: public
+    def request
+      request!
+      throw :halt, @controller.render("HTTP Basic: Access denied.\n", :status => Unauthorized.status, :layout => false)
+    end
+    
+    # Sets headers to request basic auth.
+    #
+    # ==== Returns
+    # String:: Returns the empty string to provide a response body.
+    #
+    # :api: public
+    def request!
+      @controller.status = Unauthorized.status
+      @controller.headers['WWW-Authenticate'] = 'Basic realm="%s"' % @realm
+      ""
+    end
+    
+    # ==== Returns
+    # Boolean:: Whether there has been any basic authentication credentials provided
+    #
+    # :api: public
+    def provided?
+      @auth.provided?
+    end
+    
+    # ==== Returns
+    # String:: The username provided in the request.
+    #
+    # :api: public
+    def username
+      provided? ? @auth.credentials.first : nil
+    end
+    
+    # ==== Returns
+    # String:: The password provided in the request.
+    #
+    # :api: public
+    def password
+      provided? ? @auth.credentials.last : nil
+    end
+    
+    protected
+    
+    # :api: private
+    def authenticate_or_request(&authenticator)
+      authenticate(&authenticator) || request
+    end
+    
+  end
+
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/conditional_get.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/conditional_get.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/conditional_get.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,100 @@
+# Provides conditional get support in Merb core.
+# Conditional get support is intentionally
+# simple and does not do fancy stuff like making
+# ETag value from Ruby objects for you.
+#
+# The most interesting method for end user is
+# +request_fresh?+ that is used after setting of
+# last modification time or ETag:
+#
+# ==== Example
+#
+# def show
+#   self.etag = Digest::SHA1.hexdigest(calculate_cache_key(params))
+#
+#   if request_fresh?
+#     self.status = 304
+#     return ''
+#   else
+#     @product = Product.get(params[:id])
+#     display @product
+#   end
+# end
+module Merb::ConditionalGetMixin
+
+  # Sets ETag response header by calling
+  # #to_s on the argument.
+  #
+  # ==== Parameters
+  # tag<~to_s>::
+  #   value of ETag header enclosed in double quotes
+  #   as required by the RFC
+  #
+  # :api: public
+  def etag=(tag)
+    headers[Merb::Const::ETAG] = %("#{tag}")
+  end
+
+  # ==== Returns
+  # <String>::
+  #   Value of ETag response header or nil if it's not set.
+  #
+  # :api: public
+  def etag
+    headers[Merb::Const::ETAG]
+  end
+
+  # ==== Returns
+  # <Boolean>::
+  # true if ETag response header equals If-None-Match request header,
+  # false otherwise
+  #
+  # :api: public
+  def etag_matches?(tag = self.etag)
+    tag == self.request.if_none_match
+  end
+
+  # Sets Last-Modified response header.
+  #
+  # ==== Parameters
+  # tag<Time>::
+  # resource modification timestamp converted into format
+  # required by the RFC
+  #
+  # :api: public
+  def last_modified=(time)
+    time = time.to_time if time.is_a?(DateTime)
+    # time.utc.strftime("%a, %d %b %Y %X") if we could rely on locale being American
+    headers[Merb::Const::LAST_MODIFIED] = time.httpdate
+  end
+
+  # ==== Returns
+  # <String>::
+  #   Value of Last-Modified response header or nil if it's not set.
+  #
+  # :api: public
+  def last_modified
+    last_mod = headers[Merb::Const::LAST_MODIFIED]
+    Time.rfc2822(last_mod) if last_mod
+  end
+
+  # ==== Returns
+  # <Boolean>::
+  # true if Last-Modified response header is < than
+  # If-Modified-Since request header value, false otherwise.
+  #
+  # :api: public
+  def not_modified?(time = self.last_modified)
+    request.if_modified_since && time && time <= request.if_modified_since
+  end
+
+  # ==== Returns
+  # <Boolean>::
+  # true if either ETag matches or entity is not modified,
+  # so request is fresh; false otherwise
+  #
+  # :api: public
+  def request_fresh?
+    etag_matches?(self.etag) || not_modified?(self.last_modified)
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/controller.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/controller.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/controller.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,348 @@
+module Merb
+  # Module that is mixed in to all implemented controllers.
+  module ControllerMixin
+    
+    # Enqueu a block to run in a background thread outside of the request
+    # response dispatch
+    # 
+    # ==== Parameters
+    # &blk:: proc to run later
+    # 
+    # ==== Example
+    # run_later do
+    #   SomeBackgroundTask.run
+    # end
+    # 
+    # :api: public
+    def run_later(&blk)
+      Merb.run_later(&blk)
+    end
+    
+    # Renders the block given as a parameter using chunked encoding.
+    # 
+    # ==== Parameters
+    # &blk::
+    #   A block that, when called, will use send_chunks to send chunks of data
+    #   down to the server. The chunking will terminate once the block returns.
+    # 
+    # ==== Examples
+    #   def stream
+    #     prefix = '<p>'
+    #     suffix = "</p>\r\n"
+    #     render_chunked do
+    #       IO.popen("cat /tmp/test.log") do |io|
+    #         done = false
+    #         until done
+    #           sleep 0.3
+    #           line = io.gets.chomp
+    #           
+    #           if line == 'EOF'
+    #             done = true
+    #           else
+    #             send_chunk(prefix + line + suffix)
+    #           end
+    #         end
+    #       end
+    #     end
+    #   end
+    # 
+    # :api: public
+    def render_chunked(&blk)
+      must_support_streaming!
+      headers['Transfer-Encoding'] = 'chunked'
+      Proc.new { |response|
+        @response = response
+        response.send_status_no_connection_close('')
+        response.send_header
+        blk.call
+        response.write("0\r\n\r\n")
+      }
+    end
+    
+    # Writes a chunk from +render_chunked+ to the response that is sent back to
+    # the client. This should only be called within a +render_chunked+ block.
+    #
+    # ==== Parameters
+    # data<String>:: a chunk of data to return.
+    # 
+    # :api: public
+    def send_chunk(data)
+      only_runs_on_mongrel!
+      @response.write('%x' % data.size + "\r\n")
+      @response.write(data + "\r\n")
+    end
+    
+    # ==== Parameters
+    # &blk::
+    #   A proc that should get called outside the mutex, and which will return
+    #   the value to render.
+    # 
+    # ==== Returns
+    # Proc::
+    #   A block that the server can call later, allowing Merb to release the
+    #   thread lock and render another request.
+    # 
+    # :api: public
+    def render_deferred(&blk)
+      Proc.new do |response|
+        response.write(blk.call)
+      end
+    end
+    
+    # Renders the passed in string, then calls the block outside the mutex and
+    # after the string has been returned to the client.
+    # 
+    # ==== Parameters
+    # str<String>:: A +String+ to return to the client.
+    # &blk:: A block that should get called once the string has been returned.
+    # 
+    # ==== Returns
+    # Proc::
+    #   A block that Mongrel can call after returning the string to the user.
+    # 
+    # :api: public
+    def render_then_call(str, &blk)
+      Proc.new do |response|
+        response.write(str)
+        blk.call
+      end
+    end
+    
+    # ==== Parameters
+    # url<String>::
+    #   URL to redirect to. It can be either a relative or fully-qualified URL.
+    # opts<Hash>:: An options hash (see below)
+    # 
+    # ==== Options (opts)
+    # :message<Hash>::
+    #   Messages to pass in url query string as value for "_message"
+    # :permanent<Boolean>::
+    #   When true, return status 301 Moved Permanently
+    # 
+    # ==== Returns
+    # String:: Explanation of redirect.
+    # 
+    # ==== Examples
+    #   redirect("/posts/34")
+    #   redirect("/posts/34", :message => { :notice => 'Post updated successfully!' })
+    #   redirect("http://www.merbivore.com/")
+    #   redirect("http://www.merbivore.com/", :permanent => true)
+    # 
+    # :api: public
+    def redirect(url, opts = {})
+      default_redirect_options = { :message => nil, :permanent => false }
+      opts = default_redirect_options.merge(opts)
+      if opts[:message]
+        notice = Merb::Parse.escape([Marshal.dump(opts[:message])].pack("m"))
+        url = url =~ /\?/ ? "#{url}&_message=#{notice}" : "#{url}?_message=#{notice}"
+      end
+      self.status = opts[:permanent] ? 301 : 302
+      Merb.logger.info("Redirecting to: #{url} (#{self.status})")
+      headers['Location'] = url
+      "<html><body>You are being <a href=\"#{url}\">redirected</a>.</body></html>"
+    end
+    
+    # Retreives the redirect message either locally or from the request.
+    # 
+    # :api: public
+    def message
+      @_message = defined?(@_message) ? @_message : request.message
+    end
+    
+    # Sends a file over HTTP.  When given a path to a file, it will set the
+    # right headers so that the static file is served directly.
+    # 
+    # ==== Parameters
+    # file<String>:: Path to file to send to the client.
+    # opts<Hash>:: Options for sending the file (see below).
+    # 
+    # ==== Options (opts)
+    # :disposition<String>::
+    #   The disposition of the file send. Defaults to "attachment".
+    # :filename<String>::
+    #   The name to use for the file. Defaults to the filename of file.
+    # :type<String>:: The content type.
+    #
+    # ==== Returns
+    # IO:: An I/O stream for the file.
+    # 
+    # :api: public
+    def send_file(file, opts={})
+      opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
+      disposition = opts[:disposition].dup || 'attachment'
+      disposition << %(; filename="#{opts[:filename] ? opts[:filename] : File.basename(file)}")
+      headers.update(
+        'Content-Type'              => opts[:type].strip,  # fixes a problem with extra '\r' with some browsers
+        'Content-Disposition'       => disposition,
+        'Content-Transfer-Encoding' => 'binary'
+      )
+      Proc.new do |response|
+        file = File.open(file, 'rb')
+        while chunk = file.read(16384)
+          response.write chunk
+        end
+        file.close
+      end
+    end
+    
+    # Send binary data over HTTP to the user as a file download. May set content type,
+    # apparent file name, and specify whether to show data inline or download as an attachment.
+    # 
+    # ==== Parameters
+    # data<String>:: Path to file to send to the client.
+    # opts<Hash>:: Options for sending the data (see below).
+    # 
+    # ==== Options (opts)
+    # :disposition<String>::
+    #   The disposition of the file send. Defaults to "attachment".
+    # :filename<String>::
+    #   The name to use for the file. Defaults to the filename of file.
+    # :type<String>:: The content type.
+    # 
+    # :api: public
+    def send_data(data, opts={})
+      opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
+      disposition = opts[:disposition].dup || 'attachment'
+      disposition << %(; filename="#{opts[:filename]}") if opts[:filename]
+      headers.update(
+        'Content-Type'              => opts[:type].strip,  # fixes a problem with extra '\r' with some browsers
+        'Content-Disposition'       => disposition,
+        'Content-Transfer-Encoding' => 'binary'
+      )
+      data
+    end
+    
+    # Streams a file over HTTP.
+    # 
+    # ==== Parameters
+    # opts<Hash>:: Options for the file streaming (see below).
+    # &stream::
+    #   A block that, when called, will return an object that responds to
+    #   +get_lines+ for streaming.
+    # 
+    # ==== Options
+    # :disposition<String>::
+    #   The disposition of the file send. Defaults to "attachment".
+    # :type<String>:: The content type.
+    # :content_length<Numeric>:: The length of the content to send.
+    # :filename<String>:: The name to use for the streamed file.
+    #
+    # ==== Examples
+    #   stream_file({ :filename => file_name, :type => content_type,
+    #     :content_length => content_length }) do |response|
+    #     AWS::S3::S3Object.stream(user.folder_name + "-" + user_file.unique_id, bucket_name) do |chunk|
+    #       response.write chunk
+    #     end
+    #   end
+    # 
+    # :api: public
+    def stream_file(opts={}, &stream)
+      opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
+      disposition = opts[:disposition].dup || 'attachment'
+      disposition << %(; filename="#{opts[:filename]}")
+      headers.update(
+        'Content-Type'              => opts[:type].strip,  # fixes a problem with extra '\r' with some browsers
+        'Content-Disposition'       => disposition,
+        'Content-Transfer-Encoding' => 'binary',
+        # Rack specification requires header values to respond to :each
+        'CONTENT-LENGTH'            => opts[:content_length].to_s
+      )
+      Proc.new do |response|
+        stream.call(response)
+      end
+    end
+    
+    # Uses the nginx specific +X-Accel-Redirect+ header to send a file directly
+    # from nginx.
+    # 
+    # ==== Notes
+    # Unless Content-Disposition is set before calling this method,
+    # it is set to attachment with streamed file name.
+    # 
+    # For more information, see the nginx wiki:
+    # http://wiki.codemongers.com/NginxXSendfile
+    # 
+    # and the following sample gist:
+    # http://gist.github.com/11225
+    # 
+    # there's also example application up on GitHub:
+    # 
+    # http://github.com/michaelklishin/nginx-x-accel-redirect-example-application/tree/master
+    # 
+    # ==== Parameters
+    # path<String>:: Path to file to send to the client.
+    # content_type<String>:: content type header value. By default is set to empty string to let
+    #                        Nginx detect it.
+    # 
+    # ==== Return
+    # String:: precisely a single space.
+    # 
+    # :api: public
+    def nginx_send_file(path, content_type = "")
+      # Let Nginx detect content type unless it is explicitly set
+      headers['Content-Type']        = content_type
+      headers["Content-Disposition"] ||= "attachment; filename=#{path.split('/').last}"
+      
+      headers['X-Accel-Redirect']    = path
+      
+      return ' '
+    end  
+    
+    # Sets a cookie to be included in the response.
+    # 
+    # If you need to set a cookie, then use the +cookies+ hash.
+    # 
+    # ==== Parameters
+    # name<~to_s>:: A name for the cookie.
+    # value<~to_s>:: A value for the cookie.
+    # expires<~gmtime:~strftime, Hash>:: An expiration time for the cookie, or a hash of cookie options.
+    # 
+    # :api: public
+    def set_cookie(name, value, expires)
+      options = expires.is_a?(Hash) ? expires : {:expires => expires}
+      cookies.set_cookie(name, value, options)
+    end
+    
+    # Marks a cookie as deleted and gives it an expires stamp in the past. This
+    # method is used primarily internally in Merb.
+    # 
+    # Use the +cookies+ hash to manipulate cookies instead.
+    # 
+    # ==== Parameters
+    # name<~to_s>:: A name for the cookie to delete.
+    # 
+    # :api: public
+    def delete_cookie(name)
+      set_cookie(name, nil, Merb::Const::COOKIE_EXPIRED_TIME)
+    end
+    
+    # Escapes the string representation of +obj+ and escapes it for use in XML.
+    #
+    # ==== Parameter
+    # obj<~to_s>:: The object to escape for use in XML.
+    #
+    # ==== Returns
+    # String:: The escaped object.
+    # 
+    # :api: public
+    def escape_xml(obj)
+      Merb::Parse.escape_xml(obj.to_s)
+    end
+    alias h escape_xml
+    alias escape_html escape_xml
+    
+    private
+    
+    # Marks an output method that only runs on the Mongrel webserver.
+    # 
+    # ==== Raises
+    # NotImplemented:: The Rack adapter is not mongrel.
+    # 
+    # :api: private
+    def only_runs_on_mongrel!
+      unless Merb::Config[:log_stream] == 'mongrel'
+        raise(Merb::ControllerExceptions::NotImplemented, "Current Rack adapter is not mongrel. cannot support this feature")
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/render.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/render.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/render.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,543 @@
+module Merb::RenderMixin
+  # So we can do raise TemplateNotFound
+  include Merb::ControllerExceptions
+
+  # ==== Parameters
+  # base<Module>:: Module that is including RenderMixin (probably a controller)
+  #
+  # @private
+  def self.included(base)
+    base.extend(ClassMethods)
+    base.class_eval do
+      class_inheritable_accessor :_default_render_options
+    end
+  end
+
+  module ClassMethods
+
+    def _templates_for
+      @_templates_for ||= {}
+    end
+
+    # Return the default render options.
+    #
+    # ==== Returns
+    # Hash:: An options hash
+    #
+    # :api: public
+    def default_render_options
+      self._default_render_options ||= {}
+    end
+
+    # Set default render options at the class level.
+    #
+    # ==== Parameters
+    # opts<Hash>:: An options hash
+    #
+    # :api: public
+    def render_options(opts)
+      self._default_render_options = opts
+    end
+
+    # Set the default layout to use or nil/false to disable layout rendering.
+    # This is a shortcut for render_options :layout => false.
+    #
+    # ==== Parameters
+    # layout<~to_s>:: The layout that should be used for this class.
+    #
+    # ==== Notes
+    # You can override by passing :layout => true to render method.
+    #
+    # ==== Returns
+    # Hash:: The default render options.
+    #
+    # :api: public
+    def layout(layout)
+      self.default_render_options.update(:layout => (layout || false))
+    end
+
+    # Enable the default layout logic - reset the layout option.
+    #
+    # ==== Returns
+    # ~to_s:: The layout that was previously set.
+    #
+    # :api: public
+    def default_layout
+      self.default_render_options.delete(:layout)
+    end
+
+  end
+
+  # Render the specified item, with the specified options.
+  #
+  # ==== Parameters
+  # thing<String, Symbol, nil>::
+  #   The thing to render. This will default to the current action
+  # opts<Hash>:: An options hash (see below)
+  #
+  # ==== Options (opts)
+  # :format<Symbol>:: A registered mime-type format
+  # :template<String>::
+  #   The path to the template relative to the template root
+  # :status<~to_i>::
+  #   The status to send to the client. Typically, this would be an integer
+  #   (200), or a Merb status code (Accepted)
+  # :layout<~to_s, FalseClass>::
+  #   A layout to use instead of the default. This should be relative to the
+  #   layout root. By default, the layout will be either the controller_name or
+  #   application. If you want to use an alternative content-type than the one
+  #   that the base template was rendered as, you will need to do :layout =>
+  #   "foo.#{content_type}" (i.e. "foo.json"). If you want to render without
+  #   layout, use :layout => false. This overrides layout set by +layout+ method.
+  #
+  # ==== Returns
+  # String:: The rendered template, including layout, if appropriate.
+  #
+  # ==== Raises
+  # TemplateNotFound:: There is no template for the specified location.
+  #
+  # ==== Alternatives
+  # If you pass a Hash as the first parameter, it will be moved to opts and
+  # "thing" will be the current action
+  #
+  # :api: public
+  def render(thing = nil, opts = {})
+    # render :format => :xml means render nil, :format => :xml
+    opts, thing = thing, nil if thing.is_a?(Hash)
+
+    # Merge with class level default render options
+    opts = self.class.default_render_options.merge(opts)
+
+    # If you don't specify a thing to render, assume they want to render the current action
+    thing ||= action_name.to_sym
+
+    # Content negotiation
+    self.content_type = opts[:format] if opts[:format]
+
+    # Handle options (:status)
+    _handle_options!(opts)
+
+    # Do we have a template to try to render?
+    if thing.is_a?(Symbol) || opts[:template]
+
+      template_method, template_location = 
+        _template_for(thing, content_type, controller_name, opts[:template])
+
+      # Raise an error if there's no template
+      unless template_method && self.respond_to?(template_method)
+        template_files = Merb::Template.template_extensions.map { |ext| "#{template_location}.#{ext}" }
+        raise TemplateNotFound, "Oops! No template found. Merb was looking for #{template_files.join(', ')} " + 
+          "for content type '#{content_type}'. You might have mispelled the template or file name. " + 
+          "Registered template extensions: #{Merb::Template.template_extensions.join(', ')}. " +
+          "If you use Haml or some other template plugin, make sure you required Merb plugin dependency " + 
+          "in your init file."
+      end
+
+      # Call the method in question and throw the content for later consumption by the layout
+      throw_content(:for_layout, self.send(template_method))
+
+    # Do we have a string to render?
+    elsif thing.is_a?(String)
+
+      # Throw it for later consumption by the layout
+      throw_content(:for_layout, thing)
+    end
+
+    # If we find a layout, use it. Otherwise, just render the content thrown for layout.
+    (layout = _get_layout(opts[:layout])) ? send(layout) : catch_content(:for_layout)
+  end
+
+  # Renders an object using to registered transform method based on the
+  # negotiated content-type, if a template does not exist. For instance, if the
+  # content-type is :json, Merb will first look for current_action.json.*.
+  # Failing that, it will run object.to_json.
+  #
+  # ==== Parameter
+  # object<Object>::
+  #   An object that responds_to? the transform method registered for the
+  #   negotiated mime-type.
+  # thing<String, Symbol>::
+  #   The thing to attempt to render via #render before calling the transform
+  #   method on the object. Defaults to nil.
+  # opts<Hash>::
+  #   An options hash that will be used for rendering
+  #   (passed on to #render or serialization methods like #to_json or #to_xml)
+  #
+  # ==== Returns
+  # String::
+  #   The rendered template or if no template is found, the transformed object.
+  #
+  # ==== Raises
+  # NotAcceptable::
+  #   If there is no transform method for the specified mime-type or the object
+  #   does not respond to the transform method.
+  #
+  # ==== Alternatives
+  # A string in the second parameter will be interpreted as a template:
+  #   display @object, "path/to/foo"
+  #   #=> display @object, nil, :template => "path/to/foo"
+  #
+  # A hash in the second parameters will be interpreted as opts:
+  #   display @object, :layout => "zoo"
+  #   #=> display @object, nil, :layout => "zoo"
+  #
+  # If you need to pass extra parameters to serialization method, for instance,
+  # to exclude some of attributes or serialize associations, just pass options
+  # for it.
+  # For instance,
+  #
+  # display @locations, :except => [:locatable_type, :locatable_id], :include => [:locatable]
+  #
+  # serializes object with polymorphic association, not raw locatable_* attributes.
+  #
+  #
+  # ==== Options
+  #
+  # :template                a template to use for rendering
+  # :layout                  a layout to use for rendering
+  # :status                  the status code to return (defaults to 200)
+  # :location                the value of the Location header
+  #
+  # all other options        options that will be pass to serialization method
+  #                          like #to_json or #to_xml
+  #
+  # ==== Notes
+  # The transformed object will not be used in a layout unless a :layout is
+  # explicitly passed in the opts.
+  #
+  # :api: public
+  def display(object, thing = nil, opts = {})
+    template_opt = thing.is_a?(Hash) ? thing.delete(:template) : opts.delete(:template)
+
+    case thing
+    # display @object, "path/to/foo" means display @object, nil, :template => "path/to/foo"
+    when String
+      template_opt, thing = thing, nil
+    # display @object, :template => "path/to/foo" means display @object, nil, :template => "path/to/foo"
+    when Hash
+      opts, thing = thing, nil
+    end
+
+    # Try to render without the object
+    render(thing || action_name.to_sym, opts.merge(:template => template_opt))
+
+  # If the render fails (i.e. a template was not found)
+  rescue TemplateNotFound => e
+    # Merge with class level default render options
+    # @todo can we find a way to refactor this out so we don't have to do it everywhere?
+    opts = self.class.default_render_options.merge(opts)
+
+    # Figure out what to transform and raise NotAcceptable unless there's a transform method assigned
+    transform = Merb.mime_transform_method(content_type)
+    if !transform
+      raise NotAcceptable, "#{e.message} and there was no transform method registered for #{content_type.inspect}"
+    elsif !object.respond_to?(transform)
+      raise NotAcceptable, "#{e.message} and your object does not respond to ##{transform}"
+    end
+
+    layout_opt = opts.delete(:layout)
+    _handle_options!(opts)
+    throw_content(:for_layout, opts.empty? ? object.send(transform) : object.send(transform, opts))
+    
+    meth, _ = _template_for(layout_opt, layout_opt.to_s.index(".") ? nil : content_type, "layout") if layout_opt
+    meth ? send(meth) : catch_content(:for_layout)
+  end
+
+  # Render a partial template.
+  #
+  # ==== Parameters
+  # template<~to_s>::
+  #   The path to the template, relative to the current controller or the
+  #   template root; absolute path will work too. If the template contains a "/", 
+  #   Merb will search for it relative to the template root; otherwise, 
+  #   Merb will search for it relative to the current controller.
+  # opts<Hash>:: A hash of options (see below)
+  #
+  # ==== Options (opts)
+  # :with<Object, Array>::
+  #   An object or an array of objects that will be passed into the partial.
+  # :as<~to_sym>:: The local name of the :with Object inside of the partial.
+  # :format<Symbol>:: The mime format that you want the partial to be in (:js, :html, etc.)
+  # others::
+  #   A Hash object names and values that will be the local names and values
+  #   inside the partial.
+  #
+  # ==== Examples
+  #   partial :foo, :hello => @object
+  #
+  # The "_foo" partial will be called, relative to the current controller,
+  # with a local variable of +hello+ inside of it, assigned to @object.
+  #
+  #   partial :bar, :with => ['one', 'two', 'three']
+  #
+  # The "_bar" partial will be called once for each element of the array
+  # specified by :with for a total of three iterations. Each element
+  # of the array will be available in the partial via a local variable named
+  # +bar+. Additionally, there will be two extra local variables:
+  # +collection_index+ and +collection_size+. +collection_index+ is the index
+  # of the object currently referenced by +bar+ in the collection passed to
+  # the partial. +collection_size+ is the total size of the collection.
+  #
+  # By default, the object specified by :with will be available through a
+  # local variable with the same name as the partial template. However,
+  # this can be changed using the :as option.
+  #
+  #   partial :bar, :with => "one", :as => :number
+  #
+  # In this case, "one" will be available in the partial through the local
+  # variable named +number+.
+  #
+  # :api: public
+  def partial(template, opts={})
+
+    # partial :foo becomes "#{controller_name}/_foo"
+    # partial "foo/bar" becomes "foo/_bar"
+    template = template.to_s
+    if template =~ %r{^/}
+      template_path = File.dirname(template) / "_#{File.basename(template)}"
+    else
+      kontroller = (m = template.match(/.*(?=\/)/)) ? m[0] : controller_name
+    end
+    template = "_#{File.basename(template)}"
+
+    # This handles no :with as well
+    with = [opts.delete(:with)].flatten
+    as = (opts.delete(:as) || template.match(%r[(?:.*/)?_([^\./]*)])[1]).to_sym
+
+    # Ensure that as is in the locals hash even if it isn't passed in here
+    # so that it's included in the preamble. 
+    locals = opts.merge(:collection_index => -1, :collection_size => with.size, as => opts[as])
+    template_method, template_location = _template_for(
+      template, 
+      opts.delete(:format) || content_type, 
+      kontroller, 
+      template_path, 
+      locals.keys)
+    
+    # this handles an edge-case where the name of the partial is _foo.* and your opts
+    # have :foo as a key.
+    named_local = opts.key?(as)
+    
+    sent_template = with.map do |temp|
+      locals[as] = temp unless named_local
+
+      if template_method && self.respond_to?(template_method)
+        locals[:collection_index] += 1
+        send(template_method, locals)
+      else
+        raise TemplateNotFound, "Could not find template at #{template_location}.*"
+      end
+    end.join
+    
+    sent_template
+  end
+
+  # Take the options hash and handle it as appropriate.
+  #
+  # ==== Parameters
+  # opts<Hash>:: The options hash that was passed into render.
+  #
+  # ==== Options
+  # :status<~to_i>::
+  #   The status of the response will be set to opts[:status].to_i
+  #
+  # ==== Returns
+  # Hash:: The options hash that was passed in.
+  #
+  # :api: private
+  def _handle_options!(opts)
+    self.status = opts.delete(:status).to_i if opts[:status]
+    headers["Location"] = opts.delete(:location) if opts[:location]
+    opts
+  end
+
+  # Get the layout that should be used. The content-type will be appended to
+  # the layout unless the layout already contains a "." in it.
+  #
+  # If no layout was passed in, this method will look for one with the same
+  # name as the controller, and finally one in "application.#{content_type}".
+  #
+  # ==== Parameters
+  # layout<~to_s>:: A layout, relative to the layout root. Defaults to nil.
+  #
+  # ==== Returns
+  # String:: The method name that corresponds to the found layout.
+  #
+  # ==== Raises
+  # TemplateNotFound::
+  #   If a layout was specified (either via layout in the class or by passing
+  #   one in to this method), and not found. No error will be raised if no
+  #   layout was specified, and the default layouts were not found.
+  #
+  # :api: private
+  def _get_layout(layout = nil)
+    return false if layout == false
+    
+    layout = layout.instance_of?(Symbol) && self.respond_to?(layout, true) ? send(layout) : layout
+    layout = layout.to_s if layout
+
+    # If a layout was provided, throw an error if it's not found
+    if layout      
+      template_method, template_location = 
+        _template_for(layout, layout.index(".") ? nil : content_type, "layout")
+        
+      raise TemplateNotFound, "No layout found at #{template_location}" unless template_method
+      template_method
+
+    # If a layout was not provided, try the default locations
+    else
+      template, location = _template_for(controller_name, content_type, "layout")
+      template, location = _template_for("application", content_type, "layout") unless template
+      template
+    end
+  end
+
+  # Iterate over the template roots in reverse order, and return the template
+  # and template location of the first match.
+  #
+  # ==== Parameters
+  # context<Object>:: The controller action or template (basename or absolute path).
+  # content_type<~to_s>:: The content type (like html or json).
+  # controller<~to_s>:: The name of the controller. Defaults to nil.
+  # locals<Array[Symbol]>:: A list of locals to assign from the args passed into the compiled template.
+  #
+  # ==== Options (opts)
+  # :template<String>::
+  #   The location of the template to use. Defaults to whatever matches this
+  #   context, content_type and controller.
+  #
+  # ==== Returns
+  # Array[Symbol, String]::
+  #   A pair consisting of the template method and location.
+  #
+  # :api: private
+  def _template_for(context, content_type, controller=nil, template=nil, locals=[])
+    tmp = self.class._templates_for[[context, content_type, controller, template, locals]]
+    return tmp if tmp
+
+    template_method, template_location = nil, nil
+
+    # absolute path to a template (:template => "/foo/bar")
+    if template.is_a?(String) && template =~ %r{^/}
+      template_location = self._absolute_template_location(template, content_type)
+      return [_template_method_for(template_location, locals), template_location]
+    end
+
+    self.class._template_roots.reverse_each do |root, template_meth|
+      # :template => "foo/bar.html" where root / "foo/bar.html.*" exists
+      if template
+        template_location = root / self.send(template_meth, template, content_type, nil)
+      # :layout => "foo" where root / "layouts" / "#{controller}.html.*" exists        
+      else
+        template_location = root / self.send(template_meth, context, content_type, controller)
+      end
+    
+      break if template_method = _template_method_for(template_location.to_s, locals)
+    end
+
+    # template_location is a Pathname
+    ret = [template_method, template_location.to_s]
+    unless Merb::Config[:reload_templates]
+      self.class._templates_for[[context, content_type, controller, template, locals]] = ret
+    end
+    ret
+  end
+  
+  # Return the template method for a location, and check to make sure the current controller
+  # actually responds to the method.
+  #
+  # ==== Parameters
+  # template_location<String>:: The phyical path of the template
+  # locals<Array[Symbol]>:: A list of locals to assign from the args passed into the compiled template.
+  #
+  # ==== Returns
+  # String:: The method, if it exists. Otherwise return nil.
+  #
+  # :api: private
+  def _template_method_for(template_location, locals)
+    meth = Merb::Template.template_for(template_location, [], locals)
+    meth && self.respond_to?(meth) ? meth : nil
+  end
+
+  # Called in templates to get at content thrown in another template. The
+  # results of rendering a template are automatically thrown into :for_layout,
+  # so catch_content or catch_content(:for_layout) can be used inside layouts
+  # to get the content rendered by the action template.
+  #
+  # ==== Parameters
+  # obj<Object>:: The key in the thrown_content hash. Defaults to :for_layout.
+  #
+  # :api: public
+  def catch_content(obj = :for_layout)
+    @_caught_content[obj] || ''
+  end
+
+  # Called in templates to test for the existence of previously thrown content.
+  #
+  # ==== Parameters
+  # obj<Object>:: The key in the thrown_content hash. Defaults to :for_layout.
+  #
+  # :api: public
+  def thrown_content?(obj = :for_layout)
+    @_caught_content.key?(obj)
+  end
+
+  # Called in templates to store up content for later use. Takes a string
+  # and/or a block. First, the string is evaluated, and then the block is
+  # captured using the capture() helper provided by the template languages. The
+  # two are concatenated together.
+  #
+  # ==== Parameters
+  # obj<Object>:: The key in the thrown_content hash.
+  # string<String>:: Textual content. Defaults to nil.
+  # &block:: A block to be evaluated and concatenated to string.
+  #
+  # ==== Raises
+  # ArgumentError:: Neither string nor block given.
+  #
+  # ==== Example
+  #   throw_content(:foo, "Foo")
+  #   catch_content(:foo) #=> "Foo"
+  #
+  # :api: public
+  def throw_content(obj, string = nil, &block)
+    unless string || block_given?
+      raise ArgumentError, "You must pass a block or a string into throw_content"
+    end
+    @_caught_content[obj] = string.to_s << (block_given? ? capture(&block) : "")
+  end
+
+  # Called in templates to append content for later use. Works like throw_content.
+  #
+  # @param [Object] obj
+  #   Key used in the thrown_content hash.
+  # @param [String] string
+  #   Textual content. Default to nil.
+  # @yield 
+  #   Evaluated with result concatenated to string.
+  #
+  # @raise [ArgumentError]
+  #   Neither string nor block given
+  #
+  # :api: public
+  def append_content(obj, string = nil, &block)
+    unless string || block_given?
+      raise ArgumentError, "You must pass a block or a string into append_content"
+    end
+    @_caught_content[obj] = "" if @_caught_content[obj].nil?
+    @_caught_content[obj] << string.to_s << (block_given? ? capture(&block) : "")
+  end
+
+  # Called when renderers need to be sure that existing thrown content is cleared
+  # before throwing new content. This prevents double rendering of content when
+  # multiple templates are rendered after each other.
+  #
+  # ==== Parameters
+  # obj<Object>:: The key in the thrown_content hash. Defaults to :for_layout.
+  #
+  # :api: public
+  def clear_content(obj = :for_layout)
+    @_caught_content.delete(obj) unless @_caught_content[obj].nil?
+  end
+
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/responder.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/responder.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/mixins/responder.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,521 @@
+require 'enumerator'
+require 'merb-core/controller/mime'
+
+module Merb
+  # The ResponderMixin adds methods that help you manage what
+  # formats your controllers have available, determine what format(s)
+  # the client requested and is capable of handling, and perform
+  # content negotiation to pick the proper content format to
+  # deliver.
+  # 
+  # If you hear someone say "Use provides" they're talking about the
+  # Responder.  If you hear someone ask "What happened to respond_to?"
+  # it was replaced by provides and the other Responder methods.
+  # 
+  # == A simple example
+  # 
+  # The best way to understand how all of these pieces fit together is
+  # with an example.  Here's a simple web-service ready resource that
+  # provides a list of all the widgets we know about.  The widget list is 
+  # available in 3 formats: :html (the default), plus :xml and :text.
+  # 
+  #     class Widgets < Application
+  #       provides :html   # This is the default, but you can
+  #                        # be explicit if you like.
+  #       provides :xml, :text
+  #       
+  #       def index
+  #         @widgets = Widget.fetch
+  #         render @widgets
+  #       end
+  #     end
+  # 
+  # Let's look at some example requests for this list of widgets.  We'll
+  # assume they're all GET requests, but that's only to make the examples
+  # easier; this works for the full set of RESTful methods.
+  # 
+  # 1. The simplest case, /widgets.html
+  #    Since the request includes a specific format (.html) we know
+  #    what format to return.  Since :html is in our list of provided
+  #    formats, that's what we'll return.  +render+ will look
+  #    for an index.html.erb (or another template format
+  #    like index.html.mab; see the documentation on Template engines)
+  # 
+  # 2. Almost as simple, /widgets.xml
+  #    This is very similar.  They want :xml, we have :xml, so
+  #    that's what they get.  If +render+ doesn't find an 
+  #    index.xml.builder or similar template, it will call +to_xml+
+  #    on @widgets.  This may or may not do something useful, but you can 
+  #    see how it works.
+  #
+  # 3. A browser request for /widgets
+  #    This time the URL doesn't say what format is being requested, so
+  #    we'll look to the HTTP Accept: header.  If it's '*/*' (anything),
+  #    we'll use the first format on our list, :html by default.
+  #    
+  #    If it parses to a list of accepted formats, we'll look through 
+  #    them, in order, until we find one we have available.  If we find
+  #    one, we'll use that.  Otherwise, we can't fulfill the request: 
+  #    they asked for a format we don't have.  So we raise
+  #    406: Not Acceptable.
+  # 
+  # == A more complex example
+  # 
+  # Sometimes you don't have the same code to handle each available 
+  # format. Sometimes you need to load different data to serve
+  # /widgets.xml versus /widgets.txt.  In that case, you can use
+  # +content_type+ to determine what format will be delivered.
+  # 
+  #     class Widgets < Application
+  #       def action1
+  #         if content_type == :text
+  #           Widget.load_text_formatted(params[:id])
+  #         else
+  #           render
+  #         end
+  #       end
+  #       
+  #       def action2
+  #         case content_type
+  #         when :html
+  #           handle_html()
+  #         when :xml
+  #           handle_xml()
+  #         when :text
+  #           handle_text()
+  #         else
+  #           render
+  #         end
+  #       end
+  #     end
+  # 
+  # You can do any standard Ruby flow control using +content_type+.  If
+  # you don't call it yourself, it will be called (triggering content
+  # negotiation) by +render+.
+  #
+  # Once +content_type+ has been called, the output format is frozen,
+  # and none of the provides methods can be used.
+  module ResponderMixin
+    
+    TYPES = Dictionary.new
+    MIMES = {}
+    MIME_MUTEX = Mutex.new
+    ACCEPT_RESULTS = {}
+
+    class ContentTypeAlreadySet < StandardError; end
+    
+    # ==== Parameters
+    # base<Module>:: The module that ResponderMixin was mixed into
+    #
+    # :api: private
+    def self.included(base)
+      base.extend(ClassMethods)
+      base.class_eval do
+        class_inheritable_accessor :class_provided_formats
+        self.class_provided_formats = []
+      end
+      base.reset_provides
+    end
+
+    module ClassMethods
+      
+      # Adds symbols representing formats to the controller's default list of
+      # provided_formats. These will apply to every action in the controller,
+      # unless modified in the action. If the last argument is a Hash or an
+      # Array, these are regarded as arguments to pass to the to_<mime_type>
+      # method as needed.
+      #
+      # ==== Parameters
+      # *formats<Symbol>::
+      #   A list of mime-types that the controller should provide.
+      #
+      # ==== Returns
+      # Array[Symbol]:: List of formats passed in.
+      #
+      # ==== Examples
+      #   provides :html, :xml
+      #
+      # :api: public
+      def provides(*formats)
+        self.class_provided_formats |= formats
+      end
+      
+      # This class should only provide the formats listed here, despite any
+      # other definitions previously or in superclasses.
+      #
+      # ==== Parameters
+      # *formats<Symbol>:: Registered mime-types.
+      # 
+      # ==== Returns
+      # Array[Symbol]:: List of formats passed in.      
+      #
+      # :api: public
+      def only_provides(*formats)
+        clear_provides
+        provides(*formats)
+      end
+
+      # This class should not provide any of this list of formats, despite any.
+      # other definitions previously or in superclasses.
+      # 
+      # ==== Parameters
+      # *formats<Symbol>:: Registered mime-types.
+      # 
+      # ==== Returns
+      # Array[Symbol]::
+      #   List of formats that remain after removing the ones not to provide.
+      #
+      # :api: public
+      def does_not_provide(*formats)
+        self.class_provided_formats -= formats
+      end
+
+      # Clear the list of provides.
+      #
+      # ==== Returns
+      # Array:: An empty Array.
+      #
+      # :api: public
+      def clear_provides
+        self.class_provided_formats.clear
+      end
+      
+      # Reset the list of provides to include only :html.
+      #
+      # ==== Returns
+      # Array[Symbol]:: [:html].
+      #
+      # :api: public
+      def reset_provides
+        only_provides(:html)
+      end
+    end
+
+    # ==== Returns
+    # Array[Symbol]::
+    #   The current list of formats provided for this instance of the
+    #   controller. It starts with what has been set in the controller (or
+    #   :html by default) but can be modifed on a per-action basis.      
+    #
+    # :api: private
+    def _provided_formats
+      @_provided_formats ||= class_provided_formats.dup
+    end
+    
+    # Adds formats to the list of provided formats for this particular request.
+    # Usually used to add formats to a single action. See also the
+    # controller-level provides that affects all actions in a controller.
+    #
+    # ==== Parameters
+    # *formats<Symbol>::
+    #   A list of formats to add to the per-action list of provided formats.
+    #
+    # ==== Raises
+    # Merb::ResponderMixin::ContentTypeAlreadySet::
+    #   Content negotiation already occured, and the content_type is set.
+    #
+    # ==== Returns
+    # Array[Symbol]:: List of formats passed in.
+    #
+    # :api: public
+    def provides(*formats)
+      if @_content_type
+        raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
+      end
+      @_provided_formats = self._provided_formats | formats # merges with class_provided_formats if not already
+    end
+
+    # Sets list of provided formats for this particular request. Usually used
+    # to limit formats to a single action. See also the controller-level
+    # only_provides that affects all actions in a controller.      
+    # 
+    # ==== Parameters
+    # *formats<Symbol>::
+    #   A list of formats to use as the per-action list of provided formats.
+    #
+    # ==== Returns
+    # Array[Symbol]:: List of formats passed in.
+    #
+    # :api: public
+    def only_provides(*formats)
+      @_provided_formats = []
+      provides(*formats)
+    end
+    
+    # Removes formats from the list of provided formats for this particular 
+    # request. Usually used to remove formats from a single action.  See
+    # also the controller-level does_not_provide that affects all actions in a
+    # controller.
+    #
+    # ==== Parameters
+    # *formats<Symbol>:: Registered mime-type
+    # 
+    # ==== Returns
+    # Array[Symbol]::
+    #   List of formats that remain after removing the ones not to provide.
+    #
+    # :api: public
+    def does_not_provide(*formats)
+      @_provided_formats -= formats.flatten
+    end
+    
+    def _accept_types
+      accept = request.accept
+      
+      MIME_MUTEX.synchronize do
+        return ACCEPT_RESULTS[accept] if ACCEPT_RESULTS[accept]
+      end
+      
+      types = request.accept.split(Merb::Const::ACCEPT_SPLIT).map do |entry|
+        entry =~ Merb::Const::MEDIA_RANGE
+        media_range, quality = $1, $3
+        
+        kind, sub_type = media_range.split(Merb::Const::SLASH_SPLIT)
+        mime_sym = Merb.available_accepts[media_range]
+        mime = Merb.available_mime_types[mime_sym]
+        (quality ||= 0.0) if media_range == "*/*"          
+        quality = quality ? (quality.to_f * 100).to_i : 100
+        quality *= (mime && mime[:default_quality] || 1)
+        [quality, mime_sym, media_range, kind, sub_type, mime]
+      end
+    
+      accepts = types.sort_by {|x| x.first }.reverse!.map! {|x| x[1]}      
+      
+      MIME_MUTEX.synchronize do
+        ACCEPT_RESULTS[accept] = accepts.freeze
+      end
+      
+      accepts
+    end
+    
+    # Do the content negotiation:
+    # 1. if params[:format] is there, and provided, use it
+    # 2. Parse the Accept header
+    # 3. If it's */*, use the first provided format
+    # 4. Look for one that is provided, in order of request
+    # 5. Raise 406 if none found
+    #
+    # :api: private
+    def _perform_content_negotiation
+      if fmt = params[:format]
+        accepts = [fmt.to_sym]
+      else
+        accepts = _accept_types
+      end
+
+      provided_formats = _provided_formats
+      
+      specifics = accepts & provided_formats
+      return specifics.first unless specifics.length == 0
+      return provided_formats.first if accepts.include?(:all) && !provided_formats.empty?
+      
+      message  = "A format (%s) that isn't provided (%s) has been requested. "
+      message += "Make sure the action provides the format, and be "
+      message += "careful of before filters which won't recognize "
+      message += "formats provided within actions."
+      raise Merb::ControllerExceptions::NotAcceptable,
+        (message % [accepts.join(', '), provided_formats.join(', ')])
+    end
+    
+    
+
+    # Returns the output format for this request, based on the 
+    # provided formats, <tt>params[:format]</tt> and the client's HTTP
+    # Accept header.
+    #
+    # The first time this is called, it triggers content negotiation
+    # and caches the value.  Once you call +content_type+ you can
+    # not set or change the list of provided formats.
+    #
+    # Called automatically by +render+, so you should only call it if
+    # you need the value, not to trigger content negotiation. 
+    # 
+    # ==== Parameters
+    # fmt<String>:: 
+    #   An optional format to use instead of performing content negotiation.
+    #   This can be used to pass in the values of opts[:format] from the 
+    #   render function to short-circuit content-negotiation when it's not
+    #   necessary. This optional parameter should not be considered part
+    #   of the public API.
+    #
+    # ==== Returns
+    # Symbol:: The content-type that will be used for this controller.
+    #
+    # :api: public
+    def content_type(fmt = nil)
+      self.content_type = (fmt || _perform_content_negotiation) unless @_content_type
+      @_content_type
+    end
+    
+    # Sets the content type of the current response to a value based on 
+    # a passed in key. The Content-Type header will be set to the first
+    # registered header for the mime-type.
+    #
+    # ==== Parameters
+    # type<Symbol>:: The content type.
+    #
+    # ==== Raises
+    # ArgumentError:: type is not in the list of registered mime-types.
+    #
+    # ==== Returns
+    # Symbol:: The content-type that was passed in.
+    #
+    # :api: plugin
+    def content_type=(type)
+      unless Merb.available_mime_types.has_key?(type)
+        raise Merb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{type}") 
+      end
+
+      @_content_type = type
+
+      mime = Merb.available_mime_types[type]
+      
+      headers["Content-Type"] = mime[:content_type]
+      
+      # merge any format specific response headers
+      mime[:response_headers].each { |k,v| headers[k] ||= v }
+      
+      # if given, use a block to finetune any runtime headers
+      mime[:response_block].call(self) if mime[:response_block]
+
+      @_content_type
+    end
+    
+  end
+
+  class Responder
+    # Parses the raw accept header into an array of sorted AcceptType objects.
+    #
+    # ==== Parameters
+    # accept_header<~to_s>:: The raw accept header.
+    #
+    # ==== Returns
+    # Array[AcceptType]:: The accepted types.
+    #
+    # @private
+    def self.parse(accept_header)
+      headers = accept_header.split(/,/)
+      idx, list = 0, []
+      while idx < headers.size
+        list << AcceptType.new(headers[idx], idx)
+        idx += 1
+      end
+      list.sort
+    end
+  end
+
+  class AcceptType
+    attr_reader :media_range, :quality, :index, :type, :sub_type
+
+    # ==== Parameters
+    # entry<String>:: The accept type pattern
+    # index<Fixnum>::
+    #   The index used for sorting accept types. A lower value indicates higher
+    #   priority.
+    # 
+    # :api: private
+    def initialize(entry,index)
+      @index = index
+      
+      entry =~ /\s*([^;\s]*)\s*(;\s*q=\s*(.*))?/
+      @media_range, quality = $1, $3
+      
+      @type, @sub_type = @media_range.split(%r{/})
+      (quality ||= 0.0) if @media_range == "*/*"
+      @quality = quality ? (quality.to_f * 100).to_i : 100
+      @quality *= (mime && mime[:default_quality] || 1)
+    end
+    
+    # Compares two accept types for sorting purposes.
+    #
+    # ==== Parameters
+    # entry<AcceptType>:: The accept type to compare.
+    #
+    # ==== Returns
+    # Fixnum::
+    #   -1, 0 or 1, depending on whether entry has a lower, equal or higher
+    #   priority than the accept type being compared.
+    #
+    # :api: private
+    def <=>(entry)
+      if entry.quality == quality
+        @index <=> entry.index
+      else
+        entry.quality <=> @quality
+      end
+    end
+
+
+    # ==== Parameters
+    # entry<AcceptType>:: The accept type to compare.
+    #
+    # ==== Returns
+    # Boolean::
+    #   True if the accept types are equal, i.e. if the synonyms for this
+    #   accept type includes the entry media range.
+    #
+    # :api: private
+    def eql?(entry)
+      synonyms.include?(entry.media_range)
+    end
+
+    # An alias for eql?.
+    #
+    # :api: private
+    def ==(entry); eql?(entry); end
+
+    # ==== Returns
+    # Fixnum:: A hash based on the super range.
+    #
+    # :api: private
+    def hash; super_range.hash; end
+
+    # ==== Returns
+    # Array[String]::
+    #   All Accept header values, such as "text/html", that match this type.
+    #
+    # :api: private
+    def synonyms
+      return @syns if @syns
+      if _mime = mime
+        @syns = _mime[:accepts]
+      else
+        @syns = []
+      end
+    end
+    
+    # :api: private
+    def mime
+      @mime ||= Merb.available_mime_types[Merb::ResponderMixin::MIMES[@media_range]]
+    end
+
+    # ==== Returns
+    # String::
+    #   The primary media range for this accept type, i.e. either the first
+    #   synonym or, if none exist, the media range.
+    #
+    # :api: private
+    def super_range
+      synonyms.first || @media_range
+    end
+
+    # ==== Returns
+    # Symbol: The type as a symbol, e.g. :html.
+    #
+    # :api: private
+    def to_sym
+      Merb.available_mime_types.select{|k,v| 
+        v[:accepts] == synonyms || v[:accepts][0] == synonyms[0]}.flatten.first
+    end
+
+    # ==== Returns
+    # String:: The accept type as a string, i.e. the media range.
+    #
+    # :api: private
+    def to_s
+      @media_range
+    end
+  
+  end
+
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/template.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/template.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/controller/template.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,303 @@
+module Merb::InlineTemplates
+end
+
+module Merb::Template
+  
+  EXTENSIONS            = {} unless defined?(EXTENSIONS)
+  METHOD_LIST           = {} unless defined?(METHOD_LIST)
+  SUPPORTED_LOCALS_LIST = Hash.new([].freeze) unless defined?(SUPPORTED_LOCALS_LIST)
+  MTIMES                = {} unless defined?(MTIMES)
+  
+  class << self
+    # Get the template's method name from a full path. This replaces
+    # non-alphanumeric characters with __ and "." with "_"
+    #
+    # Collisions are potentially possible with something like:
+    # ~foo.bar and __foo.bar or !foo.bar.
+    #
+    # ==== Parameters
+    # path<String>:: A full path to convert to a valid Ruby method name
+    #
+    # ==== Returns
+    # String:: The template name.
+    #
+    #
+    # We might want to replace this with something that varies the
+    # character replaced based on the non-alphanumeric character
+    # to avoid edge-case collisions.
+    #
+    # :api: private
+    def template_name(path)
+      path = File.expand_path(path)      
+      path.gsub(/[^\.a-zA-Z0-9]/, "__").gsub(/\./, "_")
+    end
+
+    chainable do
+      # For a given path, get an IO object that responds to #path.
+      #
+      # This is so that plugins can override this if they provide
+      # mechanisms for specifying templates that are not just simple
+      # files. The plugin is responsible for ensuring that the fake
+      # path provided will work with #template_for, and thus the
+      # RenderMixin in general.
+      #
+      # ==== Parameters
+      # path<String>:: A full path to find a template for. This is the
+      #   path that the RenderMixin assumes it should find the template
+      #   in.
+      # 
+      # ==== Returns
+      # IO#path:: An IO object that responds to path (File or VirtualFile).
+      #
+      # :api: plugin
+      # @overridable
+      def load_template_io(path)
+        file = Dir["#{path}.{#{template_extensions.join(',')}}"].first
+        File.open(file, "r") if file
+      end
+    end
+
+    # Get the name of the template method for a particular path.
+    #
+    # ==== Parameters
+    # path<String>:: A full path to find a template method for.
+    # template_stack<Array>:: The template stack. Not used.
+    # locals<Array[Symbol]>:: The names of local variables
+    #
+    # ==== Returns
+    # <String>:: name of the method that inlines the template.
+    #
+    # :api: private
+    def template_for(path, template_stack = [], locals=[])
+      path = File.expand_path(path)
+      
+      if needs_compilation?(path, locals)
+        template_io = load_template_io(path)
+        METHOD_LIST[path] = inline_template(template_io, locals) if template_io
+      end
+      
+      METHOD_LIST[path]
+    end
+    
+    # Decide if a template needs to be re/compiled.
+    #
+    # ==== Parameters
+    # path<String>:: The full path of the template to check support for.
+    # locals<Array[Symbol]>:: The list of locals that need to be supported
+    #
+    # ==== Returns
+    # Boolean:: Whether or not the template for the provided path needs to be recompiled
+    #
+    # :api: private
+    def needs_compilation?(path, locals)
+      return true if Merb::Config[:reload_templates] || !METHOD_LIST[path]
+      
+      current_locals = SUPPORTED_LOCALS_LIST[path]
+      current_locals != locals &&
+        !(locals - current_locals).empty?
+    end
+    
+    # Get all known template extensions
+    #
+    # ==== Returns
+    #   Array:: Extension strings.
+    #
+    # :api: plugin
+    def template_extensions
+      EXTENSIONS.keys
+    end
+    
+    # Takes a template at a particular path and inlines it into a module and
+    # adds it to the METHOD_LIST table to speed lookup later.
+    # 
+    # ==== Parameters
+    # io<#path>::
+    #   An IO that responds to #path (File or VirtualFile)
+    # locals<Array[Symbol]>::
+    #   A list of local names that should be assigned in the template method
+    #   from the arguments hash. Defaults to [].
+    # mod<Module>::
+    #   The module to put the compiled method into. Defaults to
+    #   Merb::InlineTemplates
+    #
+    # ==== Returns
+    # Symbol:: The name of the method that the template was compiled into.
+    #
+    # ==== Notes
+    # Even though this method supports inlining into any module, the method
+    # must be available to instances of AbstractController that will use it.
+    #
+    # :api: private
+    def inline_template(io, locals=[], mod = Merb::InlineTemplates)
+      full_file_path = File.expand_path(io.path)
+      engine_neutral_path = full_file_path.gsub(/\.[^\.]*$/, "")
+      
+      local_list = (SUPPORTED_LOCALS_LIST[engine_neutral_path] |= locals)
+      ret = METHOD_LIST[engine_neutral_path] =
+        engine_for(full_file_path).compile_template(io, 
+        template_name(full_file_path), local_list, mod)
+        
+      io.close
+      ret
+    end
+    
+    # Finds the engine for a particular path.
+    # 
+    # ==== Parameters
+    # path<String>:: The path of the file to find an engine for.
+    #
+    # ==== Returns
+    # Class:: The engine.
+    #
+    # :api: private
+    def engine_for(path)
+      path = File.expand_path(path)      
+      EXTENSIONS[path.match(/\.([^\.]*)$/)[1]]
+    end
+    
+    # Registers the extensions that will trigger a particular templating
+    # engine.
+    # 
+    # ==== Parameters
+    # engine<Class>:: The class of the engine that is being registered
+    # extensions<Array[String]>:: 
+    #   The list of extensions that will be registered with this templating
+    #   language
+    #
+    # ==== Raises
+    # ArgumentError:: engine does not have a compile_template method.
+    #
+    # ==== Returns
+    # nil
+    #
+    # ==== Example
+    #   Merb::Template.register_extensions(Merb::Template::Erubis, ["erb"])
+    #
+    # :api: plugin
+    def register_extensions(engine, extensions) 
+      raise ArgumentError, "The class you are registering does not have a compile_template method" unless
+        engine.respond_to?(:compile_template)
+      extensions.each{|ext| EXTENSIONS[ext] = engine }
+      Merb::AbstractController.class_eval <<-HERE
+        include #{engine}::Mixin
+      HERE
+    end
+  end
+  
+  require 'erubis'
+
+  class Erubis    
+    # ==== Parameters
+    # io<#path>:: An IO containing the full path of the template.
+    # name<String>:: The name of the method that will be created.
+    # locals<Array[Symbol]>:: A list of locals to assign from the args passed into the compiled template.
+    # mod<Module>:: The module that the compiled method will be placed into.
+    #
+    # :api: private
+    def self.compile_template(io, name, locals, mod)
+      template = ::Erubis::BlockAwareEruby.new(io.read)
+      _old_verbose, $VERBOSE = $VERBOSE, nil
+      assigns = locals.inject([]) do |assigns, local|
+        assigns << "#{local} = _locals[#{local.inspect}]"
+      end.join(";")
+      
+      code = "def #{name}(_locals={}); #{assigns}; #{template.src}; end"
+      mod.module_eval code, File.expand_path(io.path)
+      $VERBOSE = _old_verbose
+      
+      name
+    end
+
+    module Mixin
+      
+      # ==== Parameters
+      # *args:: Arguments to pass to the block.
+      # &block:: The template block to call.
+      #
+      # ==== Returns
+      # String:: The output of the block.
+      #
+      # ==== Examples
+      # Capture being used in a .html.erb page:
+      # 
+      #   <% @foo = capture do %>
+      #     <p>Some Foo content!</p> 
+      #   <% end %>
+      #
+      # :api: private
+      def capture_erb(*args, &block)
+        _old_buf, @_erb_buf = @_erb_buf, ""
+        block.call(*args)
+        ret = @_erb_buf
+        @_erb_buf = _old_buf
+        ret
+      end
+
+      # :api: private
+      def concat_erb(string, binding)
+        @_erb_buf << string
+      end
+            
+    end
+  
+    Merb::Template.register_extensions(self, %w[erb])    
+  end
+  
+end
+
+module Erubis
+  module BlockAwareEnhancer
+    # :api: private
+    def add_preamble(src)
+      src << "_old_buf, @_erb_buf = @_erb_buf, ''; "
+      src << "@_engine = 'erb'; "
+    end
+
+    # :api: private
+    def add_postamble(src)
+      src << "\n" unless src[-1] == ?\n      
+      src << "_ret = @_erb_buf; @_erb_buf = _old_buf; _ret.to_s;\n"
+    end
+
+    # :api: private
+    def add_text(src, text)
+      src << " @_erb_buf.concat('" << escape_text(text) << "'); "
+    end
+
+    # :api: private
+    def add_expr_escaped(src, code)
+      src << ' @_erb_buf.concat(' << escaped_expr(code) << ');'
+    end
+    
+    # :api: private
+    def add_stmt2(src, code, tailch)
+      src << code
+      src << " ).to_s; " if tailch == "="
+      src << ';' unless code[-1] == ?\n
+    end
+    
+    # :api: private
+    def add_expr_literal(src, code)
+      if code =~ /(do|\{)(\s*\|[^|]*\|)?\s*\Z/
+        src << ' @_erb_buf.concat( ' << code << "; "
+      else
+        src << ' @_erb_buf.concat((' << code << ').to_s);'
+      end
+    end
+  end
+
+  class BlockAwareEruby < Eruby
+    include BlockAwareEnhancer
+  end
+  
+  # module RubyEvaluator
+  # 
+  #   # DOC
+  #   def def_method(object, method_name, filename=nil)
+  #     m = object.is_a?(Module) ? :module_eval : :instance_eval
+  #     setup = "@_engine = 'erb'"
+  #     object.__send__(m, "def #{method_name}(locals={}); #{setup}; #{@src}; end", filename || @filename || '(erubis)')
+  #   end
+  #  
+  # end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/class.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/class.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/class.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,34 @@
+class Class
+  # Allows the definition of methods on a class that will be available via
+  # super.
+  # 
+  # ==== Examples
+  #     class Foo
+  #       chainable do
+  #         def hello
+  #           "hello"
+  #         end
+  #       end
+  #     end
+  #
+  #     class Foo
+  #       def hello
+  #         super + " Merb!"
+  #       end
+  #     end
+  #
+  # Foo.new.hello #=> "hello Merb!"
+  # 
+  # ==== Parameters
+  # &blk:: 
+  #   a block containing method definitions that should be
+  #   marked as chainable
+  #
+  # ==== Returns
+  # Module:: The anonymous module that was created
+  def chainable(&blk)
+    mod = Module.new(&blk)
+    include mod
+    mod
+  end
+end
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/hash.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/hash.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/hash.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,16 @@
+class Hash
+  # Returns the value of self for each argument and deletes those entries.
+  #
+  # ==== Parameters
+  # *args:: the keys whose values should be extracted and deleted.
+  #
+  # ==== Returns
+  # Array[Object]:: The values of the provided arguments in corresponding order.
+  #
+  # :api: public
+  def extract!(*args)
+    args.map do |arg|
+      self.delete(arg)
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/kernel.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/kernel.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext/kernel.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,469 @@
+require 'rubygems/dependency'
+
+module Gem
+  class Dependency
+    # :api: private
+    attr_accessor :require_block, :require_as, :original_caller
+  end
+end
+
+module Kernel
+  
+  # Keep track of all required dependencies. 
+  #
+  # @param name<String> The name of the gem to load.
+  # @param *ver<Gem::Requirement, Gem::Version, Array, #to_str>
+  #   Version requirements to be passed to Gem::Dependency.new.
+  #
+  # @return <Gem::Dependency> Dependency information
+  #
+  # :api: private
+  def track_dependency(name, clr, *ver, &blk)
+    options = ver.last.is_a?(Hash) ? ver.pop : {}
+    new_dep = Gem::Dependency.new(name, ver.empty? ? nil : ver)
+    new_dep.require_block = blk
+    new_dep.require_as = options.key?(:require_as) ? options[:require_as] : name
+    new_dep.original_caller = clr
+    
+    deps = Merb::BootLoader::Dependencies.dependencies
+
+    idx = deps.each_with_index {|d,i| break i if d.name == new_dep.name}
+
+    idx = idx.is_a?(Array) ? deps.size + 1 : idx
+    deps.delete_at(idx)
+    deps.insert(idx - 1, new_dep)
+
+    new_dep
+  end
+
+  # Loads the given string as a gem. Execution is deferred until
+  # after the logger has been instantiated and the framework directory
+  # structure is defined.
+  #
+  # If that has already happened, the gem will be activated
+  # immediately, but it will still be registered.
+  # 
+  # ==== Parameters
+  # name<String> The name of the gem to load.
+  # *ver<Gem::Requirement, Gem::Version, Array, #to_str>
+  #   Version requirements to be passed to Gem::Dependency.new.
+  #   If the last argument is a Hash, extract the :immediate option,
+  #   forcing a dependency to load immediately.
+  #
+  # ==== Options
+  #
+  # :immediate   when true, gem is loaded immediately even if framework is not yet ready.
+  # :require_as  file name to require for this gem.
+  #
+  # See examples below.
+  #
+  # ==== Notes
+  #
+  # If block is given, it is called after require is called. If you use a block to
+  # require multiple files, require first using :require_as option and the rest
+  # in the block.
+  #
+  # ==== Examples
+  #
+  # Usage scenario is typically one of the following:
+  #
+  # 1. Gem name and loaded file names are the same (ex.: amqp gem uses amqp.rb).
+  #    In this case no extra options needed.
+  #
+  # dependency "amqp"
+  #
+  # 2. Gem name is different from the file needs to be required
+  #    (ex.: ParseTree gem uses parse_tree.rb as main file).
+  #
+  # dependency "ParseTree", :require_as => "parse_tree"
+  #
+  # 3. You need to require a number of files from the library explicitly
+  #    (ex.: cherry pick features from xmpp4r). Pass an array to :require_as.
+  #
+  # dependency "xmpp4r", :require_as => %w(xmpp4r/client xmpp4r/sasl xmpp4r/vcard)
+  #
+  # 4. You need to require a specific version of the gem.
+  #
+  # dependency "RedCloth", "3.0.4"
+  #
+  # 5. You want to load dependency as soon as the method is called.
+  #
+  # dependency "syslog", :immediate => true
+  #
+  # 6. You need to execute some arbitraty code after dependency is loaded:
+  #
+  # dependency "ruby-growl" do
+  #   g = Growl.new "localhost", "ruby-growl",
+  #              ["ruby-growl Notification"]
+  #   g.notify "ruby-growl Notification", "Ruby-Growl is set up",
+  #         "Ruby-Growl is set up"
+  # end
+  #
+  # When specifying a gem version to use, you can use the same syntax RubyGems
+  # support, for instance, >= 3.0.2 or >~ 1.2.
+  #
+  # See rubygems.org/read/chapter/16 for a complete reference.
+  #
+  # ==== Returns
+  # Gem::Dependency:: The dependency information.
+  #
+  # :api: public
+  def dependency(name, *opts, &blk)
+    immediate = opts.last.delete(:immediate) if opts.last.is_a?(Hash)
+    if immediate || Merb::BootLoader.finished?(Merb::BootLoader::Dependencies)
+      load_dependency(name, caller, *opts, &blk)
+    else
+      track_dependency(name, caller, *opts, &blk)
+    end
+  end
+
+  # Loads the given string as a gem.
+  #
+  # This new version tries to load the file via ROOT/gems first before moving
+  # off to the system gems (so if you have a lower version of a gem in
+  # ROOT/gems, it'll still get loaded).
+  #
+  # @param name<String,Gem::Dependency> 
+  #   The name or dependency object of the gem to load.
+  # @param *ver<Gem::Requirement, Gem::Version, Array, #to_str>
+  #   Version requirements to be passed to Gem.activate.
+  #
+  # @note
+  #   If the gem cannot be found, the method will attempt to require the string
+  #   as a library.
+  #
+  # @return <Gem::Dependency> The dependency information.
+  #
+  # :api: private
+  def load_dependency(name, clr, *ver, &blk)
+    begin
+      dep = name.is_a?(Gem::Dependency) ? name : track_dependency(name, clr, *ver, &blk)
+      return unless dep.require_as
+      Gem.activate(dep)
+    rescue Gem::LoadError => e
+      e.set_backtrace dep.original_caller
+      Merb.fatal! "The gem #{name}, #{ver.inspect} was not found", e
+    end
+  
+    begin
+      require dep.require_as
+    rescue LoadError => e
+      e.set_backtrace dep.original_caller
+      Merb.fatal! "The file #{dep.require_as} was not found", e
+    end
+
+    if block = dep.require_block
+      # reset the require block so it doesn't get called a second time
+      dep.require_block = nil
+      block.call
+    end
+
+    Merb.logger.verbose!("loading gem '#{dep.name}' ...")
+    return dep # ensure needs explicit return
+  end
+
+  # Loads both gem and library dependencies that are passed in as arguments.
+  # Execution is deferred to the Merb::BootLoader::Dependencies.run during bootup.
+  #
+  # ==== Parameters
+  # *args<String, Hash, Array> The dependencies to load.
+  #
+  # ==== Returns
+  # Array[(Gem::Dependency, Array[Gem::Dependency])]:: Gem::Dependencies for the
+  #   dependencies specified in args.
+  #
+  # :api: public
+  def dependencies(*args)
+    args.map do |arg|
+      case arg
+      when String then dependency(arg)
+      when Hash   then arg.map { |r,v| dependency(r, v) }
+      when Array  then arg.map { |r|   dependency(r)    }
+      end
+    end
+  end
+
+  # Loads both gem and library dependencies that are passed in as arguments.
+  #
+  # @param *args<String, Hash, Array> The dependencies to load.
+  #
+  # @note
+  #   Each argument can be:
+  #   String:: Single dependency.
+  #   Hash::
+  #     Multiple dependencies where the keys are names and the values versions.
+  #   Array:: Multiple string dependencies.
+  #
+  # @example dependencies "RedCloth"                 # Loads the the RedCloth gem
+  # @example dependencies "RedCloth", "merb_helpers" # Loads RedCloth and merb_helpers
+  # @example dependencies "RedCloth" => "3.0"        # Loads RedCloth 3.0
+  #
+  # :api: private
+  def load_dependencies(*args)
+    args.map do |arg|
+      case arg
+      when String then load_dependency(arg)
+      when Hash   then arg.map { |r,v| load_dependency(r, v) }
+      when Array  then arg.map { |r|   load_dependency(r)    }
+      end
+    end
+  end
+
+  # Does a basic require, and prints a message if an error occurs.
+  #
+  # @param library<to_s> The library to attempt to include.
+  # @param message<String> The error to add to the log upon failure. Defaults to nil.
+  #
+  # :api: private
+  # @deprecated
+  def rescue_require(library, message = nil)
+    Merb.logger.warn("Deprecation warning: rescue_require is deprecated")
+    sleep 2.0
+    require library
+  rescue LoadError, RuntimeError
+    Merb.logger.error!(message) if message
+  end
+
+  # Used in Merb.root/config/init.rb to tell Merb which ORM (Object Relational
+  # Mapper) you wish to use. Currently Merb has plugins to support
+  # ActiveRecord, DataMapper, and Sequel.
+  #
+  # ==== Parameters
+  # orm<Symbol>:: The ORM to use.
+  #
+  # ==== Returns
+  # nil
+  #
+  # ==== Example
+  #   use_orm :datamapper
+  #
+  #   # This will use the DataMapper generator for your ORM
+  #   $ merb-gen model ActivityEvent
+  #
+  # ==== Notes
+  #   If for some reason this is called more than once, latter
+  #   call takes over other.
+  #
+  # :api: public
+  def use_orm(orm, &blk)
+    begin
+      Merb.orm = orm
+      orm_plugin = "merb_#{orm}"
+      Kernel.dependency(orm_plugin, &blk)
+    rescue LoadError => e
+      Merb.logger.warn!("The #{orm_plugin} gem was not found.  You may need to install it.")
+      raise e
+    end
+    nil
+  end
+
+  # Used in Merb.root/config/init.rb to tell Merb which testing framework to
+  # use. Currently Merb has plugins to support RSpec and Test::Unit.
+  #
+  # ==== Parameters
+  # test_framework<Symbol>::
+  #   The test framework to use. Currently only supports :rspec and :test_unit.
+  #
+  # ==== Returns
+  # nil
+  #
+  # ==== Example
+  #   use_test :rspec
+  #
+  #   # This will now use the RSpec generator for tests
+  #   $ merb-gen model ActivityEvent
+  #
+  # :api: public
+  def use_testing_framework(test_framework, *test_dependencies)
+    Merb.test_framework = test_framework
+    
+    Kernel.dependencies test_dependencies if Merb.env == "test" || Merb.env.nil?
+    nil
+  end
+
+  def use_test(*args)
+    use_testing_framework(*args)
+  end
+  
+  # Used in Merb.root/config/init.rb to tell Merb which template engine to
+  # prefer.
+  #
+  # ==== Parameters
+  # template_engine<Symbol>
+  #   The template engine to use.
+  #
+  # ==== Returns
+  # nil
+  #
+  # ==== Example
+  #   use_template_engine :haml
+  #
+  #   # This will now use haml templates in generators where available.
+  #   $ merb-gen resource_controller Project 
+  #
+  # :api: public
+  def use_template_engine(template_engine, &blk)
+    Merb.template_engine = template_engine
+
+    if template_engine != :erb
+      if template_engine.in?(:haml, :builder)
+        template_engine_plugin = "merb-#{template_engine}"
+      else
+        template_engine_plugin = "merb_#{template_engine}"
+      end
+      Kernel.dependency(template_engine_plugin, &blk)
+    end
+    
+    nil
+  rescue LoadError => e
+    Merb.logger.warn!("The #{template_engine_plugin} gem was not found.  You may need to install it.")
+    raise e
+  end
+
+
+  # @param i<Fixnum> The caller number. Defaults to 1.
+  #
+  # @return <Array[Array]> The file, line and method of the caller.
+  #
+  # @example
+  #   __caller_info__(1)
+  #     # => ['/usr/lib/ruby/1.8/irb/workspace.rb', '52', 'irb_binding']
+  #
+  # :api: private
+  def __caller_info__(i = 1)
+    file, line, meth = caller[i].scan(/(.*?):(\d+):in `(.*?)'/).first
+  end
+
+  # @param file<String> The file to read.
+  # @param line<Fixnum> The line number to look for.
+  # @param size<Fixnum>
+  #   Number of lines to include above and below the the line to look for.
+  #   Defaults to 4.
+  #
+  # @return <Array[Array]>
+  #   Triplets containing the line number, the line and whether this was the
+  #   searched line.
+  #
+  # @example
+  #   __caller_lines__('/usr/lib/ruby/1.8/debug.rb', 122, 2) # =>
+  #     [
+  #       [ 120, "  def check_suspend",                               false ],
+  #       [ 121, "    return if Thread.critical",                     false ],
+  #       [ 122, "    while (Thread.critical = true; @suspend_next)", true  ],
+  #       [ 123, "      DEBUGGER__.waiting.push Thread.current",      false ],
+  #       [ 124, "      @suspend_next = false",                       false ]
+  #     ]
+  #
+  # :api: private
+  def __caller_lines__(file, line, size = 4)
+    line = line.to_i
+    if file =~ /\(erubis\)/
+      yield :error, "Template Error! Problem while rendering", false
+    elsif !File.file?(file) || !File.readable?(file)
+      yield :error, "File `#{file}' not available", false
+    else
+      lines = File.read(file).split("\n")
+      first_line = (f = line - size - 1) < 0 ? 0 : f
+      
+      if first_line.zero?
+        new_size = line - 1
+        lines = lines[first_line, size + new_size + 1]
+      else
+        new_size = nil
+        lines = lines[first_line, size * 2 + 1]
+      end
+
+      lines && lines.each_with_index do |str, index|
+        line_n = index + line
+        line_n = (new_size.nil?) ? line_n - size : line_n - new_size
+        yield line_n, str.chomp
+      end
+    end
+  end
+
+  # Takes a block, profiles the results of running the block
+  # specified number of times and generates HTML report.
+  #
+  # @param name<#to_s>
+  #   The file name. The result will be written out to
+  #   Merb.root/"log/#{name}.html".
+  # @param min<Fixnum>
+  #   Minimum percentage of the total time a method must take for it to be
+  #   included in the result. Defaults to 1.
+  #
+  # @return <String>
+  #   The result of the profiling.
+  #
+  # @note
+  #   Requires ruby-prof (<tt>sudo gem install ruby-prof</tt>)
+  #
+  # @example
+  #   __profile__("MyProfile", 5, 30) do
+  #     rand(10)**rand(10)
+  #     puts "Profile run"
+  #   end
+  #
+  #   Assuming that the total time taken for #puts calls was less than 5% of the
+  #   total time to run, #puts won't appear in the profile report.
+  #   The code block will be run 30 times in the example above.
+  #
+  # :api: private
+  def __profile__(name, min=1, iter=100)
+    require 'ruby-prof' unless defined?(RubyProf)
+    return_result = ''
+    result = RubyProf.profile do
+      iter.times{return_result = yield}
+    end
+    printer = RubyProf::GraphHtmlPrinter.new(result)
+    path = File.join(Merb.root, 'log', "#{name}.html")
+    File.open(path, 'w') do |file|
+      printer.print(file, {:min_percent => min,
+                      :print_file => true})
+    end
+    return_result
+  end
+
+  # Extracts an options hash if it is the last item in the args array. Used
+  # internally in methods that take *args.
+  #
+  # @param args<Array> The arguments to extract the hash from.
+  #
+  # @example
+  #   def render(*args,&blk)
+  #     opts = extract_options_from_args!(args) || {}
+  #     # [...]
+  #   end
+  #
+  # :api: public
+  def extract_options_from_args!(args)
+    args.pop if (args.last.instance_of?(Hash) || args.last.instance_of?(Mash))
+  end
+
+  # Checks that the given objects quack like the given conditions.
+  #
+  # @param opts<Hash>
+  #   Conditions to enforce. Each key will receive a quacks_like? call with the
+  #   value (see Object#quacks_like? for details).
+  #
+  # @raise <ArgumentError>
+  #   An object failed to quack like a condition.
+  #
+  # :api: public
+  def enforce!(opts = {})
+    opts.each do |k,v|
+      raise ArgumentError, "#{k.inspect} doesn't quack like #{v.inspect}" unless k.quacks_like?(v)
+    end
+  end
+
+  unless Kernel.respond_to?(:debugger)
+
+    # Define debugger method so that code even works if debugger was not
+    # requested. Drops a note to the logs that Debugger was not available.
+    def debugger
+      Merb.logger.info! "\n***** Debugger requested, but was not " +
+        "available: Start server with --debugger " +
+        "to enable *****\n"
+    end
+  end
+  
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/core_ext.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,10 @@
+begin
+  require "extlib"
+rescue LoadError => e
+  puts "Merb-core 0.9.4 and later uses extlib for Ruby core class extensions. Install it from github.com/sam/extlib."
+  exit
+end
+
+require File.dirname(__FILE__) / "core_ext" / "kernel"
+require File.dirname(__FILE__) / "core_ext" / "hash"
+require File.dirname(__FILE__) / "core_ext" / "class"
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/cookies.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/cookies.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/cookies.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,143 @@
+module Merb
+
+  class Cookies < Mash
+  
+    # :api: private
+    def initialize(constructor = {})
+      @_options_lookup  = Mash.new
+      @_cookie_defaults = { "domain" => Merb::Controller._default_cookie_domain, "path" => '/' }
+      super constructor
+    end
+    
+    # Implicit assignment of cookie key and value.
+    #
+    # ==== Parameters
+    # name<~to_s>:: Name of the cookie.
+    # value<~to_s>:: Value of the cookie.
+    #
+    # ==== Notes
+    # By using this method, a cookie key is marked for being
+    # included in the Set-Cookie response header.
+    #
+    # :api: public
+    def []=(key, value)
+      @_options_lookup[key] ||= {}
+      super
+    end
+    
+    # Explicit assignment of cookie key, value and options
+    #
+    # ==== Parameters
+    # name<~to_s>:: Name of the cookie.
+    # value<~to_s>:: Value of the cookie.
+    # options<Hash>:: Additional options for the cookie (see below).
+    #
+    # ==== Options (options)
+    # :path<String>:: The path for which this cookie applies. Defaults to "/".
+    # :expires<Time>:: Cookie expiry date.
+    # :domain<String>:: The domain for which this cookie applies.
+    # :secure<Boolean>:: Security flag.
+    #
+    # ==== Notes
+    # By using this method, a cookie key is marked for being
+    # included in the Set-Cookie response header.
+    #
+    # :api: private
+    def set_cookie(name, value, options = {})
+      @_options_lookup[name] = options
+      self[name] = value
+    end
+    
+    # Removes the cookie on the client machine by setting the value to an empty
+    # string and setting its expiration date into the past.
+    #
+    # ==== Parameters
+    # name<~to_s>:: Name of the cookie to delete.
+    # options<Hash>:: Additional options to pass to +set_cookie+.
+    #
+    # :api: public
+    def delete(name, options = {})
+      set_cookie(name, "", options.merge("expires" => Time.at(0)))
+    end
+    
+    # Generate any necessary headers.
+    #
+    # ==== Returns
+    # Hash:: The headers to set, or an empty array if no cookies are set.
+    #
+    # :api: private
+    def extract_headers(controller_defaults = {})
+      defaults = @_cookie_defaults.merge(controller_defaults)
+      cookies = []
+      self.each do |name, value|
+        # Only set cookies that marked for inclusion in the response header. 
+        next unless @_options_lookup[name]
+        options = defaults.merge(@_options_lookup[name])
+        if (expiry = options["expires"]).respond_to?(:gmtime)
+          options["expires"] = expiry.gmtime.strftime(Merb::Const::COOKIE_EXPIRATION_FORMAT)
+        end
+        secure  = options.delete("secure")
+        kookie  = "#{name}=#{Merb::Parse.escape(value)}; "
+        # WebKit in particular doens't like empty cookie options - skip them.
+        options.each { |k, v| kookie << "#{k}=#{v}; " unless v.blank? }
+        kookie  << 'secure' if secure
+        cookies << kookie.rstrip
+      end
+      cookies.empty? ? {} : { 'Set-Cookie' => cookies }
+    end
+    
+  end
+  
+  module CookiesMixin
+    
+    def self.included(base)
+      # Allow per-controller default cookie domains (see callback below)
+      base.class_inheritable_accessor :_default_cookie_domain
+      base._default_cookie_domain = Merb::Config[:default_cookie_domain]
+      
+      # Add a callback to enable Set-Cookie headers
+      base._after_dispatch_callbacks << lambda do |c|
+        headers = c.request.cookies.extract_headers("domain" => c._default_cookie_domain)
+        c.headers.update(headers)
+      end
+    end
+    
+    # ==== Returns
+    # Merb::Cookies::
+    #   A new Merb::Cookies instance representing the cookies that came in
+    #   from the request object
+    #
+    # ==== Notes
+    # Headers are passed into the cookie object so that you can do:
+    #   cookies[:foo] = "bar"
+    #
+    # :api: public
+    def cookies
+      request.cookies
+    end
+    
+    module RequestMixin
+            
+      # ==== Returns
+      # Hash:: The cookies for this request.
+      #
+      # ==== Notes
+      # If a method #default_cookies is defined it will be called. This can
+      # be used for session fixation purposes for example. The method returns
+      # a Hash of key => value pairs.
+      #
+      # :api: public
+      def cookies
+        @cookies ||= begin
+          values  = Merb::Parse.query(@env[Merb::Const::HTTP_COOKIE], ';,')
+          cookies = Merb::Cookies.new(values)
+          cookies.update(default_cookies) if respond_to?(:default_cookies)
+          cookies
+        end
+      end
+      
+    end   
+    
+  end
+  
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/default_exception.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/default_exception.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/default_exception.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,120 @@
+Merb::BootLoader.after_app_loads do
+  module Merb
+    class Dispatcher
+      # :api: private
+      module DefaultExceptionHelper
+      
+        # :api: private
+        def humanize_exception(e)
+          e.class.name.split("::").last.gsub(/([a-z])([A-Z])/, '\1 \2')
+        end
+
+        # :api: private
+        def error_codes(exception)
+          if @show_details
+            message, message_details = exception.message.split("\n", 2)
+            "<h2>#{escape_html(message)}</h2><p>#{escape_html(message_details)}</p>"
+          else
+            "<h2>Sorry about that...</h2>"
+          end
+        end
+
+        # :api: private
+        def frame_details(line)
+          if (match = line.match(/^(.+):(\d+):(.+)$/))
+            filename = match[1]
+            lineno = match[2]
+            location = match[3]
+            if filename.index(Merb.framework_root) == 0
+              type = "framework"
+              shortname = Pathname.new(filename).relative_path_from(Pathname.new(Merb.framework_root))
+            elsif filename.index(Merb.root) == 0
+              type = "app"
+              shortname = Pathname.new(filename).relative_path_from(Pathname.new(Merb.root))
+            elsif path = Gem.path.find {|p| filename.index(p) == 0}
+              type = "gem"
+              shortname = Pathname.new(filename).relative_path_from(Pathname.new(path))
+            else
+              type = "other"
+              shortname = filename
+            end
+            [type, shortname, filename, lineno, location]
+          else
+            ['', '', '', nil, nil]
+          end
+        end
+
+        # :api: private
+        def listing(key, value, arr)
+          ret   =  []
+          ret   << "<table class=\"listing\" style=\"display: none\">"
+          ret   << "  <thead>"
+          ret   << "    <tr><th width='25%'>#{key}</th><th width='75%'>#{value}</th></tr>"
+          ret   << "  </thead>"
+          ret   << "  <tbody>"
+          (arr || []).each_with_index do |(key, val), i|
+            klass = i % 2 == 0 ? "even" : "odd"
+            ret << "    <tr class=\"#{klass}\"><td>#{key}</td><td>#{val.inspect}</td></tr>"
+          end
+          if arr.blank?
+            ret << "    <tr class='odd'><td colspan='2'>None</td></tr>"
+          end
+          ret   << "  </tbody>"
+          ret   << "</table>"
+          ret.join("\n")
+        end
+      
+        def jar?(filename)
+          filename.match(/jar\!/)
+        end
+      
+        # :api: private
+        def textmate_url(filename, line)
+          "<a href='txmt://open?url=file://#{filename}&amp;line=#{line}'>#{line}</a>"
+        end
+      
+        # :api: private
+        def render_source(filename, line)
+          line = line.to_i
+          ret   =  []
+          ret   << "<tr class='source'>"
+          ret   << "  <td class='collapse'></td>"
+          str   =  "  <td class='code' colspan='2'><div>"
+        
+          __caller_lines__(filename, line, 5) do |lline, lcode|
+            str << "<a href='txmt://open?url=file://#{filename}&amp;line=#{lline}'>#{lline}</a>"
+            str << "<em>" if line == lline
+            str << Erubis::XmlHelper.escape_xml(lcode)
+            str << "</em>" if line == lline
+            str << "\n"
+          end
+          str   << "</div></td>"
+          ret   << str
+          ret   << "</tr>"
+          ret.join("\n")
+        end
+
+        def jar?(filename)
+          filename.match(/jar\!/)
+        end
+      end
+    
+      # :api: private
+      class DefaultException < Merb::Controller
+        self._template_root = File.dirname(__FILE__) / "views"
+      
+        # :api: private
+        def _template_location(context, type = nil, controller = controller_name)
+          "#{context}.#{type}"
+        end
+      
+        # :api: private
+        def index
+          @exceptions = request.exceptions
+          @show_details = Merb::Config[:exception_details]
+          render :format => :html
+        end
+      end
+    end
+  end
+end
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/_css.html.erb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/_css.html.erb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/_css.html.erb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,200 @@
+<% if Merb.env != "test" %>
+<style type="text/css" media="screen">
+  body {
+    font-family:arial;
+    font-size:11px;
+  }
+  p.options {
+    text-align: right;
+  }
+    p.options label {
+      margin-left: 10px;
+    }
+    p.options span.all {
+      padding: 5px;
+      border: 1px solid #000;
+      background-color: #fff;
+    }
+    p.options input {
+      position: relative;
+    }
+  h1 {
+    font-size:48px;
+    letter-spacing:-4px;
+    margin:0 0 20px 0;
+    line-height:36px;
+    color:#333;
+  }
+    h1 sup {
+      font-size: 0.5em;
+    }
+    h1 sup.error_500, h1 sup.error_400 {
+      color:#990E05;
+    }
+    h1 sup.error_100, h1 sup.error_200 {
+      color:#00BF10;
+    }
+    h1 sup.error_300 {
+      /* pretty sure you cant 'see' status 300 
+      errors but if you could I think they 
+      would be blue */
+      color:#1B2099;
+    }
+  h2 {
+    font-size:24px;
+    letter-spacing:-1px;
+    margin:0;
+    line-height:28px;
+    color:#444;
+  }
+  h3 {
+    cursor: pointer;
+    color: #006;
+    text-decoration: underline;
+  }
+  a, a:visited {
+    color:#00BF10;
+  }
+  .internalError {
+    width:800px;
+    margin:50px auto;
+  }
+  .header {
+    border-bottom:10px solid #333;
+    margin-bottom:1px;
+    background-image: url("data:image/gif;base64,R0lGODlhAwADAIAAAP///8zMzCH5BAAAAAAALAAAAAADAAMAAAIEBHIJBQA7");
+    padding:20px;
+  }
+    .header ul {
+      padding: 5px;
+      background-color: white;
+    }
+      .header ul li {
+        list-style-type: none;
+        font-size: 16px;
+        margin-bottom: 6px;
+      }
+  
+  table.listing {
+    border-collapse: collapse;
+    font-size: 12px;
+    width: 100%;
+  }
+  
+  table.listing th {
+    background-color: #000;
+    color: #fff;
+  }
+  
+  table.listing td, table.listing th {
+    padding: 5px;
+    text-align: left;
+    vertical-align: top;
+  }
+  
+  table.listing tr.odd {
+    background-color: #ccc;
+  }
+  
+  table.listing tr.even {
+    background-color: #aaa;
+  }
+  
+  table.listing td[colspan=2] {
+    text-align: center;
+  }
+  
+  table.trace {
+    width:100%;
+    font-family:courier, monospace;
+    letter-spacing:-1px;
+    border-collapse: collapse;
+    border-spacing:0;
+  }
+  table.trace tr td{
+    padding:0;
+    height:26px;
+    font-size:13px;
+    vertical-align:middle;
+  }
+  table.trace tr.file{
+    border-top:2px solid #fff;
+    background-color:#F3F3F3;
+  }
+  table.trace tr.source {
+    background-color:#F8F8F8;
+    display:none;
+  }
+  table.trace .open tr.source {
+    display:table-row;
+  }
+    table.trace tr.file td.expand {
+      width:23px;
+      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAXCAIAAABvSEP3AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdVJREFUeNqMVL+TwUAYxaRIOlEhlZHGDAUzzOQ61+AqXMV1lJSU7q/QRqm8KFUcJTNn5qJkaPyoKKVz7y4mF8na5Kt29tt9+/Z97/u81+vVQ4r9frdarS6Xi7ETDIZisRjxMGPfmk4niNPpZE+xLAugbPaZ53nzvtfMBe/3+/3dbuehBrAKhZdUKkVAWa9Xsiybv0CPZDJZLr/qa5/BwgwRjYqOKIvFYjQa/aNommZh0Ww2K5UqzwfoQOPxaLPZ3FAmk0+7lplMpt1u53J5OpBOR0eZEE9wHJfP5zud93g88QhluwWbjW+5VOmKBgKBer3eaDTDYeGBQF8+x7rqIYoiPgixWJazpA6HA+MSxRArkUgMh0M409g8Ho8+9wYxxCqVSq1W26EDHGM2m4HOHQrEc38f/Yn7cLmlIRhBENzcx8cVRZnPZ/YUep2BWkjTIfA+PKVpZAXR5QxsjiqCKvGEqqp443w+0dvy17swqD0HB3S73V5PpkNg1qBqt8kwGCjmPkinM0QJbIoEa7U6UG6ToVgs4V9G2g0ESoP5Aoi7KYX5oCgf8IKbkvn9/mr1LRQKESamzgJy0g0tSZIuB3nuGqRU9Vv9C4sKkUhEkp4soxvxI8AAhWrrtXa3X8EAAAAASUVORK5CYII=);
+      background-position:top left;
+      background-repeat:no-repeat;
+    }
+    table.trace tr.file td.expand div {
+      width:23px;
+    }
+    table.trace .open tr.file td.expand {
+      width:23px;
+      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAB1CAIAAAAqdO2mAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXZJREFUeNrslK1ywkAUhcMOBomEOiSdqLxEBJX0NaijOsjyHGGmCGyQQYaiiiw4gktkcOmZbpsuuzQ/M5XnqJ2d3S/n3nM3rTzPLUP7/Tt0+pLcGQwG3W53OLyHzPMtjYL7q9UqSRLrD4E1Gj1orCvKYuFHUWTVkOM44/HjDcp8/lL4r6NerzeZPMm1KFw0QkDn83m5fP2lHA4fNQvRtNvtjsfDd0WzmSfb2e/fdTqdOvdh/HLJZLOn0+d2HJ+KRGzbdl23EpFlmed5cp2maRzHQq1lvQ5KMi6EUZBGfup6E1pTfd+vrGW7jbQ2C9hTt9BpqNyIWaAwAy6xg2eBz5iRC/NomiZhGN5sqmnkauo0BUGgVQoBjQ80oCACgNQdZHfTYBkF2mxCtWWAqunWpahxIDUt3QYUxIFQpJHyIWpXjinabKbbwItMHT+NyjchrP8QKaSQQgoppJBCCimkkEIKKaSQQgoppJBCCimkkEIKKaSo+hRgAEFD17X08O2NAAAAAElFTkSuQmCC);
+      background-position:top left;
+      background-repeat:no-repeat;        
+    }
+    table.trace .open tr.file td.expand div {
+      width:23px;
+    }
+    table.trace tr.source td.collapse {
+      width:23px;
+      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAB1CAIAAAAqdO2mAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAVxJREFUeNrs0zFygkAUBmBlUkgJHdABlQwVkVJKKUxBYWbkALTxMJwhltyDFkss03IF8pudIcwaDaDl/6pd2P327b7d+eHwMXs4lNkzggoVKlSoUKFChQoVKlSoUKFChQoVKlSoUKFChQqVEYqm6ft9+qiSJEkYho7jTlcw2fd9NOI4nq4gEdFwXXe1Cqco63VkWVbXRTqLhTpOwQRpF7quR1E0TgGhqvLKUFCyoQqG/rks3O6kZKW/eRFpevOCoGTXVTcMQ5EyxyDEkML1c5RzuZOICIyXqn7JBVez6282MWrx731HOv2qB8Hri2lamNk0DfpVVdV1Peodappmmua8bdvzuc7zfNprzrLMth1FnGh/X8MjCAIQv/cFz/+65PcDh7rbvYv2ZUfdj+PxsyzLgVl0hKwgTqeqKApx2LeOc7t98zyv/1FWOgvx9RPii23bmL9cetJ8Ed8CDAC6aFW8bCzFhwAAAABJRU5ErkJggg==);
+      background-position:bottom left;
+      background-repeat:no-repeat;  
+      background-color:#6F706F;     
+    }
+    table.trace tr td.path {
+      padding-left:10px;
+    }
+    table.trace tbody.app td.path {
+      color: #900;
+    }
+    table.trace tbody.framework td.path {
+      color: #009;
+    }
+    table.trace tbody.gem td.path {
+      color: #090;
+    }
+    table.trace tr td.code {
+      padding: 10px 0 10px 20px;
+      white-space: pre;
+    }
+      table.trace tr td.code div {
+        width: 700px;
+        overflow-x: auto;
+        overflow-y: hidden;
+      }
+      table.trace tr td.code em {
+        font-weight:bold;
+        color:#00BF10;
+      }
+      table.trace tr td.code a {
+        width: 20px;
+        float: left;
+      }
+      table.trace tr td.code .more {
+        color:#666;
+      }
+    table.trace tr td.line {
+      width:30px;
+      text-align:right;
+      padding-right:4px;
+    }
+  .footer {
+    margin-top:5px;
+    font-size:11px;
+    color:#444;
+    text-align:right;
+  }
+</style>
+<% end %>
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/_javascript.html.erb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/_javascript.html.erb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/_javascript.html.erb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,77 @@
+<% if Merb.env != "test" %>
+<script type="text/javascript">
+  //<![CDATA[
+    (function() {
+      els = document.getElementsByTagName('td');
+      var forEach = function(arr, fn) {
+        for(var i=0; i<arr.length; i++) {
+          var res = fn(arr[i]);
+          if(res === false) break;
+        }
+      }
+      var toggleClasses = function(node, first, second) {
+        var classes = node.className.split(" ");
+        var newClasses = [];
+        forEach(classes, function(k) {
+          if(k == first) newClasses.push(second);
+          else if(k == second) newClasses.push(first);
+          else newClasses.push(k);
+        });
+        node.className = newClasses.join(" ");
+      }
+      forEach(els, function(el) {
+        // swap the open & closed classes       
+        if(hasClass(el, "expand") || hasClass(el, "collapse")) {
+          el.onclick = function(e){
+            tbody = this.parentNode.parentNode;
+            toggleClasses(tbody, "open", "close");
+          }
+        }        
+      })
+      forEach(document.getElementsByTagName("h3"), function(el) {
+        el.onclick = function(e) {
+          var tag = this.nextSibling;
+          while(tag.nodeType != 1) tag = tag.nextSibling;
+          tag.style.display = tag.style.display == "none" ? "" : "none";
+        }        
+      })
+      function hasClass(node, matchClass) {
+        var classes = node.className.split(" ");
+        for(var i=0,className;className=classes[i];i++)
+          if(className == matchClass) return true;
+        return false;
+      }
+      var els = document.getElementsByTagName("p");
+      forEach(els, function(tag) {
+        if(tag.className != "options") return true;
+        var checkboxes = tag.getElementsByTagName("input");
+        forEach(checkboxes, function(box) {
+          if(window.navigator.userAgent.match(/Firefox/)) {
+            box.style.top = "3px";
+          }
+        });
+        tag.getElementsByTagName("input")[0].onclick = function(e) {
+          forEach(checkboxes, function(box) {
+            if(box == e.target) return true;
+            box.checked = e.target.checked;
+            toggleTraces(box, box);
+          })
+        };
+        var toggleTraces = function(box, target) {
+          var tbodies = tag.parentNode.getElementsByTagName("tbody");
+          forEach(tbodies, function(tbody) {
+            if(hasClass(tbody, target.parentNode.className)) {
+              if(target.checked) tbody.style.display = "";
+              else tbody.style.display = "none";
+            }
+          })
+        }
+        forEach(checkboxes, function(box) {
+          if(box == checkboxes[0]) return true;
+          box.onchange = function(e) { toggleTraces(box, e.target) }
+        })
+      })
+    })();
+  //]]>
+</script>
+<% end %>
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/index.html.erb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/index.html.erb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/default_exception/views/index.html.erb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,99 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+  <title><%= humanize_exception(@exceptions.first) %></title>
+  <%= partial :css %>
+</head>
+<body>
+  <% if @show_details %>
+  <% if @exceptions.size > 1 %>
+  <div class="internalError">
+    <div class="header">
+      <h1>Error Stack</h1>
+      <ul>
+        <% @exceptions.each_with_index do |exception,i| %>
+          <li>
+            <a href="#exception_<%= i %>"><%= humanize_exception(exception) %></a>
+            <%= escape_html(exception.message.split("\n",2).first) %>
+          </li>
+        <% end %>
+      </ul>
+    </div>
+  </div>
+  <% end %>
+  
+  <div class="internalError">
+    <div class="header">
+      <h1>Request Details</h1>
+      <h3>Parameters</h3>
+      <%= listing("Parameter", "Value", request.params) %>
+
+      <% if request.session? %>
+      <h3>Session</h3>
+      <%= listing("Key", "Value", request.session) %>
+      <% end %>
+
+      <h3>Cookies</h3>
+      <%= listing("Cookie", "Value", request.cookies) %>
+
+      <h3>Named Routes</h3>
+      <%= listing("Name", "Route", Merb::Router.named_routes) %>
+    </div>      
+  </div>
+  <% end %>
+
+  <% @exceptions.each_with_index do |exception,i| %>
+  <div class="internalError" id="exception_<%= i %>">
+    <div class="header">
+      <h1>
+        <%= humanize_exception(exception) %> 
+        <sup class="error_<%= exception.class.status %>"><%= exception.class.status %></sup>
+      </h1>
+      <%= error_codes(exception) %>
+    
+    <% if @show_details %>
+      <p class="options">
+        <label class="all">All<input type="checkbox" autocomplete="off" /></label>
+        <span class="all">
+          <label class="app">App<input type="checkbox" checked="checked" autocomplete="off"/></label>
+          <label class="framework">Framework<input type="checkbox" autocomplete="off"/></label>
+          <label class="gem">Gem<input type="checkbox" autocomplete="off"/></label>
+          <label class="other">Other<input type="checkbox" autocomplete="off"/></label>
+        </span>
+      </p>
+
+    <table class="trace">
+      <% exception.backtrace.each_with_index do |line, index| %>
+        <% type, shortname, filename, lineno, location = frame_details(line) %>
+        <tbody class="close <%= type %>" <%= "style='display:none'" unless type == "app" %>>
+          <tr class="file">
+            <td class="expand"><div>&nbsp;</div></td>              
+            <td class="path">
+              <%= shortname %>
+              <% if filename && filename.match(/\.erb$/) %>
+                (<strong>ERB Template</strong>)
+              <% else %>
+                in <strong><%= location ? location.match(/in (`.+')$/)[1] : 'main' %></strong>
+              <% end %>
+            </td>
+            <td class="line">
+              <%= textmate_url(filename, lineno) unless jar?(filename) %>
+            </td>
+          </tr>
+          <%= render_source(filename, lineno) unless jar?(filename) %>
+        </tbody>
+      <% end %>
+    </table>
+  <% end %>
+  </div>
+  <div class="footer">
+    lots of love, from <a href="http://www.merbivore.com">merb</a>
+  </div>
+  </div>
+  <% end %>
+  <%= partial :javascript %>
+</body>
+</html>

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/dispatcher.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/dispatcher.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/dispatcher.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,157 @@
+require Merb.framework_root / "merb-core" / "dispatch" / "default_exception" / "default_exception"
+
+module Merb
+  class Dispatcher
+    class << self
+      include Merb::ControllerExceptions
+      
+      # :api: private
+      attr_accessor :use_mutex
+      
+      @@work_queue = Queue.new
+      
+      # ==== Returns
+      # Queue:: the current queue of dispatch jobs.
+      # 
+      # :api: private
+      def work_queue
+        @@work_queue
+      end  
+      
+      Merb::Dispatcher.use_mutex = ::Merb::Config[:use_mutex]
+      
+      # Dispatch the rack environment. ControllerExceptions are rescued here
+      # and redispatched.
+      #
+      # ==== Parameters
+      # rack_env<Rack::Environment>::
+      #   The rack environment, which is used to instantiate a Merb::Request
+      #
+      # ==== Returns
+      # Merb::Controller::
+      #   The Merb::Controller that was dispatched to
+      # 
+      # :api: private
+      def handle(request)
+        request.handle
+      end
+    end
+  end
+  
+  class Request
+    include Merb::ControllerExceptions
+    
+    @@mutex = Mutex.new
+    
+    # Handles request routing and action dispatch.
+    # 
+    # ==== Returns
+    # Merb::Controller:: the controller that handled the action dispatch.
+    # 
+    # :api: private
+    def handle
+      start = Time.now
+      Merb.logger.info { "Started request handling: #{start.to_s}" }
+      
+      find_route!
+      return rack_response if handled?
+      
+      klass = controller
+      Merb.logger.debug { "Routed to: #{params.inspect}" }
+      
+      unless klass < Controller
+        raise NotFound, 
+          "Controller '#{klass}' not found.\n" \
+          "If Merb tries to find a controller for static files, " \
+          "you may need to check your Rackup file, see the Problems " \
+          "section at: http://wiki.merbivore.com/pages/rack-middleware"
+      end
+      
+      if klass.abstract?
+        raise NotFound, "The '#{klass}' controller has no public actions"
+      end
+      
+      controller = dispatch_action(klass, params[:action])
+      controller._benchmarks[:dispatch_time] = Time.now - start
+      Merb.logger.info { controller._benchmarks.inspect }
+      Merb.logger.flush
+      controller.rack_response
+    rescue Object => exception
+      dispatch_exception(exception).rack_response
+    end
+    
+    private
+    # Setup the controller and call the chosen action 
+    #
+    # ==== Parameters
+    # klass<Merb::Controller>:: The controller class to dispatch to.
+    # action<Symbol>:: The action to dispatch.
+    # status<Integer>:: The status code to respond with.
+    #
+    # ==== Returns
+    # Merb::Controller::
+    #   The Merb::Controller that was dispatched to.
+    # 
+    # :api: private
+    def dispatch_action(klass, action, status=200)
+      # build controller
+      controller = klass.new(self, status)
+      if Dispatcher.use_mutex
+        @@mutex.synchronize { controller._dispatch(action) }
+      else
+        controller._dispatch(action)
+      end
+      controller
+    end
+    
+    # Re-route the current request to the Exception controller if it is
+    # available, and try to render the exception nicely.  
+    #
+    # You can handle exceptions by implementing actions for specific
+    # exceptions such as not_found or for entire classes of exceptions
+    # such as client_error. You can also implement handlers for 
+    # exceptions outside the Merb exception hierarchy (e.g.
+    # StandardError is caught in standard_error).
+    #
+    # ==== Parameters
+    # exception<Object>::
+    #   The exception object that was created when trying to dispatch the
+    #   original controller.
+    #
+    # ==== Returns
+    # Exceptions::
+    #   The Merb::Controller that was dispatched to. 
+    # 
+    # :api: private
+    def dispatch_exception(exception)
+      if(exception.is_a?(Merb::ControllerExceptions::Base) &&
+         !exception.is_a?(Merb::ControllerExceptions::ServerError))
+        Merb.logger.info(Merb.exception(exception))
+      else
+        Merb.logger.error(Merb.exception(exception))
+      end
+      
+      self.exceptions = [exception]
+      
+      begin
+        e = exceptions.first
+        
+        if action_name = e.action_name
+          dispatch_action(Exceptions, action_name, e.class.status)
+        else
+          Merb::Dispatcher::DefaultException.new(self, e.class.status)._dispatch
+        end
+      rescue Object => dispatch_issue
+        if e.same?(dispatch_issue) || exceptions.size > 5
+          Merb::Dispatcher::DefaultException.new(self, e.class.status)._dispatch
+        else
+          Merb.logger.error("Dispatching #{e.class} raised another error.")
+          Merb.logger.error(Merb.exception(dispatch_issue))
+          
+          exceptions.unshift dispatch_issue
+          retry
+        end
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/request.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/request.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/request.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,612 @@
+require 'tempfile'
+
+module Merb
+
+  class Request
+    
+    # :api: private
+    attr_accessor :env, :route
+    # :api: public
+    attr_accessor :exceptions
+    # :api: private
+    attr_reader :route_params
+
+    # by setting these to false, auto-parsing is disabled; this way you can
+    # do your own parsing instead
+    cattr_accessor :parse_multipart_params, :parse_json_params,
+      :parse_xml_params
+    self.parse_multipart_params = true
+    self.parse_json_params = true
+    self.parse_xml_params = true
+
+    # Flash, and some older browsers can't use arbitrary
+    # request methods -- i.e., are limited to GET/POST.
+    # These user-agents can make POST requests in combination
+    # with these overrides to participate fully in REST.
+    # Common examples are _method or fb_sig_request_method
+    # in the params, or an X-HTTP-Method-Override header
+    cattr_accessor :http_method_overrides
+    self.http_method_overrides = []
+
+    # Initialize the request object.
+    #
+    # ==== Parameters
+    # http_request<~params:~[], ~body:IO>::
+    #   An object like an HTTP Request.
+    #
+    # :api: private
+    def initialize(rack_env)
+      @env  = rack_env
+      @body = rack_env[Merb::Const::RACK_INPUT]
+      @route_params = {}
+    end
+
+    # Returns the controller object for initialization and dispatching the
+    # request.
+    #
+    # ==== Returns
+    # Class:: The controller class matching the routed request,
+    #   e.g. Posts.
+    #
+    # :api: private
+    def controller
+      unless params[:controller]
+        raise ControllerExceptions::NotFound,
+          "Route matched, but route did not specify a controller.\n" +
+          "Did you forgot to add :controller => \"people\" or :controller " +
+          "segment to route definition?\nHere is what's specified:\n" +
+          route.inspect
+      end
+      path = [params[:namespace], params[:controller]].compact.join(Merb::Const::SLASH)
+      controller = path.snake_case.to_const_string
+
+      begin
+        Object.full_const_get(controller)
+      rescue NameError => e
+        msg = "Controller class not found for controller `#{path}'"
+        Merb.logger.warn!(msg)
+        raise ControllerExceptions::NotFound, msg
+      end
+    end
+
+    METHODS = %w{get post put delete head options}
+
+    # ==== Returns
+    # Symbol:: The name of the request method, e.g. :get.
+    #
+    # ==== Notes
+    # If the method is post, then the blocks specified in
+    # http_method_overrides will be checked for the masquerading method.
+    # The block will get the controller yielded to it.  The first matching workaround wins.
+    # To disable this behavior, set http_method_overrides = []
+    #
+    # :api: public
+    def method
+      @method ||= begin
+        request_method = @env[Merb::Const::REQUEST_METHOD].downcase.to_sym
+        case request_method
+        when :get, :head, :put, :delete, :options
+          request_method
+        when :post
+          m = nil
+          self.class.http_method_overrides.each do |o|
+            m ||= o.call(self); break if m
+          end
+          m.downcase! if m
+          METHODS.include?(m) ? m.to_sym : :post
+        else
+          raise "Unknown REQUEST_METHOD: #{@env[Merb::Const::REQUEST_METHOD]}"
+        end
+      end
+    end
+
+    # create predicate methods for querying the REQUEST_METHOD
+    # get? post? head? put? etc
+    METHODS.each do |m|
+      class_eval "def #{m}?() method == :#{m} end"
+    end
+
+    # ==== Notes
+    # Find route using requested URI and merges route
+    # parameters (:action, :controller and named segments)
+    # into request params hash.
+    #
+    # :api: private
+    def find_route!
+      @route, @route_params = Merb::Router.route_for(self)
+      params.merge! @route_params if @route_params.is_a?(Hash)
+    end
+
+    # ==== Notes
+    # Processes the return value of a deferred router block
+    # and returns the current route params for the current
+    # request evaluation
+    #
+    # :api: private
+    def _process_block_return(retval)
+      # If the return value is an array, then it is a redirect
+      # so we must set the request as a redirect and extract
+      # the redirect params and return it as a hash so that the
+      # dispatcher can handle it
+      matched! if retval.is_a?(Array)
+      retval
+    end
+
+    # Sets the request as matched. This will abort evaluating any
+    # further deferred procs.
+    #
+    # :api: private
+    def matched!
+      @matched = true
+    end
+
+    # Checks whether or not the request has been matched to a route.
+    #
+    # :api: private
+    def matched?
+      @matched
+    end
+
+    # ==== Returns
+    # (Array, Hash):: the route params for the matched route.
+    #
+    # ==== Notes
+    # If the response is an Array then it is considered a direct Rack response
+    # to be sent back as a response. Otherwise, the route_params is a Hash with
+    # routing data (controller, action, et al).
+    #
+    # :api: private
+    def rack_response
+      @route_params
+    end
+
+    # If @route_params is an Array, then it will be the rack response.
+    # In this case, the request is considered handled.
+    #
+    # ==== Returns
+    # Boolean:: true if @route_params is an Array, false otherwise.
+    #
+    # :api: private
+    def handled?
+      @route_params.is_a?(Array)
+    end
+
+    # == Params
+    #
+    # Handles processing params from raw data and merging them together to get
+    # the final request params.
+
+    private
+
+    # ==== Returns
+    # Hash:: Parameters passed from the URL like ?blah=hello.
+    #
+    # :api: private
+    def query_params
+      @query_params ||= Merb::Parse.query(query_string || '')
+    end
+
+    # Parameters passed in the body of the request. Ajax calls from
+    # prototype.js and other libraries pass content this way.
+    #
+    # ==== Returns
+    # Hash:: The parameters passed in the body.
+    #
+    # :api: private
+    def body_params
+      @body_params ||= begin
+        if content_type && content_type.match(Merb::Const::FORM_URL_ENCODED_REGEXP) # or content_type.nil?
+          Merb::Parse.query(raw_post)
+        end
+      end
+    end
+
+    # ==== Returns
+    # Mash::
+    #   The parameters gathered from the query string and the request body,
+    #   with parameters in the body taking precedence.
+    #
+    # :api: private
+    def body_and_query_params
+      # ^-- FIXME a better name for this method
+      @body_and_query_params ||= begin
+        h = query_params
+        h.merge!(body_params) if body_params
+        h.to_mash
+      end
+    end
+
+    # ==== Raises
+    # ControllerExceptions::MultiPartParseError::
+    #   Unable to parse the multipart form data.
+    #
+    # ==== Returns
+    # Hash:: The parsed multipart parameters.
+    #
+    # :api: private
+    def multipart_params
+      @multipart_params ||=
+        begin
+          # if the content-type is multipart
+          # parse the multipart. Otherwise return {}
+          if (Merb::Const::MULTIPART_REGEXP =~ content_type)
+            Merb::Parse.multipart(@body, $1, content_length)
+          else
+            {}
+          end
+        rescue ControllerExceptions::MultiPartParseError => e
+          @multipart_params = {}
+          raise e
+        end
+    end
+
+    # ==== Returns
+    # Hash:: Parameters from body if this is a JSON request.
+    #
+    # ==== Notes
+    # If the JSON object parses as a Hash, it will be merged with the
+    # parameters hash.  If it parses to anything else (such as an Array, or
+    # if it inflates to an Object) it will be accessible via the inflated_object
+    # parameter.
+    #
+    # :api: private
+    def json_params
+      @json_params ||= begin
+        if Merb::Const::JSON_MIME_TYPE_REGEXP.match(content_type)
+          begin
+            jobj = JSON.parse(raw_post)
+            jobj = jobj.to_mash if jobj.is_a?(Hash)
+          rescue JSON::ParserError
+            jobj = Mash.new
+          end
+          jobj.is_a?(Hash) ? jobj : { :inflated_object => jobj }
+        end
+      end
+    end
+
+    # ==== Returns
+    # Hash:: Parameters from body if this is an XML request.
+    #
+    # :api: private
+    def xml_params
+      @xml_params ||= begin
+        if Merb::Const::XML_MIME_TYPE_REGEXP.match(content_type)
+          Hash.from_xml(raw_post) rescue Mash.new
+        end
+      end
+    end
+
+    public
+
+    # ==== Returns
+    # Mash:: All request parameters.
+    #
+    # ==== Notes
+    # The order of precedence for the params is XML, JSON, multipart, body and
+    # request string.
+    #
+    # :api: public
+    def params
+      @params ||= begin
+        h = body_and_query_params.merge(route_params)
+        h.merge!(multipart_params) if self.class.parse_multipart_params && multipart_params
+        h.merge!(json_params) if self.class.parse_json_params && json_params
+        h.merge!(xml_params) if self.class.parse_xml_params && xml_params
+        h
+      end
+    end
+
+    # ==== Returns
+    # String:: Returns the redirect message Base64 unencoded.
+    #
+    # :api: public
+    def message
+      return {} unless params[:_message]
+      begin
+        Marshal.load(Merb::Parse.unescape(params[:_message]).unpack("m").first)
+      rescue ArgumentError, TypeError
+        {}
+      end
+    end
+
+    # ==== Notes
+    # Resets the params to a nil value.
+    #
+    # :api: private
+    def reset_params!
+      @params = nil
+    end
+
+    # ==== Returns
+    # String:: The raw post.
+    #
+    # :api: private
+    def raw_post
+      @body.rewind if @body.respond_to?(:rewind)
+      @raw_post ||= @body.read
+    end
+
+    # ==== Returns
+    # Boolean:: If the request is an XML HTTP request.
+    #
+    # :api: public
+    def xml_http_request?
+      not Merb::Const::XML_HTTP_REQUEST_REGEXP.match(@env[Merb::Const::HTTP_X_REQUESTED_WITH]).nil?
+    end
+    alias xhr? :xml_http_request?
+    alias ajax? :xml_http_request?
+
+    # ==== Returns
+    # String:: The remote IP address.
+    #
+    # :api: public
+    def remote_ip
+      return @env[Merb::Const::HTTP_CLIENT_IP] if @env.include?(Merb::Const::HTTP_CLIENT_IP)
+
+      if @env.include?(Merb::Const::HTTP_X_FORWARDED_FOR) then
+        remote_ips = @env[Merb::Const::HTTP_X_FORWARDED_FOR].split(',').reject do |ip|
+          ip =~ Merb::Const::LOCAL_IP_REGEXP
+        end
+
+        return remote_ips.first.strip unless remote_ips.empty?
+      end
+
+      return @env[Merb::Const::REMOTE_ADDR]
+    end
+
+    # ==== Returns
+    # String::
+    #   The protocol, i.e. either "https" or "http" depending on the
+    #   HTTPS header.
+    #
+    # :api: public
+    def protocol
+      ssl? ? Merb::Const::HTTPS : Merb::Const::HTTP
+    end
+
+    # ==== Returns
+    # Boolean::: True if the request is an SSL request.
+    #
+    # :api: public
+    def ssl?
+      @env[Merb::Const::UPCASE_HTTPS] == 'on' || @env[Merb::Const::HTTP_X_FORWARDED_PROTO] == Merb::Const::HTTPS
+    end
+
+    # ==== Returns
+    # String:: The HTTP referer.
+    #
+    # :api: public
+    def referer
+      @env[Merb::Const::HTTP_REFERER]
+    end
+
+    # ==== Returns
+    # String:: The full URI, including protocol and host
+    #
+    # :api: public
+    def full_uri
+      protocol + "://" + host + uri
+    end
+
+    # ==== Returns
+    # String:: The request URI.
+    #
+    # :api: public
+    def uri
+      @env[Merb::Const::REQUEST_PATH] || @env[Merb::Const::REQUEST_URI] || path_info
+    end
+
+    # ==== Returns
+    # String:: The HTTP user agent.
+    #
+    # :api: public
+    def user_agent
+      @env[Merb::Const::HTTP_USER_AGENT]
+    end
+
+    # ==== Returns
+    # String:: The server name.
+    #
+    # :api: public
+    def server_name
+      @env[Merb::Const::SERVER_NAME]
+    end
+
+    # ==== Returns
+    # String:: The accepted encodings.
+    #
+    # :api: private
+    def accept_encoding
+      @env[Merb::Const::HTTP_ACCEPT_ENCODING]
+    end
+
+    # ==== Returns
+    # String:: The script name.
+    #
+    # :api: public
+    def script_name
+      @env[Merb::Const::SCRIPT_NAME]
+    end
+
+    # ==== Returns
+    # String:: HTTP cache control.
+    #
+    # :api: public
+    def cache_control
+      @env[Merb::Const::HTTP_CACHE_CONTROL]
+    end
+
+    # ==== Returns
+    # String:: The accepted language.
+    #
+    # :api: public
+    def accept_language
+      @env[Merb::Const::HTTP_ACCEPT_LANGUAGE]
+    end
+
+    # ==== Returns
+    # String:: The server software.
+    #
+    # :api: public
+    def server_software
+      @env[Merb::Const::SERVER_SOFTWARE]
+    end
+
+    # ==== Returns
+    # String:: Value of HTTP_KEEP_ALIVE.
+    #
+    # :api: public
+    def keep_alive
+      @env[Merb::Const::HTTP_KEEP_ALIVE]
+    end
+
+    # ==== Returns
+    # String:: The accepted character sets.
+    #
+    # :api: public
+    def accept_charset
+      @env[Merb::Const::HTTP_ACCEPT_CHARSET]
+    end
+
+    # ==== Returns
+    # String:: The HTTP version
+    #
+    # :api: private
+    def version
+      @env[Merb::Const::HTTP_VERSION]
+    end
+
+    # ==== Returns
+    # String:: The gateway.
+    #
+    # :api: public
+    def gateway
+      @env[Merb::Const::GATEWAY_INTERFACE]
+    end
+
+    # ==== Returns
+    # String:: The accepted response types. Defaults to "*/*".
+    #
+    # :api: private
+    def accept
+      @env[Merb::Const::HTTP_ACCEPT].blank? ? "*/*" : @env[Merb::Const::HTTP_ACCEPT]
+    end
+
+    # ==== Returns
+    # String:: The HTTP connection.
+    #
+    # :api: private
+    def connection
+      @env[Merb::Const::HTTP_CONNECTION]
+    end
+
+    # ==== Returns
+    # String:: The query string.
+    #
+    # :api: private
+    def query_string
+      @env[Merb::Const::QUERY_STRING]
+    end
+
+    # ==== Returns
+    # String:: The request content type.
+    #
+    # :api: private
+    def content_type
+      @env[Merb::Const::UPCASE_CONTENT_TYPE]
+    end
+
+    # ==== Returns
+    # Fixnum:: The request content length.
+    #
+    # :api: public
+    def content_length
+      @content_length ||= @env[Merb::Const::CONTENT_LENGTH].to_i
+    end
+
+    # ==== Returns
+    # String::
+    #   The URI without the query string. Strips trailing "/" and reduces
+    #   duplicate "/" to a single "/".
+    #
+    # :api: public
+    def path
+      # Merb::Const::SLASH is /
+      # Merb::Const::QUESTION_MARK is ?
+      path = (uri.empty? ? Merb::Const::SLASH : uri.split(Merb::Const::QUESTION_MARK).first).squeeze(Merb::Const::SLASH)
+      path = path[0..-2] if (path[-1] == ?/) && path.size > 1
+      path
+    end
+
+    # ==== Returns
+    # String:: The path info.
+    #
+    # :api: public
+    def path_info
+      @path_info ||= Merb::Parse.unescape(@env[Merb::Const::PATH_INFO])
+    end
+
+    # ==== Returns
+    # Fixnum:: The server port.
+    #
+    # :api: public
+    def port
+      @env[Merb::Const::SERVER_PORT].to_i
+    end
+
+    # ==== Returns
+    # String:: The full hostname including the port.
+    #
+    # :api: public
+    def host
+      @env[Merb::Const::HTTP_X_FORWARDED_HOST] || @env[Merb::Const::HTTP_HOST] ||
+        @env[Merb::Const::SERVER_NAME]
+    end
+
+    # ==== Parameters
+    # tld_length<Fixnum>::
+    #   Number of domains levels to inlclude in the top level domain. Defaults
+    #   to 1.
+    #
+    # ==== Returns
+    # Array:: All the subdomain parts of the host.
+    #
+    # :api: public
+    def subdomains(tld_length = 1)
+      parts = host.split(Merb::Const::DOT)
+      parts[0..-(tld_length+2)]
+    end
+
+    # ==== Parameters
+    # tld_length<Fixnum>::
+    #   Number of domains levels to inlclude in the top level domain. Defaults
+    #   to 1.
+    #
+    # ==== Returns
+    # String:: The full domain name without the port number.
+    #
+    # :api: public
+    def domain(tld_length = 1)
+      host.split(Merb::Const::DOT).last(1 + tld_length).join(Merb::Const::DOT).sub(/:\d+$/,'')
+    end
+
+    # ==== Returns
+    # Value of If-None-Match request header.
+    #
+    # :api: private
+    def if_none_match
+      @env[Merb::Const::HTTP_IF_NONE_MATCH]
+    end
+
+    # ==== Returns
+    # Value of If-Modified-Since request header.
+    #
+    # :api: private
+    def if_modified_since
+      if time = @env[Merb::Const::HTTP_IF_MODIFIED_SINCE]
+        Time.rfc2822(time)
+      end
+    end
+
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/request_parsers.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/request_parsers.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/request_parsers.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,247 @@
+module Merb
+  module Parse
+  
+    # ==== Parameters
+    # query_string<String>:: The query string.
+    # delimiter<String>:: The query string divider. Defaults to "&".
+    # preserve_order<Boolean>:: Preserve order of args. Defaults to false.
+    #
+    # ==== Returns
+    # Mash:: The parsed query string (Dictionary if preserve_order is set).
+    #
+    # ==== Examples
+    #   Merb::Parse.query("bar=nik&post[body]=heya")
+    #     # => { :bar => "nik", :post => { :body => "heya" } }
+    #
+    # :api: plugin
+    def self.query(query_string, delimiter = '&;', preserve_order = false)
+      query = preserve_order ? Dictionary.new : {}
+      for pair in (query_string || '').split(/[#{delimiter}] */n)
+        key, value = unescape(pair).split('=',2)
+        next if key.nil?
+        if key.include?('[')
+          normalize_params(query, key, value)
+        else
+          query[key] = value
+        end
+      end
+      preserve_order ? query : query.to_mash
+    end
+
+    NAME_REGEX         = /Content-Disposition:.* name="?([^\";]*)"?/ni.freeze
+    CONTENT_TYPE_REGEX = /Content-Type: (.*)\r\n/ni.freeze
+    FILENAME_REGEX     = /Content-Disposition:.* filename="?([^\";]*)"?/ni.freeze
+    CRLF               = "\r\n".freeze
+    EOL                = CRLF
+  
+    # ==== Parameters
+    # request<IO>:: The raw request.
+    # boundary<String>:: The boundary string.
+    # content_length<Fixnum>:: The length of the content.
+    #
+    # ==== Raises
+    # ControllerExceptions::MultiPartParseError:: Failed to parse request.
+    #
+    # ==== Returns
+    # Hash:: The parsed request.
+    #
+    # :api: plugin
+    def self.multipart(request, boundary, content_length)
+      boundary = "--#{boundary}"
+      paramhsh = {}
+      buf      = ""
+      input    = request
+      input.binmode if defined? input.binmode
+      boundary_size = boundary.size + EOL.size
+      bufsize       = 16384
+      content_length -= boundary_size
+      # status is boundary delimiter line
+      status = input.read(boundary_size)
+      return {} if status == nil || status.empty?
+      raise ControllerExceptions::MultiPartParseError, "bad content body:\n'#{status}' should == '#{boundary + EOL}'"  unless status == boundary + EOL
+      # second argument to Regexp.quote is for KCODE
+      rx = /(?:#{EOL})?#{Regexp.quote(boundary,'n')}(#{EOL}|--)/
+      loop {
+        head      = nil
+        body      = ''
+        filename  = content_type = name = nil
+        read_size = 0
+        until head && buf =~ rx
+          i = buf.index("\r\n\r\n")
+          if( i == nil && read_size == 0 && content_length == 0 )
+            content_length = -1
+            break
+          end
+          if !head && i
+            head = buf.slice!(0, i+2) # First \r\n
+            buf.slice!(0, 2)          # Second \r\n
+
+            # String#[] with 2nd arg here is returning
+            # a group from match data
+            filename     = head[FILENAME_REGEX, 1]
+            content_type = head[CONTENT_TYPE_REGEX, 1]
+            name         = head[NAME_REGEX, 1]
+
+            if filename && !filename.empty?
+              body = Tempfile.new(:Merb)
+              body.binmode if defined? body.binmode
+            end
+            next
+          end
+
+          # Save the read body part.
+          if head && (boundary_size+4 < buf.size)
+            body << buf.slice!(0, buf.size - (boundary_size+4))
+          end
+
+          read_size = bufsize < content_length ? bufsize : content_length
+          if( read_size > 0 )
+            c = input.read(read_size)
+            raise ControllerExceptions::MultiPartParseError, "bad content body"  if c.nil? || c.empty?
+            buf << c
+            content_length -= c.size
+          end
+        end
+
+        # Save the rest.
+        if i = buf.index(rx)
+          # correct value of i for some edge cases
+          if (i > 2) && (j = buf.index(rx, i-2)) && (j < i)
+             i = j
+           end
+          body << buf.slice!(0, i)
+          buf.slice!(0, boundary_size+2)
+
+          content_length = -1  if $1 == "--"
+        end
+
+        if filename && !filename.empty?
+          body.rewind
+          data = {
+            :filename => File.basename(filename),
+            :content_type => content_type,
+            :tempfile => body,
+            :size => File.size(body.path)
+          }
+        else
+          data = body
+        end
+        paramhsh = normalize_params(paramhsh,name,data)
+        break  if buf.empty? || content_length == -1
+      }
+      paramhsh
+    end
+
+    # ==== Parameters
+    # value<Array, Hash, Dictionary ~to_s>:: The value for the query string.
+    # prefix<~to_s>:: The prefix to add to the query string keys.
+    #
+    # ==== Returns
+    # String:: The query string.
+    #
+    # ==== Alternatives
+    # If the value is a string, the prefix will be used as the key.
+    #
+    # ==== Examples
+    #   params_to_query_string(10, "page")
+    #     # => "page=10"
+    #   params_to_query_string({ :page => 10, :word => "ruby" })
+    #     # => "page=10&word=ruby"
+    #   params_to_query_string({ :page => 10, :word => "ruby" }, "search")
+    #     # => "search[page]=10&search[word]=ruby"
+    #   params_to_query_string([ "ice-cream", "cake" ], "shopping_list")
+    #     # => "shopping_list[]=ice-cream&shopping_list[]=cake"
+    #
+    # :api: plugin
+    def self.params_to_query_string(value, prefix = nil)
+      case value
+      when Array
+        value.map { |v|
+          params_to_query_string(v, "#{prefix}[]")
+        } * "&"
+      when Hash, Dictionary
+        value.map { |k, v|
+          params_to_query_string(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
+        } * "&"
+      else
+        "#{prefix}=#{escape(value)}"
+      end
+    end
+
+    # ==== Parameters
+    # s<String>:: String to URL escape.
+    #
+    # ==== returns
+    # String:: The escaped string.
+    #
+    # :api: public
+    def self.escape(s)
+      s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
+        '%'+$1.unpack('H2'*$1.size).join('%').upcase
+      }.tr(' ', '+')
+    end
+
+    # ==== Parameter
+    # s<String>:: String to URL unescape.
+    #
+    # ==== returns
+    # String:: The unescaped string.
+    #
+    # :api: public
+    def self.unescape(s)
+      s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
+        [$1.delete('%')].pack('H*')
+      }
+    end
+
+    # ==== Parameters
+    # s<String>:: String to XML escape.
+    #
+    # ==== returns
+    # String:: The escaped string.
+    #
+    # :api: public
+    def self.escape_xml(s)
+      Erubis::XmlHelper.escape_xml(s)
+    end
+
+    private
+
+    # Converts a query string snippet to a hash and adds it to existing
+    # parameters.
+    #
+    # ==== Parameters
+    # parms<Hash>:: Parameters to add the normalized parameters to.
+    # name<String>:: The key of the parameter to normalize.
+    # val<String>:: The value of the parameter.
+    #
+    # ==== Returns
+    # Hash:: Normalized parameters
+    #
+    # :api: private
+    def self.normalize_params(parms, name, val=nil)
+      name =~ %r([\[\]]*([^\[\]]+)\]*)
+      key = $1 || ''
+      after = $' || ''
+
+      if after == ""
+        parms[key] = val
+      elsif after == "[]"
+        (parms[key] ||= []) << val
+      elsif after =~ %r(^\[\]\[([^\[\]]+)\]$)
+        child_key = $1
+        parms[key] ||= []
+        if parms[key].last.is_a?(Hash) && !parms[key].last.key?(child_key)
+          parms[key].last.update(child_key => val)
+        else
+          parms[key] << { child_key => val }
+        end
+      else
+        parms[key] ||= {}
+        parms[key] = normalize_params(parms[key], after, val)
+      end
+      parms
+    end  
+  
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/behavior.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/behavior.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/behavior.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,794 @@
+module Merb
+  
+  class Router
+    
+    class Behavior
+      
+      class Error < StandardError; end
+      
+      # Proxy catches any methods and proxies them to the current behavior.
+      # This allows building routes without constantly having to catching the
+      # yielded behavior object
+      # 
+      # :api: private
+      class Proxy
+        
+        # Undefine as many methods as possible so that everything can be proxied
+        # along to the behavior
+        instance_methods.each { |m| undef_method m unless %w[ __id__ __send__ class kind_of? respond_to? assert_kind_of should should_not instance_variable_set instance_variable_get instance_eval].include?(m) }
+        
+        # :api: private
+        def initialize
+          @behaviors = []
+        end
+        
+        # Puts a behavior on the bottom of the stack.
+        # 
+        # ==== Notes
+        # The behaviors keep track of nested scopes.
+        # 
+        # :api: private
+        def push(behavior)
+          @behaviors.push(behavior)
+        end
+        
+        # Removes the top-most behavior.
+        # 
+        # ==== Notes
+        # This occurs at the end of a nested scope (namespace, etc).
+        # 
+        # :api: private
+        def pop
+          @behaviors.pop
+        end
+        
+        # Tests whether the top-most behavior responds to the arguments.
+        # 
+        # ==== Notes
+        # Behaviors contain the actual functionality of the proxy.
+        # 
+        # :api: private
+        def respond_to?(*args)
+          super || @behaviors.last.respond_to?(*args)
+        end
+        
+        # Rake does some stuff with methods in the global namespace, so if I don't
+        # explicitly define the Behavior methods to proxy here (specifically namespace)
+        # Rake's methods take precedence.
+        # 
+        # Removing the following:
+        # name full_name fixatable redirect
+        %w(
+          match to with register default defaults options option namespace identify
+          default_routes defer defer_to capture resources resource
+        ).each do |method|
+          class_eval %{
+            def #{method}(*args, &block)
+              @behaviors.last.#{method}(*args, &block)
+            end
+          }
+        end
+        
+        # == These methods are to be used in defer_to blocks
+        
+        # There are three possible ways to use this method.  First, if you have a named route, 
+        # you can specify the route as the first parameter as a symbol and any paramters in a 
+        # hash.  Second, you can generate the default route by just passing the params hash, 
+        # just passing the params hash.  Finally, you can use the anonymous parameters.  This 
+        # allows you to specify the parameters to a named route in the order they appear in the 
+        # router.  
+        #
+        # ==== Parameters(Named Route)
+        # name<Symbol>:: 
+        #   The name of the route. 
+        # args<Hash>:: 
+        #   Parameters for the route generation.
+        #
+        # ==== Parameters(Default Route)
+        # args<Hash>:: 
+        #   Parameters for the route generation.  This route will use the default route. 
+        #
+        # ==== Parameters(Anonymous Parameters)
+        # name<Symbol>::
+        #   The name of the route.  
+        # args<Array>:: 
+        #   An array of anonymous parameters to generate the route
+        #   with. These parameters are assigned to the route parameters
+        #   in the order that they are passed.
+        #
+        # ==== Returns
+        # String:: The generated URL.
+        #
+        # ==== Examples
+        # Named Route
+        #
+        # Merb::Router.prepare do
+        #   match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+        # end
+        #
+        # url(:articles, :title => "new_article")
+        #
+        # Default Route
+        #
+        # Merb::Router.prepare do
+        #   default_routes
+        # end
+        #
+        # url(:controller => "articles", :action => "new")
+        #
+        # Anonymous Paramters
+        #
+        # Merb::Router.prepare do
+        #   match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+        # end
+        #
+        # url(:articles, 2008, 10, "test_article")
+        #
+        # :api: public
+        def url(name, *args)
+          args << {}
+          Merb::Router.url(name, *args)
+        end
+        
+        # Generates a Rack redirection response.
+        # 
+        # ==== Notes
+        # Refer to Merb::Rack::Helpers.redirect for documentation.
+        # 
+        # :api: public
+        def redirect(url, opts = {})
+          Merb::Rack::Helpers.redirect(url, opts)
+        end
+        
+        private
+        
+        # Proxies the method calls to the behavior.
+        # 
+        # ==== Notes
+        # Please refer to:
+        # http://ruby-doc.org/core/classes/Kernel.html#M005951
+        # 
+        # :api: private
+        def method_missing(method, *args, &block)
+          behavior = @behaviors.last
+          
+          if behavior.respond_to?(method)
+            behavior.send(method, *args, &block)
+          else
+            super
+          end
+        end
+      end
+      
+      # Behavior objects are used for the Route building DSL. Each object keeps
+      # track of the current definitions for the level at which it is defined.
+      # Each time a method is called on a Behavior object that accepts a block,
+      # a new instance of the Behavior class is created.
+      # 
+      # ==== Parameters
+      # 
+      # proxy<Proxy>::
+      #   This is the object initialized by Merb::Router.prepare that tracks the
+      #   current Behavior object stack so that Behavior methods can be called
+      #   without explicitly calling them on an instance of Behavior.
+      # conditions<Hash>::
+      #   The initial route conditions. See #match.
+      # params<Hash>::
+      #   The initial route parameters. See #to.
+      # defaults<Hash>::
+      #   The initial route default parameters. See #defaults.
+      # options<Hash>::
+      #   The initial route options. See #options.
+      # blocks<Array>::
+      #   The stack of deferred routing blocks for the route
+      # 
+      # ==== Returns
+      # Behavior:: The initialized Behavior object
+      # 
+      # :api: private
+      def initialize(proxy = nil, conditions = {}, params = {}, defaults = {}, identifiers = {}, options = {}, blocks = []) #:nodoc:
+        @proxy       = proxy
+        @conditions  = conditions
+        @params      = params
+        @defaults    = defaults
+        @identifiers = identifiers
+        @options     = options
+        @blocks      = blocks
+        
+        stringify_condition_values
+      end
+      
+      # Defines the +conditions+ that are required to match a Request. Each
+      # +condition+ is applied to a method of the Request object. Conditions
+      # can also be applied to segments of the +path+.
+      # 
+      # If #match is passed a block, it will create a new route scope with
+      # the conditions passed to it and yield to the block such that all
+      # routes that are defined in the block have the conditions applied
+      # to them.
+      # 
+      # ==== Parameters
+      # 
+      # path<String, Regexp>::
+      #   The pattern against which Merb::Request path is matched.
+      # 
+      #   When +path+ is a String, any substring that is wrapped in parenthesis
+      #   is considered optional and any segment that begins with a colon, ex.:
+      #   ":login", defines both a capture and a named param. Extra conditions
+      #   can then be applied each named param individually.
+      # 
+      #   When +path+ is a Regexp, the pattern is left untouched and the
+      #   Merb::Request path is matched against it as is.
+      #
+      #   +path+ is optional.
+      # 
+      # conditions<Hash>::
+      #   Additional conditions that the request must meet in order to match.
+      #   The keys must be the names of previously defined path segments or
+      #   be methods that the Merb::Request instance will respond to.  The
+      #   value is the string or regexp that matched the returned value.
+      #   Conditions are inherited by child routes.
+      # 
+      # &block::
+      #   All routes defined in the block will be scoped to the conditions
+      #   defined by the #match method.
+      # 
+      # ==== Block parameters
+      # r<Behavior>:: +optional+ - The match behavior object.
+      # 
+      # ==== Returns
+      # Behavior::
+      #   A new instance of Behavior with the specified path and conditions.
+      # 
+      # +Tip+: When nesting always make sure the most inner sub-match registers
+      # a Route and doesn't just return new Behaviors.
+      # 
+      # ==== Examples
+      # 
+      #   # registers /foo/bar to controller => "foo", :action => "bar"
+      #   # and /foo/baz to controller => "foo", :action => "baz"
+      #   match("/foo") do
+      #     match("/bar").to(:controller => "foo", :action => "bar")
+      #     match("/baz").to(:controller => "foo", :action => "caz")
+      #   end
+      # 
+      #   # Checks the format of the segments against the specified Regexp
+      #   match("/:string/:number", :string => /[a-z]+/, :number => /\d+/).
+      #     to(:controller => "string_or_numbers")
+      # 
+      #   # Equivalent to the default_route
+      #   match("/:controller(/:action(:id))(.:format)").register
+      # 
+      #   #match only if the browser string contains MSIE or Gecko
+      #   match("/foo", :user_agent => /(MSIE|Gecko)/ )
+      #        .to(:controller => 'foo', :action => 'popular')
+      # 
+      #   # Route GET and POST requests to different actions (see also #resources)
+      #   r.match('/foo', :method => :get).to(:action => 'show')
+      #   r.match('/foo', :method => :post).to(:action => 'create')
+      # 
+      #   # match also takes regular expressions
+      # 
+      #   r.match(%r[/account/([a-z]{4,6})]).to(:controller => "account",
+      #      :action => "show", :id => "[1]")
+      # 
+      #   r.match(%r{/?(en|es|fr|be|nl)?}).to(:language => "[1]") do
+      #     match("/guides/:action/:id").to(:controller => "tour_guides")
+      #   end
+      # 
+      # :api: public
+      def match(path = {}, conditions = {}, &block)
+        path, conditions = path[:path], path if path.is_a?(Hash)
+        
+        raise Error, "The route has already been committed. Further conditions cannot be specified" if @route
+        
+        conditions.delete_if { |k, v| v.nil? }
+        conditions[:path] = merge_paths(path)
+        
+        behavior = Behavior.new(@proxy, @conditions.merge(conditions), @params, @defaults, @identifiers, @options, @blocks)
+        with_behavior_context(behavior, &block)
+      end
+      
+      # Creates a Route from one or more Behavior objects, unless a +block+ is
+      # passed in.
+      # 
+      # ==== Parameters
+      # params<Hash>:: The parameters the route maps to.
+      # 
+      # &block::
+      #   All routes defined in the block will be scoped to the params
+      #   defined by the #to method.
+      # 
+      # ==== Block parameters
+      # r<Behavior>:: +optional+ - The to behavior object.
+      # 
+      # ==== Returns
+      # Route:: It registers a new route and returns it.
+      # 
+      # ==== Examples
+      #   match('/:controller/:id).to(:action => 'show')
+      # 
+      #   to(:controller => 'simple') do
+      #     match('/test').to(:action => 'index')
+      #     match('/other').to(:action => 'other')
+      #   end
+      # 
+      # :api: public
+      def to(params = {}, &block)
+        raise Error, "The route has already been committed. Further params cannot be specified" if @route
+        
+        behavior = Behavior.new(@proxy, @conditions, @params.merge(params), @defaults, @identifiers, @options, @blocks)
+        
+        if block_given?
+          with_behavior_context(behavior, &block)
+        else
+          behavior.to_route
+        end
+      end
+      
+      # Equivalent of #to. Allows for some nicer syntax when scoping blocks
+      # 
+      # ==== Examples
+      # Merb::Router.prepare do
+      #   with(:controller => "users") do
+      #     match("/signup").to(:action => "signup")
+      #     match("/login").to(:action => "login")
+      #     match("/logout").to(:action => "logout")
+      #   end
+      # end
+      alias :with :to
+      
+      # Equivalent of #to. Allows for nicer syntax when registering routes with no params
+      # 
+      # ==== Examples
+      # Merb::Router.prepare do
+      #   match("/:controller(/:action(/:id))(.:format)").register
+      # end
+      alias :register :to
+      
+      # Sets default values for route parameters. If no value for the key
+      # can be extracted from the request, then the value provided here
+      # will be used.
+      # 
+      # ==== Parameters
+      # defaults<Hash>::
+      #   The default values for named segments.
+      # 
+      # &block::
+      #   All routes defined in the block will be scoped to the defaults defined
+      #   by the #default method.
+      # 
+      # ==== Block parameters
+      # r<Behavior>:: +optional+ - The defaults behavior object.
+      # 
+      # :api: public
+      def default(defaults = {}, &block)
+        behavior = Behavior.new(@proxy, @conditions, @params, @defaults.merge(defaults), @identifiers, @options, @blocks)
+        with_behavior_context(behavior, &block)
+      end
+      
+      alias_method :defaults, :default
+      
+      # Allows the fine tuning of certain router options.
+      # 
+      # ==== Parameters
+      # options<Hash>::
+      #   The options to set for all routes defined in the scope. The currently
+      #   supported options are:
+      #   * :controller_prefix - The module that the controller is included in.
+      #   * :name_prefix       - The prefix added to all routes named with #name
+      # 
+      # &block::
+      #   All routes defined in the block will be scoped to the options defined
+      #   by the #options method.
+      # 
+      # ==== Block parameters
+      # r<Behavior>:: The options behavior object. This is optional
+      # 
+      # ==== Examples
+      #   # If :group is not matched in the path, it will be "registered" instead
+      #   # of nil.
+      #   match("/users(/:group)").default(:group => "registered")
+      # 
+      # :api: public
+      def options(opts = {}, &block)
+        options = @options.dup
+        
+        opts.each_pair do |key, value|
+          options[key] = (options[key] || []) + [value.freeze] if value
+        end
+        
+        behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, options, @blocks)
+        with_behavior_context(behavior, &block)
+      end
+      
+      alias_method :options, :options
+      
+      # Creates a namespace for a route. This way you can have logical
+      # separation to your routes.
+      # 
+      # ==== Parameters
+      # name_or_path<String, Symbol>::
+      #   The name or path of the namespace.
+      # 
+      # options<Hash>::
+      #   Optional hash (see below)
+      # 
+      # &block::
+      #   All routes defined in the block will be scoped to the namespace defined
+      #   by the #namespace method.
+      # 
+      # ==== Options (opts)
+      # :path<String>:: match against this url
+      # 
+      # ==== Block parameters
+      # r<Behavior>:: The namespace behavior object. This is optional
+      # 
+      # ==== Examples
+      #   namespace :admin do
+      #     resources :accounts
+      #     resource :email
+      #   end
+      # 
+      #   # /super_admin/accounts
+      #   namespace(:admin, :path=>"super_admin") do
+      #     resources :accounts
+      #   end
+      # 
+      # :api: public
+      def namespace(name_or_path, opts = {}, &block)
+        name = name_or_path.to_s # We don't want this modified ever
+        path = opts.has_key?(:path) ? opts[:path] : name
+        
+        raise Error, "The route has already been committed. Further options cannot be specified" if @route
+        
+        # option keys could be nil
+        opts[:controller_prefix] = name unless opts.has_key?(:controller_prefix)
+        opts[:name_prefix]       = name unless opts.has_key?(:name_prefix)
+        opts[:resource_prefix]   = opts[:name_prefix] unless opts.has_key?(:resource_prefix)
+        
+        behavior = self
+        behavior = behavior.match("/#{path}") unless path.nil? || path.empty?
+        behavior.options(opts, &block)
+      end
+      
+      # Sets a method for instances of specified Classes to be called before
+      # insertion into a route. This is useful when using models and want a
+      # specific method to be called on it (For example, for ActiveRecord::Base
+      # it would be #to_param).
+      # 
+      # The default method called on objects is #to_s.
+      # 
+      # ==== Paramters
+      # identifiers<Hash>::
+      #   The keys are Classes and the values are the method that instances of the specified
+      #   class should have called on.
+      # 
+      # &block::
+      #   All routes defined in the block will be call the specified methods during
+      #   generation.
+      # 
+      # ==== Block parameters
+      # r<Behavior>:: The identify behavior object. This is optional
+      # 
+      # :api: public
+      def identify(identifiers = {}, &block)
+        identifiers = if Hash === identifiers
+          @identifiers.merge(identifiers)
+        else
+          { Object => identifiers }
+        end
+        
+        behavior = Behavior.new(@proxy, @conditions, @params, @defaults, identifiers.freeze, @options, @blocks)
+        with_behavior_context(behavior, &block)
+      end
+      
+      # Creates the most common routes /:controller/:action/:id.format when
+      # called with no arguments. You can pass a hash or a block to add parameters
+      # or override the default behavior.
+      # 
+      # ==== Parameters
+      # params<Hash>::
+      #   This optional hash can be used to augment the default settings
+      # 
+      # &block::
+      #   When passing a block a new behavior is yielded and more refinement is
+      #   possible.
+      # 
+      # ==== Returns
+      # Route:: the default route
+      # 
+      # ==== Examples
+      # 
+      #   # Passing an extra parameter "mode" to all matches
+      #   r.default_routes :mode => "default"
+      # 
+      #   # specifying exceptions within a block
+      #   r.default_routes do |nr|
+      #     nr.defer_to do |request, params|
+      #       nr.match(:protocol => "http://").to(:controller => "login",
+      #         :action => "new") if request.env["REQUEST_URI"] =~ /\/private\//
+      #     end
+      #   end
+      # 
+      # :api: public
+      def default_routes(params = {}, &block)
+        match("/:controller(/:action(/:id))(.:format)").to(params, &block).name(:default)
+      end
+      
+      # Takes a block and stores it for deferred conditional routes. The block
+      # takes the +request+ object and the +params+ hash as parameters.
+      # 
+      # ==== Parameters
+      # params<Hash>:: Parameters and conditions associated with this behavior.
+      # &conditional_block::
+      #   A block with the conditions to be met for the behavior to take
+      #   effect.
+      # 
+      # ==== Returns
+      # Route :: The default route.
+      # 
+      # ==== Note
+      # The block takes two parameters, request and params. The params that
+      # are passed into the block are *just* the placeholder params from the
+      # route. If you want the full parsed params, use request.params.
+      #
+      # The rationale for this is that request.params is a fairly slow
+      # operation, and if the full params parsing is not required, we would
+      # rather not do the full parsing.
+      # 
+      # ==== Examples
+      #   defer_to do |request, params|
+      #     params.merge :controller => 'here',
+      #       :action => 'there' if request.xhr?
+      #   end
+      # 
+      # :api: public
+      def defer_to(params = {}, &block)
+        defer(block).to(params)
+      end
+      
+      # Takes a Proc as a parameter and applies it as a deferred proc for all the
+      # routes defined in the block. This is mostly interesting for plugin
+      # developers.
+      # 
+      # ==== Examples
+      #   defered_block = proc do |r, p|
+      #     p.merge :controller => 'api/comments' if request.xhr?
+      #   end
+      #   defer(defered_block) do
+      #     resources :comments
+      #   end
+      # 
+      # :api: public
+      def defer(deferred_block, &block)
+        blocks = @blocks + [CachedProc.new(deferred_block)]
+        behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, @options, blocks)
+        with_behavior_context(behavior, &block)
+      end
+      
+      # Registers the route as a named route with the name given.
+      # 
+      # ==== Parameters
+      # symbol<Symbol>:: the name of the route.
+      # 
+      # ==== Raises
+      # ArgumentError:: symbol is not a Symbol.
+      # 
+      # :api: public
+      def name(prefix, name = nil)
+        unless name
+          name, prefix = prefix, nil
+        end
+        
+        full_name([prefix, @options[:name_prefix], name].flatten.compact.join('_'))
+      end
+      
+      # Names this route in Router. Name must be a Symbol. The current
+      # name_prefix is ignored.
+      #
+      # ==== Parameters
+      # symbol<Symbol>:: The name of the route.
+      #
+      # ==== Raises
+      # ArgumentError:: symbol is not a Symbol.
+      # 
+      # :api: private
+      def full_name(name)
+        raise Error, ":this is reserved. Please pick another name." if name == :this
+        
+        if @route
+          @route.name = name
+          self
+        else
+          register.full_name(name)
+        end
+      end
+      
+      # Specifies that a route can be fixatable.
+      # 
+      # ==== Parameters
+      # enabled<Boolean>:: True enables fixation on the route.
+      # 
+      # :api: public
+      def fixatable(enable = true)
+        @route.fixation = enable
+        self
+      end
+      
+      # Redirects the current route.
+      # 
+      # ==== Parameters
+      # path<String>:: The path to redirect to.
+      # 
+      # options<Hash>::
+      #   Options (see below)
+      # 
+      # ==== Options (opts)
+      # :permanent<Boolean>::
+      #   Whether or not the redirect should be permanent.
+      #   The default value is false.
+      # 
+      # :api: public
+      def redirect(url, opts = {})
+        raise Error, "The route has already been committed." if @route
+        
+        status = opts[:permanent] ? 301 : 302
+        @route = Route.new(@conditions, {:url => url.freeze, :status => status.freeze}, @blocks, :redirects => true)
+        @route.register
+        self
+      end
+      
+      # Capture any new routes that have been added within the block.
+      #
+      # This utility method lets you track routes that have been added;
+      # it doesn't affect how/which routes are added.
+      #
+      # &block:: A context in which routes are generated.
+      # 
+      # :api: public
+      def capture(&block)
+        captured_routes = {}
+        name_prefix     = [@options[:name_prefix]].flatten.compact.map { |p| "#{p}_"}
+        current_names   = Merb::Router.named_routes.keys
+        
+        behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks)
+        with_behavior_context(behavior, &block)
+        
+        Merb::Router.named_routes.reject { |k,v| current_names.include?(k) }.each do |name, route|
+          name = route.name.to_s.sub("#{name_prefix}", '').to_sym unless name_prefix.empty?
+          captured_routes[name] = route
+        end
+        
+        captured_routes
+      end
+      
+      # Proxy routes with the default behaviors.
+      # 
+      # ==== Parameters
+      # &block:: defines routes within the provided context.
+      # 
+      # :api: private
+      def _with_proxy(&block)
+        proxy = Proxy.new
+        proxy.push Behavior.new(proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks)
+        proxy.instance_eval(&block)
+        proxy
+      end
+      
+      protected
+      
+      # Returns the current route.
+      # 
+      # ==== Returns
+      # Route:: the route.
+      # 
+      # :api: private
+      def _route
+        @route
+      end
+      
+      # Turns a route definition into a Route object.
+      # 
+      # ==== Returns
+      # Route:: the route generated.
+      # 
+      # :api: private
+      def to_route
+        raise Error, "The route has already been committed." if @route
+        
+        controller = @params[:controller]
+        
+        if prefixes = @options[:controller_prefix]
+          controller ||= ":controller"
+          
+          prefixes.reverse_each do |prefix|
+            break if controller =~ %r{^/(.*)} && controller = $1
+            controller = "#{prefix}/#{controller}"
+          end
+        end
+        
+        @params.merge!(:controller => controller.to_s.gsub(%r{^/}, '')) if controller
+        
+        # Sorts the identifiers so that modules that are at the bottom of the
+        # inheritance chain come first (more specific modules first). Object
+        # should always be last.
+        identifiers = @identifiers.sort { |(first,_),(sec,_)| first <=> sec || 1 }
+        
+        @route = Route.new(@conditions.dup, at params, @blocks, :defaults => @defaults.dup, :identifiers => identifiers)
+        
+        if before = @options[:before] && @options[:before].last
+          @route.register_at(Router.routes.index(before))
+        else
+          @route.register
+        end
+        self
+      end
+      
+      # Allows to insert the route at a certain spot in the list of routes
+      # instead of appending to the list.
+      # 
+      # ==== Params
+      # route<Route>:: the route to insert before.
+      # &block:: the route definition to insert.
+      # 
+      # :api: plugin
+      def before(route, &block)
+        options(:before => route, &block)
+      end
+      
+      private
+      
+      # Takes @conditions and turns values into strings (except for Regexp and
+      # Array values).
+      # 
+      # :api: private
+      def stringify_condition_values # :nodoc:
+        @conditions.each do |key, value|
+          unless value.nil? || Regexp === value || Array === value
+            @conditions[key] = value.to_s
+          end
+        end
+      end
+      
+      # Creates a new context with a given behavior for the route definition in
+      # the block.
+      # 
+      # ==== Params
+      # behavior<Behavior>:: the behavior to proxy the calls in the block.
+      # &block:: the routing definitions to be nested within the behavior.
+      # 
+      # ==== Returns
+      # Behavior:: the behavior wrapping.
+      # 
+      # :api: private
+      def with_behavior_context(behavior, &block) # :nodoc:
+        if block_given?
+          @proxy.push(behavior)
+          retval = yield(behavior)
+          @proxy.pop
+        end
+        behavior
+      end
+      
+      # Merges the path elements together into an array to be joined for
+      # generating named routes.
+      # 
+      # ==== Parameters
+      # path<String>:: the path to merge at the end.
+      # 
+      # ==== Returns
+      # Array:: array of path elements.
+      # 
+      # ==== Notes
+      # An array of ['a', 'b'] (the 'a' namespace with the 'b' action) will
+      # produce a name of :a_b.
+      # 
+      # :api: private
+      def merge_paths(path) # :nodoc:
+        [@conditions[:path], path.freeze].flatten.compact
+      end
+      
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/cached_proc.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/cached_proc.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/cached_proc.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,64 @@
+module Merb
+  
+  class Router
+    # Cache procs for future reference in eval statement
+    # :api: private
+    class CachedProc
+      @@index = 0
+      @@list = []
+
+      # :api: private
+      attr_accessor :cache, :index
+
+      # ==== Parameters
+      # cache<Proc>:: The block of code to cache.
+      #
+      # :api: private
+      def initialize(cache)
+        @cache, @index = cache, CachedProc.register(self)
+      end
+
+      # ==== Returns
+      # String:: The CachedProc object in a format embeddable within a string.
+      #
+      # :api: private
+      def to_s
+        "CachedProc[#{@index}].cache"
+      end
+
+      class << self
+
+        # ==== Parameters
+        # cached_code<CachedProc>:: The cached code to register.
+        #
+        # ==== Returns
+        # Fixnum:: The index of the newly registered CachedProc.
+        #
+        # :api: private
+        def register(cached_code)
+          CachedProc[@@index] = cached_code
+          @@index += 1
+          @@index - 1
+        end
+
+        # Sets the cached code for a specific index.
+        #
+        # ==== Parameters
+        # index<Fixnum>:: The index of the cached code to set.
+        # code<CachedProc>:: The cached code to set.
+        #
+        # :api: private
+        def []=(index, code) @@list[index] = code end
+
+        # ==== Parameters
+        # index<Fixnum>:: The index of the cached code to retrieve.
+        #
+        # ==== Returns
+        # CachedProc:: The cached code at index.
+        #
+        # :api: private
+        def [](index) @@list[index] end
+      end
+    end # CachedProc
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/resources.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/resources.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/resources.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,329 @@
+module Merb
+  class Router
+
+    module Resources
+      # Behavior#+resources+ is a route helper for defining a collection of
+      # RESTful resources. It yields to a block for child routes.
+      #
+      # ==== Parameters
+      # name<String, Symbol>:: The name of the resources
+      # options<Hash>::
+      #   Ovverides and parameters to be associated with the route
+      #
+      # ==== Options (options)
+      # :namespace<~to_s>: The namespace for this route.
+      # :name_prefix<~to_s>:
+      #   A prefix for the named routes. If a namespace is passed and there
+      #   isn't a name prefix, the namespace will become the prefix.
+      # :controller<~to_s>: The controller for this route
+      # :collection<~to_s>: Special settings for the collections routes
+      # :member<Hash>:
+      #   Special settings and resources related to a specific member of this
+      #   resource.
+      # :identify<Symbol|Array>: The method(s) that should be called on the object
+      #   before inserting it into an URL.
+      # :keys<Array>:
+      #   A list of the keys to be used instead of :id with the resource in the order of the url.
+      # :singular<Symbol>
+      #
+      # ==== Block parameters
+      # next_level<Behavior>:: The child behavior.
+      #
+      # ==== Returns
+      # Array::
+      #   Routes which will define the specified RESTful collection of resources
+      #
+      # ==== Examples
+      #
+      #  r.resources :posts # will result in the typical RESTful CRUD
+      #    # lists resources
+      #    # GET     /posts/?(\.:format)?      :action => "index"
+      #    # GET     /posts/index(\.:format)?  :action => "index"
+      #
+      #    # shows new resource form
+      #    # GET     /posts/new                :action => "new"
+      #
+      #    # creates resource
+      #    # POST    /posts/?(\.:format)?,     :action => "create"
+      #
+      #    # shows resource
+      #    # GET     /posts/:id(\.:format)?    :action => "show"
+      #
+      #    # shows edit form
+      #    # GET     /posts/:id/edit        :action => "edit"
+      #
+      #    # updates resource
+      #    # PUT     /posts/:id(\.:format)?    :action => "update"
+      #
+      #    # shows deletion confirmation page
+      #    # GET     /posts/:id/delete      :action => "delete"
+      #
+      #    # destroys resources
+      #    # DELETE  /posts/:id(\.:format)?    :action => "destroy"
+      #
+      #  # Nesting resources
+      #  r.resources :posts do |posts|
+      #    posts.resources :comments
+      #  end
+      #
+      # :api: public
+      def resources(name, *args, &block)
+        name       = name.to_s
+        options    = extract_options_from_args!(args) || {}
+        match_opts = options.except(*resource_options)
+        options    = options.only(*resource_options)
+        singular   = options[:singular] ? options[:singular].to_s : Extlib::Inflection.singularize(name)
+        klass_name = args.first ? args.first.to_s : singular.to_const_string
+        keys       = options.delete(:keys) || options.delete(:key)
+        params     = { :controller => options.delete(:controller) || name }
+        collection = options.delete(:collection) || {}
+        member     = { :edit => :get, :delete => :get }.merge(options.delete(:member) || {})
+        
+        # Use the identifier for the class as a default
+        begin
+          if klass = Object.full_const_get(klass_name)
+            keys ||= options[:identify]
+            keys ||= @identifiers[klass]
+          elsif options[:identify]
+            raise Error, "The constant #{klass_name} does not exist, please specify the constant for this resource"
+          end
+        rescue NameError => e
+          Merb.logger.debug!("Could not find resource model #{klass_name}")
+        end
+        
+        keys = [ keys || :id ].flatten
+        
+
+        # Try pulling :namespace out of options for backwards compatibility
+        options[:name_prefix]       ||= nil # Don't use a name_prefix if not needed
+        options[:resource_prefix]   ||= nil # Don't use a resource_prefix if not needed
+        options[:controller_prefix] ||= options.delete(:namespace)
+
+        context = options[:identify]
+        context = klass && options[:identify] ? identify(klass => options.delete(:identify)) : self
+        context.namespace(name, options).to(params) do |resource|
+          root_keys = keys.map { |k| ":#{k}" }.join("/")
+          
+          # => index
+          resource.match("(/index)(.:format)", :method => :get).to(:action => "index").
+            name(name).register_resource(name)
+            
+          # => create
+          resource.match("(.:format)", :method => :post).to(:action => "create")
+          
+          # => new
+          resource.match("/new(.:format)", :method => :get).to(:action => "new").
+            name("new", singular).register_resource(name, "new")
+
+          # => user defined collection routes
+          collection.each_pair do |action, method|
+            action = action.to_s
+            resource.match("/#{action}(.:format)", :method => method).to(:action => "#{action}").
+              name(action, name).register_resource(name, action)
+          end
+
+          # => show
+          resource.match("/#{root_keys}(.:format)", match_opts.merge(:method => :get)).to(:action => "show").
+            name(singular).register_resource(klass_name, :identifiers => keys)
+
+          # => user defined member routes
+          member.each_pair do |action, method|
+            action = action.to_s
+            resource.match("/#{root_keys}/#{action}(.:format)", match_opts.merge(:method => method)).
+              to(:action => "#{action}").name(action, singular).register_resource(klass_name, action, :identifiers => keys)
+          end
+
+          # => update
+          resource.match("/#{root_keys}(.:format)", match_opts.merge(:method => :put)).
+            to(:action => "update")
+            
+          # => destroy
+          resource.match("/#{root_keys}(.:format)", match_opts.merge(:method => :delete)).
+            to(:action => "destroy")
+
+          if block_given?
+            parent_keys = keys.map do |k|
+              k == :id ? "#{singular}_id".to_sym : k
+            end
+            
+            nested_keys = parent_keys.map { |k| ":#{k}" }.join("/")
+
+            nested_match_opts = match_opts.except(:id)
+            nested_match_opts["#{singular}_id".to_sym] = match_opts[:id] if match_opts[:id]
+            
+            # Procs for building the extra collection/member resource routes
+            placeholder = Router.resource_routes[ [@options[:resource_prefix], klass_name].flatten.compact ]
+            builders    = {}
+            
+            builders[:collection] = lambda do |action, to, method|
+              resource.before(placeholder).match("/#{action}(.:format)", match_opts.merge(:method => method)).
+                to(:action => to).name(action, name).register_resource(name, action)
+            end
+            
+            builders[:member] = lambda do |action, to, method|
+              resource.match("/#{root_keys}/#{action}(.:format)", match_opts.merge(:method => method)).
+                to(:action => to).name(action, singular).register_resource(klass_name, action, :identifiers => keys)
+            end
+            
+            resource.options(:name_prefix => singular, :resource_prefix => klass_name, :parent_keys => parent_keys).
+              match("/#{nested_keys}", nested_match_opts).resource_block(builders, &block)
+          end
+        end # namespace
+      end # resources
+
+      # Behavior#+resource+ is a route helper for defining a singular RESTful
+      # resource. It yields to a block for child routes.
+      #
+      # ==== Parameters
+      # name<String, Symbol>:: The name of the resource.
+      # options<Hash>::
+      #   Overides and parameters to be associated with the route.
+      #
+      # ==== Options (options)
+      # :namespace<~to_s>: The namespace for this route.
+      # :name_prefix<~to_s>:
+      #   A prefix for the named routes. If a namespace is passed and there
+      #   isn't a name prefix, the namespace will become the prefix.
+      # :controller<~to_s>: The controller for this route
+      #
+      # ==== Block parameters
+      # next_level<Behavior>:: The child behavior.
+      #
+      # ==== Returns
+      # Array:: Routes which define a RESTful single resource.
+      #
+      # ==== Examples
+      #
+      #  r.resource :account # will result in the typical RESTful CRUD
+      #    # shows new resource form      
+      #    # GET     /account/new                :action => "new"
+      #
+      #    # creates resource      
+      #    # POST    /account/?(\.:format)?,     :action => "create"
+      #
+      #    # shows resource      
+      #    # GET     /account/(\.:format)?       :action => "show"
+      #
+      #    # shows edit form      
+      #    # GET     /account//edit           :action => "edit"
+      #
+      #    # updates resource      
+      #    # PUT     /account/(\.:format)?       :action => "update"
+      #
+      #    # shows deletion confirmation page      
+      #    # GET     /account//delete         :action => "delete"
+      #
+      #    # destroys resources      
+      #    # DELETE  /account/(\.:format)?       :action => "destroy"
+      #
+      # You can optionally pass :namespace and :controller to refine the routing
+      # or pass a block to nest resources.
+      #
+      #   r.resource :account, :namespace => "admin" do |account|
+      #     account.resources :preferences, :controller => "settings"
+      #   end
+      #
+      # :api: public
+      def resource(name, *args, &block)
+        name    = name.to_s
+        options = extract_options_from_args!(args) || {}
+        params  = { :controller => options.delete(:controller) || name.pluralize }
+        member  = { :new => :get, :edit => :get, :delete => :get }.merge(options.delete(:member) || {})
+
+        options[:name_prefix]       ||= nil # Don't use a name_prefix if not needed
+        options[:resource_prefix]   ||= nil # Don't use a resource_prefix if not needed
+        options[:controller_prefix] ||= options.delete(:namespace)
+
+        self.namespace(name, options).to(params) do |resource|
+          # => show
+          
+          resource.match("(.:format)", :method => :get).to(:action => "show").
+            name(name).register_resource(name)
+            
+          # => create
+          resource.match("(.:format)", :method => :post).to(:action => "create")
+            
+          # => update
+          resource.match("(.:format)", :method => :put).to(:action => "update")
+            
+          # => destroy
+          resource.match("(.:format)", :method => :delete).to(:action => "destroy")
+          
+          member.each_pair do |action, method|
+            action = action.to_s
+            resource.match("/#{action}(.:format)", :method => method).to(:action => action).
+              name(action, name).register_resource(name, action)
+          end
+
+          if block_given?
+            builders = {}
+            
+            builders[:member] = lambda do |action, to, method|
+              resource.match("/#{action}(.:format)", :method => method).to(:action => to).
+                name(action, name).register_resource(name, action)
+            end
+            
+            resource.options(:name_prefix => name, :resource_prefix => name).
+              resource_block(builders, &block)
+          end
+        end
+      end
+      
+    protected
+    
+      # :api: private
+      def register_resource(*key)
+        options     = extract_options_from_args!(key) || {}
+        key         = [ @options[:resource_prefix], key ].flatten.compact
+        identifiers = [ @options[:parent_keys], options[:identifiers] ]
+        @route.resource = key
+        @route.resource_identifiers = identifiers.flatten.compact.map { |id| id.to_sym }
+        self
+      end
+
+      # :api: private
+      def resource_block(builders, &block)
+        behavior = ResourceBehavior.new(builders, @proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks)
+        with_behavior_context(behavior, &block)
+      end
+      
+      def resource_options
+        [:singular, :keys, :key, :controller, :member, :collection, :identify,
+          :name_prefix, :resource_prefix, :controller_prefix, :namespace, :path]
+      end
+
+    end # Resources
+    
+    class Behavior
+      include Resources
+    end
+    
+    # Adding the collection and member methods to behavior
+    class ResourceBehavior < Behavior #:nodoc:
+      
+      # :api: private
+      def initialize(builders, *args)
+        super(*args)
+        @collection = builders[:collection]
+        @member     = builders[:member]
+      end
+      
+      # :api: private
+      def collection(action, options = {})
+        action = action.to_s
+        method = options[:method]
+        to     = options[:to] || action
+        @collection[action, to, method]
+      end
+      
+      # :api: private
+      def member(action, options = {})
+        action = action.to_s
+        method = options[:method]
+        to     = options[:to] || action
+        @member[action, to, method]
+      end
+      
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/route.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/route.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router/route.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,685 @@
+module Merb
+
+  class Router
+    # This entire class is private and should never be accessed outside of
+    # Merb::Router and Behavior
+    class Route #:nodoc:
+      SEGMENT_REGEXP               = /(:([a-z](_?[a-z0-9])*))/
+      OPTIONAL_SEGMENT_REGEX       = /^.*?([\(\)])/i
+      SEGMENT_REGEXP_WITH_BRACKETS = /(:[a-z_]+)(\[(\d+)\])?/
+      JUST_BRACKETS                = /\[(\d+)\]/
+      SEGMENT_CHARACTERS           = "[^\/.,;?]".freeze
+
+      # :api: private
+      attr_reader :conditions, :params, :segments
+      # :api: private
+      attr_reader :index, :variables, :name
+      # :api: private
+      attr_accessor :fixation, :resource_identifiers
+
+      # :api: private
+      def initialize(conditions, params, deferred_procs, options = {})
+        @conditions, @params = conditions, params
+
+        if options[:redirects]
+          @redirects         = true
+          @redirect_status   = @params[:status]
+          @redirect_url      = @params[:url]
+          @defaults          = {}
+        else
+          @generatable       = true
+          @defaults          = options[:defaults] || {}
+        end
+        
+        @identifiers       = options[:identifiers]
+        @deferred_procs    = deferred_procs
+        @segments          = []
+        @symbol_conditions = {}
+        @placeholders      = {}
+        compile
+      end
+
+      # :api: private
+      def regexp?
+        @regexp
+      end
+    
+      # :api: private  
+      def generatable?
+        @generatable && !regexp?
+      end
+
+      # :api: private
+      def allow_fixation?
+        @fixation
+      end
+      
+      # :api: private
+      def to_s
+        regexp? ?
+          "/#{conditions[:path].source}/" :
+          segment_level_to_s(segments)
+      end
+      
+      alias_method :inspect, :to_s
+
+      # Appends self to Merb::Router.routes
+
+      # :api: private
+      def register
+        @index = Merb::Router.routes.size
+        Merb::Router.routes << self
+        self
+      end
+      
+      # Inserts self to Merb::Router.routes at the specified index.
+      # :api: private      
+      def register_at(index)
+        @index = index
+        Merb::Router.routes.insert(index, self)
+        self
+      end
+      
+      # Sets the route as a resource route with the given key as the 
+      # lookup key.
+      # :api: private      
+      def resource=(key)
+        Router.resource_routes[key] = self
+        key
+      end
+      
+      # :api: private
+      def name=(name)
+        @name = name.to_sym
+        Router.named_routes[@name] = self
+        @name
+      end
+      
+      # Generates the URL for the route given the passed arguments. The
+      # method will first match the anonymous parameters to route params
+      # and will convert all the parameters according to the specifed
+      # object identifiers.
+      #
+      # Then the named parameters are passed to a compiled generation proc.
+      #
+      # ==== Parameters
+      # args<Array>::
+      #   The arguments passed to the public #url method with the name
+      #   of the route removed. This is an array of the anonymous parameters
+      #   followed by a hash containing the named parameters.
+      #
+      # defaults<Hash>::
+      #   A hash of parameters to use to generate the route if there are
+      #   any missing required parameters. This is usually the parameters
+      #   for the current request
+      #
+      # ==== Returns
+      # String:: The generated URL.
+      #
+      # :api: private
+      def generate(args = [], defaults = {}, resource = false)
+        unless generatable?
+          raise GenerationError, "Cannot generate regexp Routes" if regexp?
+          raise GenerationError, "Cannot generate this route"
+        end
+        
+        params = extract_options_from_args!(args) || { }
+        
+        params.each do |k, v|
+          params[k] = identify(v, k)
+        end
+        
+        # Support for anonymous params
+        unless args.empty?
+          # First, let's determine which variables are missing
+          variables = (resource ? @resource_identifiers : @variables) - params.keys
+          
+          args.each do |param|
+            raise GenerationError, "The route has #{@variables.length} variables: #{@variables.inspect}" if variables.empty?
+            
+            if identifier = identifier_for(param) and identifier.is_a?(Array)
+              identifier.each { |ident| params[variables.shift] = param.send(ident) }
+            else
+              params[variables.shift] ||= identify(param)
+            end
+          end
+        end
+        
+        uri = @generator[params, defaults] or raise GenerationError, "Named route #{name} could not be generated with #{params.inspect}"
+        uri = Merb::Config[:path_prefix] + uri if Merb::Config[:path_prefix]
+        uri
+      end
+      
+      # Identifies the object according to the identifiers set while building
+      # the routes. Identifying an object means picking an instance method to
+      # call on the object that will return a string representation of the
+      # object for the route being generated. If the identifier is an array,
+      # then a param_key must be present and match one of the elements of the
+      # identifier array.
+      #
+      # param_keys that end in _id are treated slightly differently in order
+      # to get nested resources to work correctly.
+      #
+      # :api: private
+      def identify(obj, param_key = nil)
+        identifier = identifier_for(obj)
+        if identifier.is_a?(Array)
+          # First check if the param_key exists as an identifier
+          return obj.send(param_key) if identifier.include?(param_key)
+          # If the param_key ends in _id, just return the object id
+          return obj.id if "#{param_key}" =~ /_id$/
+          # Otherwise, raise an error
+          raise GenerationError, "The object #{obj.inspect} cannot be identified with #{identifier.inspect} for #{param_key}"
+        else
+          identifier ? obj.send(identifier) : obj
+        end
+      end
+      
+      # Returns the identifier for the passed object. Built in core ruby classes are
+      # always identified with to_s. The method will return nil in that case (since
+      # to_s is the default for objects that do not have identifiers.)
+      #
+      # :api: private
+      def identifier_for(obj)
+        return if obj.is_a?(String)    || obj.is_a?(Symbol)     || obj.is_a?(Numeric)  ||
+                  obj.is_a?(TrueClass) || obj.is_a?(FalseClass) || obj.is_a?(NilClass) ||
+                  obj.is_a?(Array)     || obj.instance_of?(Hash)
+        
+        @identifiers.each do |klass, identifier|
+          return identifier if obj.is_a?(klass)
+        end
+        
+        return nil
+      end
+
+      # Returns the if statement and return value for for the main
+      # Router.match compiled method.
+      #
+      # :api: private
+      def compiled_statement(first)
+        els_if = first ? '  if ' : '  elsif '
+
+        code = ""
+        code << els_if << condition_statements.join(" && ") << "\n"
+        
+        # First, we need to always return the value of the
+        # deferred block if it explicitly matched the route
+        if @redirects
+          code << "    return [#{@index.inspect}, block_result] if request.matched?" << "\n" if @deferred_procs.any?
+          code << "    [#{@index.inspect}, Merb::Rack::Helpers.redirect(#{@redirect_url.inspect}, :status => #{@redirect_status.inspect})]" << "\n"
+        elsif @deferred_procs.any?
+          code << "    [#{@index.inspect}, block_result]" << "\n"
+        else
+          code << "    [#{@index.inspect}, #{params_as_string}]" << "\n"
+        end
+      end
+
+    private
+      
+    # === Compilation ===
+
+      # :api: private
+      def compile
+        compile_conditions
+        compile_params
+        @generator = Generator.new(@segments, @symbol_conditions, @identifiers).compiled
+      end
+      
+      # The Generator class handles compiling the route down to a lambda that
+      # can generate the URL from a params hash and a default params hash.
+      class Generator #:nodoc:
+
+        # :api: private        
+        def initialize(segments, symbol_conditions, identifiers)
+          @segments          = segments
+          @symbol_conditions = symbol_conditions
+          @identifiers       = identifiers
+          @stack             = []
+          @opt_segment_count = 0
+          @opt_segment_stack = [[]]
+        end
+        
+        #
+        # :api: private
+        def compiled
+          ruby  = ""
+          ruby << "lambda do |params, defaults|\n"
+          ruby << "  fragment     = params.delete(:fragment)\n"
+          ruby << "  query_params = params.dup\n"
+          
+          with(@segments) do
+            ruby << "  include_defaults = true\n"
+            ruby << "  return unless url = #{block_for_level}\n"
+          end
+          
+          ruby << "  query_params.delete_if { |key, value| value.nil? }\n"
+          ruby << "  unless query_params.empty?\n"
+          ruby << '    url << "?#{Merb::Parse.params_to_query_string(query_params)}"' << "\n"
+          ruby << "  end\n"
+          ruby << '  url << "##{fragment}" if fragment' << "\n"
+          ruby << "  url\n"
+          ruby << "end\n"
+          
+          eval(ruby)
+        end
+        
+      private
+      
+        # Cleans up methods a bunch. We don't need to pass the current segment
+        # level around everywhere anymore. It's kept track for us in the stack.
+        #
+        # :api: private
+        def with(segments, &block)
+          @stack.push(segments)
+          retval = yield
+          @stack.pop
+          retval
+        end
+  
+        # :api: private  
+        def segments
+          @stack.last || []
+        end
+
+        # :api: private        
+        def symbol_segments
+          segments.flatten.select { |s| s.is_a?(Symbol)  }
+        end
+
+        # :api: private
+        def current_segments
+          segments.select { |s| s.is_a?(Symbol) }
+        end
+
+        # :api: private        
+        def nested_segments
+          segments.select { |s| s.is_a?(Array) }.flatten.select { |s| s.is_a?(Symbol) }
+        end
+
+        # :api: private      
+        def block_for_level
+          ruby  = ""
+          ruby << "if #{segment_level_matches_conditions}\n"
+          ruby << "  #{remove_used_segments_in_query_path}\n"
+          ruby << "  #{generate_optional_segments}\n"
+          ruby << %{ "#{combine_required_and_optional_segments}"\n}
+          ruby << "end"
+        end
+
+        # :api: private        
+        def check_if_defaults_should_be_included
+          ruby = ""
+          ruby << "include_defaults = "
+          symbol_segments.each { |s| ruby << "params[#{s.inspect}] || " }
+          ruby << "false"
+        end
+
+        # --- Not so pretty ---
+        # :api: private        
+        def segment_level_matches_conditions
+          conditions = current_segments.map do |segment|
+            condition = "(cached_#{segment} = params[#{segment.inspect}] || include_defaults && defaults[#{segment.inspect}])"
+
+            if @symbol_conditions[segment] && @symbol_conditions[segment].is_a?(Regexp)
+              condition << " && cached_#{segment}.to_s =~ #{@symbol_conditions[segment].inspect}"
+            elsif @symbol_conditions[segment]
+              condition << " && cached_#{segment}.to_s == #{@symbol_conditions[segment].inspect}"
+            end
+
+            condition
+          end
+          
+          conditions << "true" if conditions.empty?
+          conditions.join(" && ")
+        end
+
+        # :api: private
+        def remove_used_segments_in_query_path
+          "#{current_segments.inspect}.each { |s| query_params.delete(s) }"
+        end
+
+        # :api: private
+        def generate_optional_segments
+          optionals = []
+
+          segments.each_with_index do |segment, i|
+            if segment.is_a?(Array) && segment.any? { |s| !s.is_a?(String) }
+              with(segment) do
+                @opt_segment_stack.last << (optional_name = "_optional_segments_#{@opt_segment_count += 1}")
+                @opt_segment_stack.push []
+                optionals << "#{check_if_defaults_should_be_included}\n"
+                optionals << "#{optional_name} = #{block_for_level}"
+                @opt_segment_stack.pop
+              end
+            end
+          end
+
+          optionals.join("\n")
+        end
+
+        # :api: private
+        def combine_required_and_optional_segments
+          bits = ""
+
+          segments.each_with_index do |segment, i|
+            bits << case
+              when segment.is_a?(String) then segment
+              when segment.is_a?(Symbol) then '#{cached_' + segment.to_s + '}'
+              when segment.is_a?(Array) && segment.any? { |s| !s.is_a?(String) } then "\#{#{@opt_segment_stack.last.shift}}"
+              else ""
+            end
+          end
+
+          bits
+        end
+        
+      end
+
+    # === Conditions ===
+
+      # :api: private
+      def compile_conditions
+        @original_conditions = conditions.dup
+        
+        if conditions[:path] && !conditions[:path].empty?
+          path = conditions[:path].flatten.compact
+          if path = compile_path(path)
+            conditions[:path] = Regexp.new("^#{path}$")
+          else
+            conditions.delete(:path)
+          end
+        else
+          # If there is no path, we can't generate it
+          @generatable = false
+        end
+      end
+
+      # The path is passed in as an array of different parts. We basically have
+      # to concat all the parts together, then parse the path and extract the
+      # variables. However, if any of the parts are a regular expression, then
+      # we abort the parsing and just convert it to a regexp.
+      #
+      # :api: private      
+      def compile_path(path)
+        @segments = []
+        compiled  = ""
+
+        return nil if path.nil? || path.empty?
+
+        path.each do |part|
+          case part
+          when Regexp
+            @regexp   = true
+            @segments = []
+            compiled << part.source.sub(/^\^/, '').sub(/\$$/, '')
+          when String
+            segments = segments_with_optionals_from_string(part.dup)
+            compile_path_segments(compiled, segments)
+            # Concat the segments
+            unless regexp?
+              if @segments[-1].is_a?(String) && segments[0].is_a?(String)
+                @segments[-1] << segments.shift
+              end
+              @segments.concat segments
+            end
+          else
+            raise ArgumentError.new("A route path can only be specified as a String or Regexp")
+          end
+        end
+        
+        unless regexp?
+          @variables = @segments.flatten.select { |s| s.is_a?(Symbol)  }
+          compiled.gsub!(%r[/+], '/')
+          compiled.gsub!(%r[(.+)/$], '\1')
+        end
+
+        compiled
+      end
+
+      # Simple nested parenthesis parser
+      #
+      # :api: private      
+      def segments_with_optionals_from_string(path, nest_level = 0)
+        segments = []
+
+        # Extract all the segments at this parenthesis level
+        while segment = path.slice!(OPTIONAL_SEGMENT_REGEX)
+          # Append the segments that we came across so far
+          # at this level
+          segments.concat segments_from_string(segment[0..-2]) if segment.length > 1
+          # If the parenthesis that we came across is an opening
+          # then we need to jump to the higher level
+          if segment[-1,1] == '('
+            segments << segments_with_optionals_from_string(path, nest_level + 1)
+          else
+            # Throw an error if we can't actually go back down (aka syntax error)
+            raise "There are too many closing parentheses" if nest_level == 0
+            return segments
+          end
+        end
+
+        # Save any last bit of the string that didn't match the original regex
+        segments.concat segments_from_string(path) unless path.empty?
+
+        # Throw an error if the string should not actually be done (aka syntax error)
+        raise "You have too many opening parentheses" unless nest_level == 0
+
+        segments
+      end
+
+      # :api: private
+      def segments_from_string(path)
+        segments = []
+
+        while match = (path.match(SEGMENT_REGEXP))
+          segments << match.pre_match unless match.pre_match.empty?
+          segments << match[2].intern
+          path = match.post_match
+        end
+        
+        raise Router::Behavior::Error, "cannot use :path as a route placeholder" if segments.include?(:path)
+
+        segments << path unless path.empty?
+        segments
+      end
+
+      # --- Yeah, this could probably be refactored
+      # :api: private
+      def compile_path_segments(compiled, segments)
+        segments.each do |segment|
+          case segment
+          when String
+            compiled << Regexp.escape(segment)
+          when Symbol
+            condition = (@symbol_conditions[segment] ||= @conditions.delete(segment))
+            compiled << compile_segment_condition(condition)
+            # Create a param for the Symbol segment if none already exists
+            @params[segment] = "#{segment.inspect}" unless @params.has_key?(segment)
+            @placeholders[segment] ||= capturing_parentheses_count(compiled)
+          when Array
+            compiled << "(?:"
+            compile_path_segments(compiled, segment)
+            compiled << ")?"
+          else
+            raise ArgumentError, "conditions[:path] segments can only be a Strings, Symbols, or Arrays"
+          end
+        end
+      end
+
+      # Handles anchors in Regexp conditions
+      # :api: private
+      def compile_segment_condition(condition)
+        return "(#{SEGMENT_CHARACTERS}+)" unless condition
+        return "(#{condition})"           unless condition.is_a?(Regexp)
+
+        condition = condition.source
+        # Handle the start anchor
+        condition = if condition =~ /^\^/
+          condition[1..-1]
+        else
+          "#{SEGMENT_CHARACTERS}*#{condition}"
+        end
+        # Handle the end anchor
+        condition = if condition =~ /\$$/
+          condition[0..-2]
+        else
+          "#{condition}#{SEGMENT_CHARACTERS}*"
+        end
+
+        "(#{condition})"
+      end
+
+      # :api: private
+      def compile_params
+        # Loop through each param and compile it
+        @defaults.merge(@params).each do |key, value|
+          if value.nil?
+            @params.delete(key)
+          elsif value.is_a?(String)
+            @params[key] = compile_param(value)
+          else
+            @params[key] = value.inspect
+          end
+        end
+      end
+
+      # This was pretty much a copy / paste from the old router
+      # :api: private
+      def compile_param(value)
+        result = []
+        match  = true
+        while match
+          if match = SEGMENT_REGEXP_WITH_BRACKETS.match(value)
+            result << match.pre_match.inspect unless match.pre_match.empty?
+            placeholder_key = match[1][1..-1].intern
+            if match[2] # has brackets, e.g. :path[2]
+              result << "#{placeholder_key}#{match[3]}"
+            else # no brackets, e.g. a named placeholder such as :controller
+              if place = @placeholders[placeholder_key]
+                # result << "(path#{place} || )" # <- Defaults
+                with_defaults  = ["(path#{place}"]
+                with_defaults << " || #{@defaults[placeholder_key].inspect}" if @defaults[placeholder_key]
+                with_defaults << ")"
+                result << with_defaults.join
+              else
+                raise GenerationError, "Placeholder not found while compiling routes: #{placeholder_key.inspect}. Add it to the conditions part of the route."
+              end
+            end
+            value = match.post_match
+          elsif match = JUST_BRACKETS.match(value)
+            result << match.pre_match.inspect unless match.pre_match.empty?
+            result << "path#{match[1]}"
+            value = match.post_match
+          else
+            result << value.inspect unless value.empty?
+          end
+        end
+
+        result.join(' + ').gsub("\\_", "_")
+      end
+
+      # :api: private
+      def condition_statements
+        statements = []
+
+        # First, let's build the conditions for the regular 
+        conditions.each_pair do |key, value|
+          statements << case value
+          when Regexp
+            captures = ""
+
+            if (max = capturing_parentheses_count(value)) > 0
+              captures << (1..max).to_a.map { |n| "#{key}#{n}" }.join(", ")
+              captures << " = "
+              captures << (1..max).to_a.map { |n| "$#{n}" }.join(", ")
+            end
+
+            # Note: =~ is slightly faster than .match
+            %{(#{value.inspect} =~ cached_#{key} #{' && ((' + captures + ') || true)' unless captures.empty?})}
+          when Array
+            %{(#{arrays_to_regexps(value).inspect} =~ cached_#{key})}
+          else
+            %{(cached_#{key} == #{value.inspect})}
+          end
+        end
+        
+        # The first one is special, so let's extract it
+        if first = @deferred_procs.first
+          deferred = ""
+          deferred << "(block_result = "
+          deferred <<   "request._process_block_return("
+          deferred <<     "#{first}.call(request, #{params_as_string})"
+          deferred <<   ")"
+          deferred << ")"
+          
+          # Let's build the rest of them now
+          if @deferred_procs.length > 1
+            deferred << deferred_condition_statement(@deferred_procs[1..-1])
+          end
+          
+          statements << deferred
+        end
+
+        statements
+      end
+      
+      # (request.matched? || ((block_result = process(proc.call))))
+      # :api: private      
+      def deferred_condition_statement(deferred)
+        if current = deferred.first
+          html  = " && (request.matched? || ("
+          html <<   "(block_result = "
+          html <<     "request._process_block_return("
+          html <<       "#{current}.call(request, block_result)"
+          html <<     ")"
+          html <<   ")"
+          html <<   "#{deferred_condition_statement(deferred[1..-1])}"
+          html << "))"
+        end
+      end
+
+      # :api: private
+      def params_as_string
+        elements = params.keys.map do |k|
+          "#{k.inspect} => #{params[k]}"
+        end
+        "{#{elements.join(', ')}}"
+      end
+
+    # ---------- Utilities ----------
+      
+      # :api: private      
+      def arrays_to_regexps(condition)
+        return condition unless condition.is_a?(Array)
+        
+        source = condition.map do |value|
+          value = if value.is_a?(Regexp)
+            value.source
+          else
+            "^#{Regexp.escape(value.to_s)}$"
+          end
+          "(?:#{value})"
+        end
+        
+        Regexp.compile(source.join('|'))
+      end
+    
+      # :api: private    
+      def segment_level_to_s(segments)
+        (segments || []).inject('') do |str, seg|
+          str << case seg
+            when String then seg
+            when Symbol then ":#{seg}"
+            when Array  then "(#{segment_level_to_s(seg)})"
+          end
+        end
+      end
+
+      # :api: private
+      def capturing_parentheses_count(regexp)
+        regexp = regexp.source if regexp.is_a?(Regexp)
+        regexp.scan(/(?!\\)[(](?!\?[#=:!>-imx])/).length
+      end
+    end
+  end  
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/router.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,360 @@
+require 'merb-core/dispatch/router/cached_proc'
+require 'merb-core/dispatch/router/behavior'
+require 'merb-core/dispatch/router/resources'
+require 'merb-core/dispatch/router/route'
+
+module Merb
+  # Router stores route definitions and finds the first
+  # route that matches the incoming request URL.
+  # 
+  # Then information from route is used by dispatcher to
+  # call action on the controller.
+  # 
+  # ==== Routes compilation.
+  # 
+  # The most interesting method of Router (and heart of
+  # route matching machinery) is match method generated
+  # on the fly from routes definitions. It is called routes
+  # compilation. Generated match method body contains
+  # one if/elsif statement that picks the first matching route
+  # definition and sets values to named parameters of the route.
+  # 
+  # Compilation is synchronized by mutex.
+  class Router
+    @routes          = []
+    @named_routes    = {}
+    @resource_routes = {}
+    @compiler_mutex  = Mutex.new
+    @root_behavior   = Behavior.new.defaults(:action => "index")
+    
+    # Raised when route lookup fails.
+    class RouteNotFound < StandardError; end;
+    # Raised when parameters given to generation
+    # method do not match route parameters.
+    class GenerationError < StandardError; end;
+    class NotCompiledError < StandardError; end;
+    
+    class << self
+      # An array containing all the application routes in order of
+      # priority.
+      # 
+      # :api: private
+      attr_accessor :routes
+      
+      # A hash containing all the named application routes. The names
+      # are absolute (as in, all routes named in a namespace will
+      # contain the name of the namespace).
+      # 
+      # :api: private
+      attr_accessor :named_routes
+      
+      # A hash of all the application resource routes. The key of the hash
+      # is an array with each element containing the "path" for the resource
+      # for example, given the following resource routes:
+      #
+      # resources :users do
+      #   resources :comments
+      # end
+      #
+      # The show comment route will have a key of ["User", "Comment"]
+      # 
+      # :api: private
+      attr_accessor :resource_routes
+      
+      # The starting point for route definition. Any route defined in a
+      # Merb::Router.prepare block will defined in context of this 
+      # behavior.
+      #
+      # ==== Examples
+      #
+      # Merb::Router.root_behavior = Merb::Router.root_bavior.match("/hello")
+      #
+      # In the previous example, all routes will have the path prefix /hello.
+      # It is important to note that this attribute must be set before any
+      # routes are defined in order for the behavior to be applied to the
+      # routes.
+      # 
+      # :api: plugin
+      attr_accessor :root_behavior
+      
+      # A block that will be run around route matching. This block must yield
+      # in order for the actual matching to happen.
+      # 
+      # :api: plugin
+      attr_accessor :around_match
+      
+      # Creates a route building context and evaluates the block in it. A
+      # copy of +root_behavior+ (and instance of Behavior) is copied as
+      # the context.
+      # 
+      # ==== Parameters
+      # first<Array>::
+      #   An array containing routes that should be prepended to the routes
+      #   defined in the block.
+      # last<Array>::
+      #   An array containing routes that should be appended to the routes
+      #   defined in the block.
+      # 
+      # ==== Returns
+      # Merb::Router::
+      #   Returns self to allow chaining of methods.
+      # 
+      # :api: public
+      def prepare(first = [], last = [], &block)
+        @routes = []
+        root_behavior._with_proxy(&block)
+        @routes = first + @routes + last
+        compile
+        self
+      end
+      
+      # Clears the routing table. Route generation and request matching
+      # won't work anymore until a new routing table is built.
+      # 
+      # :api: private
+      def reset!
+        class << self
+          alias_method :match, :match_before_compilation
+        end
+        self.routes, self.named_routes, self.resource_routes = [], {}, {}
+      end
+      
+      # Finds route matching URI of the request and returns a tuple of
+      # [route index, route params]. This method is called by the
+      # dispatcher and isn't as useful in applications.
+      # 
+      # ==== Parameters
+      # request<Merb::Request>:: request to match.
+      # 
+      # ==== Returns
+      # Array[Integer, Hash]::
+      #   Two-tuple: route index and route parameters. Route parameters
+      #   are :controller, :action and all the named segments of the route.
+      # 
+      # :api: private
+      def route_for(request)
+        index, params = if @around_match
+          send(@around_match, request) { match(request) }
+        else
+          match(request)
+        end
+        route = routes[index] if index
+        if !route
+          raise ControllerExceptions::NotFound, 
+            "No routes match the request: #{request.uri}"
+        end
+        [route, params]
+      end
+      
+      # A placeholder for the compiled match method.
+      # 
+      # ==== Notes
+      # This method is aliased as +match+ but this method gets overridden with
+      # the actual +match+ method (generated from the routes definitions) after
+      # being compiled. This method is only ever called before routes are
+      # compiled.
+      # 
+      # ==== Raises
+      # NotCompiledError:: routes have not been compiled yet.
+      # 
+      # :api: private
+      def match_before_compilation(request) #:nodoc:
+        raise NotCompiledError, "The routes have not been compiled yet"
+      end
+      
+      alias_method :match, :match_before_compilation
+      
+      # There are three possible ways to use this method.  First, if you have a named route, 
+      # you can specify the route as the first parameter as a symbol and any paramters in a 
+      # hash.  Second, you can generate the default route by just passing the params hash, 
+      # just passing the params hash.  Finally, you can use the anonymous parameters.  This 
+      # allows you to specify the parameters to a named route in the order they appear in the 
+      # router.  
+      #
+      # ==== Parameters(Named Route)
+      # name<Symbol>:: 
+      #   The name of the route. 
+      # args<Hash>:: 
+      #   Parameters for the route generation.
+      #
+      # ==== Parameters(Default Route)
+      # args<Hash>:: 
+      #   Parameters for the route generation.  This route will use the default route. 
+      #
+      # ==== Parameters(Anonymous Parameters)
+      # name<Symbol>::
+      #   The name of the route.  
+      # args<Array>:: 
+      #   An array of anonymous parameters to generate the route
+      #   with. These parameters are assigned to the route parameters
+      #   in the order that they are passed.
+      #
+      # ==== Returns
+      # String:: The generated URL.
+      #
+      # ==== Examples
+      # Named Route
+      #
+      # Merb::Router.prepare do
+      #   match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+      # end
+      #
+      # url(:articles, :title => "new_article")
+      #
+      # Default Route
+      #
+      # Merb::Router.prepare do
+      #   default_routes
+      # end
+      #
+      # url(:controller => "articles", :action => "new")
+      #
+      # Anonymous Paramters
+      #
+      # Merb::Router.prepare do
+      #   match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+      # end
+      #
+      # url(:articles, 2008, 10, "test_article")
+      # 
+      # :api: plugin
+      def url(name, *args)
+        if name.is_a?(Route)
+          route = name
+        else
+          unless name.is_a?(Symbol)
+            args.unshift(name)
+            name = :default
+          end
+
+          unless route = Merb::Router.named_routes[name]
+            raise Merb::Router::GenerationError, "Named route not found: #{name}"
+          end
+        end
+        
+        defaults = args.pop
+        
+        route.generate(args, defaults)
+      end
+      
+      # Generates a URL from the resource(s)
+      # 
+      # ==== Parameters
+      # resources<Symbol,Object>::
+      #   The identifiers for the resource route to generate. These
+      #   can either be symbols or objects. Symbols denote resource
+      #   collection routes and objects denote the members.
+      # 
+      # params<Hash>::
+      #   Any extra parameters needed to generate the route.
+      #
+      # ==== Returns
+      # String:: The generated URL
+      # 
+      # :api: plugin
+      def resource(*args)
+        defaults = args.pop
+        options  = extract_options_from_args!(args) || {}
+        key      = []
+        params   = []
+        
+        args.each do |arg|
+          if arg.is_a?(Symbol) || arg.is_a?(String)
+            key << arg.to_s
+          else
+            key << arg.class.to_s
+            params << arg
+          end
+        end
+        
+        unless route = Merb::Router.resource_routes[key]
+          raise Merb::Router::GenerationError, "Resource route not found: #{args.inspect}"
+        end
+
+        params << options
+        
+        route.generate(params, defaults, true)
+      end
+      
+      # Add functionality to the router. This can be in the form of
+      # including a new module or directly defining new methods.
+      #
+      # ==== Parameters
+      # &block<Block>::
+      #   A block of code used to extend the route builder with. This
+      #   can be including a module or directly defining some new methods
+      #   that should be available to building routes.
+      #
+      # ==== Returns
+      # nil
+      #
+      # ==== Example
+      #   Merb::Router.extensions do
+      #     def domain(name, domain, options={}, &block)
+      #       match(:domain => domain).namespace(name, :path => nil, &block)
+      #     end
+      #   end
+      #
+      # In this case, a method 'domain' will be available to the route builder
+      # which will create namespaces around domains instead of path prefixes.
+      #
+      # This can then be used as follows.
+      #
+      #   Merb::Router.prepare do
+      #     domain(:admin, "my-admin.com") do
+      #       # ... routes come here ...
+      #     end
+      #   end
+      #
+      # :api: public
+      def extensions(&block)
+        Router::Behavior.class_eval(&block)
+      end
+
+    private
+    
+      # Compiles the routes and creates the +match+ method.
+      # 
+      # :api: private
+      def compile
+        if routes.any?
+          begin
+            eval(compiled_statement, binding, "Generated Code for Router", 1)
+          rescue SyntaxError => e
+            puts "\nGenerated code failed:\n #{compiled_statement}"
+            raise e
+          end
+        else
+          reset!
+        end
+      end
+      
+      # Generates the method for evaluation defining a +match+ method to match
+      # a request with the defined routes.
+      # 
+      # :api: private
+      def compiled_statement
+        @compiler_mutex.synchronize do
+          condition_keys, if_statements = Set.new, ""
+          
+          routes.each_with_index do |route, i|
+            route.freeze
+            route.conditions.keys.each { |key| condition_keys << key }
+            if_statements << route.compiled_statement(i == 0)
+          end
+          
+          statement =  "def match(request)\n"
+          statement << condition_keys.inject("") do |cached, key|
+            cached << "  cached_#{key} = request.#{key}.to_s\n"
+          end
+          statement <<    if_statements
+          statement << "  else\n"
+          statement << "    [nil, {}]\n"
+          statement << "  end\n"
+          statement << "end"
+        end
+      end
+      
+    end # class << self
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/container.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/container.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/container.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,92 @@
+module Merb
+  class SessionContainer < Mash
+    
+    class_inheritable_accessor :session_store_type
+    cattr_accessor :subclasses 
+    self.subclasses = []
+    
+    # :api: private
+    attr_reader :session_id
+    # :api: private
+    attr_accessor :needs_new_cookie
+    
+    class << self
+      
+      # Register the subclass as an available session store type.
+      def inherited(klass)
+        self.subclasses << klass.to_s
+        super
+      end
+      
+      # Generates a new session ID and creates a new session.
+      #
+      # ==== Returns
+      # SessionContainer:: The new session.
+      # 
+      # :api: private
+      def generate
+      end
+      
+      # ==== Parameters
+      # request<Merb::Request>:: The Merb::Request that came in from Rack.
+      #
+      # ==== Notes
+      # If no sessions were found, a new SessionContainer will be generated.
+      # 
+      # ==== Returns
+      # SessionContainer:: a SessionContainer.
+      # 
+      # :api: private
+      def setup(request)
+      end
+      
+    end
+    
+    # ==== Parameters
+    # session_id<String>:: A unique identifier for this session.
+    # 
+    # :api: private
+    def initialize(session_id)
+      @_destroy = false
+      self.session_id = session_id
+    end
+    
+    # Assign a new session_id.
+    #
+    # Recreates the cookie with the default expiration time. Useful during log
+    # in for pushing back the expiration date.
+    # 
+    # :api: private
+    def session_id=(sid)
+      self.needs_new_cookie = (@session_id && @session_id != sid)
+      @session_id = sid
+    end
+    
+    # Teardown and/or persist the current session.
+    #
+    # If @_destroy is true, clear out the session completely, including
+    # removal of the session cookie itself.
+    #
+    # ==== Parameters
+    # request<Merb::Request>:: The Merb::Request that came in from Rack.
+    # 
+    # :api: private
+    def finalize(request)
+    end
+    
+    # Destroy the current session - clears data and removes session cookie.
+    # 
+    # :api: private
+    def clear!
+      @_destroy = true
+      self.clear
+    end
+    
+    # Regenerate the session_id.
+    # 
+    # :api: private
+    def regenerate
+    end
+    
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/cookie.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/cookie.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/cookie.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,203 @@
+require 'base64'        # to convert Marshal.dump to ASCII
+require 'openssl'       # to generate the HMAC message digest
+module Merb
+  
+  # If you have more than 4K of session data or don't want your data to be
+  # visible to the user, pick another session store.
+  #
+  # CookieOverflow is raised if you attempt to store more than 4K of data.
+  # TamperedWithCookie is raised if the data integrity check fails.
+  #
+  # A message digest is included with the cookie to ensure data integrity:
+  # a user cannot alter session data without knowing the secret key included
+  # in the hash.
+  #
+  # To use Cookie Sessions, set in config/merb.yml
+  #  :session_secret_key - your secret digest key
+  #  :session_store - cookie
+  class CookieSession < SessionContainer
+    # TODO (maybe):
+    # include request ip address
+    # AES encrypt marshaled data
+    
+    # Raised when storing more than 4K of session data.
+    class CookieOverflow < StandardError; end
+    
+    # Raised when the cookie fails its integrity check.
+    class TamperedWithCookie < StandardError; end
+    
+    # Cookies can typically store 4096 bytes.
+    MAX = 4096
+    DIGEST = OpenSSL::Digest::Digest.new('SHA1') # or MD5, RIPEMD160, SHA256?
+    
+    # :api: private
+    attr_accessor :_original_session_data
+    
+    # The session store type
+    self.session_store_type = :cookie
+    
+    class << self
+      # Generates a new session ID and creates a new session.
+      #
+      # ==== Returns
+      # SessionContainer:: The new session.
+      # 
+      # :api: private
+      def generate
+        self.new(Merb::SessionMixin.rand_uuid, "", Merb::Request._session_secret_key)
+      end
+      
+      # Set up a new session on request: make it available on request instance.
+      #
+      # ==== Parameters
+      # request<Merb::Request>:: The Merb::Request that came in from Rack.
+      #
+      # ==== Returns
+      # SessionContainer:: a SessionContainer. If no sessions were found,
+      # a new SessionContainer will be generated.
+      # 
+      # :api: private
+      def setup(request)
+        session = self.new(Merb::SessionMixin.rand_uuid,
+          request.session_cookie_value, request._session_secret_key)
+        session._original_session_data = session.to_cookie
+        request.session = session
+      end
+      
+    end
+    
+    # ==== Parameters
+    # session_id<String>:: A unique identifier for this session.
+    # cookie<String>:: The raw cookie data.
+    # secret<String>:: A session secret.
+    #
+    # ==== Raises
+    # ArgumentError:: blank or insufficiently long secret.
+    # 
+    # :api: private
+    def initialize(session_id, cookie, secret)
+      super session_id
+      if secret.blank? || secret.length < 16
+        msg = "You must specify a session_secret_key in your init file, and it must be at least 16 characters"
+        Merb.logger.warn(msg)
+        raise ArgumentError, msg
+      end
+      @secret = secret
+      self.update(unmarshal(cookie))
+    end
+    
+    # Teardown and/or persist the current session.
+    #
+    # If @_destroy is true, clear out the session completely, including
+    # removal of the session cookie itself.
+    #
+    # ==== Parameters
+    # request<Merb::Request>:: request object created from Rack environment.
+    # 
+    # :api: private
+    def finalize(request)
+      if @_destroy
+        request.destroy_session_cookie
+      elsif _original_session_data != (new_session_data = self.to_cookie)
+        request.set_session_cookie_value(new_session_data)
+      end
+    end
+    
+    # Regenerate the session_id.
+    # 
+    # :api: private
+    def regenerate
+      self.session_id = Merb::SessionMixin.rand_uuid
+    end
+    
+    # Create the raw cookie string; includes an HMAC keyed message digest.
+    #
+    # ==== Returns
+    # String:: Cookie value.
+    #
+    # ==== Raises
+    # CookieOverflow:: More than 4K of data put into session.
+    #
+    # ==== Notes
+    # Session data is converted to a Hash first, since a container might
+    # choose to marshal it, which would make it persist
+    # attributes like 'needs_new_cookie', which it shouldn't.
+    # 
+    # :api: private
+    def to_cookie
+      unless self.empty?
+        data = self.serialize
+        value = Merb::Parse.escape "#{data}--#{generate_digest(data)}"
+        if value.size > MAX
+          msg = "Cookies have limit of 4K. Session contents: #{data.inspect}"
+          Merb.logger.error!(msg)
+          raise CookieOverflow, msg
+        end
+        value
+      end
+    end
+    
+    private
+    
+    # Generate the HMAC keyed message digest. Uses SHA1.
+    # 
+    # ==== Returns
+    # String:: an HMAC digest of the cookie data.
+    # 
+    # :api: private
+    def generate_digest(data)
+      OpenSSL::HMAC.hexdigest(DIGEST, @secret, data)
+    end
+    
+    # Unmarshal cookie data to a hash and verify its integrity.
+    # 
+    # ==== Parameters
+    # cookie<~to_s>:: The cookie to unmarshal.
+    # 
+    # ==== Raises
+    # TamperedWithCookie:: The digests don't match.
+    # 
+    # ==== Returns
+    # Hash:: The stored session data.
+    # 
+    # :api: private
+    def unmarshal(cookie)
+      if cookie.blank?
+        {}
+      else
+        data, digest = Merb::Parse.unescape(cookie).split('--')
+        return {} if data.blank? || digest.blank?
+        unless digest == generate_digest(data)
+          clear
+          unless Merb::Config[:ignore_tampered_cookies]
+            raise TamperedWithCookie, "Maybe the site's session_secret_key has changed?"
+          end
+        end
+        unserialize(data)
+      end
+    end
+    
+    protected
+    
+    # Serialize current session data as a Hash.
+    # Uses Base64 encoding for integrity.
+    # 
+    # ==== Returns
+    # String:: Base64 encoded dump of the session hash.
+    # 
+    # :api: private
+    def serialize
+      Base64.encode64(Marshal.dump(self.to_hash)).chop
+    end
+    
+    # Unserialize the raw cookie data to a Hash
+    # 
+    # ==== Returns
+    # Hash:: the session hash Base64 decoded from the data dump.
+    # 
+    # :api: private
+    def unserialize(data)
+      Marshal.load(Base64.decode64(data)) rescue {}
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/memcached.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/memcached.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/memcached.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,74 @@
+module Merb
+
+  # Sessions stored in memcached.
+  #
+  # Requires setup in your +init.rb+.
+  # 
+  # This for the 'memcache-client' gem:
+  #
+  #   Merb::BootLoader.after_app_loads do
+  #     require 'memcache'
+  #     Merb::MemcacheSession.store = 
+  #        MemCache.new('127.0.0.1:11211', :namespace => 'my_app')
+  #   end
+  #
+  # Or this for the 'memcached' gem:
+  #
+  #   Merb::BootLoader.after_app_loads do
+  #     require 'memcache'
+  #     Merb::MemcacheSession.store = 
+  #        Memcached.new('127.0.0.1:11211', :namespace => 'my_app')
+  #   end
+  
+  class MemcacheSession < SessionStoreContainer
+    
+    # The session store type
+    self.session_store_type = :memcache
+    
+  end
+  
+  module MemcacheStore
+    
+    # Make the Memcached gem conform to the SessionStoreContainer interface
+    
+    # ==== Parameters
+    # session_id<String>:: ID of the session to retrieve.
+    #
+    # ==== Returns
+    # ContainerSession:: The session corresponding to the ID.
+    # 
+    # :api: private
+    def retrieve_session(session_id)
+      get("session:#{session_id}")
+    end
+    
+    # ==== Parameters
+    # session_id<String>:: ID of the session to set.
+    # data<ContainerSession>:: The session to set.
+    # 
+    # :api: private
+    def store_session(session_id, data)
+      set("session:#{session_id}", data)
+    end
+    
+    # ==== Parameters
+    # session_id<String>:: ID of the session to delete.
+    #
+    # :api: private
+    def delete_session(session_id)
+      delete("session:#{session_id}")
+    end
+    
+  end
+  
+end
+
+# For the memcached gem.
+class Memcached
+  include Merb::MemcacheStore
+end
+
+# For the memcache-client gem.
+class MemCache
+  include Merb::MemcacheStore
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/memory.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/memory.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/memory.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,113 @@
+module Merb
+  
+  # Sessions stored in memory.
+  #
+  # Set it up by adding the following to your init file:
+  #
+  #  Merb::Config.use do |c|
+  #    c[:session_store]      = :memory
+  #    c[:memory_session_ttl] = 3600 # in seconds, one hour
+  #  end
+  #
+  # Sessions will remain in memory until the server is stopped or the time
+  # as set in :memory_session_ttl expires. Expired sessions are cleaned up in the
+  # background by a separate thread. Every time reaper
+  # cleans up expired sessions, garbage collection is scheduled start.
+  #
+  # Memory session is accessed in a thread safe manner.
+  class MemorySession < SessionStoreContainer
+    
+    # The session store type
+    self.session_store_type = :memory
+    
+    # Bypass normal implicit class attribute reader - see below.
+    # :api: private    
+    def store
+      self.class.store
+    end
+    
+    # Lazy load/setup of MemorySessionStore.
+    # :api: private
+    def self.store
+      @_store ||= MemorySessionStore.new(Merb::Config[:memory_session_ttl])
+    end
+    
+  end
+  
+  # Used for handling multiple sessions stored in memory.
+  class MemorySessionStore
+    
+    # ==== Parameters
+    # ttl<Fixnum>:: Session validity time in seconds. Defaults to 1 hour.
+    # 
+    # :api: private
+    def initialize(ttl=nil)
+      @sessions = Hash.new
+      @timestamps = Hash.new
+      @mutex = Mutex.new
+      @session_ttl = ttl || Merb::Const::HOUR # defaults 1 hour
+      start_timer
+    end
+    
+    # ==== Parameters
+    # session_id<String>:: ID of the session to retrieve.
+    #
+    # ==== Returns
+    # ContainerSession:: The session corresponding to the ID.
+    # 
+    # :api: private
+    def retrieve_session(session_id)
+      @mutex.synchronize {
+        @timestamps[session_id] = Time.now
+        @sessions[session_id]
+      }
+    end
+    
+    # ==== Parameters
+    # session_id<String>:: ID of the session to set.
+    # data<ContainerSession>:: The session to set.
+    # 
+    # :api: private
+    def store_session(session_id, data)
+      @mutex.synchronize {
+        @timestamps[session_id] = Time.now
+        @sessions[session_id] = data
+      }
+    end
+    
+    # ==== Parameters
+    # session_id<String>:: ID of the session to delete.
+    # 
+    # :api: private
+    def delete_session(session_id)
+      @mutex.synchronize {
+        @timestamps.delete(session_id)
+        @sessions.delete(session_id)
+      }
+    end
+    
+    # Deletes any sessions that have reached their maximum validity.
+    # 
+    # :api: private
+    def reap_expired_sessions
+      @timestamps.each do |session_id,stamp|
+        delete_session(session_id) if (stamp + @session_ttl) < Time.now 
+      end
+      GC.start
+    end
+    
+    # Starts the timer that will eventually reap outdated sessions.
+    # 
+    # :api: private
+    def start_timer
+      Thread.new do
+        loop {
+          sleep @session_ttl
+          reap_expired_sessions
+        } 
+      end  
+    end
+    
+  end
+
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/store_container.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/store_container.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session/store_container.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,163 @@
+module Merb
+  
+  class SessionStoreContainer < SessionContainer
+    
+    class_inheritable_accessor :store
+    # :api: private
+    attr_accessor  :_fingerprint
+    
+    # The class attribute :store holds a reference to an object that implements 
+    # the following interface:
+    #
+    # - retrieve_session(session_id) # returns a Hash
+    # - store_session(session_id, data) # expects data to be Hash
+    # - delete_session(session_id)
+    #
+    # You can use session store classes directly by assigning to :store in your
+    # config/init.rb after_app_loads step, for example:
+    #
+    #   Merb::BootLoader.after_app_loads do
+    #     SessionStoreContainer.store = MemorySession.new
+    #   end
+    #
+    # Or you can inherit from SessionStoreContainer to create a SessionContainer
+    # that delegates to aggregated store.
+    #
+    #   class MemorySession < SessionStoreContainer
+    #     self.session_store_type = :memory
+    #   end
+    #
+    #   class MemoryContainer
+    #   
+    #     def self.retrieve_session(session_id)
+    #       ...
+    #     end
+    #   
+    #     def self.store_session(session_id, data)
+    #       ...
+    #     end
+    #   
+    #     def self.delete_session(session_id)
+    #       ...
+    #     end
+    #   
+    #   end    
+    # When used directly, report as :store store
+    self.session_store_type = :store
+    
+    class << self
+      
+      # Generates a new session ID and creates a new session.
+      # 
+      # ==== Returns
+      # SessionStoreContainer:: The new session.
+      # 
+      # :api: private
+      def generate
+        session = new(Merb::SessionMixin.rand_uuid)
+        session.needs_new_cookie = true
+        session
+      end
+      
+      # Setup a new session or retreive an existing session.
+      # 
+      # ==== Parameters
+      # request<Merb::Request>:: The Merb::Request that came in from Rack.
+      # 
+      # ==== Notes
+      # If no sessions were found, a new SessionContainer will be generated.
+      # 
+      # ==== Returns
+      # SessionContainer:: a SessionContainer.
+      # 
+      # :api: private
+      def setup(request)
+        session = retrieve(request.session_id)
+        request.session = session
+        # TODO Marshal.dump is slow - needs optimization
+        session._fingerprint = Marshal.dump(request.session.to_hash).hash
+        session
+      end
+            
+      private
+      
+      # ==== Parameters
+      # session_id<String:: The ID of the session to retrieve.
+      #
+      # ==== Returns
+      # SessionStoreContainer:: SessionStoreContainer instance with the session data. If no
+      #   sessions matched session_id, a new SessionStoreContainer will be generated.
+      #
+      # ==== Notes
+      # If there are persisted exceptions callbacks to execute, they all get executed
+      # when Memcache library raises an exception.
+      # 
+      # :api: private
+      def retrieve(session_id)
+        unless session_id.blank?
+          begin
+            session_data = store.retrieve_session(session_id)
+          rescue => err
+            Merb.logger.warn!("Could not retrieve session from #{self.name}: #{err.message}")
+          end
+          # Not in container, but assume that cookie exists
+          session_data = new(session_id) if session_data.nil?
+        else
+          # No cookie...make a new session_id
+          session_data = generate
+        end
+        if session_data.is_a?(self)
+          session_data
+        else
+          # Recreate using the existing session as the data, when switching 
+          # from another session type for example, eg. cookie to memcached
+          # or when the data is just a hash
+          new(session_id).update(session_data)
+        end
+      end
+
+    end
+    
+    # Teardown and/or persist the current session.
+    #
+    # If @_destroy is true, clear out the session completely, including
+    # removal of the session cookie itself.
+    #
+    # ==== Parameters
+    # request<Merb::Request>:: The Merb::Request that came in from Rack.
+    #
+    # ==== Notes
+    # The data (self) is converted to a Hash first, since a container might 
+    # choose to do a full Marshal on the data, which would make it persist 
+    # attributes like 'needs_new_cookie', which it shouldn't.
+    # 
+    # :api: private
+    def finalize(request)
+      if @_destroy
+        store.delete_session(self.session_id)
+        request.destroy_session_cookie
+      else
+        if _fingerprint != Marshal.dump(data = self.to_hash).hash
+          begin
+            store.store_session(request.session(self.class.session_store_type).session_id, data)
+          rescue => err
+            Merb.logger.warn!("Could not persist session to #{self.class.name}: #{err.message}")
+          end
+        end
+        if needs_new_cookie || Merb::SessionMixin.needs_new_cookie?
+          request.set_session_id_cookie(self.session_id)
+        end
+      end
+    end
+    
+    # Regenerate the session ID.
+    # 
+    # :api: private
+    def regenerate
+      store.delete_session(self.session_id)
+      self.session_id = Merb::SessionMixin.rand_uuid
+      store.store_session(self.session_id, self)
+    end
+    
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/session.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,272 @@
+require 'merb-core/dispatch/session/container'
+require 'merb-core/dispatch/session/store_container'
+
+module Merb
+  class Config
+    # Returns stores list constructed from
+    # configured session stores (:session_stores config option)
+    # or default one (:session_store config option).
+    # 
+    # :api: private
+    def self.session_stores
+      @session_stores ||= begin
+        config_stores = Array(
+          Merb::Config[:session_stores] || Merb::Config[:session_store]
+        )
+        config_stores.map { |name| name.to_sym }
+      end
+    end
+  end # Config
+  
+  # The Merb::Session module gets mixed into Merb::SessionContainer to allow
+  # app-level functionality (usually found in ./merb/session/session.rb) for
+  # session.
+  #
+  # You can use this module to implement additional methods to simplify
+  # building wizard-like application components,
+  # authentication frameworks, etc.
+  # 
+  # Session configuration options:
+  #
+  # :session_id_key           The key by which a session value/id is
+  #                           retrieved; defaults to _session_id
+  #
+  # :session_expiry           When to expire the session cookie;
+  #                           by defaults session expires when browser quits.
+  #
+  # :session_secret_key       A secret string which is used to sign/validate
+  #                           session data; min. 16 chars
+  #
+  # :default_cookie_domain    The default domain to write cookies for.
+  module Session    
+  end
+  
+  # This is mixed into Merb::Controller on framework boot.
+  module SessionMixin
+    # Raised when no suitable session store has been setup.
+    class NoSessionContainer < StandardError; end
+    
+    # Raised when storing more data than the available space reserved.
+    class SessionOverflow < StandardError; end
+    
+    # :api: private
+    def self.included(base)
+      # Register a callback to finalize sessions - needs to run before the cookie
+      # callback extracts Set-Cookie headers from request.cookies.
+      base._after_dispatch_callbacks.unshift lambda { |c| c.request.finalize_session }
+    end
+    
+    # ==== Parameters
+    # session_store<String>:: The type of session store to access.
+    #
+    # ==== Returns
+    # SessionContainer:: The session that was extracted from the request object.
+    #
+    # :api: public
+    def session(session_store = nil)
+      request.session(session_store)
+    end
+    
+    # Module methods
+    
+    # ==== Returns
+    # String:: A random 32 character string for use as a unique session ID.
+    #
+    # :api: private
+    def rand_uuid
+      values = [
+        rand(0x0010000),
+        rand(0x0010000),
+        rand(0x0010000),
+        rand(0x0010000),
+        rand(0x0010000),
+        rand(0x1000000),
+        rand(0x1000000),
+      ]
+      "%04x%04x%04x%04x%04x%06x%06x" % values
+    end
+    
+    # Marks this session as needing a new cookie.
+    # 
+    # :api: private
+    def needs_new_cookie!
+      @_new_cookie = true
+    end
+    
+    # Does session need new cookie?
+    # 
+    # ==== Returns
+    # Boolean:: true if a new cookie is needed, false otherwise.
+    # 
+    # :api: private
+    def needs_new_cookie?
+      @_new_cookie
+    end
+    
+    module_function :rand_uuid, :needs_new_cookie!, :needs_new_cookie?
+    
+    module RequestMixin
+      
+      # Adds class methods to Merb::Request object.
+      # Sets up repository of session store types.
+      # Sets the session ID key and expiry values.
+      #
+      # :api: private
+      def self.included(base)
+        base.extend ClassMethods
+        
+        # Keep track of all known session store types.
+        base.cattr_accessor :registered_session_types
+        base.registered_session_types = Dictionary.new
+        base.class_inheritable_accessor :_session_id_key, :_session_secret_key,
+                                        :_session_expiry
+        
+        base._session_id_key        = Merb::Config[:session_id_key] || '_session_id'
+        base._session_expiry        = Merb::Config[:session_expiry] || 0
+        base._session_secret_key    = Merb::Config[:session_secret_key]
+      end
+      
+      module ClassMethods
+        
+        # ==== Parameters
+        # name<~to_sym>:: Name of the session type to register.
+        # class_name<String>:: The corresponding class name.
+        #
+        # === Notres
+        # This is automatically called when Merb::SessionContainer is subclassed.
+        # 
+        # :api: private
+        def register_session_type(name, class_name)
+          self.registered_session_types[name.to_sym] = class_name
+        end
+        
+      end
+      
+      # The default session store type.
+      # 
+      # :api: private
+      def default_session_store
+        Merb::Config[:session_store] && Merb::Config[:session_store].to_sym
+      end
+      
+      # ==== Returns
+      # Hash:: All active session stores by type.
+      # 
+      # :api: private
+      def session_stores
+        @session_stores ||= {}
+      end
+      
+      # Returns session container. Merb is able to handle multiple session
+      # stores, hence a parameter to pick it.
+      #
+      # ==== Parameters
+      # session_store<String>:: The type of session store to access,
+      # defaults to default_session_store.
+      #
+      # === Notes
+      # If no suitable session store type is given, it defaults to
+      # cookie-based sessions.
+      # 
+      # ==== Returns
+      # SessionContainer::
+      #   an instance of a session store extending Merb::SessionContainer.
+      # 
+      # :api: public
+      def session(session_store = nil)
+        session_store ||= default_session_store
+        if class_name = self.class.registered_session_types[session_store]
+          session_stores[session_store] ||= Object.full_const_get(class_name).setup(self)
+        elsif fallback = self.class.registered_session_types.keys.first
+          Merb.logger.warn "Session store '#{session_store}' not found. Check your configuration in init file."
+          Merb.logger.warn "Falling back to #{fallback} session store."
+          session(fallback)
+        else
+          msg = "No session store set. Set it in init file like this: c[:session_store] = 'activerecord'"
+          Merb.logger.error!(msg)
+          raise NoSessionContainer, msg            
+        end
+      end
+      
+      # ==== Parameters
+      # new_session<Merb::SessionContainer>:: A session store instance.
+      #
+      # === Notes
+      # The session is assigned internally by its session_store_type key.
+      # 
+      # :api: private
+      def session=(new_session)
+        if self.session?(new_session.class.session_store_type)
+          original_session_id = self.session(new_session.class.session_store_type).session_id
+          if new_session.session_id != original_session_id
+            set_session_id_cookie(new_session.session_id)
+          end
+        end
+        session_stores[new_session.class.session_store_type] = new_session
+      end
+      
+      # Whether a session has been setup
+      # 
+      # ==== Returns
+      # Boolean:: true if the session is part of the session stores configured.
+      # 
+      # :api: private
+      def session?(session_store = nil)
+        (session_store ? [session_store] : session_stores).any? do |type, store|
+          store.is_a?(Merb::SessionContainer)
+        end
+      end
+      
+      # Teardown and/or persist the current sessions.
+      # 
+      # :api: private
+      def finalize_session
+        session_stores.each { |name, store| store.finalize(self) }
+      end
+      alias :finalize_sessions :finalize_session
+      
+      # Assign default cookie values
+      # 
+      # :api: private
+      def default_cookies
+        defaults = {}
+        if route && route.allow_fixation? && params.key?(_session_id_key)
+          Merb.logger.info("Fixated session id: #{_session_id_key}")
+          defaults[_session_id_key] = params[_session_id_key]
+        end
+        defaults
+      end
+
+      # Sets session cookie value.
+      #
+      # ==== Parameters
+      # value<String>:: The value of the session cookie; either the session id or the actual encoded data.
+      # options<Hash>:: Cookie options like domain, path and expired.
+      # 
+      # :api: private
+      def set_session_cookie_value(value, options = {})
+        defaults = {}
+        defaults[:expires] = Time.now + _session_expiry if _session_expiry > 0
+        cookies.set_cookie(_session_id_key, value, defaults.merge(options))
+      end
+      alias :set_session_id_cookie :set_session_cookie_value
+
+      # ==== Returns
+      # String:: The value of the session cookie; either the session id or the actual encoded data.
+      # 
+      # :api: private
+      def session_cookie_value
+        cookies[_session_id_key]
+      end
+      alias :session_id :session_cookie_value
+      
+      # Destroy the session cookie.
+      # 
+      # :api: private
+      def destroy_session_cookie
+        cookies.delete(_session_id_key)
+      end
+      
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/worker.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/worker.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/dispatch/worker.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,60 @@
+module Merb
+  class Worker
+    
+    # :api: private
+    attr_accessor :thread
+    
+    class << self
+      # ==== Returns
+      # Merb::Worker:: instance of a worker.
+      # 
+      # :api: private
+      def start
+        @worker ||= new
+        Merb.at_exit do 
+          if Merb::Dispatcher.work_queue.empty?
+            @worker.thread.abort_on_exception = false
+            @worker.thread.raise
+          else
+            @worker.thread.join
+          end
+        end
+        @worker
+      end      
+    end
+    
+    # Creates a new worker thread that loops over the work queue.
+    # 
+    # :api: private
+    def initialize
+      @thread = Thread.new do
+        loop do
+          process_queue
+          break if Merb::Dispatcher.work_queue.empty? && Merb.exiting
+        end
+      end
+    end
+    
+    # Processes tasks in the Merb::Dispatcher.work_queue.
+    # 
+    # :api: private
+    def process_queue
+      begin
+        while blk = Merb::Dispatcher.work_queue.pop
+           # we've been blocking on the queue waiting for an item sleeping.
+           # when someone pushes an item it wakes up this thread so we 
+           # immediately pass execution to the scheduler so we don't 
+           # accidentally run this block before the action finishes 
+           # it's own processing
+          Thread.pass
+          blk.call
+          break if Merb::Dispatcher.work_queue.empty? && Merb.exiting
+        end
+      rescue Exception => e
+        Merb.logger.warn! %Q!Worker Thread Crashed with Exception:\n#{Merb.exception(e)}\nRestarting Worker Thread!
+        retry
+      end
+    end
+    
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/gem_ext/erubis.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/gem_ext/erubis.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/gem_ext/erubis.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,83 @@
+require 'erubis'
+module Erubis
+  # This adds support for embedding the return value of a block call:
+  #   <%= foo do %>...<% end =%>
+  #
+  # :api: private
+  module Basic::Converter
+    def convert_input(src, input)
+      pat = @pattern
+      regexp = pat.nil? || pat == '<% %>' ? DEFAULT_REGEXP : pattern_regexp(pat)
+      pos = 0
+      is_bol = true     # is beginning of line
+      input.scan(regexp) do |indicator, code, tailch, rspace|
+        match = Regexp.last_match()
+        len  = match.begin(0) - pos
+        text = input[pos, len]
+        pos  = match.end(0)
+        ch   = indicator ? indicator[0] : nil
+        lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol)
+        is_bol = rspace ? true : false
+        add_text(src, text) if text && !text.empty?
+        ## * when '<%= %>', do nothing
+        ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
+        if ch == ?=              # <%= %>
+          rspace = nil if tailch && !tailch.empty?
+          add_text(src, lspace) if lspace
+          add_expr(src, code, indicator)
+          add_text(src, rspace) if rspace
+        elsif ch == ?\#          # <%# %>
+          n = code.count("\n") + (rspace ? 1 : 0)
+          if @trim && lspace && rspace
+            add_stmt(src, "\n" * n)
+          else
+            add_text(src, lspace) if lspace
+            add_stmt(src, "\n" * n)
+            add_text(src, rspace) if rspace
+          end
+        elsif ch == ?%           # <%% %>
+          s = "#{lspace}#{@prefix||='<%'}#{code}#{tailch}#{@postfix||='%>'}#{rspace}"
+          add_text(src, s)
+        else                     # <% %>
+          if @trim && lspace && rspace
+            if respond_to?(:add_stmt2)
+              add_stmt2(src, "#{lspace}#{code}#{rspace}", tailch)
+            else
+              add_stmt(src, "#{lspace}#{code}#{rspace}")
+            end
+          else
+            add_text(src, lspace) if lspace
+            if respond_to?(:add_stmt2)
+              add_stmt2(src, code, tailch)
+            else
+              add_stmt(src, code)
+            end
+            add_text(src, rspace) if rspace
+          end
+        end
+      end
+      #rest = $' || input                        # ruby1.8
+      rest = pos == 0 ? input : input[pos..-1]   # ruby1.9
+      add_text(src, rest)
+    end
+    
+  end
+  
+  class MEruby < Erubis::Eruby
+    include PercentLineEnhancer
+    include StringBufferEnhancer
+  end
+
+  # Loads a file, runs it through Erubis and parses it as YAML.
+  #
+  # ===== Parameters
+  # file<String>:: The name of the file to load.
+  # binding<Binding>::
+  #   The binding to use when evaluating the ERB tags. Defaults to the current
+  #   binding.
+  #
+  # :api: private
+  def self.load_yaml_file(file, binding = binding)
+    YAML::load(Erubis::MEruby.new(IO.read(File.expand_path(file))).result(binding))
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/logger.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/logger.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/logger.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,201 @@
+# Merb::Logger = Extlib::Logger
+
+class Merb::Logger < Extlib::Logger
+  # :api: public
+  def verbose!(message, level = :warn)
+    send("#{level}!", message) if Merb::Config[:verbose]
+  end
+
+  # :api: public
+  def verbose(message, level = :warn)
+    send(level, message) if Merb::Config[:verbose]
+  end
+end
+
+# require "time" # httpdate
+# ==== Public Merb Logger API
+#
+# To replace an existing logger with a new one:
+#  Merb::Logger.set_log(log{String, IO},level{Symbol, String})
+#
+# Available logging levels are
+#   Merb::Logger::{ Fatal, Error, Warn, Info, Debug }
+#
+# Logging via:
+#   Merb.logger.fatal(message<String>,&block)
+#   Merb.logger.error(message<String>,&block)
+#   Merb.logger.warn(message<String>,&block)
+#   Merb.logger.info(message<String>,&block)
+#   Merb.logger.debug(message<String>,&block)
+#
+# Logging with autoflush:
+#   Merb.logger.fatal!(message<String>,&block)
+#   Merb.logger.error!(message<String>,&block)
+#   Merb.logger.warn!(message<String>,&block)
+#   Merb.logger.info!(message<String>,&block)
+#   Merb.logger.debug!(message<String>,&block)
+#
+# Flush the buffer to
+#   Merb.logger.flush
+#
+# Remove the current log object
+#   Merb.logger.close
+#
+# ==== Private Merb Logger API
+#
+# To initialize the logger you create a new object, proxies to set_log.
+#   Merb::Logger.new(log{String, IO},level{Symbol, String})
+module Merb
+
+  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 => 7,
+      :error => 6,
+      :warn  => 4,
+      :info  => 3,
+      :debug => 0
+    }) unless const_defined?(:Levels)
+
+    @@mutex = {}
+
+    public
+
+    # To initialize the logger you create a new object, proxies to set_log.
+    #
+    # ==== 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.
+    #
+    # ==== Parameters
+    # log<IO, String>:: Either an IO object or a name of a logfile.
+    # log_level<~to_sym>::
+    #   The log level from, e.g. :fatal or :info. Defaults to :error in the
+    #   production environment and :debug otherwise.
+    # delimiter<String>::
+    #   Delimiter to use between message sections. Defaults to " ~ ".
+    # auto_flush<Boolean>::
+    #   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
+      @log.sync                 = true
+      @mutex = (@@mutex[@log] ||= Mutex.new)
+    end
+
+    # Flush the entire buffer to the log object.
+    def flush
+      return unless @buffer.size > 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) && !@log.tty?
+      @log = nil
+    end
+
+    # 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
+    # string<String>:: The message to be logged. Defaults to nil.
+    #
+    # ==== Returns
+    # String:: The resulting message added to the log file.
+    def <<(string = nil)
+      message = ""
+      message << delimiter
+      message << string if string
+      message << "\n" unless message[-1] == ?\n
+      @buffer << message
+      flush if @auto_flush
+
+      message
+    end
+    alias :push :<<
+
+    # Generate the logging methods for Merb.logger for each log level.
+    Levels.each_pair do |name, number|
+      class_eval <<-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<String>:: The message to be logged. Defaults to nil.
+      #
+      # ==== Returns
+      # self:: The logger object for chaining.
+      def #{name}(message = nil)
+        if #{number} >= level
+          message = block_given? ? yield : message
+          self << message if #{number} >= level
+        end
+        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<String>:: The message to be logged. Defaults to nil.
+      #
+      # ==== Returns
+      # self:: The logger object for chaining.
+      def #{name}!(message = nil)
+        if #{number} >= level
+          message = block_given? ? yield : message
+          self << message if #{number} >= level
+          flush if #{number} >= level
+        end
+        self
+      end
+
+      # ==== Returns
+      # Boolean:: True if this level will be logged by this logger.
+      def #{name}?
+        #{number} >= level
+      end
+      LEVELMETHODS
+    end
+
+  end
+
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/plugins.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/plugins.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/plugins.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,80 @@
+module Merb
+
+  module Plugins
+
+    # Returns the configuration settings hash for plugins. This is prepopulated from
+    # Merb.root / "config/plugins.yml" if it is present.
+    #
+    # ==== Returns
+    # Hash::
+    #   The configuration loaded from Merb.root / "config/plugins.yml" or, if
+    #   the load fails, an empty hash whose default value is another Hash.
+    #
+    # :api: plugin
+    def self.config
+      @config ||= begin
+        # this is so you can do Merb.plugins.config[:helpers][:awesome] = "bar"
+        config_hash = Hash.new {|h,k| h[k] = {}}
+        file = Merb.root / "config" / "plugins.yml"
+
+        if File.exists?(file)
+          require 'yaml'
+          to_merge = YAML.load_file(file)
+        else
+          to_merge = {}
+        end
+        
+        config_hash.merge(to_merge)
+      end
+    end
+
+    # ==== Returns
+    # Array(String):: All Rakefile load paths Merb uses for plugins.
+    #
+    # :api: plugin
+    def self.rakefiles
+      Merb.rakefiles
+    end
+    
+    # ==== Returns
+    # Array(String):: All Generator load paths Merb uses for plugins.
+    #
+    # :api: plugin
+    def self.generators
+      Merb.generators
+    end
+
+    # ==== Parameters
+    # *rakefiles:: Rakefiles to add to the list of plugin Rakefiles.
+    #
+    # ==== Notes
+    #
+    # This is a recommended way to register your plugin's Raketasks
+    # in Merb.
+    #
+    # ==== Examples
+    # From merb_sequel plugin:
+    #
+    # if defined(Merb::Plugins)
+    #   Merb::Plugins.add_rakefiles "merb_sequel" / "merbtasks"
+    # end
+    #
+    # :api: plugin
+    def self.add_rakefiles(*rakefiles)
+      Merb.add_rakefiles(*rakefiles)
+    end
+    
+    # ==== Parameters
+    # *generators:: Generator paths to add to the list of plugin generators.
+    #
+    # ==== Notes
+    #
+    # This is the recommended way to register your plugin's generators
+    # in Merb.
+    #
+    # :api: plugin
+    def self.add_generators(*generators)
+      Merb.add_generators(*generators)
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/abstract.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/abstract.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/abstract.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,336 @@
+module Merb
+  module System
+    class PortablePoller
+      def initialize(pid)
+        @pid = pid
+      end
+      # Memory usage in kilobytes (resident set size)
+      def memory
+        ps_int('rss')
+      end
+      
+      # Percentage memory usage
+      def percent_memory
+        ps_float('%mem')
+      end
+      
+      # Percentage CPU usage
+      def percent_cpu
+        ps_float('%cpu')
+      end
+      
+      private
+      
+      def ps_int(keyword)
+        `ps -o #{keyword}= -p #{@pid}`.to_i
+      end
+      
+      def ps_float(keyword)
+        `ps -o #{keyword}= -p #{@pid}`.to_f
+      end
+      
+      def ps_string(keyword)
+        `ps -o #{keyword}= -p #{@pid}`.strip
+      end
+      
+      def time_string_to_seconds(text)
+        _, minutes, seconds, useconds = *text.match(/(\d+):(\d{2}).(\d{2})/)
+        (minutes.to_i * 60) + seconds.to_i
+      end
+    end
+  end
+end
+
+module Merb
+  module Rack
+    class AbstractAdapter
+
+      # This method is designed to be overridden in a rack adapter.  It 
+      # will be called to start a server created with the new_server method.
+      # This is called from the AbstractAdapter start method.
+      #
+      # :api: plugin
+      # @overridable
+      def self.start_server
+        raise NotImplemented
+      end
+      
+      # This method is designed to be overridden in a rack adapter.  It will
+      # be called to create a new instance of the server for the adapter to 
+      # start.  The adapter should attempt to bind to a port at this point. 
+      # This is called from the AbstractAdapter start method.
+      #
+      # ==== Parameters
+      # port<Integer>:: The port the server should listen on
+      #
+      # :api: plugin
+      # @overridable
+      def self.new_server(port)
+        raise NotImplemented
+      end
+            
+      # This method is designed to be overridden in a rack adapter.  It will
+      # be called to stop the adapter server.  
+      #
+      # ==== Parameters
+      # status<Integer>:: The exit status the adapter should exit with. 
+      #
+      # ==== Returns
+      # Boolean:: True if the server was properly stopped.  
+      #
+      # :api: plugin
+      # @overridable
+      def self.stop(status)
+        raise NotImplemented
+      end
+
+      # Spawn a new worker process at a port.
+      #
+      # ==== Parameters
+      # port<Integer>:: The port to start the worker process on. 
+      #
+      # :api: private
+      def self.spawn_worker(port)
+        worker_pid = Kernel.fork
+        start_at_port(port, @opts) unless worker_pid
+
+        # If we have a worker_pid, we're in the parent.
+        throw(:new_worker) unless worker_pid
+
+        @pids[port] = worker_pid
+        $WORKERS = @pids.values
+      end
+
+      # The main start method for bootloaders that support forking.
+      # This method launches the adapters which inherit using the 
+      # new_server and start_server methods.  This method should not
+      # be overridden in adapters which want to fork.  
+      #
+      # ==== Parameters
+      # opts<Hash>:: A hash of options
+      #   socket: the socket to bind to
+      #   port: the port to bind to
+      #   cluster: the number 
+      #
+      # :api: private
+      def self.start(opts={})
+        @opts = opts
+        $WORKERS ||= []
+        parent = nil
+
+        @pids = {}
+        port = (opts[:socket] || opts[:port]).to_i
+        max_port = Merb::Config[:cluster] ? Merb::Config[:cluster] - 1 : 0
+
+        # If we only have a single merb, just start it up and dispense with
+        # the spawner/worker setup.
+        if max_port == 0
+          start_at_port(port)
+          return
+        end
+
+        $0 = process_title(:spawner, port)
+
+        # For each port, spawn a new worker. The parent will continue in
+        # the loop, while the worker will throw :new_worker and be booted
+        # out of the loop.
+        catch(:new_worker) do
+          0.upto(max_port) do |i|
+            parent = spawn_worker(port + i)
+          end
+        end
+
+        # If we're in a worker, we're done. Otherwise, we've completed
+        # setting up workers and now need to watch them.
+        return unless parent
+
+        # For each worker, set up a thread in the spawner to watch it
+        0.upto(max_port) do |i|
+          Thread.new do
+            catch(:new_worker) do
+              loop do
+                pid, status = @pids[port + i], nil
+                poller = Merb::System::PortablePoller.new(pid)
+                begin
+                  tick = 1
+                  loop do                    
+                    # Watch for the pid to exit.
+                    _, status = Process.wait2(pid, Process::WNOHANG)
+                    break if status
+                    
+                    if (tick % 120 == 0) && Merb::Config[:max_memory] && poller.memory > Merb::Config[:max_memory]
+                      tick = 1
+                      Process.kill("INT", pid)
+                      if (Process.kill(0, pid) rescue false)
+                        sleep Merb::Config[:hang_time] || 5
+                        Process.kill(9, pid)
+                        Process.wait2(pid) if (Process.kill(0, pid) rescue false)
+                      end
+                      
+                      status = Struct.new(:exitstatus).new(nil)
+                      break
+                    end
+                    tick += 1
+                    sleep 0.25
+                  end
+
+                  # If the pid doesn't exist, we want to silently exit instead of
+                  # raising here.
+                rescue SystemCallError => e
+                ensure
+                  # If there was no worker with that PID, the status was non-0
+                  # (we send back a status of 128 when ABRT is called on a 
+                  # worker, and Merb.fatal! exits with a status of 1), or if
+                  # Merb is in the process of exiting, *then* don't respawn.
+                  # Note that processes killed with kill -9 will return no
+                  # exitstatus, and we respawn them.
+                  if !status || 
+                    (status.exitstatus && status.exitstatus != 0) || 
+                    Merb.exiting then
+                    Thread.exit
+                  end
+                end
+
+                # Otherwise, respawn the worker, and watch it again.
+                spawn_worker(port + i)
+              end
+            end
+          end
+        end
+
+        # The spawner process will make it here, and when it does, it should just 
+        # sleep so it can pick up ctrl-c if it's in console mode.
+        sleep
+
+      end
+
+      # Fork a server on the specified port and start the app.
+      #
+      # ==== Parameters
+      # port<Integer>:: The port to start the server on
+      # opts<Hash>:: The hash of options, defaults to the @opts 
+      #   instance variable.  
+      #
+      # :api: private
+      def self.start_at_port(port, opts = @opts)
+        at_exit do
+          Merb::Server.remove_pid(port)
+        end
+
+        Merb::Worker.start unless Merb.testing?
+
+        # If Merb is daemonized, trap INT. If it's not daemonized,
+        # we let the master process' ctrl-c control the cluster
+        # of workers.
+        if Merb::Config[:daemonize]
+          Merb.trap('INT') do
+            Merb.exiting = true
+            stop
+            Merb.logger.warn! "Exiting port #{port}\n"
+            exit_process
+          end
+          # If it was not fork_for_class_load, we already set up
+          # ctrl-c handlers in the master thread.
+        elsif Merb::Config[:fork_for_class_load]
+          if Merb::Config[:console_trap]
+            Merb::Server.add_irb_trap
+          end
+        end
+
+        # In daemonized mode or not, support HUPing the process to
+        # restart it.
+        Merb.trap('HUP') do
+          Merb.exiting = true
+          stop
+          Merb.logger.warn! "Exiting port #{port} on #{Process.pid}\n"
+          exit_process
+        end
+
+        # ABRTing the process will kill it, and it will not be respawned.
+        Merb.trap('ABRT') do
+          Merb.exiting = true
+          stopped = stop(128)
+          Merb.logger.warn! "Exiting port #{port}\n" if stopped
+          exit_process(128)
+        end
+
+        # Each worker gets its own `ps' name.
+        $0 = process_title(:worker, port)
+
+        # Store the PID for this worker
+        Merb::Server.store_pid(port)
+
+        Merb::Config[:log_delimiter] = "#{process_title(:worker, port)} ~ "
+
+        Merb.reset_logger!
+        Merb.logger.warn!("Starting #{self.name.split("::").last} at port #{port}")
+
+        # If we can't connect to the port, keep trying until we can. Print
+        # a warning about this once. Try every 0.25s.
+        printed_warning = false
+        loop do
+          begin
+            # Call the adapter's new_server method, which should attempt
+            # to bind to a port.
+            new_server(port)
+          rescue Errno::EADDRINUSE => e
+            if Merb::Config[:bind_fail_fatal]
+              Merb.fatal! "Could not bind to #{port}. It was already in use", e
+            end
+            
+            unless printed_warning
+              Merb.logger.warn! "Port #{port} is in use, " \
+                "Waiting for it to become available."
+              printed_warning = true
+            end
+
+            sleep 0.25
+            next
+          end
+          break
+        end
+
+        Merb.logger.warn! "Successfully bound to port #{port}"
+
+        Merb::Server.change_privilege
+
+        # Call the adapter's start_server method.
+        start_server
+      end
+
+      # Exit the process with the specified status.  
+      #
+      # ==== Parameters
+      # status<Integer>:: The exit code of the process.
+      # 
+      # :api: private
+      def self.exit_process(status = 0)
+        exit(status)
+      end
+
+      # Set the process title.
+      #
+      # ==== Parameters
+      # whoami<Symbol>:: Either :spawner for the master process or :worker for any of the worker
+      #   processes. 
+      # port<Integer>:: The base port that the app is running on. 
+      #
+      # :api: private
+      def self.process_title(whoami, port)
+        name = Merb::Config[:name]
+        app  = "merb#{" : #{name}" if (name && name != "merb")}"
+        max_port  = Merb::Config[:cluster] ? (Merb::Config[:cluster] - 1) : 0
+        numbers   = ((whoami != :worker) && (max_port > 0)) ? "#{port}..#{port + max_port}" : port
+        file      = Merb::Config[:socket_file] % port if Merb::Config[:socket_file]
+        
+        listening_on = if Merb::Config[:socket]
+          "socket#{'s' if max_port > 0 && whoami != :worker} #{numbers} "\
+          "#{file ? file : "#{Merb.log_path}/#{name}.#{port}.sock"}"
+        else
+          "port#{'s' if max_port > 0 && whoami != :worker} #{port}"
+        end
+        "#{app} : #{whoami} (#{listening_on})"
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/ebb.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/ebb.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/ebb.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,26 @@
+require 'ebb'
+module Merb
+  
+  module Rack
+
+    class Ebb < Merb::Rack::AbstractAdapter
+      # start an Ebb server on given host and port.
+      # :api: plugin
+      def self.new_server(port)
+        Merb::Dispatcher.use_mutex = false
+        opts = @opts.merge(:port => port)
+        @th = Thread.new { Thread.current[:server] = ::Ebb.start_server(opts[:app], opts) }
+      end
+      
+      # :api: plugin
+      def self.start_server
+        @th.join
+      end
+      
+      # :api: plugin
+      def self.stop(status = 0)
+        ::Ebb.stop_server
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/evented_mongrel.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/evented_mongrel.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/evented_mongrel.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,14 @@
+require 'swiftcore/evented_mongrel'
+require 'merb-core/rack/handler/mongrel'
+module Merb
+  module Rack
+
+    class EventedMongrel < Mongrel
+      # :api: plugin
+      def self.new_server(port)
+        Merb::Dispatcher.use_mutex = false
+        super
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/fcgi.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/fcgi.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/fcgi.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,19 @@
+module Merb
+  module Rack
+    
+    class FastCGI
+      # ==== Parameters
+      # opts<Hash>:: Options for FastCGI (see below).
+      #
+      # ==== Options (opts)
+      # :app<String>>:: The application name.
+      #
+      # :api: plugin
+      def self.start(opts={})
+        Merb.logger.warn!("Using FastCGI adapter")
+        Merb::Server.change_privilege
+        ::Rack::Handler::FastCGI.run(opts[:app], opts)
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/irb.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/irb.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/irb.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,174 @@
+module Merb
+  module Rack
+    class Console
+      # There are three possible ways to use this method.  First, if you have a named route, 
+      # you can specify the route as the first parameter as a symbol and any paramters in a 
+      # hash.  Second, you can generate the default route by just passing the params hash, 
+      # just passing the params hash.  Finally, you can use the anonymous parameters.  This 
+      # allows you to specify the parameters to a named route in the order they appear in the 
+      # router.  
+      #
+      # ==== Parameters(Named Route)
+      # name<Symbol>:: 
+      #   The name of the route. 
+      # args<Hash>:: 
+      #   Parameters for the route generation.
+      #
+      # ==== Parameters(Default Route)
+      # args<Hash>:: 
+      #   Parameters for the route generation.  This route will use the default route. 
+      #
+      # ==== Parameters(Anonymous Parameters)
+      # name<Symbol>::
+      #   The name of the route.  
+      # args<Array>:: 
+      #   An array of anonymous parameters to generate the route
+      #   with. These parameters are assigned to the route parameters
+      #   in the order that they are passed.
+      #
+      # ==== Returns
+      # String:: The generated URL.
+      #
+      # ==== Examples
+      # Named Route
+      #
+      # Merb::Router.prepare do
+      #   match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+      # end
+      #
+      # url(:articles, :title => "new_article")
+      #
+      # Default Route
+      #
+      # Merb::Router.prepare do
+      #   default_routes
+      # end
+      #
+      # url(:controller => "articles", :action => "new")
+      #
+      # Anonymous Paramters
+      #
+      # Merb::Router.prepare do
+      #   match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+      # end
+      #
+      # url(:articles, 2008, 10, "test_article")
+      #
+      # :api: public
+      def url(name, *args)
+        args << {}
+        Merb::Router.url(name, *args)
+      end
+
+      # Reloads classes using Merb::BootLoader::ReloadClasses.
+      # :api: public
+      def reload!
+        Merb::BootLoader::ReloadClasses.reload
+      end
+
+      # Prints all routes for the application.
+      # :api: public
+      def show_routes
+        seen = []
+        unless Merb::Router.named_routes.empty?
+          puts "==== Named routes"
+          Merb::Router.named_routes.each do |name,route|
+            # something weird happens when you combine sprintf and irb
+            puts "Helper     : #{name}"
+            meth = $1.upcase if route.conditions[:method].to_s =~ /(get|post|put|delete)/
+            puts "HTTP method: #{meth || 'GET'}"
+            puts "Route      : #{route}"
+            puts "Params     : #{route.params.inspect}"
+            puts
+            seen << route
+          end
+        end
+        puts "==== Anonymous routes"
+        (Merb::Router.routes - seen).each do |route|
+          meth = $1.upcase if route.conditions[:method].to_s =~ /(get|post|put|delete)/
+          puts "HTTP method: #{meth || 'GET'}"
+          puts "Route      : #{route}"
+          puts "Params     : #{route.params.inspect}"
+          puts
+        end
+        nil
+      end
+
+      # Starts a sandboxed session (delegates to any Merb::Orms::* modules).
+      #
+      # An ORM should implement Merb::Orms::MyOrm#open_sandbox! to support this.
+      # Usually this involves starting a transaction.
+      # :api: public
+      def open_sandbox!
+        puts "Loading #{Merb.environment} environment in sandbox (Merb #{Merb::VERSION})"
+        puts "Any modifications you make will be rolled back on exit"
+        orm_modules.each { |orm| orm.open_sandbox! if orm.respond_to?(:open_sandbox!) }
+      end
+
+      # Ends a sandboxed session (delegates to any Merb::Orms::* modules).
+      #
+      # An ORM should implement Merb::Orms::MyOrm#close_sandbox! to support this.
+      # Usually this involves rolling back a transaction.
+      # :api: public
+      def close_sandbox!
+        orm_modules.each { |orm| orm.close_sandbox! if orm.respond_to?(:close_sandbox!) }
+        puts "Modifications have been rolled back"
+      end
+
+      # Explictly show logger output during IRB session
+      # :api: public
+      def trace_log!
+        Merb.logger.auto_flush = true
+      end
+
+      private
+
+      # ==== Returns
+      # Array:: All Merb::Orms::* modules.
+      # :api: private
+      def orm_modules
+        if Merb.const_defined?('Orms')
+          Merb::Orms.constants.map { |c| Merb::Orms::const_get(c) }
+        else
+          []
+        end
+      end
+
+    end
+
+    class Irb
+      # ==== Parameters
+      # opts<Hash>:
+      #   Options for IRB. Currently this is not used by the IRB adapter.
+      #
+      # ==== Notes
+      # If the +.irbrc+ file exists, it will be loaded into the IRBRC
+      # environment variable.
+      #
+      # :api: plugin
+      def self.start(opts={})
+        m = Merb::Rack::Console.new
+        m.extend Merb::Test::RequestHelper
+        m.extend ::Webrat::Methods if defined?(::Webrat)
+        Object.send(:define_method, :merb) { m }
+        ARGV.clear # Avoid passing args to IRB
+        m.open_sandbox! if sandboxed?
+        require 'irb'
+        require 'irb/completion'
+        if File.exists? ".irbrc"
+          ENV['IRBRC'] = ".irbrc"
+        end
+        IRB.start
+        at_exit do merb.close_sandbox! if sandboxed? end
+        exit
+      end
+
+      private
+
+      # :api: private
+      def self.sandboxed?
+        Merb::Config[:sandbox]
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/mongrel.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/mongrel.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/mongrel.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,44 @@
+begin
+  require 'mongrel'
+rescue LoadError => e
+  Merb.fatal! "Mongrel is not installed, but you are trying to use it. " \
+              "You need to either install mongrel or a different Ruby web " \
+              "server, like thin."
+end
+
+require 'merb-core/rack/handler/mongrel'
+
+module Merb
+
+  module Rack
+
+    class Mongrel < Merb::Rack::AbstractAdapter
+
+      # :api: plugin
+      def self.stop(status = 0)
+        if @server
+          begin
+            @server.stop(true)
+          rescue Mongrel::TimeoutError
+            Merb.logger.fatal! "Your process took too long to shut " \
+              "down, so mongrel killed it."
+          end
+          true
+        end
+      end
+
+      # :api: plugin
+      def self.new_server(port)
+        @server = ::Mongrel::HttpServer.new(@opts[:host], port)
+      end
+      
+      # :api: plugin
+      def self.start_server
+        @server.register('/', ::Merb::Rack::Handler::Mongrel.new(@opts[:app]))
+        @server.run.join
+      end
+      
+    end
+    
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/runner.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/runner.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/runner.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,30 @@
+module Merb
+  
+  module Rack
+    
+    class Runner
+      # ==== Parameters
+      # opts<Hash>:: Options for the runner (see below).
+      #
+      # ==== Options (opts)
+      # :runner_code<String>:: The code to run.
+      #
+      # ==== Notes
+      # If opts[:runner_code] matches a filename, that file will be read and
+      # the contents executed. Otherwise the code will be executed directly.
+      #
+      # :api: plugin
+      def self.start(opts={})
+        Merb::Server.change_privilege
+        if opts[:runner_code]
+          if File.exists?(opts[:runner_code])
+            eval(File.read(opts[:runner_code]), TOPLEVEL_BINDING, __FILE__, __LINE__)
+          else
+            eval(opts[:runner_code], TOPLEVEL_BINDING, __FILE__, __LINE__)
+          end
+          exit
+        end  
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/swiftiplied_mongrel.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/swiftiplied_mongrel.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/swiftiplied_mongrel.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,15 @@
+require 'swiftcore/swiftiplied_mongrel'
+require 'merb-core/rack/handler/mongrel'
+module Merb
+  module Rack
+
+    class SwiftipliedMongrel < Mongrel
+      # :api: plugin
+      def self.new_server(port)
+        Merb::Dispatcher.use_mutex = false
+        super
+      end      
+    end
+    
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/thin.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/thin.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/thin.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,42 @@
+require "thin"
+
+module Merb
+
+  module Rack
+
+    class Thin < Merb::Rack::AbstractAdapter
+      # start a Thin server on given host and port.
+
+      # :api: plugin
+      def self.new_server(port)
+        Merb::Dispatcher.use_mutex = false
+        
+        if (@opts[:socket] || @opts[:socket_file])
+          socket = port.to_s
+          socket_file = @opts[:socket_file] || "#{Merb.log_path}/#{Merb::Config[:name]}.%s.sock"
+          socket_file = socket_file % port
+          Merb.logger.warn!("Using Thin adapter with socket file #{socket_file}.")
+          @server = ::Thin::Server.new(socket_file, @opts[:app], @opts)
+        else
+          Merb.logger.warn!("Using Thin adapter on host #{@opts[:host]} and port #{port}.")
+          @opts[:host] = "#{@opts[:host]}-#{port}" if @opts[:host].include?('/')
+          @server = ::Thin::Server.new(@opts[:host], port, @opts[:app], @opts)
+        end
+      end
+
+      # :api: plugin
+      def self.start_server
+        ::Thin::Logging.silent = true
+        @server.start
+      end
+      
+      # :api: plugin
+      def self.stop(status = 0)
+        if @server
+          @server.stop
+          true
+        end
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/thin_turbo.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/thin_turbo.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/thin_turbo.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,18 @@
+require "thin-turbo"
+
+module Merb
+
+  module Rack
+
+    class ThinTurbo < Thin
+      # start a Thin Turbo server on given host and port.
+
+      # :api: plugin
+      def self.new_server(port)
+        @opts.merge!(:backend => ::Thin::Backends::Turbo)
+        super
+      end
+
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/webrick.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/webrick.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter/webrick.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,46 @@
+require 'webrick'
+require 'webrick/utils'
+require 'rack/handler/webrick'
+module Merb
+  module Rack
+
+    class WEBrick < Merb::Rack::AbstractAdapter
+      
+      class << self
+        # :api: private
+        attr_accessor :server
+      end
+
+      # :api: plugin
+      def self.new_server(port)
+        options = {
+          :Port        => port,
+          :BindAddress => @opts[:host],
+          :Logger      => Merb.logger,
+          :AccessLog   => [
+            [Merb.logger, ::WEBrick::AccessLog::COMMON_LOG_FORMAT],
+            [Merb.logger, ::WEBrick::AccessLog::REFERER_LOG_FORMAT]
+          ]
+        }
+
+        sockets = ::WEBrick::Utils.create_listeners nil, port
+        @server = ::WEBrick::HTTPServer.new(options.merge(:DoNotListen => true))
+        @server.listeners.replace sockets
+      end
+
+      # :api: plugin
+      def self.start_server
+        @server.mount("/", ::Rack::Handler::WEBrick, @opts[:app])
+        @server.start
+        exit(@status)
+      end
+      
+      # :api: plugin
+      def self.stop(status = 0)
+        @status = status
+        @server.shutdown
+      end
+
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/adapter.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,52 @@
+module Merb
+  
+  module Rack
+    
+    class Adapter
+
+      class << self
+        # Get a rack adapter by id. 
+        # ==== Parameters
+        # id<String>:: The identifier of the Rack adapter class to retrieve.
+        #
+        # ==== Returns.
+        # Class:: The adapter class.
+        #
+        # :api: private
+        def get(id)
+          if @adapters[id.to_s]
+            Object.full_const_get(@adapters[id.to_s])
+          else
+            Merb.fatal! "The adapter #{id} did not exist"
+          end
+        end
+
+        # Registers a new Rack adapter.
+        #
+        # ==== Parameters
+        # ids<Array>:: Identifiers by which this adapter is recognized by.
+        # adapter_class<Class>:: The Rack adapter class.
+        #
+        # :api: plugin
+        def register(ids, adapter_class)
+          @adapters ||= Hash.new
+          ids.each { |id| @adapters[id] = "Merb::Rack::#{adapter_class}" }
+        end
+      end # class << self
+      
+    end # Adapter
+    
+    # Register some Rack adapters
+    Adapter.register %w{ebb},            :Ebb
+    Adapter.register %w{emongrel},       :EventedMongrel
+    Adapter.register %w{fastcgi fcgi},   :FastCGI
+    Adapter.register %w{irb},            :Irb
+    Adapter.register %w{mongrel},        :Mongrel  
+    Adapter.register %w{runner},         :Runner
+    Adapter.register %w{smongrel swift}, :SwiftipliedMongrel
+    Adapter.register %w{thin},           :Thin
+    Adapter.register %w{thin-turbo tt},  :ThinTurbo
+    Adapter.register %w{webrick},        :WEBrick
+    
+  end # Rack
+end # Merb

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/application.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/application.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/application.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,54 @@
+module Merb  
+  module Rack
+    class Application
+      
+      # The main rack application call method.  This is the entry point from rack (and the webserver) 
+      # to your application.  
+      #
+      # ==== Parameters
+      # env<Hash>:: A rack request of parameters.  
+      #
+      # ==== Returns
+      # <Array>:: A rack response of [status<Integer>, headers<Hash>, body<String, Stream>]
+      #
+      # :api: private
+      def call(env) 
+        begin
+          rack_response = ::Merb::Dispatcher.handle(Merb::Request.new(env))
+        rescue Object => e
+          return [500, {Merb::Const::CONTENT_TYPE => Merb::Const::TEXT_SLASH_HTML}, e.message + Merb::Const::BREAK_TAG + e.backtrace.join(Merb::Const::BREAK_TAG)]
+        end
+        Merb.logger.info Merb::Const::DOUBLE_NEWLINE
+        Merb.logger.flush
+
+        # unless controller.headers[Merb::Const::DATE]
+        #   require "time"
+        #   controller.headers[Merb::Const::DATE] = Time.now.rfc2822.to_s
+        # end
+        rack_response
+      end
+
+      # Determines whether this request is a "deferred_action", usually a long request. 
+      # Rack uses this method to detemine whether to use an evented request or a deferred 
+      # request in evented rack handlers.  
+      #
+      # ==== Parameters
+      # env<Hash>:: The rack request
+      #
+      # ==== Returns
+      # Boolean::
+      #   True if the request should be deferred.  
+      #
+      # :api: private
+      def deferred?(env)
+        path = env[Merb::Const::PATH_INFO] ? env[Merb::Const::PATH_INFO].chomp(Merb::Const::SLASH) : Merb::Const::EMPTY_STRING
+        if path =~ Merb.deferred_actions
+          Merb.logger.info! "Deferring Request: #{path}"
+          true
+        else
+          false
+        end        
+      end # deferred?(env)
+    end # Application
+  end # Rack
+end # Merb

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/handler/mongrel.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/handler/mongrel.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/handler/mongrel.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,103 @@
+require 'stringio'
+class Mongrel::HttpResponse
+  NO_CLOSE_STATUS_FORMAT = "HTTP/1.1 %d %s\r\n".freeze
+
+  # Sends the status to the client without closing the connection.
+  #
+  # ==== Parameters
+  # content_length<Fixnum>:: The length of the content. Defaults to body length.
+  def send_status_no_connection_close(content_length=@body.length)
+    unless @status_sent
+      write(NO_CLOSE_STATUS_FORMAT % [@status, Mongrel::HTTP_STATUS_CODES[@status]])
+      @status_sent = true
+    end
+  end
+end
+
+module Merb
+  module Rack
+    module Handler
+      class Mongrel < ::Mongrel::HttpHandler
+        # Runs the server and yields it to a block.
+        #
+        # ==== Parameters
+        # app<Merb::Rack::Application>:: The app that Mongrel should handle.
+        # options<Hash>:: Options to pass to Mongrel (see below).
+        #
+        # ==== Block parameters
+        # server<Mongrel::HttpServer>:: The server to run.
+        #
+        # ==== Options (options)
+        # :Host<String>::
+        #   The hostname on which the app should run. Defaults to "0.0.0.0"
+        # :Port<Fixnum>:: The port for the app. Defaults to 8080.
+        #
+        # :api: plugin
+        def self.run(app, options={})
+          @server = ::Mongrel::HttpServer.new(options[:Host] || '0.0.0.0',
+                                             options[:Port] || 8080)
+          @server.register('/', ::Merb::Rack::Handler::Mongrel.new(app))
+          yield @server  if block_given?
+          @server.run.join
+        end
+  
+        # :api: private
+        def self.stop(block = true)
+          @server.stop
+        end
+  
+        # ==== Parameters
+        # app<Merb::Rack::Application>:: The app that Mongrel should handle.
+        #
+        # :api: plugin
+        def initialize(app)
+          @app = app
+        end
+
+        # ==== Parameters
+        # request<Merb::Request>:: The HTTP request to handle.
+        # response<HTTPResponse>:: The response object to write response to.
+        #
+        # :api: plugin
+        def process(request, response)
+          env = {}.replace(request.params)
+          env.delete Merb::Const::HTTP_CONTENT_TYPE
+          env.delete Merb::Const::HTTP_CONTENT_LENGTH
+  
+          env[Merb::Const::SCRIPT_NAME] = Merb::Const::EMPTY_STRING if env[Merb::Const::SCRIPT_NAME] == Merb::Const::SLASH
+  
+          env.update({"rack.version" => [0,1],
+                       "rack.input" => request.body || StringIO.new(""),
+                       "rack.errors" => STDERR,
+  
+                       "rack.multithread" => true,
+                       "rack.multiprocess" => false, # ???
+                       "rack.run_once" => false,
+  
+                       "rack.url_scheme" => "http"
+                     })
+          env[Merb::Const::QUERY_STRING] ||= ""
+          env.delete Merb::Const::PATH_INFO  if env[Merb::Const::PATH_INFO] == Merb::Const::EMPTY_STRING
+  
+          status, headers, body = @app.call(env)
+  
+          begin
+            response.status = status.to_i
+            headers.each { |k, vs|
+              vs.each { |v|
+                response.header[k] = v
+              }
+            }
+            
+            body.each { |part|
+              response.body << part
+            }
+            response.finished
+          ensure
+            body.close  if body.respond_to? :close
+          end
+        end
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/helpers.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/helpers.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/helpers.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,33 @@
+module Merb
+  module Rack
+    module Helpers
+      
+      # A helper to build a rack response which implements a redirect.  The status will be set to 
+      # the passed in status if passed.  If you pass in permanent it will be a 301, permanent redirect,
+      # otherwise it defaults to a temporary 302 redirect.  
+      #
+      # ==== Parameters
+      # url<~to_s>:: The url to redirect to.
+      # options<Hash>:: A hash of options for the redirect
+      #   status: The status code to use for the redirect
+      #   permanent:  True if this is a permanent redirect (301)
+      #
+      # ==== Returns
+      # <Array>:: A rack response to redirect to the specified url.  
+      #
+      # :api: plugin
+      def self.redirect(url, options = {})
+        # Build the rack array
+        status   = options.delete(:status)
+        status ||= options[:permanent] ? 301 : 302
+        
+        Merb.logger.info("Dispatcher redirecting to: #{url} (#{status})")
+        Merb.logger.flush
+        
+        [status, { Merb::Const::LOCATION => url },
+         Merb::Rack::StreamWrapper.new("<html><body>You are being <a href=\"#{url}\">redirected</a>.</body></html>")]
+      end
+      
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/conditional_get.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/conditional_get.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/conditional_get.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,32 @@
+module Merb
+  module Rack
+
+    class ConditionalGet < Merb::Rack::Middleware
+
+      # :api: plugin
+      def call(env)
+        status, headers, body = @app.call(env)
+
+        if document_not_modified?(env, headers)
+          status = 304
+          body = Merb::Const::EMPTY_STRING
+          # set Date header using RFC1123 date format as specified by HTTP
+          # RFC2616 section 3.3.1.
+        end
+        
+        [status, headers, body]
+      end
+    
+    private
+      # :api: private
+      def document_not_modified?(env, headers)
+        if etag = headers[Merb::Const::ETAG]
+          etag == env[Merb::Const::HTTP_IF_NONE_MATCH]
+        elsif last_modified = headers[Merb::Const::LAST_MODIFIED]
+          last_modified == env[Merb::Const::HTTP_IF_MODIFIED_SINCE]
+        end
+      end
+    end
+    
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/content_length.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/content_length.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/content_length.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,20 @@
+module Merb
+  module Rack
+
+    class ContentLength < Merb::Rack::Middleware
+
+      # :api: plugin
+      def call(env)
+        status, headers, body = @app.call(env)
+
+        # to_s is because Rack spec expects header
+        # values to be iterable and yield strings
+        header = 'Content-Length'.freeze
+        headers[header] = body.size.to_s unless headers.has_key?(header)
+
+        [status, headers, body]
+      end
+    end
+    
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/path_prefix.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/path_prefix.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/path_prefix.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,35 @@
+module Merb
+  module Rack
+    class PathPrefix < Merb::Rack::Middleware
+
+      # :api: private
+      def initialize(app, path_prefix = nil)
+        super(app)
+        @path_prefix = /^#{Regexp.escape(path_prefix)}/
+      end
+      
+      # :api: plugin
+      def deferred?(env)
+        strip_path_prefix(env) 
+        @app.deferred?(env)
+      end
+      
+      # :api: plugin
+      def call(env)
+        strip_path_prefix(env) 
+        @app.call(env)
+      end
+
+      # :api: private
+      def strip_path_prefix(env)
+        ['PATH_INFO', 'REQUEST_URI'].each do |path_key|
+          if env[path_key] =~ @path_prefix
+            env[path_key].sub!(@path_prefix, Merb::Const::EMPTY_STRING)
+            env[path_key] = Merb::Const::SLASH if env[path_key].empty?
+          end
+        end
+      end
+      
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/profiler.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/profiler.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/profiler.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,55 @@
+begin
+  require "ruby-prof"
+rescue LoadError => e
+  Merb.fatal! "You need ruby-prof installed to use the profiler middleware", e
+end
+
+module Merb
+  module Rack
+    class Profiler < Merb::Rack::Middleware
+
+      # :api: private
+      def initialize(app, types = [RubyProf::ALLOCATIONS, RubyProf::PROCESS_TIME])
+        super(app)
+        @types = types
+      end
+
+      # :api: plugin
+      def call(env)
+        measure_names = { RubyProf::ALLOCATIONS => 'allocations', 
+          RubyProf::PROCESS_TIME => 'time', RubyProf::MEMORY => "memory" }
+
+        ret = nil
+
+        GC.disable
+        @types.each do |type|
+          next if type.nil?
+          
+          if GC.respond_to?(:enable_stats)
+            GC.enable_stats || GC.clear_stats
+          end
+
+          RubyProf.measure_mode = type
+          RubyProf.start
+          100.times do
+            ret = super
+          end
+          result = RubyProf.stop
+          printer = RubyProf::CallTreePrinter.new(result)
+          path = "merb_profile_results" / env["PATH_INFO"]
+          FileUtils.mkdir_p(path)
+          printer.print(
+            File.open(
+              "#{path}/callgrind.out.#{measure_names[RubyProf::measure_mode]}",     
+              'w'))
+
+          GC.disable_stats if GC.respond_to?(:disable_stats)
+        end
+        GC.enable
+        ret
+      end
+
+      
+    end
+  end
+end
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/static.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/static.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/static.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,55 @@
+module Merb
+  module Rack
+    class Static < Merb::Rack::Middleware
+
+      # :api: private
+      def initialize(app,directory)
+        super(app)
+        @static_server = ::Rack::File.new(directory)
+      end
+      
+      # :api: plugin
+      def call(env)        
+        path = if env[Merb::Const::PATH_INFO]
+                 env[Merb::Const::PATH_INFO].chomp(Merb::Const::SLASH)
+               else
+                 Merb::Const::EMPTY_STRING
+               end
+        cached_path = (path.empty? ? 'index' : path) + '.html'
+        
+        if file_exist?(path) && env[Merb::Const::REQUEST_METHOD] =~ /GET|HEAD/ # Serve the file if it's there and the request method is GET or HEAD
+          serve_static(env)
+        elsif file_exist?(cached_path) && env[Merb::Const::REQUEST_METHOD] =~ /GET|HEAD/ # Serve the page cache if it's there and the request method is GET or HEAD
+          env[Merb::Const::PATH_INFO] = cached_path
+          serve_static(env)
+        elsif path =~ /favicon\.ico/
+          return [404, { Merb::Const::CONTENT_TYPE => Merb::Const::TEXT_SLASH_HTML }, "404 Not Found."]
+        else
+          @app.call(env)
+        end
+      end
+      
+        # ==== Parameters
+        # path<String>:: The path to the file relative to the server root.
+        #
+        # ==== Returns
+        # Boolean:: True if file exists under the server root and is readable.
+        #
+        # :api: private
+        def file_exist?(path)
+          full_path = ::File.join(@static_server.root, ::Merb::Parse.unescape(path))
+          ::File.file?(full_path) && ::File.readable?(full_path)
+        end
+
+        # ==== Parameters
+        # env<Hash>:: Environment variables to pass on to the server.
+        #
+        # :api: private
+        def serve_static(env)
+          env[Merb::Const::PATH_INFO] = ::Merb::Parse.unescape(env[Merb::Const::PATH_INFO])
+          @static_server.call(env)
+        end
+      
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/tracer.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/tracer.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware/tracer.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,21 @@
+module Merb
+  module Rack
+    class Tracer < Merb::Rack::Middleware
+
+      # :api: plugin
+      def call(env)
+
+        Merb.logger.debug!("Rack environment:\n" + env.inspect + "\n\n")
+
+        status, headers, body = @app.call(env)
+
+        Merb.logger.debug!("Status: #{status.inspect}")
+        Merb.logger.debug!("Headers: #{headers.inspect}")
+        Merb.logger.debug!("Body: #{body.inspect}")
+
+        [status, headers, body]
+      end
+      
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/middleware.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,26 @@
+module Merb
+  module Rack
+    class Middleware
+      
+      # @overridable
+      # :api: plugin
+      def initialize(app)
+        @app = app
+      end
+
+      # @overridable
+      # :api: plugin
+      def deferred?(env)
+        @app.deferred?(env) if @app.respond_to?(:deferred?)
+      end
+  
+      # @overridable
+      # :api: plugin  
+      def call(env)
+        @app.call(env)
+      end
+      
+    end
+  end
+end
+

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/stream_wrapper.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/stream_wrapper.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack/stream_wrapper.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,46 @@
+module Merb
+  module Rack
+
+    class StreamWrapper
+      # :api: private
+      def initialize(body)
+         @body = body
+      end
+      
+      # :api: private
+      def each(&callback)
+        if Proc === @body
+          @writer = lambda { |x| callback.call(x) }
+          @body.call(self)
+        elsif @body.is_a?(String)
+          @body.each_line(&callback)
+        else
+          @body.each(&callback)
+        end
+      end
+      
+      # :api: private
+      def write(str)
+        @writer.call str.to_s
+        str
+      end
+      
+      # :api: private
+      def to_s
+        @body.to_s
+      end
+            
+      # :api: private
+      def ==(other)
+        @body == other
+      end
+
+      # :api: private
+      def method_missing(sym, *args, &blk)
+        @body.send(sym, *args, &blk)
+      end
+       
+    end   
+  
+  end
+end  

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/rack.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,27 @@
+require 'rack'
+module Merb
+  module Rack
+    autoload :Application,         'merb-core/rack/application'
+    autoload :Adapter,             'merb-core/rack/adapter'
+    autoload :AbstractAdapter,     'merb-core/rack/adapter/abstract'
+    autoload :Ebb,                 'merb-core/rack/adapter/ebb'
+    autoload :EventedMongrel,      'merb-core/rack/adapter/evented_mongrel'    
+    autoload :FastCGI,             'merb-core/rack/adapter/fcgi'
+    autoload :Irb,                 'merb-core/rack/adapter/irb'
+    autoload :Middleware,          'merb-core/rack/middleware'
+    autoload :Mongrel,             'merb-core/rack/adapter/mongrel'
+    autoload :Runner,              'merb-core/rack/adapter/runner'    
+    autoload :SwiftipliedMongrel,  'merb-core/rack/adapter/swiftiplied_mongrel'
+    autoload :Thin,                'merb-core/rack/adapter/thin'
+    autoload :ThinTurbo,           'merb-core/rack/adapter/thin_turbo'
+    autoload :WEBrick,             'merb-core/rack/adapter/webrick'
+    autoload :PathPrefix,          'merb-core/rack/middleware/path_prefix'
+    autoload :Static,              'merb-core/rack/middleware/static'
+    autoload :Profiler,            'merb-core/rack/middleware/profiler'
+    autoload :Tracer,              'merb-core/rack/middleware/tracer'
+    autoload :ContentLength,       'merb-core/rack/middleware/content_length'
+    autoload :ConditionalGet,      'merb-core/rack/middleware/conditional_get'
+    autoload :StreamWrapper,       'merb-core/rack/stream_wrapper'
+    autoload :Helpers,             'merb-core/rack/helpers'
+  end # Rack
+end # Merb

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/server.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/server.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/server.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,387 @@
+require 'etc'
+
+module Merb
+
+  # Server encapsulates the management of Merb daemons.
+  class Server
+    class << self
+
+      # Start a Merb server, in either foreground, daemonized or cluster mode.
+      #
+      # ==== Parameters
+      # port<~to_i>::
+      #   The port to which the first server instance should bind to.
+      #   Subsequent server instances bind to the immediately following ports.
+      # cluster<~to_i>::
+      #   Number of servers to run in a cluster.
+      #
+      # ==== Alternatives
+      # If cluster is left out, then one process will be started. This process
+      # will be daemonized if Merb::Config[:daemonize] is true.
+      #
+      # :api: private
+      def start(port, cluster=nil)
+
+        @port = port
+        @cluster = cluster
+
+        if Merb::Config[:daemonize]
+          pidfile = pid_file(port)
+          pid = File.read(pidfile).chomp.to_i if File.exist?(pidfile)
+
+          unless alive?(@port)
+            remove_pid_file(@port)
+            Merb.logger.warn! "Daemonizing..." if Merb::Config[:verbose]
+            daemonize(@port)
+          else
+            Merb.fatal! "Merb is already running on port #{port}.\n" \
+              "\e[0m   \e[1;31;47mpid file: \e[34;47m#{pidfile}" \
+              "\e[1;31;47m, process id is \e[34;47m#{pid}."
+          end
+        else
+          bootup
+        end
+      end
+
+      # ==== Parameters
+      # port<~to_s>:: The port to check for Merb instances on.
+      #
+      # ==== Returns
+      # Boolean::
+      #   True if Merb is running on the specified port.
+      #
+      # :api: private
+      def alive?(port)
+        pidfile = pid_file(port)
+        pid     = pid_in_file(pidfile)
+        Process.kill(0, pid)
+        true
+      rescue Errno::ESRCH, Errno::ENOENT
+        false
+      rescue Errno::EACCES => e
+        Merb.fatal!("You don't have access to the PID file at #{pidfile}: #{e.message}")
+      end
+
+      # :api: private
+      def pid_in_file(pidfile)
+        File.read(pidfile).chomp.to_i
+      end
+
+      # ==== Parameters
+      # port<~to_s>:: The port of the Merb process to kill.
+      # sig<~to_s>:: The signal to send to the process, the default is 9 - SIGKILL.
+      #
+      # No    Name         Default Action       Description
+      # 1     SIGHUP       terminate process    terminal line hangup
+      # 2     SIGINT       terminate process    interrupt program
+      # 3     SIGQUIT      create core image    quit program
+      # 4     SIGILL       create core image    illegal instruction
+      # 9     SIGKILL      terminate process    kill program
+      # 15    SIGTERM      terminate process    software termination signal
+      # 30    SIGUSR1      terminate process    User defined signal 1
+      # 31    SIGUSR2      terminate process    User defined signal 2
+      #
+      # ==== Alternatives
+      # If you pass "all" as the port, the signal will be sent to all Merb processes.
+      #
+      # :api: private
+      def kill(port, sig = "INT")
+        if sig.is_a?(Integer)
+          sig = Signal.list.invert[sig]
+        end
+        
+        Merb::BootLoader::BuildFramework.run
+
+        # If we kill the master, then the workers should be reaped also.
+        if %w(main master all).include?(port)
+          # If a graceful exit is requested then send INT to the master process.
+          #
+          # Otherwise read pids from pid files and try to kill each process in turn.
+          kill_pid(sig, pid_file("main")) if sig == "INT"
+        else
+          kill_pid(sig, pid_file(port))
+        end
+      end
+
+      # Sends the provided signal to the process pointed at by the provided pid file.
+      # :api: private
+      def kill_pid(sig, file)
+        begin
+          pid = pid_in_file(file)
+          Merb.logger.fatal! "Killing pid #{pid} with #{sig}"
+          Process.kill(sig, pid)
+          FileUtils.rm(file) if File.exist?(file)
+        rescue Errno::EINVAL
+          Merb.logger.fatal! "Failed to kill PID #{pid} with #{sig}: '#{sig}' is an invalid " \
+            "or unsupported signal number."
+        rescue Errno::EPERM
+          Merb.logger.fatal! "Failed to kill PID #{pid} with #{sig}: Insufficient permissions."
+        rescue Errno::ESRCH
+          FileUtils.rm file
+          Merb.logger.fatal! "Failed to kill PID #{pid} with #{sig}: Process is " \
+            "deceased or zombie."
+        rescue Errno::EACCES => e
+          Merb.logger.fatal! e.message
+        rescue Errno::ENOENT => e
+          # This should not cause abnormal exit, which is why 
+          # we do not use Merb.fatal but instead just log with max level.
+          Merb.logger.fatal! "Could not find a PID file at #{file}. " \
+            "Most likely the process is no longer running and the pid file was not cleaned up."
+        rescue Exception => e
+          if !e.is_a?(SystemExit)
+            Merb.logger.fatal! "Failed to kill PID #{pid.inspect} with #{sig.inspect}: #{e.message}"
+          end
+        end
+      end
+
+      # ==== Parameters
+      # port<~to_s>:: The port of the Merb process to daemonize.
+      #
+      # :api: private
+      def daemonize(port)
+        Merb.logger.warn! "About to fork..." if Merb::Config[:verbose]
+        fork do
+          Process.setsid
+          exit if fork
+          Merb.logger.warn! "In #{Process.pid}" if Merb.logger
+          File.umask 0000
+          STDIN.reopen "/dev/null"
+          STDOUT.reopen "/dev/null", "a"
+          STDERR.reopen STDOUT
+          begin
+            Dir.chdir Merb::Config[:merb_root]
+          rescue Errno::EACCES => e
+            Merb.fatal! "You specified Merb root as #{Merb::Config[:merb_root]}, " \
+              "yet the current user does not have access to it. ", e
+          end
+          at_exit { remove_pid_file(port) }
+          Merb::Config[:port] = port
+          bootup
+        end
+      rescue NotImplementedError => e
+        Merb.fatal! "Daemonized mode is not supported on your platform. ", e
+      end
+
+      # Starts up Merb by running the bootloader and starting the adapter.
+      #
+      # :api: private
+      def bootup
+        Merb.trap("TERM") { shutdown }
+
+        Merb.logger.warn! "Running bootloaders..." if Merb::Config[:verbose]
+        BootLoader.run
+        Merb.logger.warn! "Starting Rack adapter..." if Merb::Config[:verbose]
+        Merb.adapter.start(Merb::Config.to_hash)
+      end
+
+      # Shut down Merb, reap any workers if necessary.
+      #
+      # :api: private
+      def shutdown(status = 0)
+        # reap_workers does exit but may not be called...
+        Merb::BootLoader::LoadClasses.reap_workers(status) if Merb::Config[:fork_for_class_load]
+        # which is why we exit explicitly here
+        exit(status)
+      end
+
+      # Change process user/group to those specified in Merb::Config.
+      #
+      # :api: private
+      def change_privilege
+        if Merb::Config[:user] && Merb::Config[:group]
+          Merb.logger.verbose! "About to change privilege to group " \
+            "#{Merb::Config[:group]} and user #{Merb::Config[:user]}"
+          _change_privilege(Merb::Config[:user], Merb::Config[:group])
+        elsif Merb::Config[:user]
+          Merb.logger.verbose! "About to change privilege to user " \
+            "#{Merb::Config[:user]}"
+          _change_privilege(Merb::Config[:user])
+        else
+          return true
+        end
+      end
+
+      # Removes a PID file used by the server from the filesystem.
+      # This uses :pid_file options from configuration when provided
+      # or merb.<port/socket>.pid in log directory by default.
+      #
+      # ==== Parameters
+      # port<~to_s>::
+      #   The port of the Merb process to whom the the PID file belongs to.
+      #
+      # ==== Alternatives
+      # If Merb::Config[:pid_file] has been specified, that will be used
+      # instead of the port/socket based PID file.
+      #
+      # :api: private
+      def remove_pid_file(port)
+        pidfile = pid_file(port)
+        if File.exist?(pidfile)
+          Merb.logger.warn! "Removing pid file #{pidfile} (port/socket: #{port})..."
+          FileUtils.rm(pidfile)
+        end
+      end
+
+      # Stores a PID file on the filesystem.
+      # This uses :pid_file options from configuration when provided
+      # or merb.<port>.pid in log directory by default.
+      #
+      # ==== Parameters
+      # port<~to_s>::
+      #   The port of the Merb process to whom the the PID file belongs to.
+      #
+      # ==== Alternatives
+      # If Merb::Config[:pid_file] has been specified, that will be used
+      # instead of the port/socket based PID file.
+      #
+      # :api: private
+      def store_pid(port)
+        store_details(port)
+      end
+
+      # Delete the pidfile for the specified port/socket.
+      #
+      # :api: private
+      def remove_pid(port)
+        FileUtils.rm(pid_file(port)) if File.file?(pid_file(port))
+      end
+
+      # Stores a PID file on the filesystem.
+      # This uses :pid_file options from configuration when provided
+      # or merb.<port/socket>.pid in log directory by default.
+      #
+      # ==== Parameters
+      # port<~to_s>::
+      #   The port of the Merb process to whom the the PID file belongs to.
+      #
+      # ==== Alternatives
+      # If Merb::Config[:pid_file] has been specified, that will be used
+      # instead of the port/socket based PID file.
+      #
+      # :api: private
+      def store_details(port = nil)
+        file = pid_file(port)
+        begin
+          FileUtils.mkdir_p(File.dirname(file))
+        rescue Errno::EACCES => e
+          Merb.fatal! "Failed to store Merb logs in #{File.dirname(file)}, " \
+            "permission denied. ", e
+        end
+        Merb.logger.warn! "Storing pid #{Process.pid} file to #{file}..." if Merb::Config[:verbose]
+        begin
+          File.open(file, 'w'){ |f| f.write(Process.pid.to_s) }
+        rescue Errno::EACCES => e
+          Merb.fatal! "Failed to access #{file}, permission denied.", e
+        end
+      end
+
+      # Gets the pid file for the specified port/socket.
+      #
+      # ==== Parameters
+      # port<~to_s>::
+      #   The port/socket of the Merb process to whom the the PID file belongs to.
+      #
+      # ==== Returns
+      # String::
+      #   Location of pid file for specified port. If clustered and pid_file option
+      #   is specified, it adds the port/socket value to the path.
+      #
+      # :api: private
+      def pid_file(port)
+        pidfile = Merb::Config[:pid_file] || (Merb.log_path / "merb.%s.pid")
+        pidfile % port
+      end
+
+      # Get a list of the pid files.
+      #
+      # ==== Returns
+      # Array::
+      #   List of pid file paths. If not running clustered, the array contains a single path.
+      #
+      # :api: private
+      def pid_files
+        if Merb::Config[:pid_file]
+          if Merb::Config[:cluster]
+            Dir[Merb::Config[:pid_file] % "*"]
+          else
+            [ Merb::Config[:pid_file] ]
+          end
+        else
+          Dir[Merb.log_path / "merb.*.pid"]
+        end
+       end
+
+      # Change privileges of the process to the specified user and group.
+      #
+      # ==== Parameters
+      # user<String>:: The user to change the process to.
+      # group<String>:: The group to change the process to.
+      #
+      # ==== Alternatives
+      # If group is left out, the user will be used as the group.
+      # 
+      # :api: private
+      def _change_privilege(user, group=user)
+        Merb.logger.warn! "Changing privileges to #{user}:#{group}"
+
+        uid, gid = Process.euid, Process.egid
+
+        begin
+          target_uid = Etc.getpwnam(user).uid
+        rescue ArgumentError => e
+          Merb.fatal!("Failed to change to user #{user}, does the user exist?", e)
+          return false
+        end
+
+        begin
+          target_gid = Etc.getgrnam(group).gid
+        rescue ArgumentError => e
+          Merb.fatal!("Failed to change to group #{group}, does the group exist?", e)
+          return false
+        end
+
+        if (uid != target_uid) || (gid != target_gid)
+          # Change process ownership
+          Process.initgroups(user, target_gid)
+          Process::GID.change_privilege(target_gid)
+          Process::UID.change_privilege(target_uid)
+        end
+        true
+      rescue Errno::EPERM => e
+        Merb.fatal! "Permission denied for changing user:group to #{user}:#{group}.", e
+        false
+      end
+      
+      # Add trap to enter IRB on SIGINT. Process exit if second SIGINT is received.
+      #
+      # :api: private
+      def add_irb_trap
+        Merb.trap("INT") do
+          if @interrupted
+            Merb.logger.warn! "Interrupt received a second time, exiting!\n"
+            exit
+          end
+
+          @interrupted = true
+          Merb.logger.warn! "Interrupt a second time to quit."
+          Kernel.sleep 1.5
+          ARGV.clear # Avoid passing args to IRB
+
+          if @irb.nil?
+            require "irb"
+            IRB.setup(nil)
+            @irb = IRB::Irb.new(nil)
+            IRB.conf[:MAIN_CONTEXT] = @irb.context
+          end
+
+          Merb.trap(:INT) { @irb.signal_handle }
+          catch(:IRB_EXIT) { @irb.eval_input }
+
+          Merb.logger.warn! "Exiting from IRB mode back into server mode."
+          @interrupted = false
+          add_irb_trap
+        end
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/audit.rake
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/audit.rake	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/audit.rake	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,68 @@
+namespace :audit do
+
+  desc "Print out the named and anonymous routes"
+  task :routes => :merb_env do
+    seen = []
+    unless Merb::Router.named_routes.empty?
+      puts "Named Routes"
+      Merb::Router.named_routes.each do |name,route|
+        puts "  #{name}: #{route}"
+        seen << route
+      end
+    end
+    puts "Anonymous Routes"
+    (Merb::Router.routes - seen).each do |route|
+      puts "  #{route}"
+    end
+    nil
+  end
+
+  desc "Print out all controllers"
+  task :controllers => :merb_env do
+    puts "\nControllers:\n\n"
+    abstract_controller_classes.each do |klass|
+      if klass.respond_to?(:subclasses_list)
+        puts "#{klass} < #{klass.superclass}"
+        subklasses = klass.subclasses_list.sort.map { |x| Object.full_const_get(x) }
+        unless subklasses.empty?
+          subklasses.each { |subklass| puts "- #{subklass}" }
+        else
+          puts "~ no subclasses"
+        end
+        puts
+      end
+    end
+  end
+  
+  desc "Print out controllers and their actions (use CONTROLLER=Foo,Bar to be selective)"
+  task :actions => :merb_env do
+    puts "\nControllers and their actions:\n\n"
+    filter_controllers = ENV['CONTROLLER'] ? ENV['CONTROLLER'].split(',') : nil
+    abstract_controllers = abstract_controller_classes
+    classes = Merb::AbstractController.subclasses_list.sort.map { |x| Object.full_const_get(x) }
+    classes = classes.select { |k| k.name.in?(filter_controllers) } if filter_controllers
+    classes.each do |subklass|
+      next if subklass.in?(abstract_controllers) || !subklass.respond_to?(:callable_actions)
+      puts "#{subklass} < #{subklass.superclass}"
+      unless subklass.callable_actions.empty?
+        subklass.callable_actions.sort.each do |action, null|
+          if subklass.respond_to?(:action_argument_list)
+            arguments, defaults = subklass.action_argument_list[action]
+            args = arguments.map { |name, value| value ? "#{name} = #{value.inspect}" : name.to_s }.join(', ')
+            puts args.empty? ? "- #{action}" : "- #{action}(#{args})"
+          else
+            puts "- #{action}"
+          end
+        end
+      else
+        puts "~ no callable actions"
+      end
+      puts
+    end    
+  end
+  
+  def abstract_controller_classes
+    ObjectSpace.classes.select { |x| x.superclass == Merb::AbstractController }.sort_by { |x| x.name }
+  end
+  
+end
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/gem_management.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/gem_management.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/gem_management.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,364 @@
+require 'rubygems'
+
+module ColorfulMessages
+  
+  # red
+  def error(*messages)
+    puts messages.map { |msg| "\033[1;31m#{msg}\033[0m" }
+  end
+  
+  # yellow
+  def warning(*messages)
+    puts messages.map { |msg| "\033[1;33m#{msg}\033[0m" }
+  end
+  
+  # green
+  def success(*messages)
+    puts messages.map { |msg| "\033[1;32m#{msg}\033[0m" }
+  end
+  
+  alias_method :message, :success
+  
+  # magenta
+  def note(*messages)
+    puts messages.map { |msg| "\033[1;35m#{msg}\033[0m" }
+  end
+  
+  # blue
+  def info(*messages)
+    puts messages.map { |msg| "\033[1;34m#{msg}\033[0m" }
+  end
+  
+end
+
+##############################################################################
+
+require 'rubygems/dependency_installer'
+require 'rubygems/uninstaller'
+require 'rubygems/dependency'
+
+module GemManagement
+  
+  include ColorfulMessages
+    
+  # Install a gem - looks remotely and local gem cache;
+  # won't process rdoc or ri options.
+  def install_gem(gem, options = {})
+    refresh = options.delete(:refresh) || []
+    from_cache = (options.key?(:cache) && options.delete(:cache))
+    if from_cache
+      install_gem_from_cache(gem, options)
+    else
+      version = options.delete(:version)
+      Gem.configuration.update_sources = false
+
+      # Limit source index to install dir
+      update_source_index(options[:install_dir]) if options[:install_dir]
+
+      installer = Gem::DependencyInstaller.new(options.merge(:user_install => false))
+      
+      # Force-refresh certain gems by excluding them from the current index
+      if !options[:ignore_dependencies] && refresh.respond_to?(:include?) && !refresh.empty?
+        source_index = installer.instance_variable_get(:@source_index)
+        source_index.gems.each do |name, spec| 
+          source_index.gems.delete(name) if refresh.include?(spec.name)
+        end
+      end
+      
+      exception = nil
+      begin
+        installer.install gem, version
+      rescue Gem::InstallError => e
+        exception = e
+      rescue Gem::GemNotFoundException => e
+        if from_cache && gem_file = find_gem_in_cache(gem, version)
+          puts "Located #{gem} in gem cache..."
+          installer.install gem_file
+        else
+          exception = e
+        end
+      rescue => e
+        exception = e
+      end
+      if installer.installed_gems.empty? && exception
+        error "Failed to install gem '#{gem} (#{version || 'any version'})' (#{exception.message})"
+      end
+      ensure_bin_wrapper_for_installed_gems(installer.installed_gems, options)
+      installer.installed_gems.each do |spec|
+        success "Successfully installed #{spec.full_name}"
+      end
+      return !installer.installed_gems.empty?
+    end
+  end
+
+  # Install a gem - looks in the system's gem cache instead of remotely;
+  # won't process rdoc or ri options.
+  def install_gem_from_cache(gem, options = {})
+    version = options.delete(:version)
+    Gem.configuration.update_sources = false
+    installer = Gem::DependencyInstaller.new(options.merge(:user_install => false))
+    exception = nil
+    begin
+      if gem_file = find_gem_in_cache(gem, version)
+        puts "Located #{gem} in gem cache..."
+        installer.install gem_file
+      else
+        raise Gem::InstallError, "Unknown gem #{gem}"
+      end
+    rescue Gem::InstallError => e
+      exception = e
+    end
+    if installer.installed_gems.empty? && exception
+      error "Failed to install gem '#{gem}' (#{e.message})"
+    end
+    ensure_bin_wrapper_for_installed_gems(installer.installed_gems, options)
+    installer.installed_gems.each do |spec|
+      success "Successfully installed #{spec.full_name}"
+    end
+  end
+
+  # Install a gem from source - builds and packages it first then installs.
+  # 
+  # Examples:
+  # install_gem_from_source(source_dir, :install_dir => ...)
+  # install_gem_from_source(source_dir, gem_name)
+  # install_gem_from_source(source_dir, :skip => [...])
+  def install_gem_from_source(source_dir, *args)
+    installed_gems = []
+    opts = args.last.is_a?(Hash) ? args.pop : {}
+    Dir.chdir(source_dir) do      
+      gem_name     = args[0] || File.basename(source_dir)
+      gem_pkg_dir  = File.join(source_dir, 'pkg')
+      gem_pkg_glob = File.join(gem_pkg_dir, "#{gem_name}-*.gem")
+      skip_gems    = opts.delete(:skip) || []
+
+      # Cleanup what's already there
+      clobber(source_dir)
+      FileUtils.mkdir_p(gem_pkg_dir) unless File.directory?(gem_pkg_dir)
+
+      # Recursively process all gem packages within the source dir
+      skip_gems << gem_name
+      packages = package_all(source_dir, skip_gems)
+      
+      if packages.length == 1
+        # The are no subpackages for the main package
+        refresh = [gem_name]
+      else
+        # Gather all packages into the top-level pkg directory
+        packages.each do |pkg|
+          FileUtils.copy_entry(pkg, File.join(gem_pkg_dir, File.basename(pkg)))
+        end
+        
+        # Finally package the main gem - without clobbering the already copied pkgs
+        package(source_dir, false)
+        
+        # Gather subgems to refresh during installation of the main gem
+        refresh = packages.map do |pkg|
+          File.basename(pkg, '.gem')[/^(.*?)-([\d\.]+)$/, 1] rescue nil
+        end.compact
+        
+        # Install subgems explicitly even if ignore_dependencies is set
+        if opts[:ignore_dependencies]
+          refresh.each do |name| 
+            gem_pkg = Dir[File.join(gem_pkg_dir, "#{name}-*.gem")][0]
+            install_pkg(gem_pkg, opts)
+          end
+        end
+      end
+      
+      ensure_bin_wrapper_for(opts[:install_dir], opts[:bin_dir], *installed_gems)
+      
+      # Finally install the main gem
+      if install_pkg(Dir[gem_pkg_glob][0], opts.merge(:refresh => refresh))
+        installed_gems = refresh
+      else
+        installed_gems = []
+      end
+    end
+    installed_gems
+  end
+  
+  def install_pkg(gem_pkg, opts = {})
+    if (gem_pkg && File.exists?(gem_pkg))
+      # Needs to be executed from the directory that contains all packages
+      Dir.chdir(File.dirname(gem_pkg)) { install_gem(gem_pkg, opts) }
+    else
+      false
+    end
+  end
+  
+  # Uninstall a gem.
+  def uninstall_gem(gem, options = {})
+    if options[:version] && !options[:version].is_a?(Gem::Requirement)
+      options[:version] = Gem::Requirement.new ["= #{options[:version]}"]
+    end
+    update_source_index(options[:install_dir]) if options[:install_dir]
+    Gem::Uninstaller.new(gem, options).uninstall rescue nil
+  end
+
+  def clobber(source_dir)
+    Dir.chdir(source_dir) do 
+      system "#{Gem.ruby} -S rake -s clobber" unless File.exists?('Thorfile')
+    end
+  end
+
+  def package(source_dir, clobber = true)
+    Dir.chdir(source_dir) do 
+      if File.exists?('Thorfile')
+        thor ":package"
+      elsif File.exists?('Rakefile')
+        rake "clobber" if clobber
+        rake "package"
+      end
+    end
+    Dir[File.join(source_dir, 'pkg/*.gem')]
+  end
+
+  def package_all(source_dir, skip = [], packages = [])
+    if Dir[File.join(source_dir, '{Rakefile,Thorfile}')][0]
+      name = File.basename(source_dir)
+      Dir[File.join(source_dir, '*', '{Rakefile,Thorfile}')].each do |taskfile|
+        package_all(File.dirname(taskfile), skip, packages)
+      end
+      packages.push(*package(source_dir)) unless skip.include?(name)
+    end
+    packages.uniq
+  end
+  
+  def rake(cmd)
+    cmd << " >/dev/null" if $SILENT && !Gem.win_platform?
+    system "#{Gem.ruby} -S #{which('rake')} -s #{cmd} >/dev/null"
+  end
+  
+  def thor(cmd)
+    cmd << " >/dev/null" if $SILENT && !Gem.win_platform?
+    system "#{Gem.ruby} -S #{which('thor')} #{cmd}"
+  end
+
+  # Use the local bin/* executables if available.
+  def which(executable)
+    if File.executable?(exec = File.join(Dir.pwd, 'bin', executable))
+      exec
+    else
+      executable
+    end
+  end
+  
+  # Partition gems into system, local and missing gems
+  def partition_dependencies(dependencies, gem_dir)
+    system_specs, local_specs, missing_deps = [], [], []
+    if gem_dir && File.directory?(gem_dir)
+      gem_dir = File.expand_path(gem_dir)
+      ::Gem.clear_paths; ::Gem.path.unshift(gem_dir)
+      ::Gem.source_index.refresh!
+      dependencies.each do |dep|
+        gemspecs = ::Gem.source_index.search(dep)
+        local = gemspecs.reverse.find { |s| s.loaded_from.index(gem_dir) == 0 }
+        if local
+          local_specs << local
+        elsif gemspecs.last
+          system_specs << gemspecs.last
+        else
+          missing_deps << dep
+        end
+      end
+      ::Gem.clear_paths
+    else
+      dependencies.each do |dep|
+        gemspecs = ::Gem.source_index.search(dep)
+        if gemspecs.last
+          system_specs << gemspecs.last
+        else
+          missing_deps << dep
+        end
+      end
+    end
+    [system_specs, local_specs, missing_deps]
+  end
+  
+  # Create a modified executable wrapper in the specified bin directory.
+  def ensure_bin_wrapper_for(gem_dir, bin_dir, *gems)
+    options = gems.last.is_a?(Hash) ? gems.last : {}
+    options[:no_minigems] ||= []
+    if bin_dir && File.directory?(bin_dir)
+      gems.each do |gem|
+        if gemspec_path = Dir[File.join(gem_dir, 'specifications', "#{gem}-*.gemspec")].last
+          spec = Gem::Specification.load(gemspec_path)
+          enable_minigems = !options[:no_minigems].include?(spec.name)
+          spec.executables.each do |exec|
+            executable = File.join(bin_dir, exec)
+            message "Writing executable wrapper #{executable}"
+            File.open(executable, 'w', 0755) do |f|
+              f.write(executable_wrapper(spec, exec, enable_minigems))
+            end
+          end
+        end
+      end
+    end
+  end
+  
+  def ensure_bin_wrapper_for_installed_gems(gemspecs, options)
+    if options[:install_dir] && options[:bin_dir]
+      gems = gemspecs.map { |spec| spec.name }
+      ensure_bin_wrapper_for(options[:install_dir], options[:bin_dir], *gems)
+    end
+  end
+  
+  private
+
+  def executable_wrapper(spec, bin_file_name, minigems = true)
+    requirements = ['minigems', 'rubygems']
+    requirements.reverse! unless minigems
+    try_req, then_req = requirements
+    <<-TEXT
+#!/usr/bin/env ruby
+#
+# This file was generated by Merb's GemManagement
+#
+# The application '#{spec.name}' is installed as part of a gem, and
+# this file is here to facilitate running it.
+
+begin 
+  require '#{try_req}'
+rescue LoadError 
+  require '#{then_req}'
+end
+
+# use gems dir if ../gems exists - eg. only for ./bin/#{bin_file_name}
+if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems'))
+  $BUNDLE = true; Gem.clear_paths; Gem.path.replace([gems_dir])
+  ENV["PATH"] = "\#{File.dirname(__FILE__)}:\#{gems_dir}/bin:\#{ENV["PATH"]}"
+  if (local_gem = Dir[File.join(gems_dir, "specifications", "#{spec.name}-*.gemspec")].last)
+    version = File.basename(local_gem)[/-([\\.\\d]+)\\.gemspec$/, 1]
+  end
+end
+
+version ||= "#{Gem::Requirement.default}"
+
+if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
+  version = $1
+  ARGV.shift
+end
+
+gem '#{spec.name}', version
+load '#{bin_file_name}'
+TEXT
+  end
+
+  def find_gem_in_cache(gem, version)
+    spec = if version
+      version = Gem::Requirement.new ["= #{version}"] unless version.is_a?(Gem::Requirement)
+      Gem.source_index.find_name(gem, version).first
+    else
+      Gem.source_index.find_name(gem).sort_by { |g| g.version }.last
+    end
+    if spec && File.exists?(gem_file = "#{spec.installation_path}/cache/#{spec.full_name}.gem")
+      gem_file
+    end
+  end
+
+  def update_source_index(dir)
+    Gem.source_index.load_gems_in(File.join(dir, 'specifications'))
+  end
+    
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/merb.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/merb.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/merb.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,4 @@
+local_gem_path = Gem.path if $BUNDLE
+require 'merb-core/tasks/merb_rake_helper'
+Gem.path.replace(local_gem_path) if local_gem_path
+Dir[File.dirname(__FILE__) / '*.rake'].each { |ext| load ext }

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/merb_rake_helper.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/merb_rake_helper.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/merb_rake_helper.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,59 @@
+require File.join(File.dirname(__FILE__), 'gem_management')
+
+module Merb
+  module RakeHelper
+    
+    extend GemManagement
+    
+    def self.install(name, options = {})
+      defaults = { :cache => false }
+      defaults[:install_dir] = ENV['GEM_DIR'] if ENV['GEM_DIR']
+      opts = defaults.merge(options)
+      dir = if File.directory?(subdir = File.join(Dir.pwd, name))
+        subdir
+      else
+        Dir.pwd
+      end
+      install_gem_from_source(dir, name, opts)
+      ensure_wrapper(opts[:install_dir] || Gem.default_dir, name)
+    end
+    
+    def self.install_package(pkg, options = {})
+      defaults = { :cache => false }
+      defaults[:install_dir] = ENV['GEM_DIR'] if ENV['GEM_DIR']
+      opts = defaults.merge(options)
+      # Needs to be executed from the directory that contains all packages
+      Dir.chdir(File.dirname(pkg_file = File.expand_path(pkg))) do 
+        install_gem(pkg_file, opts)
+      end
+      name = File.basename(pkg, '.gem')[/^(.*?)-([\d\.]+)$/, 1]
+      ensure_wrapper(opts[:install_dir] || Gem.default_dir, name)
+    end
+    
+    def self.uninstall(name, options = {})
+      defaults = { :ignore => true, :executables => true }
+      defaults[:install_dir] = ENV['GEM_DIR'] if ENV['GEM_DIR']
+      uninstall_gem(name, defaults.merge(options))
+    end  
+    
+    def self.sudo
+      ENV['MERB_SUDO'] ||= "sudo"
+      sudo = windows? ? "" : ENV['MERB_SUDO']
+    end
+
+    def self.windows?
+      (PLATFORM =~ /win32|cygwin/) rescue nil
+    end
+    
+    protected
+    
+    def self.ensure_wrapper(gemdir, name)
+      # See if there's a local bin dir - one directory up from ./gems
+      bindir = File.expand_path(File.join(gemdir, '..', 'bin'))
+      # Fall back to system wide bindir - usually needs sudo permissions
+      bindir = Gem.bindir unless File.directory?(bindir)
+      ensure_bin_wrapper_for(gemdir, bindir, name, :no_minigems => ['merb-gen'])
+    end
+    
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/stats.rake
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/stats.rake	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/tasks/stats.rake	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,71 @@
+def show_line(name, stats, color = nil)
+  ce = color ? "\033[0m" : ""
+  puts  "| #{color}#{name.to_s.capitalize.ljust(20)}#{ce} " + 
+        "| #{color}#{stats[:lines].to_s.rjust(7)}#{ce} " +
+        "| #{color}#{stats[:loc].to_s.rjust(7)}#{ce} " +
+        "| #{color}#{stats[:classes].to_s.rjust(7)}#{ce} " +
+        "| #{color}#{stats[:modules].to_s.rjust(7)}#{ce} " +
+        "| #{color}#{stats[:methods].to_s.rjust(7)}#{ce} |"
+  puts separator
+end
+
+def separator
+  '+----------------------+---------+---------+---------+---------+---------+'
+end
+
+def check_dir(dir)
+  Dir.foreach(dir) do |file_name|
+    if File.stat(dir / file_name).directory? and (/^\./ !~ file_name)
+      check_dir(dir / file_name)
+    end
+
+    if file_name =~ /.*\.rb$/
+      File.open(dir / file_name).each_line do |line|
+        @stats[:lines]    += 1
+        @stats[:loc]      += 1 unless line =~ /^\s*$/ || line =~ /^\s*#/
+        @stats[:classes]  += 1 if line =~ /class [A-Z]/
+        @stats[:modules]  += 1 if line =~ /module [A-Z]/
+        @stats[:methods]  += 1 if line =~ /def [a-z]/
+      end
+    end
+  end
+end
+
+desc "Lines of code statistics"
+task :stats do
+  STATISTICS_DIRS = {
+    :controllers  => 'app/controllers',
+    :helpers      => 'app/helpers',
+    :models       => 'app/models',
+    :lib          => 'lib',
+    :spec         => 'spec'
+  }.reject {|name, dir| !File.exist?(dir) }
+  EMPTY_STATS = { :lines => 0, :loc => 0, :classes => 0, :modules => 0, :methods => 0 }
+ 
+  @all = {}
+  total = EMPTY_STATS.clone
+  ce = "\033[0m"
+  cb = "\033[35m"
+  cg = "\033[4;32m"
+  cr = "\033[31m"
+ 
+  puts separator
+  puts "| #{cg}Name#{ce}                 | #{cg}Lines#{ce}   | #{cg}LOC#{ce}     | #{cg}Classes#{ce} | #{cg}Modules#{ce} | #{cg}Methods#{ce} |"
+  puts separator
+ 
+  STATISTICS_DIRS.each_pair do |name, dir| 
+    @stats = EMPTY_STATS.clone
+    check_dir(dir)
+    @all[name] = @stats
+    show_line(name, @stats)
+    @stats.each_pair { |type, count| total[type] += count }
+  end
+ 
+  show_line('Total', total, cr)
+ 
+  code_loc = [:controllers, :helpers, :models].inject(0) { |sum, e| sum += @all[e][:loc] }
+  test_loc = @all[:spec][:loc]
+ 
+  puts "   Code LOC: #{cb}#{code_loc}#{ce}     Test LOC: #{cb}#{test_loc}#{ce}     Code to test radio:  #{cb}1:%0.2f#{ce}" % (test_loc.to_f / code_loc.to_f)
+  puts
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/controller_helper.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/controller_helper.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/controller_helper.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,8 @@
+module Merb
+  module Test
+    module ControllerHelper
+      include RequestHelper
+      include MultipartRequestHelper
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/cookie_jar.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/cookie_jar.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/cookie_jar.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,120 @@
+require 'uri'
+
+module Merb
+  module Test
+    class Cookie
+      
+      # :api: private
+      attr_reader :name, :value
+      
+      # :api: private
+      def initialize(raw, default_host)
+        # separate the name / value pair from the cookie options
+        @name_value_raw, options = raw.split(/[;,] */n, 2)
+        
+        @name, @value = Merb::Parse.query(@name_value_raw, ';').to_a.first
+        @options = Merb::Parse.query(options, ';')
+        
+        @options.delete_if { |k, v| !v || v.empty? }
+        
+        @options["domain"] ||= default_host
+      end
+      
+      # :api: private
+      def raw
+        @name_value_raw
+      end
+      
+      # :api: private
+      def empty?
+        @value.nil? || @value.empty?
+      end
+      
+      # :api: private
+      def domain
+        @options["domain"]
+      end
+
+      # :api: private
+      def path
+        @options["path"] || "/"
+      end
+      
+      # :api: private
+      def expires
+        Time.parse(@options["expires"]) if @options["expires"]
+      end
+      
+      # :api: private
+      def expired?
+        expires && expires < Time.now
+      end
+      
+      # :api: private
+      def valid?(uri)
+        uri.host =~ Regexp.new("#{Regexp.escape(domain)}$") &&
+        uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
+      end
+      
+      # :api: private
+      def matches?(uri)
+        ! expired? && valid?(uri)
+      end
+      
+      # :api: private
+      def <=>(other)
+        # Orders the cookies from least specific to most
+        [name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse]
+      end
+      
+    end
+
+    class CookieJar
+      
+      # :api: private
+      def initialize
+        @jars = {}
+      end
+      
+      # :api: private
+      def update(jar, uri, raw_cookies)
+        return unless raw_cookies
+        # Initialize all the the received cookies
+        cookies = []
+        raw_cookies.each do |raw|
+          c = Cookie.new(raw, uri.host)
+          cookies << c if c.valid?(uri)
+        end
+        
+        @jars[jar] ||= []
+        
+        # Remove all the cookies that will be updated
+        @jars[jar].delete_if do |existing|
+          cookies.find { |c| [c.name, c.domain, c.path] == [existing.name, existing.domain, existing.path] }
+        end
+        
+        @jars[jar].concat cookies
+        
+        @jars[jar].sort!
+      end
+      
+      # :api: private
+      def for(jar, uri)
+        cookies = {}
+        
+        @jars[jar] ||= []
+        # The cookies are sorted by most specific first. So, we loop through
+        # all the cookies in order and add it to a hash by cookie name if
+        # the cookie can be sent to the current URI. It's added to the hash
+        # so that when we are done, the cookies will be unique by name and
+        # we'll have grabbed the most specific to the URI.
+        @jars[jar].each do |cookie|
+          cookies[cookie.name] = cookie.raw if cookie.matches?(uri)
+        end
+        
+        cookies.values.join(';')
+      end
+      
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/mock_request_helper.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/mock_request_helper.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/mock_request_helper.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,400 @@
+require 'tempfile'
+
+module Merb
+  module Test
+    module RequestHelper
+      # FakeRequest sets up a default enviroment which can be overridden either
+      # by passing and env into initialize or using request['HTTP_VAR'] = 'foo'
+      class FakeRequest < Request
+
+        # ==== Parameters
+        # env<Hash>:: Environment options that override the defaults.
+        # req<StringIO>:: The request to set as input for Rack.
+        def initialize(env = {}, req = StringIO.new)
+          env.environmentize_keys!
+          env['rack.input'] = req
+          super(DEFAULT_ENV.merge(env))
+        end
+
+        private
+        DEFAULT_ENV = Mash.new({
+          'SERVER_NAME' => 'localhost',
+          'PATH_INFO' => '/',
+          'HTTP_ACCEPT_ENCODING' => 'gzip,deflate',
+          'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.1) Gecko/20060214 Camino/1.0',
+          'SCRIPT_NAME' => '/',
+          'SERVER_PROTOCOL' => 'HTTP/1.1',
+          'HTTP_CACHE_CONTROL' => 'max-age=0',
+          'HTTP_ACCEPT_LANGUAGE' => 'en,ja;q=0.9,fr;q=0.9,de;q=0.8,es;q=0.7,it;q=0.7,nl;q=0.6,sv;q=0.5,nb;q=0.5,da;q=0.4,fi;q=0.3,pt;q=0.3,zh-Hans;q=0.2,zh-Hant;q=0.1,ko;q=0.1',
+          'HTTP_HOST' => 'localhost',
+          'REMOTE_ADDR' => '127.0.0.1',
+          'SERVER_SOFTWARE' => 'Mongrel 1.1',
+          'HTTP_KEEP_ALIVE' => '300',
+          'HTTP_REFERER' => 'http://localhost/',
+          'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
+          'HTTP_VERSION' => 'HTTP/1.1',
+          'REQUEST_URI' => '/',
+          'SERVER_PORT' => '80',
+          'GATEWAY_INTERFACE' => 'CGI/1.2',
+          'HTTP_ACCEPT' => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
+          'HTTP_CONNECTION' => 'keep-alive',
+          'REQUEST_METHOD' => 'GET'
+        }) unless defined?(DEFAULT_ENV)
+      end
+
+      # CookieJar keeps track of cookies in a simple Mash.
+      class CookieJar < Mash
+        
+        # ==== Parameters
+        # request<Merb::Request, Merb::FakeRequest>:: The controller request.
+        def update_from_request(request)
+          request.cookies.each do |key, value|
+            if value.blank?
+              self.delete(key)
+            else
+              self[key] = Merb::Parse.unescape(value)
+            end
+          end
+        end
+        
+      end
+
+      # ==== Parameters
+      # env<Hash>:: A hash of environment keys to be merged into the default list.
+      # opt<Hash>:: A hash of options (see below).
+      #
+      # ==== Options (opt)
+      # :post_body<String>:: The post body for the request.
+      # :req<String>::
+      #   The request string. This will only be used if :post_body is left out.
+      #
+      # ==== Returns
+      # FakeRequest:: A Request object that is built based on the parameters.
+      #
+      # ==== Notes
+      # If you pass a post body, the content-type will be set to URL-encoded.
+      #
+      # :api: public
+      # @deprecated
+      def fake_request(env = {}, opt = {})
+        if opt[:post_body]
+          req = opt[:post_body]
+          env[:content_type] ||= "application/x-www-form-urlencoded"
+        else
+          req = opt[:req]
+        end
+        FakeRequest.new(env, StringIO.new(req || ''))
+      end
+
+      # Dispatches an action to the given class. This bypasses the router and is
+      # suitable for unit testing of controllers.
+      #
+      # ==== Parameters
+      # controller_klass<Controller>::
+      #   The controller class object that the action should be dispatched to.
+      # action<Symbol>:: The action name, as a symbol.
+      # params<Hash>::
+      #   An optional hash that will end up as params in the controller instance.
+      # env<Hash>::
+      #   An optional hash that is passed to the fake request. Any request options
+      #   should go here (see +fake_request+), including :req or :post_body
+      #   for setting the request body itself.
+      # &blk::
+      #   The controller is yielded to the block provided for actions *prior* to
+      #   the action being dispatched.
+      #
+      # ==== Example
+      #   dispatch_to(MyController, :create, :name => 'Homer' ) do |controller|
+      #     controller.stub!(:current_user).and_return(@user)
+      #   end
+      #
+      # ==== Notes
+      # Does not use routes.
+      #
+      # :api: public
+      # @deprecated
+      def dispatch_to(controller_klass, action, params = {}, env = {}, &blk)
+        params = merge_controller_and_action(controller_klass, action, params)
+        dispatch_request(build_request(params, env), controller_klass, action.to_s, &blk)
+      end
+      
+      # Keep track of cookie values in CookieJar within the context of the
+      # block; you need to set this up for secific controllers.
+      #
+      # ==== Parameters
+      # *controller_classes:: Controller classes to operate on in the context of the block.
+      # &blk:: The context to operate on; optionally accepts the cookie jar as an argument.
+      #
+      # :api: public
+      # @deprecated
+      def with_cookies(*controller_classes, &blk)
+        cookie_jar = CookieJar.new
+        before_cb = lambda { |c| c.cookies.update(cookie_jar) }
+        after_cb  = lambda { |c| cookie_jar.update_from_request(c.request) }
+        controller_classes.each do |klass|
+          klass._before_dispatch_callbacks << before_cb
+          klass._after_dispatch_callbacks  << after_cb
+        end
+        blk.arity == 1 ? blk.call(cookie_jar) : blk.call
+        controller_classes.each do |klass|
+          klass._before_dispatch_callbacks.delete before_cb
+          klass._after_dispatch_callbacks.delete after_cb
+        end
+      end
+
+      # Dispatches an action to the given class and using HTTP Basic Authentication
+      # This bypasses the router and is suitable for unit testing of controllers.
+      #
+      # ==== Parameters
+      # controller_klass<Controller>::
+      #   The controller class object that the action should be dispatched to.
+      # action<Symbol>:: The action name, as a symbol.
+      # username<String>:: The username.
+      # password<String>:: The password.
+      # params<Hash>::
+      #   An optional hash that will end up as params in the controller instance.
+      # env<Hash>::
+      #   An optional hash that is passed to the fake request. Any request options
+      #   should go here (see +fake_request+), including :req or :post_body
+      #   for setting the request body itself.
+      # &blk::
+      #   The controller is yielded to the block provided for actions *prior* to
+      #   the action being dispatched.
+      #
+      # ==== Example
+      #   dispatch_with_basic_authentication_to(MyController, :create, 'Fred', 'secret', :name => 'Homer' ) do |controller|
+      #     controller.stub!(:current_user).and_return(@user)
+      #   end
+      #
+      # ==== Notes
+      # Does not use routes.
+      #
+      # :api: public
+      # @deprecated
+      def dispatch_with_basic_authentication_to(controller_klass, action, username, password, params = {}, env = {}, &blk)
+        env["X_HTTP_AUTHORIZATION"] = "Basic #{Base64.encode64("#{username}:#{password}")}"
+        
+        params = merge_controller_and_action(controller_klass, action, params)        
+        dispatch_request(build_request(params, env), controller_klass, action.to_s, &blk)
+      end
+      
+      # :api: private
+      def merge_controller_and_action(controller_klass, action, params)
+        params[:controller] = controller_klass.name.to_const_path
+        params[:action]     = action.to_s
+        
+        params
+      end
+
+      # Prepares and returns a request suitable for dispatching with
+      # dispatch_request. If you don't need to modify the request
+      # object before dispatching (e.g. to add cookies), you probably
+      # want to use dispatch_to instead.
+      #
+      # ==== Parameters
+      # params<Hash>::
+      #   An optional hash that will end up as params in the controller instance.
+      # env<Hash>::
+      #   An optional hash that is passed to the fake request. Any request options
+      #   should go here (see +fake_request+), including :req or :post_body
+      #   for setting the request body itself.
+      #
+      # ==== Example
+      #   req = build_request(:id => 1)
+      #   req.cookies['app_cookie'] = "testing"
+      #   dispatch_request(req, MyController, :edit)
+      #
+      # ==== Notes
+      # Does not use routes.
+      #
+      # :api: public    
+      # @deprecated  
+      def build_request(params = {}, env = {})
+        params             = Merb::Parse.params_to_query_string(params)
+
+        query_string = env[:query_string] || env['QUERY_STRING']
+        env[:query_string] = query_string ? "#{query_string}&#{params}" : params
+        
+        post_body = env[:post_body] || env['POST_BODY']
+        fake_request(env, { :post_body => post_body, :req => env[:req] })
+      end
+
+      # An HTTP GET request that operates through the router.
+      #
+      # ==== Parameters
+      # path<String>:: The path that should go to the router as the request uri.
+      # params<Hash>::
+      #   An optional hash that will end up as params in the controller instance.
+      # env<Hash>::
+      #   An optional hash that is passed to the fake request. Any request options
+      #   should go here (see +fake_request+).
+      # &blk::
+      #   The controller is yielded to the block provided for actions *prior* to
+      #   the action being dispatched.
+      #
+      # :api: public  
+      # @deprecated    
+      def get(path, params = {}, env = {}, &block)
+        env[:request_method] = "GET"
+        mock_request(path, params, env, &block)
+      end
+
+      # An HTTP POST request that operates through the router.
+      #
+      # ==== Parameters
+      # path<String>:: The path that should go to the router as the request uri.
+      # params<Hash>::
+      #   An optional hash that will end up as params in the controller instance.
+      # env<Hash>::
+      #   An optional hash that is passed to the fake request. Any request options
+      #   should go here (see fake_request).
+      # &blk::
+      #   The controller is yielded to the block provided for actions *prior* to
+      #   the action being dispatched.
+      #
+      # :api: public  
+      # @deprecated    
+      def post(path, params = {}, env = {}, &block)
+        env[:request_method] = "POST"
+        mock_request(path, params, env, &block)
+      end
+
+      # An HTTP PUT request that operates through the router.
+      #
+      # ==== Parameters
+      # path<String>:: The path that should go to the router as the request uri.
+      # params<Hash>::
+      #   An optional hash that will end up as params in the controller instance.
+      # env<Hash>::
+      #   An optional hash that is passed to the fake request. Any request options
+      #   should go here (see fake_request).
+      # &blk::
+      #   The controller is yielded to the block provided for actions *prior* to
+      #   the action being dispatched.
+      #
+      # :api: public      
+      def put(path, params = {}, env = {}, &block)
+        env[:request_method] = "PUT"
+        mock_request(path, params, env, &block)
+      end
+
+      # An HTTP DELETE request that operates through the router
+      #
+      # ==== Parameters
+      # path<String>:: The path that should go to the router as the request uri.
+      # params<Hash>::
+      #   An optional hash that will end up as params in the controller instance.
+      # env<Hash>::
+      #   An optional hash that is passed to the fake request. Any request options
+      #   should go here (see fake_request).
+      # &blk::
+      #   The controller is yielded to the block provided for actions *prior* to
+      #   the action being dispatched.
+      #
+      # :api: public
+      # @deprecated
+      def delete(path, params = {}, env = {}, &block)
+        env[:request_method] = "DELETE"
+        mock_request(path, params, env, &block)
+      end
+
+      # A generic request that checks the router for the controller and action.
+      # This request goes through the Merb::Router and finishes at the controller.
+      #
+      # ==== Parameters
+      # path<String>:: The path that should go to the router as the request uri.
+      # params<Hash>::
+      #   An optional hash that will end up as params in the controller instance.
+      # env<Hash>::
+      #   An optional hash that is passed to the fake request. Any request options
+      #   should go here (see +fake_request+).
+      # &blk::
+      #   The controller is yielded to the block provided for actions *prior* to
+      #   the action being dispatched.
+      #
+      # ==== Example
+      #   request(path, { :name => 'Homer' }, { :request_method => "PUT" }) do |controller|
+      #     controller.stub!(:current_user).and_return(@user)
+      #   end
+      #
+      # ==== Notes
+      # Uses Routes.
+      #
+      # :api: plugin
+      # @deprecated
+      def mock_request(path, params = {}, env= {}, &block)
+        env[:request_method] ||= "GET"
+        env[:request_uri], env[:query_string] = path.split('?')
+        
+        multipart = env.delete(:test_with_multipart)
+
+        request = build_request(params, env)
+
+        opts = check_request_for_route(request) # Check that the request will be routed correctly
+        controller_name = (opts[:namespace] ? opts.delete(:namespace) + '/' : '') + opts.delete(:controller)
+        klass = Object.full_const_get(controller_name.snake_case.to_const_string)
+        
+        action = opts.delete(:action).to_s
+        params.merge!(opts)
+
+        multipart.nil? ? dispatch_to(klass, action, params, env, &block) : dispatch_multipart_to(klass, action, params, env, &block)
+      end
+
+
+      # The workhorse for the dispatch*to helpers.
+      #
+      # ==== Parameters
+      # request<Merb::Test::RequestHelper::FakeRequest, Merb::Request>::
+      #   A request object that has been setup for testing.
+      # controller_klass<Merb::Controller>::
+      #   The class object off the controller to dispatch the action to.
+      # action<Symbol>:: The action to dispatch the request to.
+      # &blk::
+      #   The controller is yielded to the block provided for actions *prior* to
+      #   the action being dispatched.
+      #
+      # ==== Returns
+      # An instance of +controller_klass+ based on the parameters.
+      #
+      # ==== Notes
+      # Does not use routes.
+      #
+      # :api: public
+      # @deprecated
+      def dispatch_request(request, controller_klass, action, &blk)
+        controller = controller_klass.new(request)
+        yield controller if block_given?
+        controller._dispatch(action)
+
+        Merb.logger.info controller._benchmarks.inspect
+        Merb.logger.flush
+
+        controller
+      end
+
+      # Checks to see that a request is routable.
+      #
+      # ==== Parameters
+      # request<Merb::Test::RequestHelper::FakeRequest, Merb::Request>::
+      #   The request object to inspect.
+      #
+      # ==== Raises
+      # Merb::ControllerExceptions::BadRequest::
+      #   No matching route was found.
+      #
+      # ==== Returns
+      # Hash:: The parameters built based on the matching route.
+      #
+      # :api: plugin
+      # @deprecated
+      def check_request_for_route(request)
+        match =  ::Merb::Router.match(request)
+        if match[0].nil? && match[1].empty?
+          raise ::Merb::ControllerExceptions::BadRequest, "No routes match the request. Request uri: #{request.uri}"
+        else
+          match[1]
+        end
+      end # check_request_for_route
+    end # RequestHelper
+  end # Test
+end # Merb

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/multipart_request_helper.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/multipart_request_helper.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/multipart_request_helper.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,176 @@
+module Merb::Test::MultipartRequestHelper
+  require 'rubygems'
+  gem "mime-types"
+  require 'mime/types'
+
+  class Param
+    attr_accessor :key, :value
+
+    # ==== Parameters
+    # key<~to_s>:: The parameter key.
+    # value<~to_s>:: The parameter value.
+    def initialize(key, value)
+      @key   = key
+      @value = value
+    end
+
+    # ==== Returns
+    # String:: The parameter in a form suitable for a multipart request.
+    def to_multipart
+      return %(Content-Disposition: form-data; name="#{key}"\r\n\r\n#{value}\r\n)
+    end
+  end
+
+  class FileParam
+    attr_accessor :key, :filename, :content
+
+    # ==== Parameters
+    # key<~to_s>:: The parameter key.
+    # filename<~to_s>:: Name of the file for this parameter.
+    # content<~to_s>:: Content of the file for this parameter.
+    def initialize(key, filename, content)
+      @key      = key
+      @filename = filename
+      @content  = content
+    end
+
+    # ==== Returns
+    # String::
+    #   The file parameter in a form suitable for a multipart request.
+    def to_multipart
+      return %(Content-Disposition: form-data; name="#{key}"; filename="#{filename}"\r\n) + "Content-Type: #{MIME::Types.type_for(@filename)}\r\n\r\n" + content + "\r\n"
+    end
+  end
+
+  class Post
+    BOUNDARY = '----------0xKhTmLbOuNdArY'
+    CONTENT_TYPE = "multipart/form-data, boundary=" + BOUNDARY
+
+    # ==== Parameters
+    # params<Hash>:: Optional params for the controller.
+    def initialize(params = {})
+      @multipart_params = []
+      push_params(params)
+    end
+
+    # Saves the params in an array of multipart params as Param and
+    # FileParam objects.
+    #
+    # ==== Parameters
+    # params<Hash>:: The params to add to the multipart params.
+    # prefix<~to_s>:: An optional prefix for the request string keys.
+    def push_params(params, prefix = nil)
+      params.sort_by {|k| k.to_s}.each do |key, value|
+        param_key = prefix.nil? ? key : "#{prefix}[#{key}]"
+        if value.respond_to?(:read)
+          @multipart_params << FileParam.new(param_key, value.path, value.read)
+        else
+          if value.is_a?(Hash) || value.is_a?(Mash)
+            value.keys.each do |k|
+              push_params(value, param_key)
+            end
+          else
+            @multipart_params << Param.new(param_key, value)
+          end
+        end
+      end
+    end
+
+    # ==== Returns
+    # Array[String, String]:: The query and the content type.
+    def to_multipart
+      query = @multipart_params.collect { |param| "--" + BOUNDARY + "\r\n" + param.to_multipart }.join("") + "--" + BOUNDARY + "--"
+      return query, CONTENT_TYPE
+    end
+  end 
+
+  # Similar to dispatch_to but allows for sending files inside params.  
+  #
+  # ==== Paramters 
+  # controller_klass<Controller>::
+  #   The controller class object that the action should be dispatched to.
+  # action<Symbol>:: The action name, as a symbol.
+  # params<Hash>::
+  #   An optional hash that will end up as params in the controller instance.
+  # env<Hash>::
+  #   An optional hash that is passed to the fake request. Any request options
+  #   should go here (see +fake_request+).
+  # &blk:: The block is executed in the context of the controller.
+  #  
+  # ==== Example
+  #   dispatch_multipart_to(MyController, :create, :my_file => @a_file ) do |controller|
+  #     controller.stub!(:current_user).and_return(@user)
+  #   end
+  #
+  # ==== Notes
+  # Set your option to contain a file object to simulate file uploads.
+  #   
+  # Does not use routes.
+  #---
+  # @public
+  def dispatch_multipart_to(controller_klass, action, params = {}, env = {}, &blk)
+    request = multipart_fake_request(env, params)
+    dispatch_request(request, controller_klass, action, &blk)
+  end
+
+  # An HTTP POST request that operates through the router and uses multipart
+  # parameters.
+  #
+  # ==== Parameters
+  # path<String>:: The path that should go to the router as the request uri.
+  # params<Hash>::
+  #   An optional hash that will end up as params in the controller instance.
+  # env<Hash>::
+  #   An optional hash that is passed to the fake request. Any request options
+  #   should go here (see +fake_request+).
+  # block<Proc>:: The block is executed in the context of the controller.
+  #
+  # ==== Notes
+  # To include an uploaded file, put a file object as a value in params.
+  def multipart_post(path, params = {}, env = {}, &block)
+    env[:request_method] = "POST"
+    env[:test_with_multipart] = true
+    mock_request(path, params, env, &block)
+  end
+
+  # An HTTP PUT request that operates through the router and uses multipart
+  # parameters.
+  #
+  # ==== Parameters
+  # path<String>:: The path that should go to the router as the request uri.
+  # params<Hash>::
+  #   An optional hash that will end up as params in the controller instance.
+  # env<Hash>::
+  #   An optional hash that is passed to the fake request. Any request options
+  #   should go here (see +fake_request+).
+  # block<Proc>:: The block is executed in the context of the controller.
+  #
+  # ==== Notes
+  # To include an uplaoded file, put a file object as a value in params.
+  def multipart_put(path, params = {}, env = {}, &block)
+    env[:request_method] = "PUT"
+    env[:test_with_multipart] = true
+    mock_request(path, params, env, &block)
+  end
+  
+  # ==== Parameters
+  # env<Hash>::
+  #   An optional hash that is passed to the fake request. Any request options
+  #   should go here (see +fake_request+).
+  # params<Hash>::
+  #   An optional hash that will end up as params in the controller instance.
+  # 
+  # ==== Returns
+  # FakeRequest::
+  #   A multipart Request object that is built based on the parameters.
+  def multipart_fake_request(env = {}, params = {})
+    if params.empty?
+      fake_request(env)
+    else
+      m = Post.new(params)
+      body, head = m.to_multipart
+      fake_request(env.merge( :content_type => head, 
+                              :content_length => body.length), :post_body => body)
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/request_helper.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/request_helper.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/request_helper.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,83 @@
+require "rack"
+
+module Merb
+  module Test
+    module MakeRequest
+
+      def request(uri, env = {})
+        uri = url(uri) if uri.is_a?(Symbol)
+        uri = URI(uri)
+        uri.scheme ||= "http"
+        uri.host   ||= "example.org"
+
+        if (env[:method] == "POST" || env["REQUEST_METHOD"] == "POST")
+          params = env.delete(:body_params) if env.key?(:body_params)
+          params = env.delete(:params) if env.key?(:params) && !env.key?(:input)
+
+          unless env.key?(:input)
+            env[:input] = Merb::Parse.params_to_query_string(params)
+            env["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
+          end
+        end
+
+        if env[:params]
+          uri.query = [
+            uri.query, Merb::Parse.params_to_query_string(env.delete(:params))
+          ].compact.join("&")
+        end
+        
+        ignore_cookies = env.has_key?(:jar) && env[:jar].nil?
+
+        unless ignore_cookies
+          # Setup a default cookie jar container
+          @__cookie_jar__ ||= Merb::Test::CookieJar.new
+          # Grab the cookie group name
+          jar = env.delete(:jar) || :default
+          # Add the cookies explicitly set by the user
+          @__cookie_jar__.update(jar, uri, env.delete(:cookie)) if env.has_key?(:cookie)
+          # Set the cookie header with the cookies
+          env["HTTP_COOKIE"] = @__cookie_jar__.for(jar, uri)
+        end
+        
+        app = Merb::Config[:app]
+        rack = app.call(::Rack::MockRequest.env_for(uri.to_s, env))
+
+        rack = Struct.new(:status, :headers, :body, :url, :original_env).
+          new(rack[0], rack[1], rack[2], uri.to_s, env)
+          
+        @__cookie_jar__.update(jar, uri, rack.headers["Set-Cookie"]) unless ignore_cookies
+
+        Merb::Dispatcher.work_queue.size.times do
+          Merb::Dispatcher.work_queue.pop.call
+        end
+
+        rack
+      end
+    end
+    
+    module RequestHelper
+      include MakeRequest
+
+      def describe_request(rack)
+        "a #{rack.original_env[:method] || rack.original_env["REQUEST_METHOD"] || "GET"} to '#{rack.url}'"
+      end
+
+      def describe_input(input)
+        if input.respond_to?(:controller_name)
+          "#{input.controller_name}##{input.action_name}"
+        elsif input.respond_to?(:original_env)
+          describe_request(input)
+        else
+          input
+        end
+      end
+      
+      def status_code(input)
+        input.respond_to?(:status) ? input.status : input
+      end
+      
+      def requesting(*args)   request(*args) end
+      def response_for(*args) request(*args) end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/route_helper.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/route_helper.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers/route_helper.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,93 @@
+module Merb
+  module Test
+    module RouteHelper
+      include RequestHelper
+      
+      # There are three possible ways to use this method.  First, if you have a named route, 
+      # you can specify the route as the first parameter as a symbol and any paramters in a 
+      # hash.  Second, you can generate the default route by just passing the params hash, 
+      # just passing the params hash.  Finally, you can use the anonymous parameters.  This 
+      # allows you to specify the parameters to a named route in the order they appear in the 
+      # router.  
+      #
+      # ==== Parameters(Named Route)
+      # name<Symbol>:: 
+      #   The name of the route. 
+      # args<Hash>:: 
+      #   Parameters for the route generation.
+      #
+      # ==== Parameters(Default Route)
+      # args<Hash>:: 
+      #   Parameters for the route generation.  This route will use the default route. 
+      #
+      # ==== Parameters(Anonymous Parameters)
+      # name<Symbol>::
+      #   The name of the route.  
+      # args<Array>:: 
+      #   An array of anonymous parameters to generate the route
+      #   with. These parameters are assigned to the route parameters
+      #   in the order that they are passed.
+      #
+      # ==== Returns
+      # String:: The generated URL.
+      #
+      # ==== Examples
+      # Named Route
+      #
+      # Merb::Router.prepare do
+      #   match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+      # end
+      #
+      # url(:articles, :title => "new_article")
+      #
+      # Default Route
+      #
+      # Merb::Router.prepare do
+      #   default_routes
+      # end
+      #
+      # url(:controller => "articles", :action => "new")
+      #
+      # Anonymous Paramters
+      #
+      # Merb::Router.prepare do
+      #   match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+      # end
+      #
+      # url(:articles, 2008, 10, "test_article")
+      #
+      # :api: public
+      def url(*args)
+        args << (@request_params || {})
+        Merb::Router.url(*args)
+      end
+      
+      # Mimics the resource method available to controllers
+      #
+      # ==== Paramaters
+      # resources<Object>:: The resources to generate URLs from
+      # params<Hash>:: Any extra parameters that are required.
+      #
+      # ==== Returns
+      # String:: The generated URL.
+      def resource(*args)
+        args << @request_params || {}
+        Merb::Router.resource(*args)
+      end
+      
+      # ==== Parameters
+      # path<~to_string>:: The URL of the request.
+      # method<~to_sym>:: HTTP request method.
+      # env<Hash>:: Additional parameters for the request.
+      #
+      # ==== Returns
+      # Hash:: A hash containing the controller and action along with any parameters
+      def request_to(path, method = :get, env = {})
+        env[:request_method] ||= method.to_s.upcase
+        env[:request_uri] = path
+        
+        check_request_for_route(build_request({}, env))
+      end
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/helpers.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,10 @@
+# This is a place holder to allow plugins etc a place to include 
+# testing helpers
+module Merb::Test::Helpers; end
+
+require "merb-core/test/helpers/cookie_jar"
+require "merb-core/test/helpers/mock_request_helper"
+require "merb-core/test/helpers/route_helper"
+require "merb-core/test/helpers/request_helper"
+require "merb-core/test/helpers/multipart_request_helper"
+require "merb-core/test/helpers/controller_helper"

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/controller_matchers.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/controller_matchers.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/controller_matchers.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,108 @@
+module Merb::Test::Rspec::ControllerMatchers
+
+  class BeRedirect
+    # ==== Parameters
+    # target<Fixnum, ~status>::
+    #   Either the status code or a controller with a status code.
+    #
+    # ==== Returns
+    # Boolean:: True if the status code is in the range 300..305 or 307.
+    def matches?(target)
+      @target = target
+      [307, *(300..305)].include?(target.respond_to?(:status) ? target.status : target)
+    end
+
+    # ==== Returns
+    # String:: The failure message.
+    def failure_message
+      "expected#{inspect_target} to redirect"
+    end
+
+    # ==== Returns
+    # String:: The failure message to be displayed in negative matches.
+    def negative_failure_message
+      "expected#{inspect_target} not to redirect"
+    end
+
+    # ==== Returns
+    # String:: The controller and action name.
+    def inspect_target
+      " #{@target.controller_name}##{@target.action_name}" if @target.respond_to?(:controller_name) && @target.respond_to?(:action_name)
+    end
+  end
+
+  class BeError
+    def initialize(expected)
+      @expected = expected
+    end
+    
+    def matches?(target)
+      @target = target
+      @target.request.exceptions &&
+        @target.request.exceptions.first.is_a?(@expected)
+    end
+    
+    def failure_message
+      "expected #{@target} to be a #{@expected} error, but it was " << 
+        @target.request.exceptions.first.inspect
+    end
+    
+    def negative_failure_message
+      "expected #{@target} not to be a #{@expected} error, but it was"
+    end
+  end
+  
+  def be_error(expected)
+    BeError.new(expected)
+  end
+
+  class Provide
+
+    # === Parameters
+    # expected<Symbol>:: A format to check
+    def initialize(expected)
+      @expected = expected
+    end
+
+    # ==== Parameters
+    # target<Symbol>::
+    #   A ControllerClass or controller_instance
+    #
+    # ==== Returns
+    # Boolean:: True if the formats provided by the target controller/class include the expected
+    def matches?(target)
+      @target = target
+      provided_formats.include?( @expected )
+    end
+
+    # ==== Returns
+    # String:: The failure message.
+    def failure_message
+      "expected #{@target.name} to provide #{@expected}, but it doesn't"
+    end
+
+    # ==== Returns
+    # String:: The failure message to be displayed in negative matches.
+    def negative_failure_message
+      "expected #{@target.name} not to provide #{@expected}, but it does"
+    end
+
+    # ==== Returns
+    # Array[Symbol]:: The formats the expected provides
+    def provided_formats
+      @target.class_provided_formats
+    end
+  end
+  
+  # Passes if the controller actually provides the target format
+  #
+  # === Parameters
+  # expected<Symbol>:: A format to check
+  #
+  # ==== Examples
+  #   ControllerClass.should provide( :html )
+  #   controller_instance.should provide( :xml )
+  def provide( expected )
+    Provide.new( expected )
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/request_matchers.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/request_matchers.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/request_matchers.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,126 @@
+Spec::Matchers.create(:be_successful, :respond_successfully) do
+  matches do |rack|
+    @status = rack.respond_to?(:status) ? rack.status : rack
+    @inspect = describe_input(rack)
+
+    (200..207).include?(@status)
+  end
+  
+  message do |not_string, rack|
+    if @inspect.is_a?(Numeric)
+      "Expected status code#{not_string} to be successful, " \
+      "but it was #{@inspect}"
+    else
+      "Expected #{@inspect}#{not_string} " \
+      "to be successful, but it returned a #{@status}"
+    end
+  end
+end
+
+Spec::Matchers.create(:be_missing, :be_client_error) do
+  matches do |rack|
+    @status = rack.respond_to?(:status) ? rack.status : rack
+    @inspect = describe_input(rack)
+
+    (400..417).include?(@status)
+  end
+  
+  message do |not_string, rack|
+    unless @inspect.is_a?(Numeric)
+      "Expected #{@inspect}#{not_string} " \
+      "to be missing, but it returned a #{@status}"
+    else
+      "Expected #{not_string ? "not to get " : ""}a missing error code, " \
+      "but got #{@inspect}"
+    end
+  end
+end
+
+Spec::Matchers.create(:have_body) do
+  matches do |rack, body|
+    @actual = if rack.respond_to?(:body)
+      rack.body.to_s
+    else
+      rack.to_s
+    end
+    
+    @actual == body
+  end
+  
+  negative_failure_message do |rack, body|
+    "Expected the response not to match:\n    #{body}\nActual response was:\n    #{@actual}" 
+  end
+  
+  failure_message do |rack, body|
+    "Expected the response to match:\n    #{body}\nActual response was:\n    #{@actual}" 
+  end
+end
+
+Spec::Matchers.create(:have_content_type) do
+  matches do |rack, mime_symbol|
+    content_type = rack.headers["Content-Type"].split("; ").first
+    if registered_mime = Merb.available_mime_types[mime_symbol]
+      registered_mime[:accepts].include?(content_type)
+    else
+      @error = "Mime #{mime_symbol.inspect} was not registered"
+      false
+    end
+  end
+  
+  failure_message do |rack, mime_symbol|
+    if @error
+      @error
+    else
+      ret = "Expected your response to be of the #{mime_symbol} type, "
+      if mime = Merb.available_accepts[rack.headers["Content-Type"]]
+        ret << "but it was #{mime}"
+      else
+        ret << "but it was #{rack.headers["Content-Type"]}, which was " \
+               "not a registered Merb content type."
+      end
+    end
+  end
+end
+
+Spec::Matchers.create(:redirect) do
+  matches do |rack|
+    @inspect = describe_input(rack)
+    @status_code = status_code(rack)
+    (300..399).include?(@status_code)
+  end
+  
+  message do |not_string, rack|
+    "Expected #{@inspect}#{not_string} to be a redirect, but the " \
+    "status code was #{@status_code}"
+  end
+end
+
+Spec::Matchers.create(:redirect_to) do
+  expected_value do |location|
+    url(location) if location.is_a?(Symbol)
+  end
+  
+  matches do |rack, location|
+    @inspect = describe_input(rack)
+    
+    return false unless rack.headers["Location"]
+    @location, @query = rack.headers["Location"].split("?")
+    @status_code = status_code(rack)
+    @status_code.in?(300..399) && @location == location
+  end
+  
+  negative_failure_message do |rack, location|
+    "Expected #{@inspect} not to redirect to " \
+    "<#{location}> but it did."
+  end
+  
+  failure_message do |rack, location|
+    if !rack.status.in?(300..399)
+      "Expected #{@inspect} to be a redirect, but " \
+      "it returned status code #{rack.status}."
+    elsif rack.headers["Location"] != location
+      "Expected #{@inspect} to redirect to " \
+      "<#{location}>, but it redirected to <#{rack.headers["Location"]}>"
+    end
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/route_matchers.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/route_matchers.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers/route_matchers.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,137 @@
+module Merb::Test::Rspec::RouteMatchers
+
+  class RouteToMatcher
+
+    # ==== Parameters
+    # klass_or_name<Class, String>::
+    #   The controller class or class name to match routes for.
+    # action<~to_s>:: The name of the action to match routes for.
+    def initialize(klass_or_name, action)
+      @expected_controller = Class === klass_or_name ? klass_or_name.name : klass_or_name
+      @expected_action = action.to_s
+    end
+
+    # ==== Parameters
+    # target<Hash>:: The route parameters to match.
+    #
+    # ==== Returns
+    # Boolean:: True if the controller action and parameters match.
+    def matches?(target)
+      @target_env = target.dup
+      @target_controller, @target_action = @target_env.delete(:controller).to_s, @target_env.delete(:action).to_s
+
+      @target_controller = "#{target.delete(:namespace)}::#{@target_controller}" if target.has_key?(:namespace)
+
+      @expected_controller.snake_case == @target_controller.snake_case && @expected_action == @target_action && match_parameters(@target_env)
+    end
+
+    # ==== Parameters
+    # target<Hash>:: The route parameters to match.
+    #
+    # ==== Returns
+    # Boolean::
+    #   True if the parameter matcher created with #with matches or if no
+    #   parameter matcher exists.
+    def match_parameters(target)
+      @parameter_matcher.nil? ? true : @parameter_matcher.matches?(target)
+    end
+
+    # Creates a new paramter matcher.
+    #
+    # ==== Parameters
+    # parameters<Hash, ~to_param>:: The parameters to match.
+    #
+    # ==== Returns
+    # RouteToMatcher:: This matcher.
+    #
+    # ==== Alternatives
+    # If parameters is an object, then a new expected hash will be constructed
+    # with the key :id set to parameters.to_param.
+    def with(parameters)
+      @parameter_matcher = ParameterMatcher.new(parameters)
+
+      self
+    end
+
+    # ==== Returns
+    # String:: The failure message.
+    def failure_message
+      "expected the request to route to #{@expected_controller.to_const_string}##{@expected_action}#{expected_parameters_message}, but was #{@target_controller.to_const_string}##{@target_action}#{actual_parameters_message}"
+    end
+
+    # ==== Returns
+    # String:: The failure message to be displayed in negative matches.
+    def negative_failure_message
+      "expected the request not to route to #{@expected_controller.camel_case}##{@expected_action}#{expected_parameters_message}, but it did"
+    end
+
+    def expected_parameters_message
+      " with #{@parameter_matcher.expected.inspect}" if @parameter_matcher
+    end
+
+    def actual_parameters_message
+      " with #{(@parameter_matcher.actual || {}).inspect}" if @parameter_matcher
+    end
+  end
+
+  class ParameterMatcher
+    attr_accessor :expected, :actual
+
+    # ==== Parameters
+    # hash_or_object<Hash, ~to_param>:: The parameters to match.
+    #
+    # ==== Alternatives
+    # If hash_or_object is an object, then a new expected hash will be
+    # constructed with the key :id set to hash_or_object.to_param.
+    def initialize(hash_or_object)
+      @expected = {}
+      case hash_or_object
+      when Hash then @expected = hash_or_object
+      else @expected[:id] = hash_or_object.to_param
+      end
+    end
+
+    # ==== Parameters
+    # parameter_hash<Hash>:: The route parameters to match.
+    #
+    # ==== Returns
+    # Boolean:: True if the route parameters match the expected ones.
+    def matches?(parameter_hash)
+      @actual = parameter_hash.dup.except(:controller, :action)
+
+      return @actual.empty? if @expected.empty?
+      @expected.all? {|(k, v)| @actual.has_key?(k) && @actual[k] == v}
+    end
+
+    # ==== Returns
+    # String:: The failure message.
+    def failure_message
+      "expected the route to contain parameters #{@expected.inspect}, but instead contained #{@actual.inspect}"
+    end
+
+    # ==== Returns
+    # String:: The failure message to be displayed in negative matches.
+    def negative_failure_message
+      "expected the route not to contain parameters #{@expected.inspect}, but it did"
+    end
+  end
+
+  # Passes when the actual route parameters match the expected controller class
+  # and controller action. Exposes a +with+ method for specifying parameters.
+  #
+  # ==== Parameters
+  # klass_or_name<Class, String>::
+  #   The controller class or class name to match routes for.
+  # action<~to_s>:: The name of the action to match routes for.
+  #
+  # ==== Example
+  #   # Passes if a GET request to "/" is routed to the Widgets controller's
+  #   # index action.
+  #   request_to("/", :get).should route_to(Widgets, :index)
+  #
+  #   # Use the 'with' method for parameter checks
+  #   request_to("/123").should route_to(widgets, :show).with(:id => "123")
+  def route_to(klass_or_name, action)
+    RouteToMatcher.new(klass_or_name, action)
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/matchers.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,15 @@
+module Merb::Test::Rspec; end
+
+require "merb-core/test/matchers/controller_matchers"
+require "merb-core/test/matchers/route_matchers"
+require "merb-core/test/matchers/request_matchers"
+
+Merb::Test::ControllerHelper.send(:include, Merb::Test::Rspec::ControllerMatchers)
+Merb::Test::RouteHelper.send(:include, Merb::Test::Rspec::RouteMatchers)
+
+if defined?(::Webrat)
+  module Merb::Test::ViewHelper
+    include ::Webrat::Matchers
+    include ::Webrat::HaveTagMatcher
+  end
+end
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/run_spec.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/run_spec.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/run_spec.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,40 @@
+require "stringio"
+require 'rubygems'
+require 'spec'
+require 'spec/runner/formatter/specdoc_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      class BaseTextFormatter
+        def dump_failure(counter, failure)
+          output = @options.error_stream
+          output.puts
+          output.puts "#{counter.to_s})"
+          output.puts colourise("#{failure.header}\n#{failure.exception.message}", failure)
+          output.puts format_backtrace(failure.exception.backtrace)
+          output.flush
+        end
+      end
+    end
+  end
+end
+
+def run_spec(spec, base_dir)
+
+  $VERBOSE = nil
+  err, out = StringIO.new, StringIO.new
+  def out.tty?() true end
+  options = Spec::Runner::OptionParser.parse(%W(#{spec} -fs --color), err, out)
+  options.filename_pattern = File.expand_path(spec)
+  failure = ! Spec::Runner::CommandLine.run(options)
+  File.open(base_dir / "results" / "#{File.basename(spec)}_out", "w") do |file|
+    file.puts out.string
+  end
+  File.open(base_dir / "results" / "#{File.basename(spec)}_err", "w") do |file|
+    file.puts err.string
+  end
+  exit!(failure ? -1 : 0)
+end
+
+run_spec(ARGV[0], File.expand_path(File.join(File.dirname(__FILE__), "..", "..", ".."))) if ENV["NOW"]

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/run_specs.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/run_specs.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/run_specs.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,133 @@
+require 'rubygems'
+require 'benchmark'
+require 'spec'
+require 'spec/runner/formatter/base_text_formatter'
+require 'spec/spec_helper.rb'
+
+# Load this stuff so it only has to be loaded once for the entire suite
+require 'spec/mocks'
+require 'spec/mocks/extensions'
+require 'spec/runner/formatter/specdoc_formatter'
+require 'base64'
+require 'nkf'
+require 'kconv'
+require 'rack'
+require 'fileutils'
+
+begin
+  require 'json'
+rescue
+  require 'json/pure'
+end
+
+Merb::Dispatcher
+
+module Merb
+  class Counter
+
+    attr_accessor :time
+    def initialize
+      @examples, @failures, @errors, @pending, @total_time = 0, 0, 0, 0, 0
+      @err = ""
+      @mutex = Mutex.new
+    end
+  
+    def failed?
+      @failures > 0
+    end
+  
+    def add(spec, out, err)
+      @mutex.synchronize do
+        puts
+        puts "Running #{spec}."
+        STDOUT.puts out
+        STDOUT.flush
+        match = out.match(/(\d+) examples?, (\d+) failures?(?:, (\d+) errors?)?(?:, (\d+) pending?)?/m)
+        time = out.match(/Finished in (\d+\.\d+) seconds/)
+        @total_time += time[1].to_f if time
+        if match
+          e, f, errors, pending = match[1..-1]
+          @examples += e.to_i
+          @failures += f.to_i
+          @errors += errors.to_i
+          @pending += pending.to_i
+        end
+        unless err.chomp.empty?
+          @err << err.chomp << "\n"
+        end
+      end
+    end
+
+    def report
+      i = 0
+      @err.gsub!(/^\d*\)\s*/) do
+        "#{i += 1})\n"
+      end
+      
+      puts @err
+      puts
+      if @failures != 0 || @errors != 0
+        print "\e[31m" # Red
+      elsif @pending != 0
+        print "\e[33m" # Yellow
+      else
+        print "\e[32m" # Green
+      end
+      puts "#{@examples} examples, #{@failures} failures, #{@errors} errors, #{@pending} pending, #{sprintf("suite run in %3.3f seconds", @time.real)}"
+      # TODO: we need to report pending examples all together
+       puts "\e[0m"    
+    end  
+  end
+end
+
+require File.dirname(__FILE__) / "run_spec"
+
+# Runs specs in all files matching the file pattern.
+#
+# ==== Parameters
+# globs<String, Array[String]>:: File patterns to look for.
+# spec_cmd<~to_s>:: The spec command. Defaults to "spec".
+# run_opts<String>:: Options to pass to spec commands, for instance,
+#                    if you want to use profiling formatter.
+# except<Array[String]>:: File paths to skip.
+def run_specs(globs, spec_cmd='spec', run_opts = "-c", except = [])
+  require "optparse"
+  require "spec"
+  globs = globs.is_a?(Array) ? globs : [globs]
+  
+  forking = (ENV["FORK"] ? ENV["FORK"] == "1" : Merb.forking_environment?)
+  base_dir = File.expand_path(File.dirname(__FILE__) / ".." / ".." / "..")
+  
+  counter = Merb::Counter.new
+  forks   = 0
+  failure = false
+
+  FileUtils.rm_rf(base_dir / "results")
+  FileUtils.mkdir_p(base_dir / "results")
+
+  time = Benchmark.measure do
+    files = {}
+    globs.each do |glob|
+      Dir[glob].each do |spec|
+        if forking
+          Kernel.fork do
+            run_spec(spec, base_dir)
+          end
+          Process.wait
+        else
+          `NOW=1 #{Gem.ruby} #{File.dirname(__FILE__) / "run_spec.rb"} \"#{spec}\"`
+        end
+        out = File.read(base_dir / "results" / "#{File.basename(spec)}_out")
+        err = File.read(base_dir / "results" / "#{File.basename(spec)}_err")
+        counter.add(spec, out, err)        
+      end
+    end
+  end
+  
+  Process.waitall
+  
+  counter.time = time
+  counter.report
+  FileUtils.rm_rf(base_dir / "results")  
+  exit!(counter.failed? ? -1 : 0)
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/tasks/spectasks.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/tasks/spectasks.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/tasks/spectasks.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,78 @@
+desc "Run specs, run a specific spec with TASK=spec/path_to_spec.rb"
+task :spec => [ "spec:default" ]
+
+namespace :spec do
+  OPTS_FILENAME = "./spec/spec.opts"
+  if File.exist?(OPTS_FILENAME)
+    SPEC_OPTS = ["--options", OPTS_FILENAME]
+  else
+    SPEC_OPTS = ["--color", "--format", "specdoc"]
+  end
+  
+  Spec::Rake::SpecTask.new('default') do |t|
+      t.spec_opts = SPEC_OPTS
+    if(ENV['TASK'])
+      t.spec_files = [ENV['TASK']]
+    else
+      t.spec_files = Dir['spec/**/*_spec.rb'].sort
+    end
+  end
+
+  desc "Run all model specs, run a spec for a specific Model with MODEL=MyModel"
+  Spec::Rake::SpecTask.new('model') do |t|
+    t.spec_opts = SPEC_OPTS
+    if(ENV['MODEL'])
+      t.spec_files = Dir["spec/models/**/#{ENV['MODEL']}_spec.rb"].sort
+    else
+      t.spec_files = Dir['spec/models/**/*_spec.rb'].sort
+    end
+  end
+
+  desc "Run all request specs, run a spec for a specific Request with REQUEST=MyRequest"
+  Spec::Rake::SpecTask.new('request') do |t|
+    t.spec_opts = SPEC_OPTS
+    if(ENV['REQUEST'])
+      t.spec_files = Dir["spec/requests/**/#{ENV['REQUEST']}_spec.rb"].sort
+    else    
+      t.spec_files = Dir['spec/requests/**/*_spec.rb'].sort
+    end
+  end
+  
+  desc "Run all controller specs, run a spec for a specific Controller with CONTROLLER=MyController"
+  Spec::Rake::SpecTask.new('controller') do |t|
+    t.spec_opts = SPEC_OPTS
+    if(ENV['CONTROLLER'])
+      t.spec_files = Dir["spec/controllers/**/#{ENV['CONTROLLER']}_spec.rb"].sort
+    else    
+      t.spec_files = Dir['spec/controllers/**/*_spec.rb'].sort
+    end
+  end
+  
+  desc "Run all view specs, run specs for a specific controller (and view) with CONTROLLER=MyController (VIEW=MyView)"
+  Spec::Rake::SpecTask.new('view') do |t|
+    t.spec_opts = SPEC_OPTS
+    if(ENV['CONTROLLER'] and ENV['VIEW'])
+      t.spec_files = Dir["spec/views/**/#{ENV['CONTROLLER']}/#{ENV['VIEW']}*_spec.rb"].sort
+    elsif(ENV['CONTROLLER'])
+      t.spec_files = Dir["spec/views/**/#{ENV['CONTROLLER']}/*_spec.rb"].sort
+    else
+      t.spec_files = Dir['spec/views/**/*_spec.rb'].sort
+    end
+  end
+
+  desc "Run all specs and output the result in html"
+  Spec::Rake::SpecTask.new('html') do |t|
+    t.spec_opts = ["--format", "html"]
+    t.libs = ['lib', 'server/lib' ]
+    t.spec_files = Dir['spec/**/*_spec.rb'].sort
+  end
+
+  desc "Run specs and check coverage with rcov"
+  Spec::Rake::SpecTask.new('coverage') do |t|
+    t.spec_opts = SPEC_OPTS
+    t.spec_files = Dir['spec/**/*_spec.rb'].sort
+    t.libs = ['lib', 'server/lib' ]
+    t.rcov = true
+    t.rcov_opts = ["--exclude 'config,spec,#{Gem::path.join(',')}'"]    
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/hpricot.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/hpricot.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/hpricot.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,32 @@
+# http://yehudakatz.com/2007/01/27/a-better-assert_select-assert_elements/
+# based on assert_elements
+# Author: Yehuda Katz
+# Email:  wycats @nospam@ gmail.com
+# Web:    http://www.yehudakatz.com
+#
+# which was based on HpricotTestHelper
+# Author: Luke Redpath
+# Email: contact @nospam@ lukeredpath.co.uk
+# Web: www.lukeredpath.co.uk / opensource.agileevolved.com
+
+class Hpricot::Elem
+  def contain?(value)
+    self.inner_text.include?(value)
+  end
+  
+  alias_method :contains?, :contain?
+
+  def match?(regex)
+    self.inner_text.match(regex)
+  end
+  
+  alias_method :matches?, :match?
+  
+  # courtesy of 'thomas' from the comments
+  # of _whys blog - get in touch if you want a better credit!
+  def inner_text
+    self.children.collect do |child|
+      child.is_a?(Hpricot::Text) ? child.content : ((child.respond_to?("inner_text") && child.inner_text) || "")
+    end.join.strip
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/object.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/object.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/object.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,14 @@
+class Object
+  # ==== Parameters
+  # attr<~to_s>:: The name of the instance variable to get.
+  #
+  # ==== Returns
+  # Object:: The instance variable @attr for this object.
+  # 
+  # ==== Examples
+  #   # In a spec
+  #   @my_obj.assigns(:my_value).should == @my_value
+  def assigns(attr)
+    self.instance_variable_get("@#{attr}")
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/rspec.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/rspec.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/rspec.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,168 @@
+require 'spec'
+module Kernel
+  def given(*args, &example_group_block)
+    args << {} unless Hash === args.last
+    params = args.last
+    
+    params[:shared] = true
+    
+    describe(*args) do
+      prepend_before(:each) do
+        self.instance_eval(&example_group_block)
+      end
+    end
+  end  
+end
+
+module Spec
+  module Matchers
+    def fail
+      raise_error(Spec::Expectations::ExpectationNotMetError)
+    end
+
+    def fail_with(message)
+      raise_error(Spec::Expectations::ExpectationNotMetError, message)
+    end
+  end
+end
+
+module Merb
+  module Test
+    def self.add_helpers(&block)
+      if Merb.test_framework == :rspec
+        ExampleGroup.class_eval(&block)
+      else
+        raise NotImplementedError
+      end
+    end
+
+    module Matchers
+    end
+    
+    class ExampleGroup < Spec::Example::ExampleGroup
+      include ::Merb::Test::Matchers
+      include ::Merb::Test::RouteHelper
+      include ::Merb::Test::ControllerHelper
+      
+      if defined?(::Webrat)
+        include ::Webrat::Methods
+      end
+      
+      class << self
+        # This is a copy of the method in rspec, so we can have
+        # describe "...", :when => "logged in", and the like
+        def describe(*args, &example_group_block)
+          ret = super
+          
+          params = args.last.is_a?(Hash) ? args.last : {}
+          if example_group_block
+            params[:when] = params[:when] || params[:given]
+            ret.module_eval %{it_should_behave_like "#{params[:when]}"} if params[:when]
+          end
+        end
+        alias context describe
+
+        def given(*args, &example_group_block)
+          args << {} unless Hash === args.last
+          params = args.last
+          
+          params[:shared] = true
+          
+          describe(*args, &example_group_block)
+        end
+      end
+
+      ::Spec::Example::ExampleGroupFactory.default(self)
+    end
+  end
+end
+
+module Spec
+  module Matchers
+  
+    def self.create(*names, &block)
+      @guid ||= 0
+      Merb::Test::Matchers.module_eval do
+        klass = Class.new(MatcherDSL) do
+          def initialize(expected_value)
+            @expected_value = expected_value
+          end          
+        end
+        klass.class_eval(&block)
+        
+        names.each do |name|
+          define_method(name) do |*expected_value|
+            # Avoid a warning for the form should foo.
+            klass.new(expected_value && expected_value[0])
+          end
+        end
+      end
+    end
+  
+    class MatcherDSL
+      include Merb::Test::RouteHelper
+      
+      def self.matches(&block)
+        define_method(:matches_proxy, &block)
+        
+        define_method(:matches?) do |object|
+          @object = object
+          if block.arity == 2
+            matches_proxy(@object, @expected_value)
+          else
+            matches_proxy(@object)
+          end
+        end
+      end
+      
+      def self.expected_value(&block)
+        define_method(:transform_expected, &block)
+        
+        define_method(:initialize) do |expected_value|
+          @expected_value = transform_expected(expected_value) || expected_value
+        end
+      end
+      
+      def self.negative_failure_message(&block)
+        define_method(:proxy_negative_failure_message, &block)
+        
+        define_method(:negative_failure_message) do
+          proxy_negative_failure_message(@object, @expected_value)
+        end
+      end
+
+      def self.failure_message(&block)
+        define_method(:proxy_failure_message, &block)
+        
+        define_method(:failure_message) do
+          proxy_failure_message(@object, @expected_value)
+        end
+      end
+      
+      def self.message(&block)
+        class_eval do
+          def failure_message
+            generic_message(@object, @expected_value, nil)
+          end
+          
+          def negative_failure_message
+            generic_message(@object, @expected_value, " not")
+          end
+        end
+        
+        define_method(:proxy_generic_message, &block)
+
+        ar = block.arity
+        
+        define_method(:generic_message) do |object, expected, not_string|
+          if ar == 3
+            proxy_generic_message(not_string, object, expected)
+          else
+            proxy_generic_message(not_string, object)
+          end
+        end
+      end
+    end
+  
+  end
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/string.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/string.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test/test_ext/string.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,14 @@
+class String
+  def contain?(value)
+    self.include?(value)
+  end
+  
+  alias_method :contains?, :contain?
+
+  def match?(regex)
+    self.match(regex)
+  end
+  
+  alias_method :matches?, :match?
+  
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/test.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,21 @@
+require 'merb-core/test/test_ext/object'
+require 'merb-core/test/test_ext/string'
+
+module Merb; module Test; end; end
+
+require 'merb-core/test/helpers'
+
+begin
+  require 'webrat'
+  require 'webrat/merb'
+rescue LoadError => e
+  if Merb.testing?
+    Merb.logger.warn! "Couldn't load Webrat, so some features, like `visit' will not " \
+                      "be available. Please install webrat if you want these features."
+  end
+end
+
+if Merb.test_framework.to_s == "rspec"
+  require 'merb-core/test/test_ext/rspec'
+  require 'merb-core/test/matchers'
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/two-oh.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/two-oh.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/two-oh.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,50 @@
+module Merb::Test::MultipartRequestHelper
+  
+  def multipart_request(path, params = {}, env = {})
+    multipart = Merb::Test::MultipartRequestHelper::Post.new(params)
+    body, head = multipart.to_multipart
+    env["CONTENT_TYPE"] = head
+    env["CONTENT_LENGTH"] = body.size
+    env[:input] = StringIO.new(body)
+    request(path, env)
+  end
+
+  # An HTTP POST request that operates through the router and uses multipart
+  # parameters.
+  #
+  # ==== Parameters
+  # path<String>:: The path that should go to the router as the request uri.
+  # params<Hash>::
+  #   An optional hash that will end up as params in the controller instance.
+  # env<Hash>::
+  #   An optional hash that is passed to the fake request. Any request options
+  #   should go here (see +fake_request+).
+  # block<Proc>:: The block is executed in the context of the controller.
+  #
+  # ==== Notes
+  # To include an uploaded file, put a file object as a value in params.
+  def multipart_post(path, params = {}, env = {})
+    env[:method] = "POST"
+    multipart_request(path, params, env)
+  end
+
+  # An HTTP PUT request that operates through the router and uses multipart
+  # parameters.
+  #
+  # ==== Parameters
+  # path<String>:: The path that should go to the router as the request uri.
+  # params<Hash>::
+  #   An optional hash that will end up as params in the controller instance.
+  # env<Hash>::
+  #   An optional hash that is passed to the fake request. Any request options
+  #   should go here (see +fake_request+).
+  # block<Proc>:: The block is executed in the context of the controller.
+  #
+  # ==== Notes
+  # To include an uplaoded file, put a file object as a value in params.
+  def multipart_put(path, params = {}, env = {}, &block)
+    env[:method] = "PUT"
+    multipart_request(path, params, env)
+  end
+  
+end
\ No newline at end of file

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/version.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/version.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core/version.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,5 @@
+module Merb
+  VERSION    = '1.0.12'  unless defined?(Merb::VERSION)
+  DM_VERSION = '0.9.11' unless defined?(Merb::DM_VERSION)
+  DO_VERSION = '0.9.11' unless defined?(Merb::DO_VERSION)
+end

Added: packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core.rb
===================================================================
--- packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core.rb	                        (rev 0)
+++ packages-wip/merb/trunk/merb-core/debian/libmerb-core-ruby1.8/usr/lib/ruby/1.8/merb-core.rb	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,800 @@
+# require 'merb' must happen after Merb::Config is instantiated
+require "rubygems"
+
+# Add the local gems dir if found within the app root; any dependencies loaded
+# hereafter will try to load from the local gems before loading system gems.
+root_key = %w[-m --merb-root].detect { |o| ARGV.index(o) }
+root = ARGV[ARGV.index(root_key) + 1] if root_key
+root = root.to_a.empty? ? Dir.getwd : root
+if File.directory?(gems_dir = File.join(root, "gems")) && !$BUNDLE
+  $BUNDLE = true; Gem.clear_paths; Gem.path.unshift(gems_dir)
+  # Warn if local merb-core is available but not loaded.
+  if File.expand_path($0).index(root) != 0 && 
+    (local_mc = Dir[File.join(gems_dir, "specifications", "merb-core-*.gemspec")].last)
+    puts "Warning: please use bin/#{File.basename($0)} to load #{File.basename(local_mc, ".gemspec")} from ./gems"
+  end
+end
+
+require "thread"
+require "set"
+require "fileutils"
+require "socket"
+require "pathname"
+require "extlib"
+require "extlib/dictionary"
+
+Thread.abort_on_exception = true
+
+__DIR__ = File.dirname(__FILE__)
+
+$LOAD_PATH.unshift __DIR__ unless
+  $LOAD_PATH.include?(__DIR__) ||
+  $LOAD_PATH.include?(File.expand_path(__DIR__))
+
+# Some dependencies tend to require&rescue for optionally required files;
+# doing so will load the full rubygems, even though it was just optional.
+$MINIGEMS_SKIPPABLE = ['encoding/character/utf-8']
+
+module Merb
+  # Create stub module for global controller helpers.
+  module GlobalHelpers; end
+  class ReservedError < StandardError; end
+  
+  class << self
+    attr_reader :exiting
+
+    # The list of procs that have been registered with Merb to run when
+    # Merb exits gracefully.
+    #
+    # ==== Returns
+    # Array:: The current list of procs
+    #
+    # :api: private
+    def at_exit_procs
+      @at_exit_procs ||= []
+    end
+    
+    # Set the current exiting state of Merb. Setting this state to true
+    # also alerts Extlib to exit and clean up its state.
+    #
+    # ==== Returns
+    # Boolean:: The current exiting state of Merb
+    #
+    # :api: private
+    def exiting=(bool)
+      Extlib.exiting = bool
+      @exiting = bool
+      if bool
+        if Extlib.const_defined?("Pooling") && Extlib::Pooling.scavenger
+          Extlib::Pooling.scavenger.wakeup
+        end
+        while prc = self.at_exit_procs.pop
+          prc.call
+        end unless Merb::Config[:reap_workers_quickly]
+      end
+      @exiting
+    end
+    
+    # Register a proc to run when Merb is exiting gracefully. It will *not*
+    # be run when Merb exits quickly.
+    #
+    # ==== Returns
+    # Array:: The current list of procs to run when Merb exits gracefully
+    #
+    # :api: plugin
+    def at_exit(&blk)
+      self.at_exit_procs << blk
+    end
+
+    # Merge environment settings
+    #
+    # This can allow you to have a "localdev" environment that runs like your "development".
+    #   OR
+    # A "staging" environment that runs identical to your "production" environment.
+    #
+    # ==== Examples
+    # From any environment config file (ie, development.rb, custom.rb, localdev.rb, etc).
+    #   staging.rb:
+    #     Merb.merge_env "production"         # We want to use all the settings production uses
+    #     Merb::Config.use do |c|
+    #       c[:log_level]         = "debug"   # except we want debug log level
+    #       c[:log_stream]        = @some_io  # and log to this IO handle
+    #       c[:exception_details] = true      # and we want to see exception details
+    #     end
+    #
+    # ==== Parameters
+    # env<~String>:: Environment to run like
+    # use_db<~Boolean>:: Should Merb use the merged environments DB connection
+    #     Defaults to +false+
+    #
+    # :api: public
+    def merge_env(env,use_db=false)
+      if Merb.environment_info.nil?
+        Merb.environment_info = {
+          :real_env => Merb.environment,
+          :merged_envs => [],
+          :db_env => Merb.environment
+        }
+      end
+      
+      #Only load if it hasn't been loaded
+      unless Merb.environment_info[:merged_envs].member? env
+        Merb.environment_info[:merged_envs] << env
+        
+        env_file = Merb.dir_for(:config) / "environments" / ("#{env}.rb")
+        if File.exists?(env_file)
+          load(env_file)
+        else
+          Merb.logger.warn! "Environment file does not exist! #{env_file}"
+        end
+      end
+      
+      # Mark specific environment to load when ORM loads,
+      # if multiple environments are loaded, the last one
+      # with use_db as TRUE will be loaded
+      if use_db
+        Merb.environment_info[:db_env] = env
+      end
+    end
+
+    # Start Merb by setting up the Config and then starting the server.
+    # Set the Merb application environment and the root path.
+    #
+    # ==== Parameters
+    # argv<String, Hash>::
+    #   The config arguments to start Merb with. Defaults to +ARGV+.
+    #
+    # :api: public
+    def start(argv = ARGV)
+      Merb::Config[:original_log_stream] = Merb::Config[:log_stream]
+      Merb::Config[:log_stream] ||= STDOUT
+      if Hash === argv
+        Merb::Config.setup(argv)
+      elsif !argv.nil?
+        Merb::Config.parse_args(argv)
+      end
+
+      Merb::Config[:log_stream] = STDOUT
+      
+      Merb.environment = Merb::Config[:environment]
+      Merb.root = Merb::Config[:merb_root]
+
+      case Merb::Config[:action]
+      when :kill
+        Merb::Server.kill(Merb::Config[:port], 2)
+      when :kill_9
+        Merb::Server.kill(Merb::Config[:port], 9)
+      when :fast_deploy
+        Merb::Server.kill("main", "HUP")
+      else
+        Merb::Server.start(Merb::Config[:port], Merb::Config[:cluster])
+        @started = true
+      end
+    end
+
+    # Start the Merb environment, but only if it hasn't been loaded yet.
+    #
+    # ==== Parameters
+    # argv<String, Hash>::
+    #   The config arguments to start Merb with. Defaults to +ARGV+.
+    #
+    # :api: public
+    def start_environment(argv=ARGV)
+      start(argv) unless (@started ||= false)
+    end
+
+    # Restart the Merb environment explicitly.
+    #
+    # ==== Parameters
+    # argv<String, Hash>::
+    #   The config arguments to restart Merb with. Defaults to +Merb::Config+.
+    #
+    # :api: public
+    def restart_environment(argv={})
+      @started = false
+      start_environment(Merb::Config.to_hash.merge(argv))
+    end
+
+    # :api: public
+    attr_accessor :environment, :adapter
+    # :api: private
+    attr_accessor :load_paths, :environment_info, :started
+
+    # :api: public
+    alias :env :environment
+    # :api: public
+    alias :started? :started
+
+    Merb.load_paths = Dictionary.new { [Merb.root] } unless Merb.load_paths.is_a?(Dictionary)
+
+    # This is the mechanism for setting up your application layout.
+    # There are three application layouts in Merb:
+    #
+    # 1. Regular app/:type layout of Ruby on Rails fame:
+    #
+    # app/models       for models
+    # app/mailers      for mailers (special type of controllers)
+    # app/parts        for parts, Merb components
+    # app/views        for templates
+    # app/controllers  for controller
+    # lib              for libraries
+    #
+    # 2. Flat application layout:
+    #
+    # application.rb       for models, controllers, mailers, etc
+    # config/init.rb       for initialization and router configuration
+    # config/framework.rb  for framework and dependencies configuration
+    # views                for views
+    #
+    # 3. Camping-style "very flat" application layout, where the whole Merb
+    # application and configs are contained within a single file.
+    #
+    # ==== Notes
+    # Autoloading for lib uses an empty glob by default. If you
+    # want to have your libraries under lib use autoload, add
+    # the following to Merb init file:
+    #
+    # Merb.push_path(:lib, Merb.root / "lib", "**/*.rb") # glob set explicity.
+    #
+    # Then lib/magicwand/lib/magicwand.rb with MagicWand module will
+    # be autoloaded when you first access that constant.
+    #
+    # ==== Examples
+    # This method gives you a way to build up your own application
+    # structure, for instance, to reflect the structure Rails
+    # uses to simplify transition of legacy application, you can
+    # set it up like this:
+    #
+    # Merb.push_path(:model,      Merb.root / "app" / "models",      "**/*.rb")
+    # Merb.push_path(:mailer,     Merb.root / "app" / "models",      "**/*.rb")
+    # Merb.push_path(:controller, Merb.root / "app" / "controllers", "**/*.rb")
+    # Merb.push_path(:view,       Merb.root / "app" / "views",       "**/*.rb")
+    #
+    # ==== Parameters
+    # type<Symbol>:: The type of path being registered (i.e. :view)
+    # path<String>:: The full path
+    # file_glob<String>::
+    #   A glob that will be used to autoload files under the path. Defaults to
+    #   "**/*.rb".
+    #
+    # :api: public
+    def push_path(type, path, file_glob = "**/*.rb")
+      enforce!(type => Symbol)
+      load_paths[type] = [path, file_glob]
+    end
+
+    # Removes given types of application components
+    # from load path Merb uses for autoloading.
+    #
+    # ==== Parameters
+    # *args<Array(Symbol)>::
+    #   component(s) names, for instance, :views, :models
+    #
+    # ==== Examples
+    # Using this combined with Merb::GlobalHelpers.push_path you can make 
+    # your Merb application use legacy Rails application components.
+    #
+    # Merb.root = "path/to/legacy/app/root"
+    # Merb.remove_paths(:mailer)
+    # Merb.push_path(:mailer, Merb.root / "app" / "models", "**/*.rb")
+    #
+    # Will make Merb use app/models for mailers just like Ruby on Rails does.
+    #
+    # :api: public
+    def remove_paths(*args)
+      args.each {|arg| load_paths.delete(arg)}
+    end
+
+    # ==== Parameters
+    # type<Symbol>:: The type of path to retrieve directory for, e.g. :view.
+    #
+    # ==== Returns
+    # String:: The directory for the requested type.
+    #
+    # :api: public
+    def dir_for(type)
+      Merb.load_paths[type].first
+    end
+
+    # ==== Parameters
+    # type<Symbol>:: The type of path to retrieve glob for, e.g. :view.
+    #
+    # ===== Returns
+    # String:: The pattern with which to match files within the type directory.
+    #
+    # :api: public
+    def glob_for(type)
+      Merb.load_paths[type][1]
+    end
+
+    # ==== Returns
+    # String:: The Merb root path.
+    #
+    # :api: public
+    def root
+      @root || Merb::Config[:merb_root] || File.expand_path(Dir.pwd)
+    end
+
+    # ==== Parameters
+    # value<String>:: Path to the root directory.
+    #
+    # :api: public
+    def root=(value)
+      @root = value
+    end
+
+    # ==== Parameters
+    # *path::
+    #   The relative path (or list of path components) to a directory under the
+    #   root of the application.
+    #
+    # ==== Returns
+    # String:: The full path including the root.
+    #
+    # ==== Examples
+    #   Merb.root = "/home/merb/app"
+    #   Merb.path("images") # => "/home/merb/app/images"
+    #   Merb.path("views", "admin") # => "/home/merb/app/views/admin"
+    #
+    # @public
+    def root_path(*path)
+      File.join(root, *path)
+    end
+
+    # Return the Merb Logger object for the current thread.
+    # Set it up if it does not exist.
+    # 
+    # :api: public
+    def logger
+      Thread.current[:merb_logger] ||= Merb::Logger.new
+    end
+
+    # Removes the logger for the current thread (nil).
+    # 
+    # :api: public
+    def reset_logger!
+      Thread.current[:merb_logger] = nil
+    end
+
+    # ==== Returns
+    # String::
+    #   The path to the log file. 
+    #   If this Merb instance is running as a daemon this will return +STDOUT+.
+    #
+    # ==== Notes
+    # When Merb.testing? the port is modified to become :test - this keeps this
+    # special environment situation from ending up in the memoized @streams
+    # just once, thereby never taking changes into account again. Now, it will
+    # be memoized as :test - and just logging to merb_test.log.
+    # 
+    # :api: public
+    def log_stream(port = "main")
+      port = :test if Merb.testing?
+      @streams ||= {}
+      @streams[port] ||= begin
+        log = if Merb.testing?
+          log_path / "merb_test.log"
+        elsif !Merb::Config[:daemonize] && !Merb::Config[:force_logging]
+          STDOUT
+        else
+          log_path / "merb.#{port}.log"
+        end
+        
+        if log.is_a?(IO)
+          stream = log
+        elsif File.exist?(log)
+          stream = File.open(log, (File::WRONLY | File::APPEND))
+        else
+          FileUtils.mkdir_p(File.dirname(log))
+          stream = File.open(log, (File::WRONLY | File::APPEND | File::CREAT))
+          stream.write("#{Time.now.httpdate} #{Merb::Config[:log_delimiter]} " \
+            "info #{Merb::Config[:log_delimiter]} Logfile created\n")
+        end
+        stream.sync = true
+        stream
+      end
+    end
+
+    # ==== Returns
+    # String:: Path to the log directory which contains the log file.
+    # 
+    # :api: public
+    def log_path
+      case Merb::Config[:log_file]
+      when String then File.dirname(Merb::Config[:log_file])
+      else Merb.root_path("log")
+      end
+    end
+
+    # ==== Returns
+    # String:: The path of root directory of the Merb framework.
+    # 
+    # :api: public
+    def framework_root
+      @framework_root ||= File.dirname(__FILE__)
+    end
+
+    # ==== Returns
+    # RegExp::
+    #   Regular expression against which deferred actions
+    #   are matched by Rack application handler.
+    #
+    # ==== Notes
+    # Concatenates :deferred_actions configuration option values.
+    # 
+    # :api: public
+    def deferred_actions
+      @deferred ||= begin
+        if Merb::Config[:deferred_actions].empty?
+          /^\0$/
+        else
+          /#{Merb::Config[:deferred_actions].join("|")}/
+        end
+      end
+    end
+
+    # Perform a hard Exit.
+    # Print a backtrace to the merb logger before exiting if verbose is enabled.
+    #
+    # :api: private
+    def fatal!(str, e = nil)
+      Merb::Config[:log_stream] = STDOUT if STDOUT.tty?
+      Merb.reset_logger!
+      
+      Merb.logger.fatal!
+      Merb.logger.fatal!("\e[1;31;47mFATAL: #{str}\e[0m")
+      Merb.logger.fatal!
+
+      print_colorized_backtrace(e) if e && Merb::Config[:verbose]
+      
+      if Merb::Config[:show_ugly_backtraces]
+        raise e
+      else
+        exit(1)
+      end
+    end
+    
+    # Print a colorized backtrace to the merb logger.
+    #
+    # :api: private
+    def print_colorized_backtrace(e)      
+      e.backtrace.map! do |line|
+        line.gsub(/^#{Merb.framework_root}/, "\e[34mFRAMEWORK_ROOT\e[31m")
+      end
+      
+      Merb.logger.fatal! "\e[34mFRAMEWORK_ROOT\e[0m = #{Merb.framework_root}"
+      Merb.logger.fatal!
+      Merb.logger.fatal! "\e[31m#{e.class}: \e[1;31;47m#{e.message}\e[0m"
+      e.backtrace.each do |line|
+        Merb.logger.fatal! "\e[31m#{line}\e[0m"
+      end      
+    end
+
+    # Set up default variables under Merb
+    attr_accessor :klass_hashes, :orm, :test_framework, :template_engine
+
+    # Returns the default ORM for this application. For instance, :datamapper.
+    #
+    # ==== Returns
+    # <Symbol>:: default ORM.
+    #
+    # :api: public
+    def orm
+      @orm ||= :none
+    end
+    
+    # @deprecated
+    def orm_generator_scope
+      Merb.logger.warn!("WARNING: Merb.orm_generator_scope is deprecated!")
+      return :merb_default if Merb.orm == :none
+      Merb.orm
+    end
+
+    # Returns the default test framework for this application. For instance :rspec.
+    #
+    # ==== Returns
+    # <Symbol>:: default test framework.
+    #
+    # :api: public
+    def test_framework
+      @test_framework ||= :rspec
+    end
+    
+    # @deprecated
+    def test_framework_generator_scope
+      Merb.logger.warn!("WARNING: Merb.test_framework_generator_scope is deprecated")
+      Merb.test_framework
+    end
+    
+    # Returns the default template engine for this application. For instance :haml.
+    #
+    # ==== Returns
+    # <Symbol>:: default template engine.
+    #
+    # :api: public
+    def template_engine
+      @template_engine ||= :erb
+    end
+
+    Merb.klass_hashes = []
+
+    # ==== Returns
+    # Boolean:: True if Merb is running as an application with bundled gems.
+    #
+    # ==== Notes
+    # Bundling required gems makes your application independent from the 
+    # environment it runs in. It is a good practice to freeze application 
+    # framework and gems and is very useful when application is run in 
+    # some sort of sandbox, for instance, shared hosting with preconfigured gems.
+    #
+    # :api: public
+    def bundled?
+      $BUNDLE || ENV.key?("BUNDLE")
+    end
+
+    # Load configuration and assign the logger.
+    #
+    # ==== Parameters
+    # options<Hash>:: Options to pass on to the Merb config.
+    #
+    # ==== Options
+    # :host<String>::             host to bind to,
+    #                             default is 0.0.0.0.
+    #
+    # :port<Fixnum>::             port to run Merb application on,
+    #                             default is 4000.
+    #
+    # :adapter<String>::          name of Rack adapter to use,
+    #                             default is "runner"
+    #
+    # :rackup<String>::           name of Rack init file to use,
+    #                             default is "rack.rb"
+    #
+    # :reload_classes<Boolean>::  whether Merb should reload
+    #                             classes on each request,
+    #                             default is true
+    #
+    # :environment<String>::      name of environment to use,
+    #                             default is development
+    #
+    # :merb_root<String>::        Merb application root,
+    #                             default is Dir.pwd
+    #
+    # :use_mutex<Boolean>::       turns action dispatch synchronization
+    #                             on or off, default is on (true)
+    #
+    # :log_delimiter<String>::    what Merb logger uses as delimiter
+    #                             between message sections, default is " ~ "
+    #
+    # :log_auto_flush<Boolean>::  whether the log should automatically
+    #                             flush after new messages are
+    #                             added, defaults to true.
+    #
+    # :log_stream<IO>::           IO handle for logger. Defaults to STDOUT.
+    #
+    # :log_file<String>::         File path for logger. Overrides :log_stream.
+    #
+    # :log_level<Symbol>::        logger level, default is :info
+    #
+    # :disabled_components<Array[Symbol]>::
+    #   array of disabled component names,
+    #   for instance, to disable json gem,
+    #   specify :json. Default is empty array.
+    #
+    # :deferred_actions<Array(Symbol, String)]>::
+    #   names of actions that should be deferred
+    #   no matter what controller they belong to.
+    #   Default is empty array.
+    #
+    # Some of these options come from command line on Merb
+    # application start, some of them are set in Merb init file
+    # or environment-specific.
+    #
+    # :api: public
+    def load_config(options = {})
+      Merb::Config.setup(Merb::Config.defaults.merge(options))
+      Merb::BootLoader::Logger.run
+    end
+
+    # Load all basic dependencies (selected BootLoaders only).
+    # This sets up Merb framework component paths
+    # (directories for models, controllers, etc) using
+    # framework.rb or default layout, loads init file
+    # and dependencies specified in it and runs before_app_loads hooks.
+    #
+    # ==== Parameters
+    # options<Hash>:: Options to pass on to the Merb config.
+    #
+    # :api: public
+    def load_dependencies(options = {})
+      load_config(options)
+      Merb::BootLoader::BuildFramework.run
+      Merb::BootLoader::Dependencies.run
+      Merb::BootLoader::BeforeAppLoads.run
+    end
+
+    # Reload application and framework classes.
+    # See Merb::BootLoader::ReloadClasses for details.
+    #
+    # :api: public
+    def reload
+      Merb::BootLoader::ReloadClasses.reload
+    end
+
+    # ==== Returns
+    # Boolean:: True if Merb environment is testing for instance,
+    # Merb is running with RSpec, Test::Unit of other testing facility.
+    #
+    # :api: public
+    def testing?
+      $TESTING ||= env?(:test) || Merb::Config[:testing]
+    end
+
+    # Ask the question about which environment you're in.
+    # ==== Parameters
+    # env<Symbol, String>:: Name of the environment to query
+    #
+    # ==== Examples
+    # Merb.env #=> production
+    # Merb.env?(:production) #=> true
+    # Merb.env?(:development) #=> false
+    #
+    # :api: public
+    def env?(env)
+      Merb.env == env.to_s
+    end
+
+    # If block was given configures using the block.
+    #
+    # ==== Parameters
+    # &block:: Configuration parameter block, see example below.
+    #
+    # ==== Returns
+    # Hash:: The current configuration.
+    #
+    # ==== Notes
+    # See Merb::GlobalHelpers.load_config for configuration
+    # options list.
+    #
+    # ==== Examples
+    #   Merb.config do
+    #     beer               "good"
+    #     hashish            :foo => "bar"
+    #     environment        "development"
+    #     log_level          "debug"
+    #     use_mutex          false
+    #     exception_details  true
+    #     reload_classes     true
+    #     reload_time        0.5
+    #   end
+    #
+    # :api: public
+    def config(&block)
+      Merb::Config.configure(&block) if block_given?
+      Config
+    end
+
+    # Disables the given core components, like a Gem for example.
+    #
+    # ==== Parameters
+    # *args:: One or more symbols of Merb internal components.
+    #
+    # :api: public
+    def disable(*components)
+      disabled_components.push(*components)
+    end
+
+    # ==== Parameters
+    # Array:: All components that should be disabled.
+    #
+    # :api: public
+    def disabled_components=(components)
+      disabled_components.replace components
+    end
+
+    # ==== Returns
+    # Array:: All components that have been disabled.
+    #
+    # :api: public
+    def disabled_components
+      Merb::Config[:disabled_components] ||= []
+    end
+
+    # ==== Returns
+    # Boolean:: True if all components (or just one) are disabled.
+    #
+    # :api: public
+    def disabled?(*components)
+      components.all? { |c| disabled_components.include?(c) }
+    end
+
+    # ==== Returns
+    # Array(String):: Paths Rakefiles are loaded from.
+    #
+    # ==== Notes
+    # Recommended way to find out what paths Rakefiles
+    # are loaded from.
+    #
+    # :api: public
+    def rakefiles
+      @rakefiles ||= []
+    end
+    
+    # === Returns
+    # Array(String):: Paths generators are loaded from
+    #
+    # === Notes
+    # Recommended way to find out what paths generators are loaded from.
+    #
+    # :api: public
+    def generators
+      @generators ||= []
+    end
+
+    # ==== Parameters
+    # *rakefiles:: Rakefile paths to add to the list of Rakefiles.
+    #
+    # ==== Notes
+    # Recommended way to add Rakefiles load path for plugins authors.
+    #
+    # :api: public
+    def add_rakefiles(*rakefiles)
+      @rakefiles ||= []
+      @rakefiles += rakefiles
+    end
+    
+    # ==== Parameters
+    # *generators:: Generator paths to add to the list of generators.
+    #
+    # ==== Notes
+    # Recommended way to add Generator load paths for plugin authors.
+    #
+    # :api: public
+    def add_generators(*generators)
+      @generators ||= []
+      @generators += generators
+    end
+
+    # Install a signal handler for a given signal unless signals have
+    # been disabled with Merb.disable(:signals)
+    # ==== Parameters
+    # signal:: The name of the signal to install a handler for.
+    # &block:: The block to be run when the given signal is received.
+    #
+    # :api: public
+    def trap(signal, &block)
+      if Signal.list.include?(signal)
+        Kernel.trap(signal, &block) unless Merb.disabled?(:signals)
+      end
+    end
+
+    # :api: plugin
+    def forking_environment?
+      !on_windows? && !on_jruby?
+    end
+
+    # :api: plugin
+    def on_jruby?
+      RUBY_PLATFORM =~ Merb::Const::JAVA_PLATFORM_REGEXP
+    end
+
+    # :api: plugin
+    def on_windows?
+      RUBY_PLATFORM =~ Merb::Const::WIN_PLATFORM_REGEXP
+    end
+
+    def run_later(&blk)
+      Merb::Dispatcher.work_queue << blk
+    end
+  end
+end
+
+require "merb-core/autoload"
+require "merb-core/server"
+require "merb-core/gem_ext/erubis"
+require "merb-core/logger"
+require "merb-core/version"
+require "merb-core/controller/mime"
+
+# Set the environment if it hasn't already been set.
+Merb.environment ||= ENV["MERB_ENV"] || Merb::Config[:environment] || (Merb.testing? ? "test" : "development")

Added: packages-wip/merb/trunk/merb-gen/.config
===================================================================
--- packages-wip/merb/trunk/merb-gen/.config	                        (rev 0)
+++ packages-wip/merb/trunk/merb-gen/.config	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,20 @@
+prefix=/usr
+bindir=$prefix/bin
+libdir=$prefix/lib
+datadir=$prefix/share
+mandir=$prefix/share/man
+sysconfdir=/etc
+localstatedir=/var
+libruby=/usr/lib/ruby
+librubyver=/usr/lib/ruby/1.8
+librubyverarch=/usr/lib/ruby/1.8/i486-linux
+siteruby=/usr/local/lib/site_ruby
+siterubyver=/usr/local/lib/site_ruby/1.8
+siterubyverarch=/usr/local/lib/site_ruby/1.8/i486-linux
+rbdir=$librubyver
+sodir=$librubyverarch
+rubypath=/usr/bin/ruby1.8
+rubyprog=/usr/bin/ruby1.8
+makeprog=make
+shebang=ruby
+without-ext=no

Added: packages-wip/merb/trunk/merb-gen/InstalledFiles
===================================================================
--- packages-wip/merb/trunk/merb-gen/InstalledFiles	                        (rev 0)
+++ packages-wip/merb/trunk/merb-gen/InstalledFiles	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,143 @@
+/usr/bin/merb-gen
+/usr/lib/ruby/1.8/merb-gen.rb
+/usr/lib/ruby/1.8/merb-gen/app_generator.rb
+/usr/lib/ruby/1.8/merb-gen/templater.rb
+/usr/lib/ruby/1.8/merb-gen/generator.rb
+/usr/lib/ruby/1.8/merb-gen/namespaced_generator.rb
+/usr/lib/ruby/1.8/merb-gen/named_generator.rb
+/usr/lib/ruby/1.8/generators/helper.rb
+/usr/lib/ruby/1.8/generators/resource.rb
+/usr/lib/ruby/1.8/generators/thor.rb
+/usr/lib/ruby/1.8/generators/model.rb
+/usr/lib/ruby/1.8/generators/session_migration.rb
+/usr/lib/ruby/1.8/generators/part_controller.rb
+/usr/lib/ruby/1.8/generators/merb_plugin.rb
+/usr/lib/ruby/1.8/generators/resource_controller.rb
+/usr/lib/ruby/1.8/generators/migration.rb
+/usr/lib/ruby/1.8/generators/layout.rb
+/usr/lib/ruby/1.8/generators/controller.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_plugin/Rakefile
+/usr/lib/ruby/1.8/generators/templates/application/merb_plugin/LICENSE
+/usr/lib/ruby/1.8/generators/templates/application/merb_plugin/TODO
+/usr/lib/ruby/1.8/generators/templates/application/merb_plugin/README
+/usr/lib/ruby/1.8/generators/templates/application/merb_plugin/test/%base_name%_test.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_plugin/test/test_helper.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_plugin/lib/%base_name%.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_plugin/lib/%base_name%/merbtasks.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_plugin/spec/spec_helper.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_plugin/spec/%base_name%_spec.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/autotest/merb_rspec.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/autotest/discover.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/autotest/merb.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/test/test_helper.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/doc/rdoc/generators/merb_generator.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/index.html.erb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/merb.css
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/merb_doc_styles.css
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/merb.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/prototype.js
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/api_grease.js
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/public/favicon.ico
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/public/merb.fcgi
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/public/robots.txt
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/public/javascripts/application.js
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/public/stylesheets/master.css
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/public/images/merb.jpg
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/merb/session/session.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/merb/merb-auth/strategies.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/merb/merb-auth/setup.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/app/views/exceptions/not_acceptable.html.erb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/app/views/exceptions/not_found.html.erb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/app/helpers/global_helpers.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/app/models/user.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/app/controllers/exceptions.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/app/controllers/application.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/spec/spec.opts
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/spec/spec_helper.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/config/router.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/config/dependencies.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/config/database.yml
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/config/rack.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/config/init.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/config/environments/staging.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/config/environments/development.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/config/environments/test.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/config/environments/rake.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_stack/config/environments/production.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/autotest/merb_rspec.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/autotest/discover.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/autotest/merb.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/test/test_helper.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/doc/rdoc/generators/merb_generator.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/index.html.erb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/merb.css
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/merb_doc_styles.css
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/merb.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/prototype.js
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/api_grease.js
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/public/favicon.ico
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/public/merb.fcgi
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/public/robots.txt
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/public/javascripts/application.js
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/public/stylesheets/master.css
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/public/images/merb.jpg
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/lib/merb/session.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/app/views/exceptions/not_acceptable.html.erb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/app/views/exceptions/not_found.html.erb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/app/helpers/global_helpers.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/app/controllers/exceptions.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/app/controllers/application.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/spec/spec.opts
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/spec/spec_helper.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/config/router.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/config/rack.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/config/init.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/config/environments/staging.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/config/environments/development.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/config/environments/test.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/config/environments/rake.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_core/config/environments/production.rb
+/usr/lib/ruby/1.8/generators/templates/application/common/doc.thor
+/usr/lib/ruby/1.8/generators/templates/application/common/Rakefile
+/usr/lib/ruby/1.8/generators/templates/application/common/dothtaccess
+/usr/lib/ruby/1.8/generators/templates/application/common/jquery.js
+/usr/lib/ruby/1.8/generators/templates/application/common/dotgitignore
+/usr/lib/ruby/1.8/generators/templates/application/common/merb_thor/app_script.rb
+/usr/lib/ruby/1.8/generators/templates/application/common/merb_thor/main.thor
+/usr/lib/ruby/1.8/generators/templates/application/common/merb_thor/utils.rb
+/usr/lib/ruby/1.8/generators/templates/application/common/merb_thor/ops.rb
+/usr/lib/ruby/1.8/generators/templates/application/common/merb_thor/gem_ext.rb
+/usr/lib/ruby/1.8/generators/templates/application/common/merb_thor/common.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_flat/README.txt
+/usr/lib/ruby/1.8/generators/templates/application/merb_flat/application.rbt
+/usr/lib/ruby/1.8/generators/templates/application/merb_flat/views/foo.html.erb
+/usr/lib/ruby/1.8/generators/templates/application/merb_flat/test/test_helper.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_flat/spec/spec_helper.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_flat/config/framework.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_flat/config/init.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_very_flat/application.rbt
+/usr/lib/ruby/1.8/generators/templates/application/merb_very_flat/test/test_helper.rb
+/usr/lib/ruby/1.8/generators/templates/application/merb_very_flat/spec/spec_helper.rb
+/usr/lib/ruby/1.8/generators/templates/component/resource_controller/test/controllers/%file_name%_test.rb
+/usr/lib/ruby/1.8/generators/templates/component/resource_controller/app/views/%file_name%/index.html.erb
+/usr/lib/ruby/1.8/generators/templates/component/resource_controller/app/views/%file_name%/new.html.erb
+/usr/lib/ruby/1.8/generators/templates/component/resource_controller/app/views/%file_name%/edit.html.erb
+/usr/lib/ruby/1.8/generators/templates/component/resource_controller/app/views/%file_name%/show.html.erb
+/usr/lib/ruby/1.8/generators/templates/component/resource_controller/app/controllers/%file_name%.rb
+/usr/lib/ruby/1.8/generators/templates/component/resource_controller/spec/requests/%file_name%_spec.rb
+/usr/lib/ruby/1.8/generators/templates/component/controller/test/requests/%file_name%_test.rb
+/usr/lib/ruby/1.8/generators/templates/component/controller/app/views/%file_name%/index.html.erb
+/usr/lib/ruby/1.8/generators/templates/component/controller/app/controllers/%file_name%.rb
+/usr/lib/ruby/1.8/generators/templates/component/controller/spec/requests/%file_name%_spec.rb
+/usr/lib/ruby/1.8/generators/templates/component/model/test/models/%file_name%_test.rb
+/usr/lib/ruby/1.8/generators/templates/component/model/app/models/%file_name%.rb
+/usr/lib/ruby/1.8/generators/templates/component/model/spec/models/%file_name%_spec.rb
+/usr/lib/ruby/1.8/generators/templates/component/part_controller/app/parts/%file_name%_part.rb
+/usr/lib/ruby/1.8/generators/templates/component/part_controller/app/parts/views/%file_name%_part/index.html.erb
+/usr/lib/ruby/1.8/generators/templates/component/layout/app/views/layout/%file_name%.html.erb
+/usr/lib/ruby/1.8/generators/templates/component/layout/spec/views/layout/%file_name%.html.erb_spec.rb
+/usr/lib/ruby/1.8/generators/templates/component/helper/app/helpers/%file_name%_helper.rb
+/usr/lib/ruby/1.8/generators/merb/merb_flat.rb
+/usr/lib/ruby/1.8/generators/merb/merb_core.rb
+/usr/lib/ruby/1.8/generators/merb/merb_stack.rb
+/usr/lib/ruby/1.8/generators/merb/merb_very_flat.rb

Modified: packages-wip/merb/trunk/merb-gen/bin/merb-gen
===================================================================
--- packages-wip/merb/trunk/merb-gen/bin/merb-gen	2009-07-30 20:19:53 UTC (rev 3861)
+++ packages-wip/merb/trunk/merb-gen/bin/merb-gen	2009-07-30 20:20:09 UTC (rev 3862)
@@ -1,4 +1,4 @@
-#!/usr/bin/env ruby
+#! /usr/bin/ruby1.8
 
 require 'rubygems'
 require 'merb-gen'

Added: packages-wip/merb/trunk/merb-haml/.config
===================================================================
--- packages-wip/merb/trunk/merb-haml/.config	                        (rev 0)
+++ packages-wip/merb/trunk/merb-haml/.config	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,20 @@
+prefix=/usr
+bindir=$prefix/bin
+libdir=$prefix/lib
+datadir=$prefix/share
+mandir=$prefix/share/man
+sysconfdir=/etc
+localstatedir=/var
+libruby=/usr/lib/ruby
+librubyver=/usr/lib/ruby/1.8
+librubyverarch=/usr/lib/ruby/1.8/i486-linux
+siteruby=/usr/local/lib/site_ruby
+siterubyver=/usr/local/lib/site_ruby/1.8
+siterubyverarch=/usr/local/lib/site_ruby/1.8/i486-linux
+rbdir=$librubyver
+sodir=$librubyverarch
+rubypath=/usr/bin/ruby1.8
+rubyprog=/usr/bin/ruby1.8
+makeprog=make
+shebang=ruby
+without-ext=no

Added: packages-wip/merb/trunk/merb-haml/InstalledFiles
===================================================================
--- packages-wip/merb/trunk/merb-haml/InstalledFiles	                        (rev 0)
+++ packages-wip/merb/trunk/merb-haml/InstalledFiles	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,24 @@
+/usr/lib/ruby/1.8/merb-haml.rb
+/usr/lib/ruby/1.8/merb-haml/merbtasks.rb
+/usr/lib/ruby/1.8/merb-haml/template.rb
+/usr/lib/ruby/1.8/generators/resource_controller.rb
+/usr/lib/ruby/1.8/generators/layout.rb
+/usr/lib/ruby/1.8/generators/controller.rb
+/usr/lib/ruby/1.8/generators/templates/resource_controller/datamapper/app/views/%file_name%/edit.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/datamapper/app/views/%file_name%/index.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/datamapper/app/views/%file_name%/show.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/datamapper/app/views/%file_name%/new.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/sequel/app/views/%file_name%/edit.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/sequel/app/views/%file_name%/index.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/sequel/app/views/%file_name%/show.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/sequel/app/views/%file_name%/new.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/none/app/views/%file_name%/edit.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/none/app/views/%file_name%/index.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/none/app/views/%file_name%/show.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/none/app/views/%file_name%/new.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/activerecord/app/views/%file_name%/edit.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/activerecord/app/views/%file_name%/index.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/activerecord/app/views/%file_name%/show.html.haml
+/usr/lib/ruby/1.8/generators/templates/resource_controller/activerecord/app/views/%file_name%/new.html.haml
+/usr/lib/ruby/1.8/generators/templates/controller/app/views/%file_name%/index.html.haml
+/usr/lib/ruby/1.8/generators/templates/layout/app/views/layout/%file_name%.html.haml

Added: packages-wip/merb/trunk/merb-helpers/.config
===================================================================
--- packages-wip/merb/trunk/merb-helpers/.config	                        (rev 0)
+++ packages-wip/merb/trunk/merb-helpers/.config	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,20 @@
+prefix=/usr
+bindir=$prefix/bin
+libdir=$prefix/lib
+datadir=$prefix/share
+mandir=$prefix/share/man
+sysconfdir=/etc
+localstatedir=/var
+libruby=/usr/lib/ruby
+librubyver=/usr/lib/ruby/1.8
+librubyverarch=/usr/lib/ruby/1.8/i486-linux
+siteruby=/usr/local/lib/site_ruby
+siterubyver=/usr/local/lib/site_ruby/1.8
+siterubyverarch=/usr/local/lib/site_ruby/1.8/i486-linux
+rbdir=$librubyver
+sodir=$librubyverarch
+rubypath=/usr/bin/ruby1.8
+rubyprog=/usr/bin/ruby1.8
+makeprog=make
+shebang=ruby
+without-ext=no

Added: packages-wip/merb/trunk/merb-helpers/InstalledFiles
===================================================================
--- packages-wip/merb/trunk/merb-helpers/InstalledFiles	                        (rev 0)
+++ packages-wip/merb/trunk/merb-helpers/InstalledFiles	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,11 @@
+/usr/lib/ruby/1.8/merb-helpers.rb
+/usr/lib/ruby/1.8/merb-helpers/core_ext.rb
+/usr/lib/ruby/1.8/merb-helpers/form_helpers.rb
+/usr/lib/ruby/1.8/merb-helpers/date_time_helpers.rb
+/usr/lib/ruby/1.8/merb-helpers/tag_helpers.rb
+/usr/lib/ruby/1.8/merb-helpers/time_dsl.rb
+/usr/lib/ruby/1.8/merb-helpers/text_helpers.rb
+/usr/lib/ruby/1.8/merb-helpers/date_time_formatting.rb
+/usr/lib/ruby/1.8/merb-helpers/form/builder.rb
+/usr/lib/ruby/1.8/merb-helpers/form/helpers.rb
+/usr/lib/ruby/1.8/merb-helpers/core_ext/numeric.rb

Added: packages-wip/merb/trunk/merb-slices/.config
===================================================================
--- packages-wip/merb/trunk/merb-slices/.config	                        (rev 0)
+++ packages-wip/merb/trunk/merb-slices/.config	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,20 @@
+prefix=/usr
+bindir=$prefix/bin
+libdir=$prefix/lib
+datadir=$prefix/share
+mandir=$prefix/share/man
+sysconfdir=/etc
+localstatedir=/var
+libruby=/usr/lib/ruby
+librubyver=/usr/lib/ruby/1.8
+librubyverarch=/usr/lib/ruby/1.8/i486-linux
+siteruby=/usr/local/lib/site_ruby
+siterubyver=/usr/local/lib/site_ruby/1.8
+siterubyverarch=/usr/local/lib/site_ruby/1.8/i486-linux
+rbdir=$librubyver
+sodir=$librubyverarch
+rubypath=/usr/bin/ruby1.8
+rubyprog=/usr/bin/ruby1.8
+makeprog=make
+shebang=ruby
+without-ext=no

Added: packages-wip/merb/trunk/merb-slices/InstalledFiles
===================================================================
--- packages-wip/merb/trunk/merb-slices/InstalledFiles	                        (rev 0)
+++ packages-wip/merb/trunk/merb-slices/InstalledFiles	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,43 @@
+/usr/bin/slice
+/usr/lib/ruby/1.8/merb-slices.rb
+/usr/lib/ruby/1.8/merb-slices/merbtasks.rb
+/usr/lib/ruby/1.8/merb-slices/router_ext.rb
+/usr/lib/ruby/1.8/merb-slices/module_mixin.rb
+/usr/lib/ruby/1.8/merb-slices/controller_mixin.rb
+/usr/lib/ruby/1.8/merb-slices/module.rb
+/usr/lib/ruby/1.8/generators/full.rb
+/usr/lib/ruby/1.8/generators/base.rb
+/usr/lib/ruby/1.8/generators/thin.rb
+/usr/lib/ruby/1.8/generators/very_thin.rb
+/usr/lib/ruby/1.8/generators/templates/very_thin/README
+/usr/lib/ruby/1.8/generators/templates/very_thin/lib/%base_name%.rb
+/usr/lib/ruby/1.8/generators/templates/thin/README
+/usr/lib/ruby/1.8/generators/templates/thin/views/main/index.html.erb
+/usr/lib/ruby/1.8/generators/templates/thin/views/layout/%symbol_name%.html.erb
+/usr/lib/ruby/1.8/generators/templates/thin/stubs/application.rb
+/usr/lib/ruby/1.8/generators/templates/thin/lib/%base_name%.rb
+/usr/lib/ruby/1.8/generators/templates/common/Rakefile
+/usr/lib/ruby/1.8/generators/templates/common/LICENSE
+/usr/lib/ruby/1.8/generators/templates/common/TODO
+/usr/lib/ruby/1.8/generators/templates/common/application.rb
+/usr/lib/ruby/1.8/generators/templates/common/public/javascripts/master.js
+/usr/lib/ruby/1.8/generators/templates/common/public/stylesheets/master.css
+/usr/lib/ruby/1.8/generators/templates/common/lib/%base_name%/merbtasks.rb
+/usr/lib/ruby/1.8/generators/templates/common/lib/%base_name%/spectasks.rb
+/usr/lib/ruby/1.8/generators/templates/common/lib/%base_name%/slicetasks.rb
+/usr/lib/ruby/1.8/generators/templates/full/Rakefile
+/usr/lib/ruby/1.8/generators/templates/full/TODO
+/usr/lib/ruby/1.8/generators/templates/full/README
+/usr/lib/ruby/1.8/generators/templates/full/stubs/app/controllers/main.rb
+/usr/lib/ruby/1.8/generators/templates/full/stubs/app/controllers/application.rb
+/usr/lib/ruby/1.8/generators/templates/full/lib/%base_name%.rb
+/usr/lib/ruby/1.8/generators/templates/full/app/views/main/index.html.erb
+/usr/lib/ruby/1.8/generators/templates/full/app/views/layout/%symbol_name%.html.erb
+/usr/lib/ruby/1.8/generators/templates/full/app/helpers/application_helper.rb
+/usr/lib/ruby/1.8/generators/templates/full/app/controllers/main.rb
+/usr/lib/ruby/1.8/generators/templates/full/app/controllers/application.rb
+/usr/lib/ruby/1.8/generators/templates/full/spec/spec_helper.rb
+/usr/lib/ruby/1.8/generators/templates/full/spec/%base_name%_spec.rb
+/usr/lib/ruby/1.8/generators/templates/full/spec/requests/main_spec.rb
+/usr/lib/ruby/1.8/generators/templates/full/config/router.rb
+/usr/lib/ruby/1.8/generators/templates/full/config/init.rb

Modified: packages-wip/merb/trunk/merb-slices/bin/slice
===================================================================
--- packages-wip/merb/trunk/merb-slices/bin/slice	2009-07-30 20:19:53 UTC (rev 3861)
+++ packages-wip/merb/trunk/merb-slices/bin/slice	2009-07-30 20:20:09 UTC (rev 3862)
@@ -1,4 +1,4 @@
-#!/usr/bin/env ruby
+#! /usr/bin/ruby1.8
 
 __DIR__ = Dir.pwd
 

Added: packages-wip/merb/trunk/patches/load_dependencies_uses_require
===================================================================
--- packages-wip/merb/trunk/patches/load_dependencies_uses_require	                        (rev 0)
+++ packages-wip/merb/trunk/patches/load_dependencies_uses_require	2009-07-30 20:20:09 UTC (rev 3862)
@@ -0,0 +1,29 @@
+Index: merb-1.0.12/merb-core/lib/merb-core/core_ext/kernel.rb
+===================================================================
+--- merb-1.0.12.orig/merb-core/lib/merb-core/core_ext/kernel.rb	2009-07-29 16:04:40.000000000 -0600
++++ merb-1.0.12/merb-core/lib/merb-core/core_ext/kernel.rb	2009-07-29 16:06:30.000000000 -0600
+@@ -140,11 +140,21 @@
+       dep = name.is_a?(Gem::Dependency) ? name : track_dependency(name, clr, *ver, &blk)
+       return unless dep.require_as
+       Gem.activate(dep)
++  
+     rescue Gem::LoadError => e
+-      e.set_backtrace dep.original_caller
+-      Merb.fatal! "The gem #{name}, #{ver.inspect} was not found", e
++      begin
++        Merb.logger.debug "Falling back to a regular require"
++        if name.kind_of?(Gem::Dependency)
++          require name.name
++        else
++          require name
++        end
++      rescue LoadError => le
++        e.set_backtrace dep.original_caller
++        Merb.fatal! "The gem #{name}, #{ver.inspect} was not found and we could not require it"
++      end
+     end
+-  
++
+     begin
+       require dep.require_as
+     rescue LoadError => e




More information about the Pkg-ruby-extras-commits mailing list