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