##// END OF EJS Templates
Don't load redcarpet with JRuby....
Jean-Philippe Lang -
r12178:a657a1245062
parent child
Show More
@@ -1,100 +1,104
1 1 source 'https://rubygems.org'
2 2
3 3 gem "rails", "3.2.16"
4 4 gem "jquery-rails", "~> 2.0.2"
5 5 gem "coderay", "~> 1.1.0"
6 6 gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
7 7 gem "builder", "3.0.0"
8 # TODO: upgrade to redcarpet 3.x when ruby1.8 support is dropped
9 gem "redcarpet", "~> 2.3.0"
10 8
11 9 # Optional gem for LDAP authentication
12 10 group :ldap do
13 11 gem "net-ldap", "~> 0.3.1"
14 12 end
15 13
16 14 # Optional gem for OpenID authentication
17 15 group :openid do
18 16 gem "ruby-openid", "~> 2.3.0", :require => "openid"
19 17 gem "rack-openid"
20 18 end
21 19
22 # Optional gem for exporting the gantt to a PNG file, not supported with jruby
23 20 platforms :mri, :mingw do
21 # Optional gem for exporting the gantt to a PNG file, not supported with jruby
24 22 group :rmagick do
25 23 # RMagick 2 supports ruby 1.9
26 24 # RMagick 1 would be fine for ruby 1.8 but Bundler does not support
27 25 # different requirements for the same gem on different platforms
28 26 gem "rmagick", ">= 2.0.0"
29 27 end
28
29 # Optional Markdown support, not for JRuby
30 group :markdown do
31 # TODO: upgrade to redcarpet 3.x when ruby1.8 support is dropped
32 gem "redcarpet", "~> 2.3.0"
33 end
30 34 end
31 35
32 36 platforms :jruby do
33 37 # jruby-openssl is bundled with JRuby 1.7.0
34 38 gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
35 39 gem "activerecord-jdbc-adapter", "~> 1.3.2"
36 40 end
37 41
38 42 # Include database gems for the adapters found in the database
39 43 # configuration file
40 44 require 'erb'
41 45 require 'yaml'
42 46 database_file = File.join(File.dirname(__FILE__), "config/database.yml")
43 47 if File.exist?(database_file)
44 48 database_config = YAML::load(ERB.new(IO.read(database_file)).result)
45 49 adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
46 50 if adapters.any?
47 51 adapters.each do |adapter|
48 52 case adapter
49 53 when 'mysql2'
50 54 gem "mysql2", "~> 0.3.11", :platforms => [:mri, :mingw]
51 55 gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
52 56 when 'mysql'
53 57 gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw]
54 58 gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
55 59 when /postgresql/
56 60 gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw]
57 61 gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
58 62 when /sqlite3/
59 63 gem "sqlite3", :platforms => [:mri, :mingw]
60 64 gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
61 65 when /sqlserver/
62 66 gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw]
63 67 gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
64 68 else
65 69 warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
66 70 end
67 71 end
68 72 else
69 73 warn("No adapter found in config/database.yml, please configure it first")
70 74 end
71 75 else
72 76 warn("Please configure your config/database.yml first")
73 77 end
74 78
75 79 group :development do
76 80 gem "rdoc", ">= 2.4.2"
77 81 gem "yard"
78 82 end
79 83
80 84 group :test do
81 85 gem "shoulda", "~> 3.3.2"
82 86 gem "mocha", ">= 0.14", :require => 'mocha/api'
83 87 if RUBY_VERSION >= '1.9.3'
84 88 gem "capybara", "~> 2.1.0"
85 89 gem "selenium-webdriver"
86 90 end
87 91 end
88 92
89 93 local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
90 94 if File.exists?(local_gemfile)
91 95 puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v`
92 96 instance_eval File.read(local_gemfile)
93 97 end
94 98
95 99 # Load plugins' Gemfiles
96 100 Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
97 101 puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
98 102 #TODO: switch to "eval_gemfile file" when bundler >= 1.2.0 will be required (rails 4)
99 103 instance_eval File.read(file), file
100 104 end
@@ -1,274 +1,281
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2013 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require 'redmine/core_ext'
19 19
20 20 begin
21 21 require 'RMagick' unless Object.const_defined?(:Magick)
22 22 rescue LoadError
23 23 # RMagick is not available
24 24 end
25 begin
26 require 'Redcarpet' unless Object.const_defined?(:Redcarpet)
27 rescue LoadError
28 # Redcarpet is not available
29 end
25 30
26 31 require 'redmine/scm/base'
27 32 require 'redmine/access_control'
28 33 require 'redmine/access_keys'
29 34 require 'redmine/activity'
30 35 require 'redmine/activity/fetcher'
31 36 require 'redmine/ciphering'
32 37 require 'redmine/codeset_util'
33 38 require 'redmine/field_format'
34 39 require 'redmine/i18n'
35 40 require 'redmine/menu_manager'
36 41 require 'redmine/notifiable'
37 42 require 'redmine/platform'
38 43 require 'redmine/mime_type'
39 44 require 'redmine/notifiable'
40 45 require 'redmine/search'
41 46 require 'redmine/syntax_highlighting'
42 47 require 'redmine/thumbnail'
43 48 require 'redmine/unified_diff'
44 49 require 'redmine/utils'
45 50 require 'redmine/version'
46 51 require 'redmine/wiki_formatting'
47 52
48 53 require 'redmine/default_data/loader'
49 54 require 'redmine/helpers/calendar'
50 55 require 'redmine/helpers/diff'
51 56 require 'redmine/helpers/gantt'
52 57 require 'redmine/helpers/time_report'
53 58 require 'redmine/views/other_formats_builder'
54 59 require 'redmine/views/labelled_form_builder'
55 60 require 'redmine/views/builders'
56 61
57 62 require 'redmine/themes'
58 63 require 'redmine/hook'
59 64 require 'redmine/plugin'
60 65
61 66 if RUBY_VERSION < '1.9'
62 67 require 'fastercsv'
63 68 else
64 69 require 'csv'
65 70 FCSV = CSV
66 71 end
67 72
68 73 Redmine::Scm::Base.add "Subversion"
69 74 Redmine::Scm::Base.add "Darcs"
70 75 Redmine::Scm::Base.add "Mercurial"
71 76 Redmine::Scm::Base.add "Cvs"
72 77 Redmine::Scm::Base.add "Bazaar"
73 78 Redmine::Scm::Base.add "Git"
74 79 Redmine::Scm::Base.add "Filesystem"
75 80
76 81 # Permissions
77 82 Redmine::AccessControl.map do |map|
78 83 map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true, :read => true
79 84 map.permission :search_project, {:search => :index}, :public => true, :read => true
80 85 map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin
81 86 map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member
82 87 map.permission :close_project, {:projects => [:close, :reopen]}, :require => :member, :read => true
83 88 map.permission :select_project_modules, {:projects => :modules}, :require => :member
84 89 map.permission :manage_members, {:projects => :settings, :members => [:index, :show, :create, :update, :destroy, :autocomplete]}, :require => :member
85 90 map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
86 91 map.permission :add_subprojects, {:projects => [:new, :create]}, :require => :member
87 92
88 93 map.project_module :issue_tracking do |map|
89 94 # Issue categories
90 95 map.permission :manage_categories, {:projects => :settings, :issue_categories => [:index, :show, :new, :create, :edit, :update, :destroy]}, :require => :member
91 96 # Issues
92 97 map.permission :view_issues, {:issues => [:index, :show],
93 98 :auto_complete => [:issues],
94 99 :context_menus => [:issues],
95 100 :versions => [:index, :show, :status_by],
96 101 :journals => [:index, :diff],
97 102 :queries => :index,
98 103 :reports => [:issue_report, :issue_report_details]},
99 104 :read => true
100 105 map.permission :add_issues, {:issues => [:new, :create, :update_form], :attachments => :upload}
101 106 map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new], :attachments => :upload}
102 107 map.permission :manage_issue_relations, {:issue_relations => [:index, :show, :create, :destroy]}
103 108 map.permission :manage_subtasks, {}
104 109 map.permission :set_issues_private, {}
105 110 map.permission :set_own_issues_private, {}, :require => :loggedin
106 111 map.permission :add_issue_notes, {:issues => [:edit, :update, :update_form], :journals => [:new], :attachments => :upload}
107 112 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
108 113 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
109 114 map.permission :view_private_notes, {}, :read => true, :require => :member
110 115 map.permission :set_notes_private, {}, :require => :member
111 116 map.permission :move_issues, {:issues => [:bulk_edit, :bulk_update]}, :require => :loggedin
112 117 map.permission :delete_issues, {:issues => :destroy}, :require => :member
113 118 # Queries
114 119 map.permission :manage_public_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :member
115 120 map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
116 121 # Watchers
117 122 map.permission :view_issue_watchers, {}, :read => true
118 123 map.permission :add_issue_watchers, {:watchers => [:new, :create, :append, :autocomplete_for_user]}
119 124 map.permission :delete_issue_watchers, {:watchers => :destroy}
120 125 end
121 126
122 127 map.project_module :time_tracking do |map|
123 128 map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
124 129 map.permission :view_time_entries, {:timelog => [:index, :report, :show]}, :read => true
125 130 map.permission :edit_time_entries, {:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
126 131 map.permission :edit_own_time_entries, {:timelog => [:edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
127 132 map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
128 133 end
129 134
130 135 map.project_module :news do |map|
131 136 map.permission :manage_news, {:news => [:new, :create, :edit, :update, :destroy], :comments => [:destroy]}, :require => :member
132 137 map.permission :view_news, {:news => [:index, :show]}, :public => true, :read => true
133 138 map.permission :comment_news, {:comments => :create}
134 139 end
135 140
136 141 map.project_module :documents do |map|
137 142 map.permission :add_documents, {:documents => [:new, :create, :add_attachment]}, :require => :loggedin
138 143 map.permission :edit_documents, {:documents => [:edit, :update, :add_attachment]}, :require => :loggedin
139 144 map.permission :delete_documents, {:documents => [:destroy]}, :require => :loggedin
140 145 map.permission :view_documents, {:documents => [:index, :show, :download]}, :read => true
141 146 end
142 147
143 148 map.project_module :files do |map|
144 149 map.permission :manage_files, {:files => [:new, :create]}, :require => :loggedin
145 150 map.permission :view_files, {:files => :index, :versions => :download}, :read => true
146 151 end
147 152
148 153 map.project_module :wiki do |map|
149 154 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
150 155 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
151 156 map.permission :delete_wiki_pages, {:wiki => [:destroy, :destroy_version]}, :require => :member
152 157 map.permission :view_wiki_pages, {:wiki => [:index, :show, :special, :date_index]}, :read => true
153 158 map.permission :export_wiki_pages, {:wiki => [:export]}, :read => true
154 159 map.permission :view_wiki_edits, {:wiki => [:history, :diff, :annotate]}, :read => true
155 160 map.permission :edit_wiki_pages, :wiki => [:edit, :update, :preview, :add_attachment]
156 161 map.permission :delete_wiki_pages_attachments, {}
157 162 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
158 163 end
159 164
160 165 map.project_module :repository do |map|
161 166 map.permission :manage_repository, {:repositories => [:new, :create, :edit, :update, :committers, :destroy]}, :require => :member
162 167 map.permission :browse_repository, {:repositories => [:show, :browse, :entry, :raw, :annotate, :changes, :diff, :stats, :graph]}, :read => true
163 168 map.permission :view_changesets, {:repositories => [:show, :revisions, :revision]}, :read => true
164 169 map.permission :commit_access, {}
165 170 map.permission :manage_related_issues, {:repositories => [:add_related_issue, :remove_related_issue]}
166 171 end
167 172
168 173 map.project_module :boards do |map|
169 174 map.permission :manage_boards, {:boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
170 175 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true, :read => true
171 176 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
172 177 map.permission :edit_messages, {:messages => :edit}, :require => :member
173 178 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
174 179 map.permission :delete_messages, {:messages => :destroy}, :require => :member
175 180 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
176 181 end
177 182
178 183 map.project_module :calendar do |map|
179 184 map.permission :view_calendar, {:calendars => [:show, :update]}, :read => true
180 185 end
181 186
182 187 map.project_module :gantt do |map|
183 188 map.permission :view_gantt, {:gantts => [:show, :update]}, :read => true
184 189 end
185 190 end
186 191
187 192 Redmine::MenuManager.map :top_menu do |menu|
188 193 menu.push :home, :home_path
189 194 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
190 195 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
191 196 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
192 197 menu.push :help, Redmine::Info.help_url, :last => true
193 198 end
194 199
195 200 Redmine::MenuManager.map :account_menu do |menu|
196 201 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
197 202 menu.push :register, :register_path, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
198 203 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
199 204 menu.push :logout, :signout_path, :html => {:method => 'post'}, :if => Proc.new { User.current.logged? }
200 205 end
201 206
202 207 Redmine::MenuManager.map :application_menu do |menu|
203 208 # Empty
204 209 end
205 210
206 211 Redmine::MenuManager.map :admin_menu do |menu|
207 212 menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
208 213 menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
209 214 menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
210 215 menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
211 216 menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
212 217 menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
213 218 :html => {:class => 'issue_statuses'}
214 219 menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
215 220 menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
216 221 :html => {:class => 'custom_fields'}
217 222 menu.push :enumerations, {:controller => 'enumerations'}
218 223 menu.push :settings, {:controller => 'settings'}
219 224 menu.push :ldap_authentication, {:controller => 'auth_sources', :action => 'index'},
220 225 :html => {:class => 'server_authentication'}
221 226 menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
222 227 menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
223 228 end
224 229
225 230 Redmine::MenuManager.map :project_menu do |menu|
226 231 menu.push :overview, { :controller => 'projects', :action => 'show' }
227 232 menu.push :activity, { :controller => 'activities', :action => 'index' }
228 233 menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id,
229 234 :if => Proc.new { |p| p.shared_versions.any? }
230 235 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
231 236 menu.push :new_issue, { :controller => 'issues', :action => 'new', :copy_from => nil }, :param => :project_id, :caption => :label_issue_new,
232 237 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
233 238 menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
234 239 menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
235 240 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
236 241 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
237 242 menu.push :wiki, { :controller => 'wiki', :action => 'show', :id => nil }, :param => :project_id,
238 243 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
239 244 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
240 245 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
241 246 menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural, :param => :project_id
242 247 menu.push :repository, { :controller => 'repositories', :action => 'show', :repository_id => nil, :path => nil, :rev => nil },
243 248 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
244 249 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
245 250 end
246 251
247 252 Redmine::Activity.map do |activity|
248 253 activity.register :issues, :class_name => %w(Issue Journal)
249 254 activity.register :changesets
250 255 activity.register :news
251 256 activity.register :documents, :class_name => %w(Document Attachment)
252 257 activity.register :files, :class_name => 'Attachment'
253 258 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
254 259 activity.register :messages, :default => false
255 260 activity.register :time_entries, :default => false
256 261 end
257 262
258 263 Redmine::Search.map do |search|
259 264 search.register :issues
260 265 search.register :news
261 266 search.register :documents
262 267 search.register :changesets
263 268 search.register :wiki_pages
264 269 search.register :messages
265 270 search.register :projects
266 271 end
267 272
268 273 Redmine::WikiFormatting.map do |format|
269 274 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
270 format.register :markdown, Redmine::WikiFormatting::Markdown::Formatter, Redmine::WikiFormatting::Markdown::Helper,
271 :label => 'Markdown (experimental)'
275 if Object.const_defined?(:Redcarpet)
276 format.register :markdown, Redmine::WikiFormatting::Markdown::Formatter, Redmine::WikiFormatting::Markdown::Helper,
277 :label => 'Markdown (experimental)'
278 end
272 279 end
273 280
274 281 ActionView::Template.register_template_handler :rsb, Redmine::Views::ApiTemplateHandler
@@ -1,447 +1,448
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2013 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require 'cgi'
19 require 'redmine/scm/adapters'
19 20
20 21 if RUBY_VERSION < '1.9'
21 22 require 'iconv'
22 23 end
23 24
24 25 module Redmine
25 26 module Scm
26 27 module Adapters
27 28 class AbstractAdapter #:nodoc:
28 29
29 30 # raised if scm command exited with error, e.g. unknown revision.
30 31 class ScmCommandAborted < CommandFailed; end
31 32
32 33 class << self
33 34 def client_command
34 35 ""
35 36 end
36 37
37 38 def shell_quote_command
38 39 if Redmine::Platform.mswin? && RUBY_PLATFORM == 'java'
39 40 client_command
40 41 else
41 42 shell_quote(client_command)
42 43 end
43 44 end
44 45
45 46 # Returns the version of the scm client
46 47 # Eg: [1, 5, 0] or [] if unknown
47 48 def client_version
48 49 []
49 50 end
50 51
51 52 # Returns the version string of the scm client
52 53 # Eg: '1.5.0' or 'Unknown version' if unknown
53 54 def client_version_string
54 55 v = client_version || 'Unknown version'
55 56 v.is_a?(Array) ? v.join('.') : v.to_s
56 57 end
57 58
58 59 # Returns true if the current client version is above
59 60 # or equals the given one
60 61 # If option is :unknown is set to true, it will return
61 62 # true if the client version is unknown
62 63 def client_version_above?(v, options={})
63 64 ((client_version <=> v) >= 0) || (client_version.empty? && options[:unknown])
64 65 end
65 66
66 67 def client_available
67 68 true
68 69 end
69 70
70 71 def shell_quote(str)
71 72 if Redmine::Platform.mswin?
72 73 '"' + str.gsub(/"/, '\\"') + '"'
73 74 else
74 75 "'" + str.gsub(/'/, "'\"'\"'") + "'"
75 76 end
76 77 end
77 78 end
78 79
79 80 def initialize(url, root_url=nil, login=nil, password=nil,
80 81 path_encoding=nil)
81 82 @url = url
82 83 @login = login if login && !login.empty?
83 84 @password = (password || "") if @login
84 85 @root_url = root_url.blank? ? retrieve_root_url : root_url
85 86 end
86 87
87 88 def adapter_name
88 89 'Abstract'
89 90 end
90 91
91 92 def supports_cat?
92 93 true
93 94 end
94 95
95 96 def supports_annotate?
96 97 respond_to?('annotate')
97 98 end
98 99
99 100 def root_url
100 101 @root_url
101 102 end
102 103
103 104 def url
104 105 @url
105 106 end
106 107
107 108 def path_encoding
108 109 nil
109 110 end
110 111
111 112 # get info about the svn repository
112 113 def info
113 114 return nil
114 115 end
115 116
116 117 # Returns the entry identified by path and revision identifier
117 118 # or nil if entry doesn't exist in the repository
118 119 def entry(path=nil, identifier=nil)
119 120 parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
120 121 search_path = parts[0..-2].join('/')
121 122 search_name = parts[-1]
122 123 if search_path.blank? && search_name.blank?
123 124 # Root entry
124 125 Entry.new(:path => '', :kind => 'dir')
125 126 else
126 127 # Search for the entry in the parent directory
127 128 es = entries(search_path, identifier)
128 129 es ? es.detect {|e| e.name == search_name} : nil
129 130 end
130 131 end
131 132
132 133 # Returns an Entries collection
133 134 # or nil if the given path doesn't exist in the repository
134 135 def entries(path=nil, identifier=nil, options={})
135 136 return nil
136 137 end
137 138
138 139 def branches
139 140 return nil
140 141 end
141 142
142 143 def tags
143 144 return nil
144 145 end
145 146
146 147 def default_branch
147 148 return nil
148 149 end
149 150
150 151 def properties(path, identifier=nil)
151 152 return nil
152 153 end
153 154
154 155 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
155 156 return nil
156 157 end
157 158
158 159 def diff(path, identifier_from, identifier_to=nil)
159 160 return nil
160 161 end
161 162
162 163 def cat(path, identifier=nil)
163 164 return nil
164 165 end
165 166
166 167 def with_leading_slash(path)
167 168 path ||= ''
168 169 (path[0,1]!="/") ? "/#{path}" : path
169 170 end
170 171
171 172 def with_trailling_slash(path)
172 173 path ||= ''
173 174 (path[-1,1] == "/") ? path : "#{path}/"
174 175 end
175 176
176 177 def without_leading_slash(path)
177 178 path ||= ''
178 179 path.gsub(%r{^/+}, '')
179 180 end
180 181
181 182 def without_trailling_slash(path)
182 183 path ||= ''
183 184 (path[-1,1] == "/") ? path[0..-2] : path
184 185 end
185 186
186 187 def shell_quote(str)
187 188 self.class.shell_quote(str)
188 189 end
189 190
190 191 private
191 192 def retrieve_root_url
192 193 info = self.info
193 194 info ? info.root_url : nil
194 195 end
195 196
196 197 def target(path, sq=true)
197 198 path ||= ''
198 199 base = path.match(/^\//) ? root_url : url
199 200 str = "#{base}/#{path}".gsub(/[?<>\*]/, '')
200 201 if sq
201 202 str = shell_quote(str)
202 203 end
203 204 str
204 205 end
205 206
206 207 def logger
207 208 self.class.logger
208 209 end
209 210
210 211 def shellout(cmd, options = {}, &block)
211 212 self.class.shellout(cmd, options, &block)
212 213 end
213 214
214 215 def self.logger
215 216 Rails.logger
216 217 end
217 218
218 219 # Path to the file where scm stderr output is logged
219 220 # Returns nil if the log file is not writable
220 221 def self.stderr_log_file
221 222 if @stderr_log_file.nil?
222 223 writable = false
223 224 path = Redmine::Configuration['scm_stderr_log_file'].presence
224 225 path ||= Rails.root.join("log/#{Rails.env}.scm.stderr.log").to_s
225 226 if File.exists?(path)
226 227 if File.file?(path) && File.writable?(path)
227 228 writable = true
228 229 else
229 230 logger.warn("SCM log file (#{path}) is not writable")
230 231 end
231 232 else
232 233 begin
233 234 File.open(path, "w") {}
234 235 writable = true
235 236 rescue => e
236 237 logger.warn("SCM log file (#{path}) cannot be created: #{e.message}")
237 238 end
238 239 end
239 240 @stderr_log_file = writable ? path : false
240 241 end
241 242 @stderr_log_file || nil
242 243 end
243 244
244 245 def self.shellout(cmd, options = {}, &block)
245 246 if logger && logger.debug?
246 247 logger.debug "Shelling out: #{strip_credential(cmd)}"
247 248 # Capture stderr in a log file
248 249 if stderr_log_file
249 250 cmd = "#{cmd} 2>>#{shell_quote(stderr_log_file)}"
250 251 end
251 252 end
252 253 begin
253 254 mode = "r+"
254 255 IO.popen(cmd, mode) do |io|
255 256 io.set_encoding("ASCII-8BIT") if io.respond_to?(:set_encoding)
256 257 io.close_write unless options[:write_stdin]
257 258 block.call(io) if block_given?
258 259 end
259 260 ## If scm command does not exist,
260 261 ## Linux JRuby 1.6.2 (ruby-1.8.7-p330) raises java.io.IOException
261 262 ## in production environment.
262 263 # rescue Errno::ENOENT => e
263 264 rescue Exception => e
264 265 msg = strip_credential(e.message)
265 266 # The command failed, log it and re-raise
266 267 logmsg = "SCM command failed, "
267 268 logmsg += "make sure that your SCM command (e.g. svn) is "
268 269 logmsg += "in PATH (#{ENV['PATH']})\n"
269 270 logmsg += "You can configure your scm commands in config/configuration.yml.\n"
270 271 logmsg += "#{strip_credential(cmd)}\n"
271 272 logmsg += "with: #{msg}"
272 273 logger.error(logmsg)
273 274 raise CommandFailed.new(msg)
274 275 end
275 276 end
276 277
277 278 # Hides username/password in a given command
278 279 def self.strip_credential(cmd)
279 280 q = (Redmine::Platform.mswin? ? '"' : "'")
280 281 cmd.to_s.gsub(/(\-\-(password|username))\s+(#{q}[^#{q}]+#{q}|[^#{q}]\S+)/, '\\1 xxxx')
281 282 end
282 283
283 284 def strip_credential(cmd)
284 285 self.class.strip_credential(cmd)
285 286 end
286 287
287 288 def scm_iconv(to, from, str)
288 289 return nil if str.nil?
289 290 return str if to == from
290 291 if str.respond_to?(:force_encoding)
291 292 str.force_encoding(from)
292 293 begin
293 294 str.encode(to)
294 295 rescue Exception => err
295 296 logger.error("failed to convert from #{from} to #{to}. #{err}")
296 297 nil
297 298 end
298 299 else
299 300 begin
300 301 Iconv.conv(to, from, str)
301 302 rescue Iconv::Failure => err
302 303 logger.error("failed to convert from #{from} to #{to}. #{err}")
303 304 nil
304 305 end
305 306 end
306 307 end
307 308
308 309 def parse_xml(xml)
309 310 if RUBY_PLATFORM == 'java'
310 311 xml = xml.sub(%r{<\?xml[^>]*\?>}, '')
311 312 end
312 313 ActiveSupport::XmlMini.parse(xml)
313 314 end
314 315 end
315 316
316 317 class Entries < Array
317 318 def sort_by_name
318 319 dup.sort! {|x,y|
319 320 if x.kind == y.kind
320 321 x.name.to_s <=> y.name.to_s
321 322 else
322 323 x.kind <=> y.kind
323 324 end
324 325 }
325 326 end
326 327
327 328 def revisions
328 329 revisions ||= Revisions.new(collect{|entry| entry.lastrev}.compact)
329 330 end
330 331 end
331 332
332 333 class Info
333 334 attr_accessor :root_url, :lastrev
334 335 def initialize(attributes={})
335 336 self.root_url = attributes[:root_url] if attributes[:root_url]
336 337 self.lastrev = attributes[:lastrev]
337 338 end
338 339 end
339 340
340 341 class Entry
341 342 attr_accessor :name, :path, :kind, :size, :lastrev, :changeset
342 343
343 344 def initialize(attributes={})
344 345 self.name = attributes[:name] if attributes[:name]
345 346 self.path = attributes[:path] if attributes[:path]
346 347 self.kind = attributes[:kind] if attributes[:kind]
347 348 self.size = attributes[:size].to_i if attributes[:size]
348 349 self.lastrev = attributes[:lastrev]
349 350 end
350 351
351 352 def is_file?
352 353 'file' == self.kind
353 354 end
354 355
355 356 def is_dir?
356 357 'dir' == self.kind
357 358 end
358 359
359 360 def is_text?
360 361 Redmine::MimeType.is_type?('text', name)
361 362 end
362 363
363 364 def author
364 365 if changeset
365 366 changeset.author.to_s
366 367 elsif lastrev
367 368 Redmine::CodesetUtil.replace_invalid_utf8(lastrev.author.to_s.split('<').first)
368 369 end
369 370 end
370 371 end
371 372
372 373 class Revisions < Array
373 374 def latest
374 375 sort {|x,y|
375 376 unless x.time.nil? or y.time.nil?
376 377 x.time <=> y.time
377 378 else
378 379 0
379 380 end
380 381 }.last
381 382 end
382 383 end
383 384
384 385 class Revision
385 386 attr_accessor :scmid, :name, :author, :time, :message,
386 387 :paths, :revision, :branch, :identifier,
387 388 :parents
388 389
389 390 def initialize(attributes={})
390 391 self.identifier = attributes[:identifier]
391 392 self.scmid = attributes[:scmid]
392 393 self.name = attributes[:name] || self.identifier
393 394 self.author = attributes[:author]
394 395 self.time = attributes[:time]
395 396 self.message = attributes[:message] || ""
396 397 self.paths = attributes[:paths]
397 398 self.revision = attributes[:revision]
398 399 self.branch = attributes[:branch]
399 400 self.parents = attributes[:parents]
400 401 end
401 402
402 403 # Returns the readable identifier.
403 404 def format_identifier
404 405 self.identifier.to_s
405 406 end
406 407
407 408 def ==(other)
408 409 if other.nil?
409 410 false
410 411 elsif scmid.present?
411 412 scmid == other.scmid
412 413 elsif identifier.present?
413 414 identifier == other.identifier
414 415 elsif revision.present?
415 416 revision == other.revision
416 417 end
417 418 end
418 419 end
419 420
420 421 class Annotate
421 422 attr_reader :lines, :revisions
422 423
423 424 def initialize
424 425 @lines = []
425 426 @revisions = []
426 427 end
427 428
428 429 def add_line(line, revision)
429 430 @lines << line
430 431 @revisions << revision
431 432 end
432 433
433 434 def content
434 435 content = lines.join("\n")
435 436 end
436 437
437 438 def empty?
438 439 lines.empty?
439 440 end
440 441 end
441 442
442 443 class Branch < String
443 444 attr_accessor :revision, :scmid
444 445 end
445 446 end
446 447 end
447 448 end
@@ -1,62 +1,66
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2013 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../../../../test_helper', __FILE__)
19 19
20 20 class Redmine::WikiFormatting::MarkdownFormatterTest < ActionView::TestCase
21 21 include ApplicationHelper
22 22
23 if Object.const_defined?(:Redcarpet)
24
23 25 def setup
24 26 @formatter = Redmine::WikiFormatting::Markdown::Formatter
25 27 end
26 28
27 29 def test_inline_style
28 30 assert_equal "<p><strong>foo</strong></p>", @formatter.new("**foo**").to_html.strip
29 31 end
30 32
31 33 def test_wiki_links_should_be_preserved
32 34 text = 'This is a wiki link: [[Foo]]'
33 35 assert_include '[[Foo]]', @formatter.new(text).to_html
34 36 end
35 37
36 38 def test_redmine_links_with_double_quotes_should_be_preserved
37 39 text = 'This is a redmine link: version:"1.0"'
38 40 assert_include 'version:"1.0"', @formatter.new(text).to_html
39 41 end
40 42
41 43 def test_should_support_syntax_highligth
42 44 text = <<-STR
43 45 ~~~ruby
44 46 def foo
45 47 end
46 48 ~~~
47 49 STR
48 50 assert_select_in @formatter.new(text).to_html, 'pre code.ruby.syntaxhl' do
49 51 assert_select 'span.keyword', :text => 'def'
50 52 end
51 53 end
52 54
53 55 def test_external_links_should_have_external_css_class
54 56 text = 'This is a [link](http://example.net/)'
55 57 assert_equal '<p>This is a <a class="external" href="http://example.net/">link</a></p>', @formatter.new(text).to_html.strip
56 58 end
57 59
58 60 def test_locals_links_should_not_have_external_css_class
59 61 text = 'This is a [link](/issues)'
60 62 assert_equal '<p>This is a <a href="/issues">link</a></p>', @formatter.new(text).to_html.strip
61 63 end
64
65 end
62 66 end
General Comments 0
You need to be logged in to leave comments. Login now