[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}&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}&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> </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