Defect #1754
closedRedmine not compatible with RedCloth >= 3.301
Added by Simone Carletti over 16 years ago. Updated about 16 years ago.
0%
Description
After a couple of year the new version of RedCloth has been released at the end of July.
Although a middle release was already available (called RedCloth 3.301 and available via --source http://code.whytheluckystiff.net) this is the first release > 3.0.4 available from RubyForge.
It means every new user that will install RedCloth will have this release by default.
Redmine 0.7.3 is not compatible with RedCloth > 3.0.4.
This is because in Redmine extends RedCloth and assumes that RedCloth provides a hard_breaks
accessor method but:
- RedCloth 3.301 doesn't provide hard_breaks method
- RedCloth 4.x does but the main class is no longer RedCloth but RedCloth::TextileDoc
Files
redcloth-rename.patch (75.7 KB) redcloth-rename.patch | rename of the included modified redcloth library | Gerrit Kaiser, 2008-08-26 03:01 |
Related issues
Updated by Simone Carletti over 16 years ago
I just noticed RedCloth lib is included in the lib folder.
For some reason (I guess because Rails loads it if available), the one installed in the server seems to take precedence thus Redmine is going to ignore the lib/RedCloth if an other release is installed.
ActionView::TemplateError (undefined method `hard_breaks=' for "Tagged release 0.9.1":Redmine::WikiFormatting::TextileFormatter) on line #21 of repositories/_revisions.rhtml: 18: <td class="checkbox"><%= radio_button_tag('rev_to', changeset.revision, (line_num==2), :id => "cbto-#{line_num}", :onclick => "if ($('cb-#{line_num}').checked==true) {$('cb-#{line_num-1}').checked=true;}") if show_diff && (line_num > 1) %></td> 19: <td class="committed_on"><%= format_time(changeset.committed_on) %></td> 20: <td class="author"><%=h changeset.committer.to_s.split('<').first %></td> 21: <td class="comments"><%= textilizable(changeset.comments) %></td> 22: </tr> 23: <% line_num += 1 %> 24: <% end %> /home/redmine/releases/0.7.3/lib/redmine/wiki_formatting.rb:33:in `initialize' /home/redmine/releases/0.7.3/lib/redmine/wiki_formatting.rb:168:in `new' /home/redmine/releases/0.7.3/lib/redmine/wiki_formatting.rb:168:in `to_html' /home/redmine/releases/0.7.3/app/helpers/application_helper.rb:226:in `textilizable' /home/redmine/releases/0.7.3/app/views/repositories/_revisions.rhtml:21:in `_run_erb_47app47views47repositories47_revisions46rhtml' /home/redmine/releases/0.7.3/app/views/repositories/_revisions.rhtml:14:in `each' /home/redmine/releases/0.7.3/app/views/repositories/_revisions.rhtml:14:in `_run_erb_47app47views47repositories47_revisions46rhtml' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/helpers/capture_helper.rb:142:in `call' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/helpers/capture_helper.rb:142:in `capture_erb_with_buffer' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/helpers/capture_helper.rb:44:in `capture' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/helpers/form_tag_helper.rb:417:in `form_tag_in_block' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/helpers/form_tag_helper.rb:39:in `form_tag' /home/redmine/releases/0.7.3/app/views/repositories/_revisions.rhtml:1:in `_run_erb_47app47views47repositories47_revisions46rhtml' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/base.rb:637:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/base.rb:637:in `compile_and_render_template' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/base.rb:365:in `render_template' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/base.rb:316:in `render_file' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/base.rb:331:in `render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/partials.rb:120:in `render_partial' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/base.rb:352:in `render' /home/redmine/releases/0.7.3/app/views/repositories/show.rhtml:14:in `_run_erb_47app47views47repositories47show46rhtml' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/base.rb:637:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/base.rb:637:in `compile_and_render_template' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/base.rb:365:in `render_template' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/base.rb:316:in `render_file' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1100:in `render_for_file' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:836:in `render_with_no_layout' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/layout.rb:262:in `render_without_benchmark' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:51:in `render' /usr/lib/ruby/1.8/benchmark.rb:293:in `measure' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:51:in `render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1153:in `default_render' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1159:in `perform_action_without_filters' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:697:in `call_filters' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:689:in `perform_action_without_benchmark' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' /usr/lib/ruby/1.8/benchmark.rb:293:in `measure' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/rescue.rb:199:in `perform_action_without_caching' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/caching.rb:678:in `passenger_orig_perform_action' /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/query_cache.rb:33:in `cache' /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/query_cache.rb:8:in `cache' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/caching.rb:677:in `passenger_orig_perform_action' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/request_handler.rb:53:in `perform_action' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:524:in `send' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:524:in `process_without_filters' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:685:in `process_without_session_management_support' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/session_management.rb:123:in `process' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:388:in `process' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:171:in `handle_request' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:115:in `dispatch' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:126:in `dispatch_cgi' /usr/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:9:in `dispatch' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/request_handler.rb:38:in `process_request' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_request_handler.rb:163:in `main_loop' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/application_spawner.rb:307:in `start_request_handler' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/application_spawner.rb:276:in `handle_spawn_application' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/utils.rb:165:in `safe_fork' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/utils.rb:163:in `fork' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/utils.rb:163:in `safe_fork' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/application_spawner.rb:274:in `handle_spawn_application' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/utils.rb:165:in `safe_fork' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/utils.rb:163:in `fork' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/utils.rb:163:in `safe_fork' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/application_spawner.rb:273:in `handle_spawn_application' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:317:in `__send__' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:317:in `main_loop' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:168:in `start_synchronously' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:135:in `start' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:112:in `fork' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:112:in `start' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/application_spawner.rb:177:in `start' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/framework_spawner.rb:270:in `handle_spawn_application' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/framework_spawner.rb:263:in `synchronize' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/framework_spawner.rb:263:in `handle_spawn_application' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:317:in `__send__' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:317:in `main_loop' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:168:in `start_synchronously' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:135:in `start' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:112:in `fork' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:112:in `start' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/railz/framework_spawner.rb:87:in `start' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/spawn_manager.rb:224:in `spawn_rails_application' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/spawn_manager.rb:219:in `synchronize' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/spawn_manager.rb:219:in `spawn_rails_application' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/spawn_manager.rb:122:in `spawn_application' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/spawn_manager.rb:253:in `handle_spawn_application' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:317:in `__send__' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:317:in `main_loop' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/lib/passenger/abstract_server.rb:168:in `start_synchronously' /usr/lib/ruby/gems/1.8/gems/passenger-2.0.2/bin/passenger-spawn-server:46 Rendering /home/redmine/releases/0.7.3/public/500.html (500 Internal Server Error)
Updated by Ignacio Carrera over 16 years ago
I just added
require 'rubygems' gem 'RedCloth', '3.0.4'
in config/environment.rb
, just after Rails' bootstrap, to make it work.
-- nachokb
Updated by Simone Carletti over 16 years ago
Ignacio Carrera wrote:
I just added
[...]
in
config/environment.rb
, just after Rails' bootstrap, to make it work.-- nachokb
I don't like this approach: it forces you to require an outdated library.
It can be used as a temporary workaround (I preferred the other way, I changed the base class extended by wiki formatter) but I would not suggest this as the final solution.
Additionally, it is prone to some side effects.
Because Rails loads RedCloth at initialization time before you require it, if you try to require it when the gem has alredy being loaded you may find yourself to deal with a "GEM alredy loaded" error.
Updated by Jean-Philippe Lang over 16 years ago
I think I should move the included and modified RedCloth to Redmine::RedCloth to prevent this kind of problem.
What do you think ?
Updated by Simone Carletti over 16 years ago
Jean-Philippe Lang wrote:
I think I should move the included and modified RedCloth to Redmine::RedCloth to prevent this kind of problem.
What do you think ?
That would be a possibile solution, even if I don't really like it but just because RedCloth has beed completely rewritten from scratch with a C parser and the new release it's now 30 times faster!
I started to work on a patch that was able to support both <= 3.3, ~> 3.3 and >= 4.x but I found a small problem trying to integrate special functions inline_auto_link, inline_auto_mailto.
My idea was to try to use RedCloth as an external instance (as Rails does) instead of extending it. This solution limits compatibility issues because libraries tends to change internally but preserving API access.
I was basically working on an unique initializer
def initialize(string) @redcloth = RedCloth.new(args, [:filter_html, :no_span_caps]) # != 3.301 ignores restrictions @redcloth.hard_breaks = true if @redcloth.respond_to?("hard_breaks=") # != 3.301 end
and some Modules to be mixed into TextileFormatter depending on RedCloth version.
For instance, RedCloth >= 3.3 Module would include the hard_break patch
# Patch for RedCloth. Fixed in RedCloth r128 but _why hasn't released it yet. # <a href="http://code.whytheluckystiff.net/redcloth/changeset/128">http://code.whytheluckystiff.net/redcloth/changeset/128</a> def hard_break( text ) text.gsub!( /(.)\n(?!\n|\Z|>| *(>? *[#*=]+(\s|$)|[{|]))/, "\\1<br />\n" ) if hard_breaks end
but not those for RedCloth >= 3.3.
However, because I don't really know the full Redmine structure, I stopped just to learn more about how Redmine calls WikiFormatter before taking bad design ways.
Updated by Gerrit Kaiser about 16 years ago
- File redcloth-rename.patch redcloth-rename.patch added
We worked around the problem by simply renaming the included RedCloth (Patch against r1764 attached). That way at least Redmine can be run on systems with the RedCloth 4 gem installed.
Updated by Dmitry Shaposhnik about 16 years ago
I can confirm - after renaming it works well (with RubyEE and mod_passenger).
Updated by Simone Carletti about 16 years ago
I just want to let you know Rails 2.1.1 includes a nice change that could probably (partially) contribute to fix this issue.
- Add the gem load paths before the framework is loaded, so certain gems like RedCloth and BlueCloth can be frozen.
In other words, as soon as Redmine will support Rails 2.1 (if I'm not wrong Redmine 0.8 should be compatible with Rails 2.1), RedCloth GEM could be frozen within Redcloth distribution.
I would suggest to consider to upgrade support at least to RedCloth 4.0 that is exceptionally faster than the previous major release.
Updated by Babar O'Cap about 16 years ago
Just to say that JRuby is also not compatible with RedCloth > 3.0.4. for the moment.
Updated by Jean-Philippe Lang about 16 years ago
- Status changed from New to Closed
- Target version set to 0.8
- Resolution set to Fixed
For now, I've renamed the bundled RedCloth to RedCloth3 as proposed by Gerrit.
Moving to RedCloth 4 is not planned yet. It would require some work to port the changes/improvements done on the bundled RedCloth. I have made a few tests, the performance improvement on an average ticket page is not so big. An alternative and considerably faster solution would be to cache the textile output.