diff options
Diffstat (limited to 'git/test/fixtures/diff_mode_only')
-rwxr-xr-x | git/test/fixtures/diff_mode_only | 1152 |
1 files changed, 1152 insertions, 0 deletions
diff --git a/git/test/fixtures/diff_mode_only b/git/test/fixtures/diff_mode_only new file mode 100755 index 00000000..6fc18f69 --- /dev/null +++ b/git/test/fixtures/diff_mode_only @@ -0,0 +1,1152 @@ +diff --git a/bin/merb b/bin/merb +old mode 100644 +new mode 100755 +diff --git a/lib/merb.rb b/lib/merb.rb +index 76cb3e269e46fdf9b63cda7cb563c6cf40fdcb15..a2ab4ed47f9cb2ab942da5c46a2b561758a0d704 100644 +--- a/lib/merb.rb ++++ b/lib/merb.rb +@@ -15,7 +15,7 @@ require 'merb_core/core_ext' + require 'merb_core/gem_ext/erubis' + require 'merb_core/logger' + require 'merb_core/version' +- ++require 'merb_core/controller/mime' + + module Merb + class << self +@@ -23,6 +23,7 @@ module Merb + def start(argv=ARGV) + Merb::Config.parse_args(argv) + BootLoader.run ++ + case Merb::Config[:adapter] + when "mongrel" + adapter = Merb::Rack::Mongrel +diff --git a/lib/merb_core/boot/bootloader.rb b/lib/merb_core/boot/bootloader.rb +index d873924860bf4da06ac93db5c6a188f63dd1c3cc..57da75f05e28e8a256922bf345ccd3902e0a0b02 100644 +--- a/lib/merb_core/boot/bootloader.rb ++++ b/lib/merb_core/boot/bootloader.rb +@@ -20,7 +20,7 @@ module Merb + end + + def run +- subclasses.each {|klass| Object.full_const_get(klass).new.run } ++ subclasses.each {|klass| Object.full_const_get(klass).run } + end + + def after(klass) +@@ -37,95 +37,128 @@ module Merb + + end + +-class Merb::BootLoader::BuildFramework < Merb::BootLoader +- def run +- build_framework ++class Merb::BootLoader::LoadInit < Merb::BootLoader ++ def self.run ++ if Merb::Config[:init_file] ++ require Merb.root / Merb::Config[:init_file] ++ elsif File.exists?(Merb.root / "config" / "merb_init.rb") ++ require Merb.root / "config" / "merb_init" ++ elsif File.exists?(Merb.root / "merb_init.rb") ++ require Merb.root / "merb_init" ++ elsif File.exists?(Merb.root / "application.rb") ++ require Merb.root / "application" ++ end ++ end ++end ++ ++class Merb::BootLoader::Environment < Merb::BootLoader ++ def self.run ++ Merb.environment = Merb::Config[:environment] ++ end ++end ++ ++class Merb::BootLoader::Logger < Merb::BootLoader ++ def self.run ++ Merb.logger = Merb::Logger.new(Merb.dir_for(:log) / "test_log") ++ Merb.logger.level = Merb::Logger.const_get(Merb::Config[:log_level].upcase) rescue Merb::Logger::INFO + end ++end ++ ++class Merb::BootLoader::BuildFramework < Merb::BootLoader ++ class << self ++ def run ++ build_framework ++ end + +- # This method should be overridden in merb_init.rb before Merb.start to set up a different +- # framework structure +- def build_framework +- %[view model controller helper mailer part].each do |component| +- Merb.push_path(component.to_sym, Merb.root_path("app/#{component}s")) ++ # This method should be overridden in merb_init.rb before Merb.start to set up a different ++ # framework structure ++ def build_framework ++ %w[view model controller helper 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/router.rb")) ++ Merb.push_path(:lib, Merb.root_path("lib")) + end +- Merb.push_path(:application, Merb.root_path("app/controllers/application.rb")) +- Merb.push_path(:config, Merb.root_path("config/router.rb")) +- Merb.push_path(:lib, Merb.root_path("lib")) + end + end + + class Merb::BootLoader::LoadPaths < Merb::BootLoader + LOADED_CLASSES = {} + +- def run +- # Add models, controllers, and lib to the load path +- $LOAD_PATH.unshift Merb.load_paths[:model].first if Merb.load_paths[:model] +- $LOAD_PATH.unshift Merb.load_paths[:controller].first if Merb.load_paths[:controller] +- $LOAD_PATH.unshift Merb.load_paths[:lib].first if Merb.load_paths[:lib] ++ class << self ++ def run ++ # Add models, controllers, and lib to the load path ++ $LOAD_PATH.unshift Merb.load_paths[:model].first if Merb.load_paths[:model] ++ $LOAD_PATH.unshift Merb.load_paths[:controller].first if Merb.load_paths[:controller] ++ $LOAD_PATH.unshift Merb.load_paths[:lib].first if Merb.load_paths[:lib] + +- # Require all the files in the registered load paths +- puts Merb.load_paths.inspect +- Merb.load_paths.each do |name, path| +- Dir[path.first / path.last].each do |file| +- klasses = ObjectSpace.classes.dup +- require f +- LOADED_CLASSES[file] = ObjectSpace.classes - klasses ++ # Require all the files in the registered load paths ++ puts Merb.load_paths.inspect ++ Merb.load_paths.each do |name, path| ++ Dir[path.first / path.last].each do |file| ++ klasses = ObjectSpace.classes.dup ++ require file ++ LOADED_CLASSES[file] = ObjectSpace.classes - klasses ++ end + end + end +- end + +- def reload(file) +- if klasses = LOADED_CLASSES[file] +- klasses.each do |klass| +- remove_constant(klass) ++ def reload(file) ++ if klasses = LOADED_CLASSES[file] ++ klasses.each do |klass| ++ remove_constant(klass) ++ end + end ++ load file + end +- load file +- end + +- def remove_constant(const) +- # This is to support superclasses (like AbstractController) that track +- # their subclasses in a class variable. Classes that wish to use this +- # functionality are required to alias it to _subclasses_list. Plugins +- # for ORMs and other libraries should keep this in mind. +- if klass.superclass.respond_to?(:_subclasses_list) +- klass.superclass.send(:_subclasses_list).delete(klass) +- klass.superclass.send(:_subclasses_list).delete(klass.to_s) +- end ++ def remove_constant(const) ++ # This is to support superclasses (like AbstractController) that track ++ # their subclasses in a class variable. Classes that wish to use this ++ # functionality are required to alias it to _subclasses_list. Plugins ++ # for ORMs and other libraries should keep this in mind. ++ if klass.superclass.respond_to?(:_subclasses_list) ++ klass.superclass.send(:_subclasses_list).delete(klass) ++ klass.superclass.send(:_subclasses_list).delete(klass.to_s) ++ end + +- parts = const.to_s.split("::") +- base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::")) +- object = parts[-1].intern +- Merb.logger.debugger("Removing constant #{object} from #{base}") +- base.send(:remove_const, object) if object ++ parts = const.to_s.split("::") ++ base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::")) ++ object = parts[-1].intern ++ Merb.logger.debugger("Removing constant #{object} from #{base}") ++ base.send(:remove_const, object) if object ++ end + end + + end + + class Merb::BootLoader::Templates < Merb::BootLoader +- def run +- template_paths.each do |path| +- Merb::Template.inline_template(path) ++ class << self ++ def run ++ template_paths.each do |path| ++ Merb::Template.inline_template(path) ++ end + end +- end + +- def template_paths +- extension_glob = "{#{Merb::Template::EXTENSIONS.keys.join(',')}}" ++ def template_paths ++ extension_glob = "{#{Merb::Template::EXTENSIONS.keys.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. +- template_paths = Merb::AbstractController._abstract_subclasses.map do |klass| +- Object.full_const_get(klass)._template_root +- end.uniq.map {|path| Dir["#{path}/**/*.#{extension_glob}"] } ++ # 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. ++ template_paths = Merb::AbstractController._abstract_subclasses.map do |klass| ++ Object.full_const_get(klass)._template_root ++ end.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 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) + +- template_paths.flatten.compact.uniq +- end ++ template_paths.flatten.compact.uniq ++ end ++ end + end + + class Merb::BootLoader::Libraries < Merb::BootLoader +@@ -145,18 +178,41 @@ class Merb::BootLoader::Libraries < Merb::BootLoader + def self.add_libraries(hsh) + @@libraries.merge!(hsh) + end +- +- def run ++ ++ def self.run + @@libraries.each do |exclude, choices| + require_first_working(*choices) unless Merb::Config[exclude] + end + end +- +- def require_first_working(first, *rest) ++ ++ def self.require_first_working(first, *rest) + p first, rest + require first + rescue LoadError + raise LoadError if rest.empty? + require_first_working rest.unshift, *rest + end ++end ++ ++class Merb::BootLoader::MimeTypes < Merb::BootLoader ++ def self.run ++ # Sets 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, adds "Encoding: UTF-8" response header ++ # :js:: to_json, text/javascript ot application/javascript or application/x-javascript ++ # :json:: to_json, application/json or text/x-json ++ Merb.available_mime_types.clear ++ Merb.add_mime_type(:all, nil, %w[*/*]) ++ Merb.add_mime_type(:yaml, :to_yaml, %w[application/x-yaml text/yaml]) ++ Merb.add_mime_type(:text, :to_text, %w[text/plain]) ++ Merb.add_mime_type(:html, :to_html, %w[text/html application/xhtml+xml application/html]) ++ Merb.add_mime_type(:xml, :to_xml, %w[application/xml text/xml application/x-xml], :Encoding => "UTF-8") ++ Merb.add_mime_type(:js, :to_json, %w[text/javascript application/javascript application/x-javascript]) ++ Merb.add_mime_type(:json, :to_json, %w[application/json text/x-json]) ++ end + end +\ No newline at end of file +diff --git a/lib/merb_core/config.rb b/lib/merb_core/config.rb +index c92f2e6f071c234551ecb16a4716d47fa92f6c7b..ab0864e0174b54833c758f9f22a840d3b53c7653 100644 +--- a/lib/merb_core/config.rb ++++ b/lib/merb_core/config.rb +@@ -92,6 +92,10 @@ module Merb + options[:cluster] = nodes + end + ++ opts.on("-I", "--init-file FILE", "Name of the file to load first") do |init_file| ++ options[:init_file] = init_file ++ end ++ + opts.on("-p", "--port PORTNUM", "Port to run merb on, defaults to 4000.") do |port| + options[:port] = port + end +@@ -261,29 +265,29 @@ module Merb + + @configuration = Merb::Config.apply_configuration_from_file options, environment_merb_yml + +- case Merb::Config[:environment].to_s +- when 'production' +- Merb::Config[:reloader] = Merb::Config.fetch(:reloader, false) +- Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, false) +- Merb::Config[:cache_templates] = true +- else +- Merb::Config[:reloader] = Merb::Config.fetch(:reloader, true) +- Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, true) +- end +- +- Merb::Config[:reloader_time] ||= 0.5 if Merb::Config[:reloader] == true +- +- +- if Merb::Config[:reloader] +- Thread.abort_on_exception = true +- Thread.new do +- loop do +- sleep( Merb::Config[:reloader_time] ) +- ::Merb::BootLoader.reload if ::Merb::BootLoader.app_loaded? +- end +- Thread.exit +- end +- end ++ # case Merb::Config[:environment].to_s ++ # when 'production' ++ # Merb::Config[:reloader] = Merb::Config.fetch(:reloader, false) ++ # Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, false) ++ # Merb::Config[:cache_templates] = true ++ # else ++ # Merb::Config[:reloader] = Merb::Config.fetch(:reloader, true) ++ # Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, true) ++ # end ++ # ++ # Merb::Config[:reloader_time] ||= 0.5 if Merb::Config[:reloader] == true ++ # ++ # ++ # if Merb::Config[:reloader] ++ # Thread.abort_on_exception = true ++ # Thread.new do ++ # loop do ++ # sleep( Merb::Config[:reloader_time] ) ++ # ::Merb::BootLoader.reload if ::Merb::BootLoader.app_loaded? ++ # end ++ # Thread.exit ++ # end ++ # end + @configuration + end + +diff --git a/lib/merb_core/controller/abstract_controller.rb b/lib/merb_core/controller/abstract_controller.rb +index fbf83372793da6da4b803b799994f0e341fddf88..f5e9a59057d67a6d56377a516a726cf51aa03d6f 100644 +--- a/lib/merb_core/controller/abstract_controller.rb ++++ b/lib/merb_core/controller/abstract_controller.rb +@@ -96,7 +96,7 @@ class Merb::AbstractController + # the superclass. + #--- + # @public +- def _template_location(action, controller = controller_name, type = nil) ++ def _template_location(action, type = nil, controller = controller_name) + "#{controller}/#{action}" + end + +@@ -106,6 +106,8 @@ class Merb::AbstractController + # own subclasses. We're using a Set so we don't have to worry about + # uniqueness. + self._abstract_subclasses = Set.new ++ self._template_root = Merb.dir_for(:view) ++ + def self.subclasses_list() _abstract_subclasses end + + class << self +@@ -114,7 +116,6 @@ class Merb::AbstractController + # The controller that is being inherited from Merb::AbstractController + def inherited(klass) + _abstract_subclasses << klass.to_s +- klass._template_root ||= Merb.dir_for(:view) + super + end + +diff --git a/lib/merb_core/controller/merb_controller.rb b/lib/merb_core/controller/merb_controller.rb +index 7283f006bb0501b29f825da129600cf045264b62..98af6ef3330a6b3f46d7bb1f8643261e28155ae5 100644 +--- a/lib/merb_core/controller/merb_controller.rb ++++ b/lib/merb_core/controller/merb_controller.rb +@@ -71,6 +71,10 @@ class Merb::Controller < Merb::AbstractController + end + end + ++ def _template_location(action, type = nil, controller = controller_name) ++ "#{controller}/#{action}.#{type}" ++ end ++ + # Sets the variables that came in through the dispatch as available to + # the controller. This is called by .build, so see it for more + # information. +@@ -107,9 +111,7 @@ class Merb::Controller < Merb::AbstractController + request.cookies[_session_id_key] = request.params[_session_id_key] + end + end +- @_request, @_response, @_status, @_headers = +- request, response, status, headers +- ++ @request, @response, @status, @headers = request, response, status, headers + nil + end + +@@ -135,7 +137,8 @@ class Merb::Controller < Merb::AbstractController + @_benchmarks[:action_time] = Time.now - start + end + +- _attr_reader :request, :response, :status, :headers ++ attr_reader :request, :response, :headers ++ attr_accessor :status + def params() request.params end + def cookies() request.cookies end + def session() request.session end +diff --git a/lib/merb_core/controller/mime.rb b/lib/merb_core/controller/mime.rb +index d17570786ca318cff7201c4b1e947ae229b01de8..ff9abe4d1c452aeabfcf5f7dc7a2c7cdd3f67035 100644 +--- a/lib/merb_core/controller/mime.rb ++++ b/lib/merb_core/controller/mime.rb +@@ -8,7 +8,7 @@ module Merb + + # Any specific outgoing headers should be included here. These are not + # the content-type header but anything in addition to it. +- # +tranform_method+ should be set to a symbol of the method used to ++ # +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. +@@ -71,27 +71,6 @@ module Merb + def mime_by_request_header(header) + available_mime_types.find {|key,info| info[request_headers].include?(header)}.first + end +- +- # Resets 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, adds "Encoding: UTF-8" response header +- # :js:: to_json, text/javascript ot application/javascript or application/x-javascript +- # :json:: to_json, application/json or text/x-json +- def reset_default_mime_types! +- available_mime_types.clear +- Merb.add_mime_type(:all, nil, %w[*/*]) +- Merb.add_mime_type(:yaml, :to_yaml, %w[application/x-yaml text/yaml]) +- Merb.add_mime_type(:text, :to_text, %w[text/plain]) +- Merb.add_mime_type(:html, :to_html, %w[text/html application/xhtml+xml application/html]) +- Merb.add_mime_type(:xml, :to_xml, %w[application/xml text/xml application/x-xml], :Encoding => "UTF-8") +- Merb.add_mime_type(:js, :to_json, %w[text/javascript application/javascript application/x-javascript]) +- Merb.add_mime_type(:json, :to_json, %w[application/json text/x-json]) +- end + + end + end +\ No newline at end of file +diff --git a/lib/merb_core/controller/mixins/render.rb b/lib/merb_core/controller/mixins/render.rb +index 8e096546d4647bb597ab2e00a4b15d09db35e9c9..a298263af7d655d9ce43007554f3827046831287 100644 +--- a/lib/merb_core/controller/mixins/render.rb ++++ b/lib/merb_core/controller/mixins/render.rb +@@ -51,21 +51,22 @@ module Merb::RenderMixin + + # If you don't specify a thing to render, assume they want to render the current action + thing ||= action_name.to_sym +- ++ + # Content negotiation + opts[:format] ? (self.content_type = opts[:format]) : content_type + + # Do we have a template to try to render? + if thing.is_a?(Symbol) || opts[:template] +- ++ + # Find a template path to look up (_template_location adds flexibility here) +- template_location = _template_root / (opts[:template] || _template_location(thing)) ++ template_location = _template_root / (opts[:template] || _template_location(thing, content_type)) ++ + # Get the method name from the previously inlined list + template_method = Merb::Template.template_for(template_location) + + # Raise an error if there's no template + raise TemplateNotFound, "No template found at #{template_location}" unless +- self.respond_to?(template_method) ++ template_method && self.respond_to?(template_method) + + # Call the method in question and throw the content for later consumption by the layout + throw_content(:for_layout, self.send(template_method)) +diff --git a/lib/merb_core/controller/mixins/responder.rb b/lib/merb_core/controller/mixins/responder.rb +index e910b2b32c844ab51cf2a10d0ad26c314dbb3631..5ac67fb907aaf9f95effc7eb3cbb07b8963ce022 100644 +--- a/lib/merb_core/controller/mixins/responder.rb ++++ b/lib/merb_core/controller/mixins/responder.rb +@@ -97,6 +97,8 @@ module Merb + # and none of the provides methods can be used. + module ResponderMixin + ++ TYPES = {} ++ + class ContentTypeAlreadySet < StandardError; end + + # ==== Parameters +@@ -105,6 +107,7 @@ module Merb + base.extend(ClassMethods) + base.class_eval do + class_inheritable_accessor :class_provided_formats ++ self.class_provided_formats = [] + end + base.reset_provides + end +@@ -178,171 +181,253 @@ module Merb + def reset_provides + only_provides(:html) + end +- +- # ==== Returns +- # 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. +- def _provided_formats +- @_provided_formats ||= class_provided_formats.dup ++ end ++ ++ # ==== Returns ++ # 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. ++ def _provided_formats ++ @_provided_formats ||= class_provided_formats.dup ++ end ++ ++ # Sets the provided formats for this action. Usually, you would ++ # use a combination of +provides+, +only_provides+ and +does_not_provide+ ++ # to manage this, but you can set it directly. ++ # ++ # ==== Parameters ++ # *formats<Symbol>:: A list of formats to be passed to provides ++ # ++ # ==== Raises ++ # Merb::ResponderMixin::ContentTypeAlreadySet:: ++ # Content negotiation already occured, and the content_type is set. ++ # ++ # ==== Returns ++ # Array:: List of formats passed in ++ def _set_provided_formats(*formats) ++ if @_content_type ++ raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set" + end +- +- # Sets the provided formats for this action. Usually, you would +- # use a combination of +provides+, +only_provides+ and +does_not_provide+ +- # to manage this, but you can set it directly. +- # +- # ==== Parameters +- # *formats<Symbol>:: A list of formats to be passed to provides +- # +- # ==== Raises +- # Merb::ResponderMixin::ContentTypeAlreadySet:: +- # Content negotiation already occured, and the content_type is set. +- # +- # ==== Returns +- # Array:: List of formats passed in +- def _set_provided_formats(*formats) +- if @_content_type +- raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set" +- end +- @_provided_formats = [] +- provides(*formats) ++ @_provided_formats = [] ++ provides(*formats) ++ end ++ alias :_provided_formats= :_set_provided_formats ++ ++ # 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:: List of formats passed in ++ # ++ #--- ++ # @public ++ def provides(*formats) ++ if @_content_type ++ raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set" + end +- alias :_provided_formats= :_set_provided_formats +- +- # 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:: List of formats passed in +- # +- #--- +- # @public +- def provides(*formats) +- if @_content_type +- raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set" +- end +- formats.each do |fmt| +- _provided_formats << fmt unless _provided_formats.include?(fmt) +- end ++ formats.each do |fmt| ++ _provided_formats << fmt unless _provided_formats.include?(fmt) + end ++ 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:: List of formats passed in +- # +- #--- +- # @public +- def only_provides(*formats) +- self._provided_formats = *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:: List of formats that remain after removing the ones not to provide +- # +- #--- +- # @public +- def does_not_provide(*formats) +- formats.flatten! +- self._provided_formats -= formats +- 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 +- def _perform_content_negotiation # :nodoc: +- raise Merb::ControllerExceptions::NotAcceptable if provided_formats.empty? +- if fmt = params[:format] +- return fmt.to_sym if provided_formats.include?(fmt.to_sym) +- else +- accepts = Responder.parse(request.accept).map {|t| t.to_sym} +- return provided_formats.first if accepts.include?(:all) +- return accepts.each { |type| break type if provided_formats.include?(type) } +- end +- raise Merb::ControllerExceptions::NotAcceptable ++ # 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:: List of formats passed in ++ # ++ #--- ++ # @public ++ def only_provides(*formats) ++ self._provided_formats = *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:: List of formats that remain after removing the ones not to provide ++ # ++ #--- ++ # @public ++ def does_not_provide(*formats) ++ formats.flatten! ++ self._provided_formats -= formats ++ 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 ++ def _perform_content_negotiation # :nodoc: ++ raise Merb::ControllerExceptions::NotAcceptable if _provided_formats.empty? ++ if fmt = params[:format] && _provided_formats.include?(fmt.to_sym) ++ return fmt.to_sym + end ++ accepts = Responder.parse(request.accept).map {|t| t.to_sym} ++ return _provided_formats.first if accepts.include?(:all) ++ (accepts & _provided_formats).first || (raise Merb::ControllerExceptions::NotAcceptable) ++ 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. +- # +- #--- +- # @public +- def content_type(fmt = nil) +- self.content_type = (fmt || _perform_content_negotiation) unless @_content_type +- @_content_type ++ # 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. ++ # ++ #--- ++ # @public ++ def content_type(fmt = nil) ++ @_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>:: A type that is in the list of registered mime-types. ++ # ++ # ==== Raises ++ # ArgumentError:: "type" is not in the list of registered mime-types. ++ # ++ # ==== Returns ++ # Symbol:: The content-type that was passed in. ++ # ++ #--- ++ # @semipublic ++ def content_type=(type) ++ unless Merb.available_mime_types.has_key?(type) ++ raise Merb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{type}") ++ end ++ headers['Content-Type'] = Merb.available_mime_types[type].first ++ @_content_type = type ++ end ++ ++ end ++ ++ class Responder ++ ++ protected ++ def self.parse(accept_header) ++ # parse the raw accept header into a unique, sorted array of AcceptType objects ++ list = accept_header.to_s.split(/,/).enum_for(:each_with_index).map do |entry,index| ++ AcceptType.new(entry,index += 1) ++ end.sort.uniq ++ # firefox (and possibly other browsers) send broken default accept headers. ++ # fix them up by sorting alternate xml forms (namely application/xhtml+xml) ++ # ahead of pure xml types (application/xml,text/xml). ++ if app_xml = list.detect{|e| e.super_range == 'application/xml'} ++ list.select{|e| e.to_s =~ /\+xml/}.each { |acc_type| ++ list[list.index(acc_type)],list[list.index(app_xml)] = ++ list[list.index(app_xml)],list[list.index(acc_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>:: A type that is in the list of registered mime-types. +- # +- # ==== Raises +- # ArgumentError:: "type" is not in the list of registered mime-types. +- # +- # ==== Returns +- # Symbol:: The content-type that was passed in. +- # +- #--- +- # @semipublic +- def content_type=(type) +- unless Merb.available_mime_types.has_key?(type) +- raise Merb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{type}") +- end +- headers['Content-Type'] = Merb.available_mime_types[type].first +- @_content_type = type ++ list ++ end ++ ++ public ++ def self.params_to_query_string(value, prefix = nil) ++ case value ++ when Array ++ value.map { |v| ++ params_to_query_string(v, "#{prefix}[]") ++ } * "&" ++ when Hash ++ value.map { |k, v| ++ params_to_query_string(v, prefix ? "#{prefix}[#{Merb::Request.escape(k)}]" : Merb::Request.escape(k)) ++ } * "&" ++ else ++ "#{prefix}=#{Merb::Request.escape(value)}" + end ++ end + +- end ++ end ++ ++ class AcceptType ++ ++ attr_reader :media_range, :quality, :index, :type, :sub_type + ++ def initialize(entry,index) ++ @index = index ++ @media_range, quality = entry.split(/;\s*q=/).map{|a| a.strip } ++ @type, @sub_type = @media_range.split(/\//) ++ quality ||= 0.0 if @media_range == '*/*' ++ @quality = ((quality || 1.0).to_f * 100).to_i ++ end ++ ++ def <=>(entry) ++ c = entry.quality <=> quality ++ c = index <=> entry.index if c == 0 ++ c ++ end ++ ++ def eql?(entry) ++ synonyms.include?(entry.media_range) ++ end ++ ++ def ==(entry); eql?(entry); end ++ ++ def hash; super_range.hash; end ++ ++ def synonyms ++ @syns ||= Merb.available_mime_types.values.map do |e| ++ e[:request_headers] if e[:request_headers].include?(@media_range) ++ end.compact.flatten ++ end ++ ++ def super_range ++ synonyms.first || @media_range ++ end ++ ++ def to_sym ++ Merb.available_mime_types.select{|k,v| ++ v[:request_headers] == synonyms || v[:request_headers][0] == synonyms[0]}.flatten.first ++ end ++ ++ def to_s ++ @media_range ++ end ++ + end ++ + + end +\ No newline at end of file +diff --git a/lib/merb_core/dispatch/dispatcher.rb b/lib/merb_core/dispatch/dispatcher.rb +index c458c9f9ad454d3b0c3055d6b2a8e88b17712b44..f7fed0f539a20f9cce08b72c551725ad0563bf37 100644 +--- a/lib/merb_core/dispatch/dispatcher.rb ++++ b/lib/merb_core/dispatch/dispatcher.rb +@@ -33,10 +33,10 @@ class Merb::Dispatcher + + # this is the custom dispatch_exception; it allows failures to still be dispatched + # to the error controller +- rescue => exception +- Merb.logger.error(Merb.exception(exception)) +- exception = controller_exception(exception) +- dispatch_exception(request, response, exception) ++ # rescue => exception ++ # Merb.logger.error(Merb.exception(exception)) ++ # exception = controller_exception(exception) ++ # dispatch_exception(request, response, exception) + end + + private +@@ -49,10 +49,10 @@ class Merb::Dispatcher + def dispatch_action(klass, action, request, response, status=200) + # build controller + controller = klass.build(request, response, status) +- if @@use_mutex +- @@mutex.synchronize { controller.dispatch(action) } ++ if use_mutex ++ @@mutex.synchronize { controller._dispatch(action) } + else +- controller.dispatch(action) ++ controller._dispatch(action) + end + [controller, action] + end +diff --git a/lib/merb_core/rack/adapter.rb b/lib/merb_core/rack/adapter.rb +index ffc7117e9733e83b0567bbe4a43fac7663800b7d..217399a5382d0b3878aaea3d3e302173c5b5f119 100644 +--- a/lib/merb_core/rack/adapter.rb ++++ b/lib/merb_core/rack/adapter.rb +@@ -40,7 +40,7 @@ module Merb + begin + controller, action = ::Merb::Dispatcher.handle(request, response) + rescue Object => e +- return [500, {"Content-Type"=>"text/html"}, "Internal Server Error"] ++ return [500, {"Content-Type"=>"text/html"}, e.message + "<br/>" + e.backtrace.join("<br/>")] + end + [controller.status, controller.headers, controller.body] + end +diff --git a/lib/merb_core/test/request_helper.rb b/lib/merb_core/test/request_helper.rb +index 10a9fb3ace56eaf1db0fa300df3fb2ab88a7118a..f302a3b71539182ba142cd208fe6d6aae171b1a1 100644 +--- a/lib/merb_core/test/request_helper.rb ++++ b/lib/merb_core/test/request_helper.rb +@@ -26,8 +26,10 @@ module Merb::Test::RequestHelper + Merb::Test::FakeRequest.new(env, StringIO.new(req)) + end + +- def dispatch_to(controller_klass, action, env = {}, opt = {}, &blk) +- request = fake_request(env, opt) ++ def dispatch_to(controller_klass, action, params = {}, env = {}, &blk) ++ request = fake_request(env, ++ :query_string => Merb::Responder.params_to_query_string(params)) ++ + controller = controller_klass.build(request) + controller.instance_eval(&blk) if block_given? + controller._dispatch(action) +diff --git a/spec/public/abstract_controller/spec_helper.rb b/spec/public/abstract_controller/spec_helper.rb +index df759008d14e7572b5c44de24f77f828f83f1682..694cee2592a210a5c1fa40ca7846beeaa09725fe 100644 +--- a/spec/public/abstract_controller/spec_helper.rb ++++ b/spec/public/abstract_controller/spec_helper.rb +@@ -1,12 +1,10 @@ + __DIR__ = File.dirname(__FILE__) + require File.join(__DIR__, "..", "..", "spec_helper") + +-# The framework structure *must* be set up before loading in framework +-# files. + require File.join(__DIR__, "controllers", "filters") + require File.join(__DIR__, "controllers", "render") + +-Merb::BootLoader::Templates.new.run ++Merb::BootLoader::Templates.run + + module Merb::Test::Behaviors + def dispatch_should_make_body(klass, body, action = :index) +diff --git a/spec/public/controller/base_spec.rb b/spec/public/controller/base_spec.rb +index 1709e612629ed2c2b6af4579a8b89684aca9aa3c..5bcdb59948cc22592639b1aee9bd233ff2c306fa 100644 +--- a/spec/public/controller/base_spec.rb ++++ b/spec/public/controller/base_spec.rb +@@ -10,11 +10,11 @@ describe Merb::Controller, " callable actions" do + end + + it "should dispatch to callable actions" do +- dispatch_to(Merb::Test::Fixtures::TestFoo, :index).body.should == "index" ++ dispatch_to(Merb::Test::Fixtures::TestBase, :index).body.should == "index" + end + + it "should not dispatch to hidden actions" do +- calling { dispatch_to(Merb::Test::Fixtures::TestFoo, :hidden) }. ++ calling { dispatch_to(Merb::Test::Fixtures::TestBase, :hidden) }. + should raise_error(Merb::ControllerExceptions::ActionNotFound) + end + +diff --git a/spec/public/controller/controllers/base.rb b/spec/public/controller/controllers/base.rb +index a1b3beb27899df781d943427d9b23945f02e14de..c4b69a440a9da3c3486208d2cb95ccb8bdb974b9 100644 +--- a/spec/public/controller/controllers/base.rb ++++ b/spec/public/controller/controllers/base.rb +@@ -3,7 +3,7 @@ module Merb::Test::Fixtures + self._template_root = File.dirname(__FILE__) / "views" + end + +- class TestFoo < ControllerTesting ++ class TestBase < ControllerTesting + def index + "index" + end +diff --git a/spec/public/controller/controllers/responder.rb b/spec/public/controller/controllers/responder.rb +new file mode 100644 +index 0000000000000000000000000000000000000000..867192e8f6e995a43fd5cd3daffa0ec11b3d31e5 +--- /dev/null ++++ b/spec/public/controller/controllers/responder.rb +@@ -0,0 +1,25 @@ ++module Merb::Test::Fixtures ++ class ControllerTesting < Merb::Controller ++ self._template_root = File.dirname(__FILE__) / "views" ++ end ++ ++ class TestResponder < ControllerTesting ++ def index ++ render ++ end ++ end ++ ++ class TestHtmlDefault < TestResponder; end ++ ++ class TestClassProvides < TestResponder; ++ provides :xml ++ end ++ ++ class TestLocalProvides < TestResponder; ++ def index ++ provides :xml ++ render ++ end ++ end ++ ++end +\ No newline at end of file +diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.html.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.html.erb +new file mode 100644 +index 0000000000000000000000000000000000000000..1bfb77d4a44c444bba6888ae7740f7df4b074c58 +--- /dev/null ++++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.html.erb +@@ -0,0 +1 @@ ++This should not be rendered +\ No newline at end of file +diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.xml.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.xml.erb +new file mode 100644 +index 0000000000000000000000000000000000000000..7c91f633987348e87e5e34e1d9e87d9dd0e5100c +--- /dev/null ++++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.xml.erb +@@ -0,0 +1 @@ ++<XML:Class provides='true' /> +\ No newline at end of file +diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_html_default/index.html.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_html_default/index.html.erb +new file mode 100644 +index 0000000000000000000000000000000000000000..eb4b52bf5a7aaba8f1706de419f42789c05684a2 +--- /dev/null ++++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_html_default/index.html.erb +@@ -0,0 +1 @@ ++HTML: Default +\ No newline at end of file +diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.html.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.html.erb +new file mode 100644 +index 0000000000000000000000000000000000000000..a3a841a89c62e6174038935a42da9cd24ff54413 +--- /dev/null ++++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.html.erb +@@ -0,0 +1 @@ ++This should not render +\ No newline at end of file +diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.xml.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.xml.erb +new file mode 100644 +index 0000000000000000000000000000000000000000..c1384ec6af0357b585cc367035d1bc3a30347ade +--- /dev/null ++++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.xml.erb +@@ -0,0 +1 @@ ++<XML:Local provides='true' /> +\ No newline at end of file +diff --git a/spec/public/controller/responder_spec.rb b/spec/public/controller/responder_spec.rb +index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bcf18532442e5965cf6ca8501770d7b7a1eb2429 100644 +--- a/spec/public/controller/responder_spec.rb ++++ b/spec/public/controller/responder_spec.rb +@@ -0,0 +1,31 @@ ++require File.join(File.dirname(__FILE__), "spec_helper") ++ ++describe Merb::Controller, " responds" do ++ ++ before do ++ Merb.push_path(:layout, File.dirname(__FILE__) / "controllers" / "views" / "layouts") ++ Merb::Router.prepare do |r| ++ r.default_routes ++ end ++ end ++ ++ it "should default the mime-type to HTML" do ++ dispatch_to(Merb::Test::Fixtures::TestHtmlDefault, :index).body.should == "HTML: Default" ++ end ++ ++ it "should use other mime-types if they are provided on the class level" do ++ controller = dispatch_to(Merb::Test::Fixtures::TestClassProvides, :index, {}, :http_accept => "application/xml") ++ controller.body.should == "<XML:Class provides='true' />" ++ end ++ ++ it "should fail if none of the acceptable mime-types are available" do ++ calling { dispatch_to(Merb::Test::Fixtures::TestClassProvides, :index, {}, :http_accept => "application/json") }. ++ should raise_error(Merb::ControllerExceptions::NotAcceptable) ++ end ++ ++ it "should use mime-types that are provided at the local level" do ++ controller = dispatch_to(Merb::Test::Fixtures::TestLocalProvides, :index, {}, :http_accept => "application/xml") ++ controller.body.should == "<XML:Local provides='true' />" ++ end ++ ++end +\ No newline at end of file +diff --git a/spec/public/controller/spec_helper.rb b/spec/public/controller/spec_helper.rb +index f68628a63740f4ce0235a15d71c5889e55ecaf78..e360194c1fbaf72c3298c61543c2d3a19b512b41 100644 +--- a/spec/public/controller/spec_helper.rb ++++ b/spec/public/controller/spec_helper.rb +@@ -1,4 +1,10 @@ + __DIR__ = File.dirname(__FILE__) ++require 'ruby-debug' ++ + require File.join(__DIR__, "..", "..", "spec_helper") + +-require File.join(__DIR__, "controllers", "base") +\ No newline at end of file ++require File.join(__DIR__, "controllers", "base") ++require File.join(__DIR__, "controllers", "responder") ++ ++Merb::BootLoader::Templates.run ++Merb::BootLoader::MimeTypes.run +\ No newline at end of file |