##// END OF EJS Templates
route: scm: split entry and raw actions...
Toshi MARUYAMA -
r9442:b0414ec1fbab
parent child
Show More
@@ -1,448 +1,457
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 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 'SVG/Graph/Bar'
18 require 'SVG/Graph/Bar'
19 require 'SVG/Graph/BarHorizontal'
19 require 'SVG/Graph/BarHorizontal'
20 require 'digest/sha1'
20 require 'digest/sha1'
21 require 'redmine/scm/adapters/abstract_adapter'
21 require 'redmine/scm/adapters/abstract_adapter'
22
22
23 class ChangesetNotFound < Exception; end
23 class ChangesetNotFound < Exception; end
24 class InvalidRevisionParam < Exception; end
24 class InvalidRevisionParam < Exception; end
25
25
26 class RepositoriesController < ApplicationController
26 class RepositoriesController < ApplicationController
27 menu_item :repository
27 menu_item :repository
28 menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers]
28 menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers]
29 default_search_scope :changesets
29 default_search_scope :changesets
30
30
31 before_filter :find_project_by_project_id, :only => [:new, :create]
31 before_filter :find_project_by_project_id, :only => [:new, :create]
32 before_filter :find_repository, :only => [:edit, :update, :destroy, :committers]
32 before_filter :find_repository, :only => [:edit, :update, :destroy, :committers]
33 before_filter :find_project_repository, :except => [:new, :create, :edit, :update, :destroy, :committers]
33 before_filter :find_project_repository, :except => [:new, :create, :edit, :update, :destroy, :committers]
34 before_filter :find_changeset, :only => [:revision, :add_related_issue, :remove_related_issue]
34 before_filter :find_changeset, :only => [:revision, :add_related_issue, :remove_related_issue]
35 before_filter :authorize
35 before_filter :authorize
36 accept_rss_auth :revisions
36 accept_rss_auth :revisions
37
37
38 rescue_from Redmine::Scm::Adapters::CommandFailed, :with => :show_error_command_failed
38 rescue_from Redmine::Scm::Adapters::CommandFailed, :with => :show_error_command_failed
39
39
40 def new
40 def new
41 scm = params[:repository_scm] || (Redmine::Scm::Base.all & Setting.enabled_scm).first
41 scm = params[:repository_scm] || (Redmine::Scm::Base.all & Setting.enabled_scm).first
42 @repository = Repository.factory(scm)
42 @repository = Repository.factory(scm)
43 @repository.is_default = @project.repository.nil?
43 @repository.is_default = @project.repository.nil?
44 @repository.project = @project
44 @repository.project = @project
45 render :layout => !request.xhr?
45 render :layout => !request.xhr?
46 end
46 end
47
47
48 def create
48 def create
49 attrs = pickup_extra_info
49 attrs = pickup_extra_info
50 @repository = Repository.factory(params[:repository_scm], attrs[:attrs])
50 @repository = Repository.factory(params[:repository_scm], attrs[:attrs])
51 if attrs[:attrs_extra].keys.any?
51 if attrs[:attrs_extra].keys.any?
52 @repository.merge_extra_info(attrs[:attrs_extra])
52 @repository.merge_extra_info(attrs[:attrs_extra])
53 end
53 end
54 @repository.project = @project
54 @repository.project = @project
55 if request.post? && @repository.save
55 if request.post? && @repository.save
56 redirect_to settings_project_path(@project, :tab => 'repositories')
56 redirect_to settings_project_path(@project, :tab => 'repositories')
57 else
57 else
58 render :action => 'new'
58 render :action => 'new'
59 end
59 end
60 end
60 end
61
61
62 def edit
62 def edit
63 end
63 end
64
64
65 def update
65 def update
66 attrs = pickup_extra_info
66 attrs = pickup_extra_info
67 @repository.attributes = attrs[:attrs]
67 @repository.attributes = attrs[:attrs]
68 if attrs[:attrs_extra].keys.any?
68 if attrs[:attrs_extra].keys.any?
69 @repository.merge_extra_info(attrs[:attrs_extra])
69 @repository.merge_extra_info(attrs[:attrs_extra])
70 end
70 end
71 @repository.project = @project
71 @repository.project = @project
72 if request.put? && @repository.save
72 if request.put? && @repository.save
73 redirect_to settings_project_path(@project, :tab => 'repositories')
73 redirect_to settings_project_path(@project, :tab => 'repositories')
74 else
74 else
75 render :action => 'edit'
75 render :action => 'edit'
76 end
76 end
77 end
77 end
78
78
79 def pickup_extra_info
79 def pickup_extra_info
80 p = {}
80 p = {}
81 p_extra = {}
81 p_extra = {}
82 params[:repository].each do |k, v|
82 params[:repository].each do |k, v|
83 if k =~ /^extra_/
83 if k =~ /^extra_/
84 p_extra[k] = v
84 p_extra[k] = v
85 else
85 else
86 p[k] = v
86 p[k] = v
87 end
87 end
88 end
88 end
89 {:attrs => p, :attrs_extra => p_extra}
89 {:attrs => p, :attrs_extra => p_extra}
90 end
90 end
91 private :pickup_extra_info
91 private :pickup_extra_info
92
92
93 def committers
93 def committers
94 @committers = @repository.committers
94 @committers = @repository.committers
95 @users = @project.users
95 @users = @project.users
96 additional_user_ids = @committers.collect(&:last).collect(&:to_i) - @users.collect(&:id)
96 additional_user_ids = @committers.collect(&:last).collect(&:to_i) - @users.collect(&:id)
97 @users += User.find_all_by_id(additional_user_ids) unless additional_user_ids.empty?
97 @users += User.find_all_by_id(additional_user_ids) unless additional_user_ids.empty?
98 @users.compact!
98 @users.compact!
99 @users.sort!
99 @users.sort!
100 if request.post? && params[:committers].is_a?(Hash)
100 if request.post? && params[:committers].is_a?(Hash)
101 # Build a hash with repository usernames as keys and corresponding user ids as values
101 # Build a hash with repository usernames as keys and corresponding user ids as values
102 @repository.committer_ids = params[:committers].values.inject({}) {|h, c| h[c.first] = c.last; h}
102 @repository.committer_ids = params[:committers].values.inject({}) {|h, c| h[c.first] = c.last; h}
103 flash[:notice] = l(:notice_successful_update)
103 flash[:notice] = l(:notice_successful_update)
104 redirect_to settings_project_path(@project, :tab => 'repositories')
104 redirect_to settings_project_path(@project, :tab => 'repositories')
105 end
105 end
106 end
106 end
107
107
108 def destroy
108 def destroy
109 @repository.destroy if request.delete?
109 @repository.destroy if request.delete?
110 redirect_to settings_project_path(@project, :tab => 'repositories')
110 redirect_to settings_project_path(@project, :tab => 'repositories')
111 end
111 end
112
112
113 def show
113 def show
114 @repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty?
114 @repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty?
115
115
116 @entries = @repository.entries(@path, @rev)
116 @entries = @repository.entries(@path, @rev)
117 @changeset = @repository.find_changeset_by_name(@rev)
117 @changeset = @repository.find_changeset_by_name(@rev)
118 if request.xhr?
118 if request.xhr?
119 @entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
119 @entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
120 else
120 else
121 (show_error_not_found; return) unless @entries
121 (show_error_not_found; return) unless @entries
122 @changesets = @repository.latest_changesets(@path, @rev)
122 @changesets = @repository.latest_changesets(@path, @rev)
123 @properties = @repository.properties(@path, @rev)
123 @properties = @repository.properties(@path, @rev)
124 @repositories = @project.repositories
124 @repositories = @project.repositories
125 render :action => 'show'
125 render :action => 'show'
126 end
126 end
127 end
127 end
128
128
129 alias_method :browse, :show
129 alias_method :browse, :show
130
130
131 def changes
131 def changes
132 @entry = @repository.entry(@path, @rev)
132 @entry = @repository.entry(@path, @rev)
133 (show_error_not_found; return) unless @entry
133 (show_error_not_found; return) unless @entry
134 @changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i)
134 @changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i)
135 @properties = @repository.properties(@path, @rev)
135 @properties = @repository.properties(@path, @rev)
136 @changeset = @repository.find_changeset_by_name(@rev)
136 @changeset = @repository.find_changeset_by_name(@rev)
137 end
137 end
138
138
139 def revisions
139 def revisions
140 @changeset_count = @repository.changesets.count
140 @changeset_count = @repository.changesets.count
141 @changeset_pages = Paginator.new self, @changeset_count,
141 @changeset_pages = Paginator.new self, @changeset_count,
142 per_page_option,
142 per_page_option,
143 params['page']
143 params['page']
144 @changesets = @repository.changesets.find(:all,
144 @changesets = @repository.changesets.find(:all,
145 :limit => @changeset_pages.items_per_page,
145 :limit => @changeset_pages.items_per_page,
146 :offset => @changeset_pages.current.offset,
146 :offset => @changeset_pages.current.offset,
147 :include => [:user, :repository, :parents])
147 :include => [:user, :repository, :parents])
148
148
149 respond_to do |format|
149 respond_to do |format|
150 format.html { render :layout => false if request.xhr? }
150 format.html { render :layout => false if request.xhr? }
151 format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") }
151 format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") }
152 end
152 end
153 end
153 end
154
154
155 def raw
156 entry_and_raw(true)
157 end
158
155 def entry
159 def entry
160 entry_and_raw(false)
161 end
162
163 def entry_and_raw(is_raw)
156 @entry = @repository.entry(@path, @rev)
164 @entry = @repository.entry(@path, @rev)
157 (show_error_not_found; return) unless @entry
165 (show_error_not_found; return) unless @entry
158
166
159 # If the entry is a dir, show the browser
167 # If the entry is a dir, show the browser
160 (show; return) if @entry.is_dir?
168 (show; return) if @entry.is_dir?
161
169
162 @content = @repository.cat(@path, @rev)
170 @content = @repository.cat(@path, @rev)
163 (show_error_not_found; return) unless @content
171 (show_error_not_found; return) unless @content
164 if 'raw' == params[:format] ||
172 if is_raw ||
165 (@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) ||
173 (@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) ||
166 ! is_entry_text_data?(@content, @path)
174 ! is_entry_text_data?(@content, @path)
167 # Force the download
175 # Force the download
168 send_opt = { :filename => filename_for_content_disposition(@path.split('/').last) }
176 send_opt = { :filename => filename_for_content_disposition(@path.split('/').last) }
169 send_type = Redmine::MimeType.of(@path)
177 send_type = Redmine::MimeType.of(@path)
170 send_opt[:type] = send_type.to_s if send_type
178 send_opt[:type] = send_type.to_s if send_type
171 send_data @content, send_opt
179 send_data @content, send_opt
172 else
180 else
173 # Prevent empty lines when displaying a file with Windows style eol
181 # Prevent empty lines when displaying a file with Windows style eol
174 # TODO: UTF-16
182 # TODO: UTF-16
175 # Is this needs? AttachmentsController reads file simply.
183 # Is this needs? AttachmentsController reads file simply.
176 @content.gsub!("\r\n", "\n")
184 @content.gsub!("\r\n", "\n")
177 @changeset = @repository.find_changeset_by_name(@rev)
185 @changeset = @repository.find_changeset_by_name(@rev)
178 end
186 end
179 end
187 end
188 private :entry_and_raw
180
189
181 def is_entry_text_data?(ent, path)
190 def is_entry_text_data?(ent, path)
182 # UTF-16 contains "\x00".
191 # UTF-16 contains "\x00".
183 # It is very strict that file contains less than 30% of ascii symbols
192 # It is very strict that file contains less than 30% of ascii symbols
184 # in non Western Europe.
193 # in non Western Europe.
185 return true if Redmine::MimeType.is_type?('text', path)
194 return true if Redmine::MimeType.is_type?('text', path)
186 # Ruby 1.8.6 has a bug of integer divisions.
195 # Ruby 1.8.6 has a bug of integer divisions.
187 # http://apidock.com/ruby/v1_8_6_287/String/is_binary_data%3F
196 # http://apidock.com/ruby/v1_8_6_287/String/is_binary_data%3F
188 return false if ent.is_binary_data?
197 return false if ent.is_binary_data?
189 true
198 true
190 end
199 end
191 private :is_entry_text_data?
200 private :is_entry_text_data?
192
201
193 def annotate
202 def annotate
194 @entry = @repository.entry(@path, @rev)
203 @entry = @repository.entry(@path, @rev)
195 (show_error_not_found; return) unless @entry
204 (show_error_not_found; return) unless @entry
196
205
197 @annotate = @repository.scm.annotate(@path, @rev)
206 @annotate = @repository.scm.annotate(@path, @rev)
198 if @annotate.nil? || @annotate.empty?
207 if @annotate.nil? || @annotate.empty?
199 (render_error l(:error_scm_annotate); return)
208 (render_error l(:error_scm_annotate); return)
200 end
209 end
201 ann_buf_size = 0
210 ann_buf_size = 0
202 @annotate.lines.each do |buf|
211 @annotate.lines.each do |buf|
203 ann_buf_size += buf.size
212 ann_buf_size += buf.size
204 end
213 end
205 if ann_buf_size > Setting.file_max_size_displayed.to_i.kilobyte
214 if ann_buf_size > Setting.file_max_size_displayed.to_i.kilobyte
206 (render_error l(:error_scm_annotate_big_text_file); return)
215 (render_error l(:error_scm_annotate_big_text_file); return)
207 end
216 end
208 @changeset = @repository.find_changeset_by_name(@rev)
217 @changeset = @repository.find_changeset_by_name(@rev)
209 end
218 end
210
219
211 def revision
220 def revision
212 respond_to do |format|
221 respond_to do |format|
213 format.html
222 format.html
214 format.js {render :layout => false}
223 format.js {render :layout => false}
215 end
224 end
216 end
225 end
217
226
218 # Adds a related issue to a changeset
227 # Adds a related issue to a changeset
219 # POST /projects/:project_id/repository/(:repository_id/)revisions/:rev/issues
228 # POST /projects/:project_id/repository/(:repository_id/)revisions/:rev/issues
220 def add_related_issue
229 def add_related_issue
221 @issue = @changeset.find_referenced_issue_by_id(params[:issue_id])
230 @issue = @changeset.find_referenced_issue_by_id(params[:issue_id])
222 if @issue && (!@issue.visible? || @changeset.issues.include?(@issue))
231 if @issue && (!@issue.visible? || @changeset.issues.include?(@issue))
223 @issue = nil
232 @issue = nil
224 end
233 end
225
234
226 if @issue
235 if @issue
227 @changeset.issues << @issue
236 @changeset.issues << @issue
228 respond_to do |format|
237 respond_to do |format|
229 format.js {
238 format.js {
230 render :update do |page|
239 render :update do |page|
231 page.replace_html "related-issues", :partial => "related_issues"
240 page.replace_html "related-issues", :partial => "related_issues"
232 page.visual_effect :highlight, "related-issue-#{@issue.id}"
241 page.visual_effect :highlight, "related-issue-#{@issue.id}"
233 end
242 end
234 }
243 }
235 end
244 end
236 else
245 else
237 respond_to do |format|
246 respond_to do |format|
238 format.js {
247 format.js {
239 render :update do |page|
248 render :update do |page|
240 page.alert(l(:label_issue) + ' ' + l('activerecord.errors.messages.invalid'))
249 page.alert(l(:label_issue) + ' ' + l('activerecord.errors.messages.invalid'))
241 end
250 end
242 }
251 }
243 end
252 end
244 end
253 end
245 end
254 end
246
255
247 # Removes a related issue from a changeset
256 # Removes a related issue from a changeset
248 # DELETE /projects/:project_id/repository/(:repository_id/)revisions/:rev/issues/:issue_id
257 # DELETE /projects/:project_id/repository/(:repository_id/)revisions/:rev/issues/:issue_id
249 def remove_related_issue
258 def remove_related_issue
250 @issue = Issue.visible.find_by_id(params[:issue_id])
259 @issue = Issue.visible.find_by_id(params[:issue_id])
251 if @issue
260 if @issue
252 @changeset.issues.delete(@issue)
261 @changeset.issues.delete(@issue)
253 end
262 end
254
263
255 respond_to do |format|
264 respond_to do |format|
256 format.js {
265 format.js {
257 render :update do |page|
266 render :update do |page|
258 page.remove "related-issue-#{@issue.id}"
267 page.remove "related-issue-#{@issue.id}"
259 end if @issue
268 end if @issue
260 }
269 }
261 end
270 end
262 end
271 end
263
272
264 def diff
273 def diff
265 if params[:format] == 'diff'
274 if params[:format] == 'diff'
266 @diff = @repository.diff(@path, @rev, @rev_to)
275 @diff = @repository.diff(@path, @rev, @rev_to)
267 (show_error_not_found; return) unless @diff
276 (show_error_not_found; return) unless @diff
268 filename = "changeset_r#{@rev}"
277 filename = "changeset_r#{@rev}"
269 filename << "_r#{@rev_to}" if @rev_to
278 filename << "_r#{@rev_to}" if @rev_to
270 send_data @diff.join, :filename => "#{filename}.diff",
279 send_data @diff.join, :filename => "#{filename}.diff",
271 :type => 'text/x-patch',
280 :type => 'text/x-patch',
272 :disposition => 'attachment'
281 :disposition => 'attachment'
273 else
282 else
274 @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
283 @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
275 @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
284 @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
276
285
277 # Save diff type as user preference
286 # Save diff type as user preference
278 if User.current.logged? && @diff_type != User.current.pref[:diff_type]
287 if User.current.logged? && @diff_type != User.current.pref[:diff_type]
279 User.current.pref[:diff_type] = @diff_type
288 User.current.pref[:diff_type] = @diff_type
280 User.current.preference.save
289 User.current.preference.save
281 end
290 end
282 @cache_key = "repositories/diff/#{@repository.id}/" +
291 @cache_key = "repositories/diff/#{@repository.id}/" +
283 Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}")
292 Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}")
284 unless read_fragment(@cache_key)
293 unless read_fragment(@cache_key)
285 @diff = @repository.diff(@path, @rev, @rev_to)
294 @diff = @repository.diff(@path, @rev, @rev_to)
286 show_error_not_found unless @diff
295 show_error_not_found unless @diff
287 end
296 end
288
297
289 @changeset = @repository.find_changeset_by_name(@rev)
298 @changeset = @repository.find_changeset_by_name(@rev)
290 @changeset_to = @rev_to ? @repository.find_changeset_by_name(@rev_to) : nil
299 @changeset_to = @rev_to ? @repository.find_changeset_by_name(@rev_to) : nil
291 @diff_format_revisions = @repository.diff_format_revisions(@changeset, @changeset_to)
300 @diff_format_revisions = @repository.diff_format_revisions(@changeset, @changeset_to)
292 end
301 end
293 end
302 end
294
303
295 def stats
304 def stats
296 end
305 end
297
306
298 def graph
307 def graph
299 data = nil
308 data = nil
300 case params[:graph]
309 case params[:graph]
301 when "commits_per_month"
310 when "commits_per_month"
302 data = graph_commits_per_month(@repository)
311 data = graph_commits_per_month(@repository)
303 when "commits_per_author"
312 when "commits_per_author"
304 data = graph_commits_per_author(@repository)
313 data = graph_commits_per_author(@repository)
305 end
314 end
306 if data
315 if data
307 headers["Content-Type"] = "image/svg+xml"
316 headers["Content-Type"] = "image/svg+xml"
308 send_data(data, :type => "image/svg+xml", :disposition => "inline")
317 send_data(data, :type => "image/svg+xml", :disposition => "inline")
309 else
318 else
310 render_404
319 render_404
311 end
320 end
312 end
321 end
313
322
314 private
323 private
315
324
316 def find_repository
325 def find_repository
317 @repository = Repository.find(params[:id])
326 @repository = Repository.find(params[:id])
318 @project = @repository.project
327 @project = @repository.project
319 rescue ActiveRecord::RecordNotFound
328 rescue ActiveRecord::RecordNotFound
320 render_404
329 render_404
321 end
330 end
322
331
323 REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
332 REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
324
333
325 def find_project_repository
334 def find_project_repository
326 @project = Project.find(params[:id])
335 @project = Project.find(params[:id])
327 if params[:repository_id].present?
336 if params[:repository_id].present?
328 @repository = @project.repositories.find_by_identifier_param(params[:repository_id])
337 @repository = @project.repositories.find_by_identifier_param(params[:repository_id])
329 else
338 else
330 @repository = @project.repository
339 @repository = @project.repository
331 end
340 end
332 (render_404; return false) unless @repository
341 (render_404; return false) unless @repository
333 @path = params[:path].is_a?(Array) ? params[:path].join('/') : params[:path].to_s
342 @path = params[:path].is_a?(Array) ? params[:path].join('/') : params[:path].to_s
334 @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip
343 @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip
335 @rev_to = params[:rev_to]
344 @rev_to = params[:rev_to]
336
345
337 unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE)
346 unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE)
338 if @repository.branches.blank?
347 if @repository.branches.blank?
339 raise InvalidRevisionParam
348 raise InvalidRevisionParam
340 end
349 end
341 end
350 end
342 rescue ActiveRecord::RecordNotFound
351 rescue ActiveRecord::RecordNotFound
343 render_404
352 render_404
344 rescue InvalidRevisionParam
353 rescue InvalidRevisionParam
345 show_error_not_found
354 show_error_not_found
346 end
355 end
347
356
348 def find_changeset
357 def find_changeset
349 if @rev.present?
358 if @rev.present?
350 @changeset = @repository.find_changeset_by_name(@rev)
359 @changeset = @repository.find_changeset_by_name(@rev)
351 end
360 end
352 show_error_not_found unless @changeset
361 show_error_not_found unless @changeset
353 end
362 end
354
363
355 def show_error_not_found
364 def show_error_not_found
356 render_error :message => l(:error_scm_not_found), :status => 404
365 render_error :message => l(:error_scm_not_found), :status => 404
357 end
366 end
358
367
359 # Handler for Redmine::Scm::Adapters::CommandFailed exception
368 # Handler for Redmine::Scm::Adapters::CommandFailed exception
360 def show_error_command_failed(exception)
369 def show_error_command_failed(exception)
361 render_error l(:error_scm_command_failed, exception.message)
370 render_error l(:error_scm_command_failed, exception.message)
362 end
371 end
363
372
364 def graph_commits_per_month(repository)
373 def graph_commits_per_month(repository)
365 @date_to = Date.today
374 @date_to = Date.today
366 @date_from = @date_to << 11
375 @date_from = @date_to << 11
367 @date_from = Date.civil(@date_from.year, @date_from.month, 1)
376 @date_from = Date.civil(@date_from.year, @date_from.month, 1)
368 commits_by_day = Changeset.count(
377 commits_by_day = Changeset.count(
369 :all, :group => :commit_date,
378 :all, :group => :commit_date,
370 :conditions => ["repository_id = ? AND commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
379 :conditions => ["repository_id = ? AND commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
371 commits_by_month = [0] * 12
380 commits_by_month = [0] * 12
372 commits_by_day.each {|c| commits_by_month[(@date_to.month - c.first.to_date.month) % 12] += c.last }
381 commits_by_day.each {|c| commits_by_month[(@date_to.month - c.first.to_date.month) % 12] += c.last }
373
382
374 changes_by_day = Change.count(
383 changes_by_day = Change.count(
375 :all, :group => :commit_date, :include => :changeset,
384 :all, :group => :commit_date, :include => :changeset,
376 :conditions => ["#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
385 :conditions => ["#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
377 changes_by_month = [0] * 12
386 changes_by_month = [0] * 12
378 changes_by_day.each {|c| changes_by_month[(@date_to.month - c.first.to_date.month) % 12] += c.last }
387 changes_by_day.each {|c| changes_by_month[(@date_to.month - c.first.to_date.month) % 12] += c.last }
379
388
380 fields = []
389 fields = []
381 12.times {|m| fields << month_name(((Date.today.month - 1 - m) % 12) + 1)}
390 12.times {|m| fields << month_name(((Date.today.month - 1 - m) % 12) + 1)}
382
391
383 graph = SVG::Graph::Bar.new(
392 graph = SVG::Graph::Bar.new(
384 :height => 300,
393 :height => 300,
385 :width => 800,
394 :width => 800,
386 :fields => fields.reverse,
395 :fields => fields.reverse,
387 :stack => :side,
396 :stack => :side,
388 :scale_integers => true,
397 :scale_integers => true,
389 :step_x_labels => 2,
398 :step_x_labels => 2,
390 :show_data_values => false,
399 :show_data_values => false,
391 :graph_title => l(:label_commits_per_month),
400 :graph_title => l(:label_commits_per_month),
392 :show_graph_title => true
401 :show_graph_title => true
393 )
402 )
394
403
395 graph.add_data(
404 graph.add_data(
396 :data => commits_by_month[0..11].reverse,
405 :data => commits_by_month[0..11].reverse,
397 :title => l(:label_revision_plural)
406 :title => l(:label_revision_plural)
398 )
407 )
399
408
400 graph.add_data(
409 graph.add_data(
401 :data => changes_by_month[0..11].reverse,
410 :data => changes_by_month[0..11].reverse,
402 :title => l(:label_change_plural)
411 :title => l(:label_change_plural)
403 )
412 )
404
413
405 graph.burn
414 graph.burn
406 end
415 end
407
416
408 def graph_commits_per_author(repository)
417 def graph_commits_per_author(repository)
409 commits_by_author = Changeset.count(:all, :group => :committer, :conditions => ["repository_id = ?", repository.id])
418 commits_by_author = Changeset.count(:all, :group => :committer, :conditions => ["repository_id = ?", repository.id])
410 commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}
419 commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}
411
420
412 changes_by_author = Change.count(:all, :group => :committer, :include => :changeset, :conditions => ["#{Changeset.table_name}.repository_id = ?", repository.id])
421 changes_by_author = Change.count(:all, :group => :committer, :include => :changeset, :conditions => ["#{Changeset.table_name}.repository_id = ?", repository.id])
413 h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
422 h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
414
423
415 fields = commits_by_author.collect {|r| r.first}
424 fields = commits_by_author.collect {|r| r.first}
416 commits_data = commits_by_author.collect {|r| r.last}
425 commits_data = commits_by_author.collect {|r| r.last}
417 changes_data = commits_by_author.collect {|r| h[r.first] || 0}
426 changes_data = commits_by_author.collect {|r| h[r.first] || 0}
418
427
419 fields = fields + [""]*(10 - fields.length) if fields.length<10
428 fields = fields + [""]*(10 - fields.length) if fields.length<10
420 commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
429 commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
421 changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
430 changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
422
431
423 # Remove email adress in usernames
432 # Remove email adress in usernames
424 fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') }
433 fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') }
425
434
426 graph = SVG::Graph::BarHorizontal.new(
435 graph = SVG::Graph::BarHorizontal.new(
427 :height => 400,
436 :height => 400,
428 :width => 800,
437 :width => 800,
429 :fields => fields,
438 :fields => fields,
430 :stack => :side,
439 :stack => :side,
431 :scale_integers => true,
440 :scale_integers => true,
432 :show_data_values => false,
441 :show_data_values => false,
433 :rotate_y_labels => false,
442 :rotate_y_labels => false,
434 :graph_title => l(:label_commits_per_author),
443 :graph_title => l(:label_commits_per_author),
435 :show_graph_title => true
444 :show_graph_title => true
436 )
445 )
437 graph.add_data(
446 graph.add_data(
438 :data => commits_data,
447 :data => commits_data,
439 :title => l(:label_revision_plural)
448 :title => l(:label_revision_plural)
440 )
449 )
441 graph.add_data(
450 graph.add_data(
442 :data => changes_data,
451 :data => changes_data,
443 :title => l(:label_change_plural)
452 :title => l(:label_change_plural)
444 )
453 )
445 graph.burn
454 graph.burn
446 end
455 end
447 end
456 end
448
457
@@ -1,344 +1,334
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 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 RedmineApp::Application.routes.draw do
18 RedmineApp::Application.routes.draw do
19 root :to => 'welcome#index', :as => 'home'
19 root :to => 'welcome#index', :as => 'home'
20
20
21 match 'login', :to => 'account#login', :as => 'signin'
21 match 'login', :to => 'account#login', :as => 'signin'
22 match 'logout', :to => 'account#logout', :as => 'signout'
22 match 'logout', :to => 'account#logout', :as => 'signout'
23 match 'account/register', :to => 'account#register', :via => [:get, :post]
23 match 'account/register', :to => 'account#register', :via => [:get, :post]
24 match 'account/lost_password', :to => 'account#lost_password', :via => [:get, :post]
24 match 'account/lost_password', :to => 'account#lost_password', :via => [:get, :post]
25 match 'account/activate', :to => 'account#activate', :via => :get
25 match 'account/activate', :to => 'account#activate', :via => :get
26
26
27 match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news'
27 match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news'
28 match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue'
28 match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue'
29 match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue'
29 match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue'
30 match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue'
30 match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue'
31
31
32 match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post
32 match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post
33 match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post]
33 match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post]
34
34
35 match 'boards/:board_id/topics/new', :to => 'messages#new', :via => [:get, :post]
35 match 'boards/:board_id/topics/new', :to => 'messages#new', :via => [:get, :post]
36 get 'boards/:board_id/topics/:id', :to => 'messages#show'
36 get 'boards/:board_id/topics/:id', :to => 'messages#show'
37 match 'boards/:board_id/topics/quote/:id', :to => 'messages#quote', :via => [:get, :post]
37 match 'boards/:board_id/topics/quote/:id', :to => 'messages#quote', :via => [:get, :post]
38 get 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
38 get 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
39
39
40 post 'boards/:board_id/topics/preview', :to => 'messages#preview'
40 post 'boards/:board_id/topics/preview', :to => 'messages#preview'
41 post 'boards/:board_id/topics/:id/replies', :to => 'messages#reply'
41 post 'boards/:board_id/topics/:id/replies', :to => 'messages#reply'
42 post 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
42 post 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
43 post 'boards/:board_id/topics/:id/destroy', :to => 'messages#destroy'
43 post 'boards/:board_id/topics/:id/destroy', :to => 'messages#destroy'
44
44
45 # Misc issue routes. TODO: move into resources
45 # Misc issue routes. TODO: move into resources
46 match '/issues/auto_complete', :to => 'auto_completes#issues', :via => :get, :as => 'auto_complete_issues'
46 match '/issues/auto_complete', :to => 'auto_completes#issues', :via => :get, :as => 'auto_complete_issues'
47 match '/issues/context_menu', :to => 'context_menus#issues', :as => 'issues_context_menu'
47 match '/issues/context_menu', :to => 'context_menus#issues', :as => 'issues_context_menu'
48 match '/issues/changes', :to => 'journals#index', :as => 'issue_changes'
48 match '/issues/changes', :to => 'journals#index', :as => 'issue_changes'
49 match '/issues/:id/quoted', :to => 'journals#new', :id => /\d+/, :via => :post, :as => 'quoted_issue'
49 match '/issues/:id/quoted', :to => 'journals#new', :id => /\d+/, :via => :post, :as => 'quoted_issue'
50
50
51 match '/journals/diff/:id', :to => 'journals#diff', :id => /\d+/, :via => :get
51 match '/journals/diff/:id', :to => 'journals#diff', :id => /\d+/, :via => :get
52 match '/journals/edit/:id', :to => 'journals#edit', :id => /\d+/, :via => [:get, :post]
52 match '/journals/edit/:id', :to => 'journals#edit', :id => /\d+/, :via => [:get, :post]
53
53
54 match '/projects/:project_id/issues/gantt', :to => 'gantts#show'
54 match '/projects/:project_id/issues/gantt', :to => 'gantts#show'
55 match '/issues/gantt', :to => 'gantts#show'
55 match '/issues/gantt', :to => 'gantts#show'
56
56
57 match '/projects/:project_id/issues/calendar', :to => 'calendars#show'
57 match '/projects/:project_id/issues/calendar', :to => 'calendars#show'
58 match '/issues/calendar', :to => 'calendars#show'
58 match '/issues/calendar', :to => 'calendars#show'
59
59
60 match 'projects/:id/issues/report', :to => 'reports#issue_report', :via => :get
60 match 'projects/:id/issues/report', :to => 'reports#issue_report', :via => :get
61 match 'projects/:id/issues/report/:detail', :to => 'reports#issue_report_details', :via => :get
61 match 'projects/:id/issues/report/:detail', :to => 'reports#issue_report_details', :via => :get
62
62
63 match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
63 match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
64 match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
64 match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
65 match 'my/page', :controller => 'my', :action => 'page', :via => :get
65 match 'my/page', :controller => 'my', :action => 'page', :via => :get
66 match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page
66 match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page
67 match 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key', :via => :post
67 match 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key', :via => :post
68 match 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key', :via => :post
68 match 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key', :via => :post
69 match 'my/password', :controller => 'my', :action => 'password', :via => [:get, :post]
69 match 'my/password', :controller => 'my', :action => 'password', :via => [:get, :post]
70 match 'my/page_layout', :controller => 'my', :action => 'page_layout', :via => :get
70 match 'my/page_layout', :controller => 'my', :action => 'page_layout', :via => :get
71 match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post
71 match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post
72 match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post
72 match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post
73 match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post
73 match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post
74
74
75 resources :users
75 resources :users
76 match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => :put, :as => 'user_membership'
76 match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => :put, :as => 'user_membership'
77 match 'users/:id/memberships/:membership_id', :to => 'users#destroy_membership', :via => :delete
77 match 'users/:id/memberships/:membership_id', :to => 'users#destroy_membership', :via => :delete
78 match 'users/:id/memberships', :to => 'users#edit_membership', :via => :post, :as => 'user_memberships'
78 match 'users/:id/memberships', :to => 'users#edit_membership', :via => :post, :as => 'user_memberships'
79
79
80 match 'watchers/new', :controller=> 'watchers', :action => 'new', :via => :get
80 match 'watchers/new', :controller=> 'watchers', :action => 'new', :via => :get
81 match 'watchers', :controller=> 'watchers', :action => 'create', :via => :post
81 match 'watchers', :controller=> 'watchers', :action => 'create', :via => :post
82 match 'watchers/append', :controller=> 'watchers', :action => 'append', :via => :post
82 match 'watchers/append', :controller=> 'watchers', :action => 'append', :via => :post
83 match 'watchers/destroy', :controller=> 'watchers', :action => 'destroy', :via => :post
83 match 'watchers/destroy', :controller=> 'watchers', :action => 'destroy', :via => :post
84 match 'watchers/watch', :controller=> 'watchers', :action => 'watch', :via => :post
84 match 'watchers/watch', :controller=> 'watchers', :action => 'watch', :via => :post
85 match 'watchers/unwatch', :controller=> 'watchers', :action => 'unwatch', :via => :post
85 match 'watchers/unwatch', :controller=> 'watchers', :action => 'unwatch', :via => :post
86 match 'watchers/autocomplete_for_user', :controller=> 'watchers', :action => 'autocomplete_for_user', :via => :get
86 match 'watchers/autocomplete_for_user', :controller=> 'watchers', :action => 'autocomplete_for_user', :via => :get
87
87
88 match 'projects/:id/settings/:tab', :to => "projects#settings"
88 match 'projects/:id/settings/:tab', :to => "projects#settings"
89
89
90 resources :projects do
90 resources :projects do
91 member do
91 member do
92 get 'settings'
92 get 'settings'
93 post 'modules'
93 post 'modules'
94 post 'archive'
94 post 'archive'
95 post 'unarchive'
95 post 'unarchive'
96 match 'copy', :via => [:get, :post]
96 match 'copy', :via => [:get, :post]
97 end
97 end
98
98
99 resources :memberships, :shallow => true, :controller => 'members', :only => [:index, :show, :create, :update, :destroy] do
99 resources :memberships, :shallow => true, :controller => 'members', :only => [:index, :show, :create, :update, :destroy] do
100 collection do
100 collection do
101 get 'autocomplete'
101 get 'autocomplete'
102 end
102 end
103 end
103 end
104
104
105 resource :enumerations, :controller => 'project_enumerations', :only => [:update, :destroy]
105 resource :enumerations, :controller => 'project_enumerations', :only => [:update, :destroy]
106
106
107 match 'issues/:copy_from/copy', :to => 'issues#new'
107 match 'issues/:copy_from/copy', :to => 'issues#new'
108 resources :issues, :only => [:index, :new, :create] do
108 resources :issues, :only => [:index, :new, :create] do
109 resources :time_entries, :controller => 'timelog' do
109 resources :time_entries, :controller => 'timelog' do
110 collection do
110 collection do
111 get 'report'
111 get 'report'
112 end
112 end
113 end
113 end
114 end
114 end
115 # issue form update
115 # issue form update
116 match 'issues/new', :controller => 'issues', :action => 'new', :via => [:put, :post], :as => 'issue_form'
116 match 'issues/new', :controller => 'issues', :action => 'new', :via => [:put, :post], :as => 'issue_form'
117
117
118 resources :files, :only => [:index, :new, :create]
118 resources :files, :only => [:index, :new, :create]
119
119
120 resources :versions, :except => [:index, :show, :edit, :update, :destroy] do
120 resources :versions, :except => [:index, :show, :edit, :update, :destroy] do
121 collection do
121 collection do
122 put 'close_completed'
122 put 'close_completed'
123 end
123 end
124 end
124 end
125 match 'versions.:format', :to => 'versions#index'
125 match 'versions.:format', :to => 'versions#index'
126 match 'roadmap', :to => 'versions#index', :format => false
126 match 'roadmap', :to => 'versions#index', :format => false
127 match 'versions', :to => 'versions#index'
127 match 'versions', :to => 'versions#index'
128
128
129 resources :news, :except => [:show, :edit, :update, :destroy]
129 resources :news, :except => [:show, :edit, :update, :destroy]
130 resources :time_entries, :controller => 'timelog' do
130 resources :time_entries, :controller => 'timelog' do
131 get 'report', :on => :collection
131 get 'report', :on => :collection
132 end
132 end
133 resources :queries, :only => [:new, :create]
133 resources :queries, :only => [:new, :create]
134 resources :issue_categories, :shallow => true
134 resources :issue_categories, :shallow => true
135 resources :documents, :except => [:show, :edit, :update, :destroy]
135 resources :documents, :except => [:show, :edit, :update, :destroy]
136 resources :boards
136 resources :boards
137 resources :repositories, :shallow => true, :except => [:index, :show] do
137 resources :repositories, :shallow => true, :except => [:index, :show] do
138 member do
138 member do
139 match 'committers', :via => [:get, :post]
139 match 'committers', :via => [:get, :post]
140 end
140 end
141 end
141 end
142
142
143 match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
143 match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
144 match 'wiki/:id/diff/:version/vs/:version_from', :controller => 'wiki', :action => 'diff'
144 match 'wiki/:id/diff/:version/vs/:version_from', :controller => 'wiki', :action => 'diff'
145 match 'wiki/:id/diff/:version', :controller => 'wiki', :action => 'diff'
145 match 'wiki/:id/diff/:version', :controller => 'wiki', :action => 'diff'
146 resources :wiki, :except => [:index, :new, :create] do
146 resources :wiki, :except => [:index, :new, :create] do
147 member do
147 member do
148 get 'rename'
148 get 'rename'
149 post 'rename'
149 post 'rename'
150 get 'history'
150 get 'history'
151 get 'diff'
151 get 'diff'
152 match 'preview', :via => [:post, :put]
152 match 'preview', :via => [:post, :put]
153 post 'protect'
153 post 'protect'
154 post 'add_attachment'
154 post 'add_attachment'
155 end
155 end
156 collection do
156 collection do
157 get 'export'
157 get 'export'
158 get 'date_index'
158 get 'date_index'
159 end
159 end
160 end
160 end
161 match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
161 match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
162 match 'wiki/:id/annotate/:version', :controller => 'wiki', :action => 'annotate'
162 match 'wiki/:id/annotate/:version', :controller => 'wiki', :action => 'annotate'
163 end
163 end
164
164
165 resources :issues do
165 resources :issues do
166 collection do
166 collection do
167 match 'bulk_edit', :via => [:get, :post]
167 match 'bulk_edit', :via => [:get, :post]
168 post 'bulk_update'
168 post 'bulk_update'
169 end
169 end
170 resources :time_entries, :controller => 'timelog' do
170 resources :time_entries, :controller => 'timelog' do
171 collection do
171 collection do
172 get 'report'
172 get 'report'
173 end
173 end
174 end
174 end
175 resources :relations, :shallow => true, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy]
175 resources :relations, :shallow => true, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy]
176 end
176 end
177 match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete
177 match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete
178
178
179 resources :queries, :except => [:show]
179 resources :queries, :except => [:show]
180
180
181 resources :news, :only => [:index, :show, :edit, :update, :destroy]
181 resources :news, :only => [:index, :show, :edit, :update, :destroy]
182 match '/news/:id/comments', :to => 'comments#create', :via => :post
182 match '/news/:id/comments', :to => 'comments#create', :via => :post
183 match '/news/:id/comments/:comment_id', :to => 'comments#destroy', :via => :delete
183 match '/news/:id/comments/:comment_id', :to => 'comments#destroy', :via => :delete
184
184
185 resources :versions, :only => [:show, :edit, :update, :destroy] do
185 resources :versions, :only => [:show, :edit, :update, :destroy] do
186 post 'status_by', :on => :member
186 post 'status_by', :on => :member
187 end
187 end
188
188
189 resources :documents, :only => [:show, :edit, :update, :destroy] do
189 resources :documents, :only => [:show, :edit, :update, :destroy] do
190 post 'add_attachment', :on => :member
190 post 'add_attachment', :on => :member
191 end
191 end
192
192
193 match '/time_entries/context_menu', :to => 'context_menus#time_entries', :as => :time_entries_context_menu
193 match '/time_entries/context_menu', :to => 'context_menus#time_entries', :as => :time_entries_context_menu
194
194
195 resources :time_entries, :controller => 'timelog', :except => :destroy do
195 resources :time_entries, :controller => 'timelog', :except => :destroy do
196 collection do
196 collection do
197 get 'report'
197 get 'report'
198 get 'bulk_edit'
198 get 'bulk_edit'
199 post 'bulk_update'
199 post 'bulk_update'
200 end
200 end
201 end
201 end
202 match '/time_entries/:id', :to => 'timelog#destroy', :via => :delete, :id => /\d+/
202 match '/time_entries/:id', :to => 'timelog#destroy', :via => :delete, :id => /\d+/
203 # TODO: delete /time_entries for bulk deletion
203 # TODO: delete /time_entries for bulk deletion
204 match '/time_entries/destroy', :to => 'timelog#destroy', :via => :delete
204 match '/time_entries/destroy', :to => 'timelog#destroy', :via => :delete
205
205
206 # TODO: port to be part of the resources route(s)
206 # TODO: port to be part of the resources route(s)
207 match 'projects/:id/settings/:tab', :to => 'projects#settings', :via => :get
207 match 'projects/:id/settings/:tab', :to => 'projects#settings', :via => :get
208
208
209 get 'projects/:id/activity', :to => 'activities#index'
209 get 'projects/:id/activity', :to => 'activities#index'
210 get 'projects/:id/activity.:format', :to => 'activities#index'
210 get 'projects/:id/activity.:format', :to => 'activities#index'
211 get 'activity', :to => 'activities#index'
211 get 'activity', :to => 'activities#index'
212
212
213 # repositories routes
213 # repositories routes
214 get 'projects/:id/repository/:repository_id/statistics', :to => 'repositories#stats'
214 get 'projects/:id/repository/:repository_id/statistics', :to => 'repositories#stats'
215 get 'projects/:id/repository/:repository_id/graph', :to => 'repositories#graph'
215 get 'projects/:id/repository/:repository_id/graph', :to => 'repositories#graph'
216
216
217 get 'projects/:id/repository/:repository_id/changes(/*path(.:ext))',
217 get 'projects/:id/repository/:repository_id/changes(/*path(.:ext))',
218 :to => 'repositories#changes'
218 :to => 'repositories#changes'
219
219
220 get 'projects/:id/repository/:repository_id/revisions/:rev', :to => 'repositories#revision'
220 get 'projects/:id/repository/:repository_id/revisions/:rev', :to => 'repositories#revision'
221 get 'projects/:id/repository/:repository_id/revision', :to => 'repositories#revision'
221 get 'projects/:id/repository/:repository_id/revision', :to => 'repositories#revision'
222 post 'projects/:id/repository/:repository_id/revisions/:rev/issues', :to => 'repositories#add_related_issue'
222 post 'projects/:id/repository/:repository_id/revisions/:rev/issues', :to => 'repositories#add_related_issue'
223 delete 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
223 delete 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
224 get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions'
224 get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions'
225 get 'projects/:id/repository/:repository_id/revisions/:rev/:format(/*path(.:ext))',
226 :to => 'repositories#entry',
227 :constraints => {
228 :format => 'raw',
229 :rev => /[a-z0-9\.\-_]+/
230 }
231 get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))',
225 get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))',
232 :controller => 'repositories',
226 :controller => 'repositories',
233 :constraints => {
227 :constraints => {
234 :action => /(browse|show|entry|annotate|diff)/,
228 :action => /(browse|show|entry|raw|annotate|diff)/,
235 :rev => /[a-z0-9\.\-_]+/
229 :rev => /[a-z0-9\.\-_]+/
236 }
230 }
237
231
238 get 'projects/:id/repository/statistics', :to => 'repositories#stats'
232 get 'projects/:id/repository/statistics', :to => 'repositories#stats'
239 get 'projects/:id/repository/graph', :to => 'repositories#graph'
233 get 'projects/:id/repository/graph', :to => 'repositories#graph'
240
234
241 get 'projects/:id/repository/changes(/*path(.:ext))',
235 get 'projects/:id/repository/changes(/*path(.:ext))',
242 :to => 'repositories#changes'
236 :to => 'repositories#changes'
243
237
244 get 'projects/:id/repository/revisions', :to => 'repositories#revisions'
238 get 'projects/:id/repository/revisions', :to => 'repositories#revisions'
245 get 'projects/:id/repository/revisions/:rev', :to => 'repositories#revision'
239 get 'projects/:id/repository/revisions/:rev', :to => 'repositories#revision'
246 get 'projects/:id/repository/revision', :to => 'repositories#revision'
240 get 'projects/:id/repository/revision', :to => 'repositories#revision'
247 post 'projects/:id/repository/revisions/:rev/issues', :to => 'repositories#add_related_issue'
241 post 'projects/:id/repository/revisions/:rev/issues', :to => 'repositories#add_related_issue'
248 delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
242 delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
249 get 'projects/:id/repository/revisions/:rev/:format(/*path(.:ext))',
250 :to => 'repositories#entry',
251 :constraints => {
252 :format => 'raw',
253 :rev => /[a-z0-9\.\-_]+/
254 }
255 get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))',
243 get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))',
256 :controller => 'repositories',
244 :controller => 'repositories',
257 :constraints => {
245 :constraints => {
258 :action => /(browse|show|entry|annotate|diff)/,
246 :action => /(browse|show|entry|raw|annotate|diff)/,
259 :rev => /[a-z0-9\.\-_]+/
247 :rev => /[a-z0-9\.\-_]+/
260 }
248 }
261 get 'projects/:id/repository/:repository_id/:format(/*path(.:ext))', :to => 'repositories#entry', :format => /raw/
249 get 'projects/:id/repository/:repository_id/:action(/*path(.:ext))',
262 get 'projects/:id/repository/:repository_id/:action(/*path(.:ext))', :controller => 'repositories', :action => /(browse|show|entry|changes|annotate|diff)/
250 :controller => 'repositories',
251 :action => /(browse|show|entry|raw|changes|annotate|diff)/
263 get 'projects/:id/repository/:repository_id', :to => 'repositories#show', :path => nil
252 get 'projects/:id/repository/:repository_id', :to => 'repositories#show', :path => nil
264
253
265 get 'projects/:id/repository/:format(/*path(.:ext))', :to => 'repositories#entry', :format => /raw/
254 get 'projects/:id/repository/:action(/*path(.:ext))',
266 get 'projects/:id/repository/:action(/*path(.:ext))', :controller => 'repositories', :action => /(browse|show|entry|changes|annotate|diff)/
255 :controller => 'repositories',
256 :action => /(browse|show|entry|raw|changes|annotate|diff)/
267 get 'projects/:id/repository', :to => 'repositories#show', :path => nil
257 get 'projects/:id/repository', :to => 'repositories#show', :path => nil
268
258
269 # additional routes for having the file name at the end of url
259 # additional routes for having the file name at the end of url
270 match 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/, :via => :get
260 match 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/, :via => :get
271 match 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/, :via => :get
261 match 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/, :via => :get
272 match 'attachments/download/:id', :controller => 'attachments', :action => 'download', :id => /\d+/, :via => :get
262 match 'attachments/download/:id', :controller => 'attachments', :action => 'download', :id => /\d+/, :via => :get
273 resources :attachments, :only => [:show, :destroy]
263 resources :attachments, :only => [:show, :destroy]
274
264
275 resources :groups do
265 resources :groups do
276 member do
266 member do
277 get 'autocomplete_for_user'
267 get 'autocomplete_for_user'
278 end
268 end
279 end
269 end
280
270
281 match 'groups/:id/users', :controller => 'groups', :action => 'add_users', :id => /\d+/, :via => :post, :as => 'group_users'
271 match 'groups/:id/users', :controller => 'groups', :action => 'add_users', :id => /\d+/, :via => :post, :as => 'group_users'
282 match 'groups/:id/users/:user_id', :controller => 'groups', :action => 'remove_user', :id => /\d+/, :via => :delete, :as => 'group_user'
272 match 'groups/:id/users/:user_id', :controller => 'groups', :action => 'remove_user', :id => /\d+/, :via => :delete, :as => 'group_user'
283 match 'groups/destroy_membership/:id', :controller => 'groups', :action => 'destroy_membership', :id => /\d+/, :via => :post
273 match 'groups/destroy_membership/:id', :controller => 'groups', :action => 'destroy_membership', :id => /\d+/, :via => :post
284 match 'groups/edit_membership/:id', :controller => 'groups', :action => 'edit_membership', :id => /\d+/, :via => :post
274 match 'groups/edit_membership/:id', :controller => 'groups', :action => 'edit_membership', :id => /\d+/, :via => :post
285
275
286 resources :trackers, :except => :show
276 resources :trackers, :except => :show
287 resources :issue_statuses, :except => :show do
277 resources :issue_statuses, :except => :show do
288 collection do
278 collection do
289 post 'update_issue_done_ratio'
279 post 'update_issue_done_ratio'
290 end
280 end
291 end
281 end
292 resources :custom_fields, :except => :show
282 resources :custom_fields, :except => :show
293 resources :roles, :except => :show do
283 resources :roles, :except => :show do
294 collection do
284 collection do
295 match 'permissions', :via => [:get, :post]
285 match 'permissions', :via => [:get, :post]
296 end
286 end
297 end
287 end
298 resources :enumerations, :except => :show
288 resources :enumerations, :except => :show
299
289
300 get 'projects/:id/search', :controller => 'search', :action => 'index'
290 get 'projects/:id/search', :controller => 'search', :action => 'index'
301 get 'search', :controller => 'search', :action => 'index'
291 get 'search', :controller => 'search', :action => 'index'
302
292
303 match 'mail_handler', :controller => 'mail_handler', :action => 'index', :via => :post
293 match 'mail_handler', :controller => 'mail_handler', :action => 'index', :via => :post
304
294
305 match 'admin', :controller => 'admin', :action => 'index', :via => :get
295 match 'admin', :controller => 'admin', :action => 'index', :via => :get
306 match 'admin/projects', :controller => 'admin', :action => 'projects', :via => :get
296 match 'admin/projects', :controller => 'admin', :action => 'projects', :via => :get
307 match 'admin/plugins', :controller => 'admin', :action => 'plugins', :via => :get
297 match 'admin/plugins', :controller => 'admin', :action => 'plugins', :via => :get
308 match 'admin/info', :controller => 'admin', :action => 'info', :via => :get
298 match 'admin/info', :controller => 'admin', :action => 'info', :via => :get
309 match 'admin/test_email', :controller => 'admin', :action => 'test_email', :via => :get
299 match 'admin/test_email', :controller => 'admin', :action => 'test_email', :via => :get
310 match 'admin/default_configuration', :controller => 'admin', :action => 'default_configuration', :via => :post
300 match 'admin/default_configuration', :controller => 'admin', :action => 'default_configuration', :via => :post
311
301
312 resources :auth_sources do
302 resources :auth_sources do
313 member do
303 member do
314 get 'test_connection'
304 get 'test_connection'
315 end
305 end
316 end
306 end
317
307
318 match 'workflows', :controller => 'workflows', :action => 'index', :via => :get
308 match 'workflows', :controller => 'workflows', :action => 'index', :via => :get
319 match 'workflows/edit', :controller => 'workflows', :action => 'edit', :via => [:get, :post]
309 match 'workflows/edit', :controller => 'workflows', :action => 'edit', :via => [:get, :post]
320 match 'workflows/copy', :controller => 'workflows', :action => 'copy', :via => [:get, :post]
310 match 'workflows/copy', :controller => 'workflows', :action => 'copy', :via => [:get, :post]
321 match 'settings', :controller => 'settings', :action => 'index', :via => :get
311 match 'settings', :controller => 'settings', :action => 'index', :via => :get
322 match 'settings/edit', :controller => 'settings', :action => 'edit', :via => [:get, :post]
312 match 'settings/edit', :controller => 'settings', :action => 'edit', :via => [:get, :post]
323 match 'settings/plugin/:id', :controller => 'settings', :action => 'plugin', :via => [:get, :post]
313 match 'settings/plugin/:id', :controller => 'settings', :action => 'plugin', :via => [:get, :post]
324
314
325 match 'sys/projects', :to => 'sys#projects', :via => :get
315 match 'sys/projects', :to => 'sys#projects', :via => :get
326 match 'sys/projects/:id/repository', :to => 'sys#create_project_repository', :via => :post
316 match 'sys/projects/:id/repository', :to => 'sys#create_project_repository', :via => :post
327 match 'sys/fetch_changesets', :to => 'sys#fetch_changesets', :via => :get
317 match 'sys/fetch_changesets', :to => 'sys#fetch_changesets', :via => :get
328
318
329 match 'uploads', :to => 'attachments#upload', :via => :post
319 match 'uploads', :to => 'attachments#upload', :via => :post
330
320
331 get 'robots.txt', :to => 'welcome#robots'
321 get 'robots.txt', :to => 'welcome#robots'
332
322
333 Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir|
323 Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir|
334 file = File.join(plugin_dir, "config/routes.rb")
324 file = File.join(plugin_dir, "config/routes.rb")
335 if File.exists?(file)
325 if File.exists?(file)
336 begin
326 begin
337 instance_eval File.read(file)
327 instance_eval File.read(file)
338 rescue Exception => e
328 rescue Exception => e
339 puts "An error occurred while loading the routes definition of #{File.basename(plugin_dir)} plugin (#{file}): #{e.message}."
329 puts "An error occurred while loading the routes definition of #{File.basename(plugin_dir)} plugin (#{file}): #{e.message}."
340 exit 1
330 exit 1
341 end
331 end
342 end
332 end
343 end
333 end
344 end
334 end
@@ -1,238 +1,238
1 require 'redmine/access_control'
1 require 'redmine/access_control'
2 require 'redmine/menu_manager'
2 require 'redmine/menu_manager'
3 require 'redmine/activity'
3 require 'redmine/activity'
4 require 'redmine/search'
4 require 'redmine/search'
5 require 'redmine/custom_field_format'
5 require 'redmine/custom_field_format'
6 require 'redmine/mime_type'
6 require 'redmine/mime_type'
7 require 'redmine/core_ext'
7 require 'redmine/core_ext'
8 require 'redmine/themes'
8 require 'redmine/themes'
9 require 'redmine/hook'
9 require 'redmine/hook'
10 require 'redmine/plugin'
10 require 'redmine/plugin'
11 require 'redmine/notifiable'
11 require 'redmine/notifiable'
12 require 'redmine/wiki_formatting'
12 require 'redmine/wiki_formatting'
13 require 'redmine/scm/base'
13 require 'redmine/scm/base'
14
14
15 begin
15 begin
16 require 'RMagick' unless Object.const_defined?(:Magick)
16 require 'RMagick' unless Object.const_defined?(:Magick)
17 rescue LoadError
17 rescue LoadError
18 # RMagick is not available
18 # RMagick is not available
19 end
19 end
20
20
21 if RUBY_VERSION < '1.9'
21 if RUBY_VERSION < '1.9'
22 require 'fastercsv'
22 require 'fastercsv'
23 else
23 else
24 require 'csv'
24 require 'csv'
25 FCSV = CSV
25 FCSV = CSV
26 end
26 end
27
27
28 Redmine::Scm::Base.add "Subversion"
28 Redmine::Scm::Base.add "Subversion"
29 Redmine::Scm::Base.add "Darcs"
29 Redmine::Scm::Base.add "Darcs"
30 Redmine::Scm::Base.add "Mercurial"
30 Redmine::Scm::Base.add "Mercurial"
31 Redmine::Scm::Base.add "Cvs"
31 Redmine::Scm::Base.add "Cvs"
32 Redmine::Scm::Base.add "Bazaar"
32 Redmine::Scm::Base.add "Bazaar"
33 Redmine::Scm::Base.add "Git"
33 Redmine::Scm::Base.add "Git"
34 Redmine::Scm::Base.add "Filesystem"
34 Redmine::Scm::Base.add "Filesystem"
35
35
36 Redmine::CustomFieldFormat.map do |fields|
36 Redmine::CustomFieldFormat.map do |fields|
37 fields.register 'string'
37 fields.register 'string'
38 fields.register 'text'
38 fields.register 'text'
39 fields.register 'int', :label => :label_integer
39 fields.register 'int', :label => :label_integer
40 fields.register 'float'
40 fields.register 'float'
41 fields.register 'list'
41 fields.register 'list'
42 fields.register 'date'
42 fields.register 'date'
43 fields.register 'bool', :label => :label_boolean
43 fields.register 'bool', :label => :label_boolean
44 fields.register 'user', :only => %w(Issue TimeEntry Version Project), :edit_as => 'list'
44 fields.register 'user', :only => %w(Issue TimeEntry Version Project), :edit_as => 'list'
45 fields.register 'version', :only => %w(Issue TimeEntry Version Project), :edit_as => 'list'
45 fields.register 'version', :only => %w(Issue TimeEntry Version Project), :edit_as => 'list'
46 end
46 end
47
47
48 # Permissions
48 # Permissions
49 Redmine::AccessControl.map do |map|
49 Redmine::AccessControl.map do |map|
50 map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true
50 map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true
51 map.permission :search_project, {:search => :index}, :public => true
51 map.permission :search_project, {:search => :index}, :public => true
52 map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin
52 map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin
53 map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member
53 map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member
54 map.permission :select_project_modules, {:projects => :modules}, :require => :member
54 map.permission :select_project_modules, {:projects => :modules}, :require => :member
55 map.permission :manage_members, {:projects => :settings, :members => [:index, :show, :create, :update, :destroy, :autocomplete]}, :require => :member
55 map.permission :manage_members, {:projects => :settings, :members => [:index, :show, :create, :update, :destroy, :autocomplete]}, :require => :member
56 map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
56 map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
57 map.permission :add_subprojects, {:projects => [:new, :create]}, :require => :member
57 map.permission :add_subprojects, {:projects => [:new, :create]}, :require => :member
58
58
59 map.project_module :issue_tracking do |map|
59 map.project_module :issue_tracking do |map|
60 # Issue categories
60 # Issue categories
61 map.permission :manage_categories, {:projects => :settings, :issue_categories => [:index, :show, :new, :create, :edit, :update, :destroy]}, :require => :member
61 map.permission :manage_categories, {:projects => :settings, :issue_categories => [:index, :show, :new, :create, :edit, :update, :destroy]}, :require => :member
62 # Issues
62 # Issues
63 map.permission :view_issues, {:issues => [:index, :show],
63 map.permission :view_issues, {:issues => [:index, :show],
64 :auto_complete => [:issues],
64 :auto_complete => [:issues],
65 :context_menus => [:issues],
65 :context_menus => [:issues],
66 :versions => [:index, :show, :status_by],
66 :versions => [:index, :show, :status_by],
67 :journals => [:index, :diff],
67 :journals => [:index, :diff],
68 :queries => :index,
68 :queries => :index,
69 :reports => [:issue_report, :issue_report_details]}
69 :reports => [:issue_report, :issue_report_details]}
70 map.permission :add_issues, {:issues => [:new, :create, :update_form], :attachments => :upload}
70 map.permission :add_issues, {:issues => [:new, :create, :update_form], :attachments => :upload}
71 map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new], :attachments => :upload}
71 map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new], :attachments => :upload}
72 map.permission :manage_issue_relations, {:issue_relations => [:index, :show, :create, :destroy]}
72 map.permission :manage_issue_relations, {:issue_relations => [:index, :show, :create, :destroy]}
73 map.permission :manage_subtasks, {}
73 map.permission :manage_subtasks, {}
74 map.permission :set_issues_private, {}
74 map.permission :set_issues_private, {}
75 map.permission :set_own_issues_private, {}, :require => :loggedin
75 map.permission :set_own_issues_private, {}, :require => :loggedin
76 map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new], :attachments => :upload}
76 map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new], :attachments => :upload}
77 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
77 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
78 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
78 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
79 map.permission :move_issues, {:issues => [:bulk_edit, :bulk_update]}, :require => :loggedin
79 map.permission :move_issues, {:issues => [:bulk_edit, :bulk_update]}, :require => :loggedin
80 map.permission :delete_issues, {:issues => :destroy}, :require => :member
80 map.permission :delete_issues, {:issues => :destroy}, :require => :member
81 # Queries
81 # Queries
82 map.permission :manage_public_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :member
82 map.permission :manage_public_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :member
83 map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
83 map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
84 # Watchers
84 # Watchers
85 map.permission :view_issue_watchers, {}
85 map.permission :view_issue_watchers, {}
86 map.permission :add_issue_watchers, {:watchers => :new}
86 map.permission :add_issue_watchers, {:watchers => :new}
87 map.permission :delete_issue_watchers, {:watchers => :destroy}
87 map.permission :delete_issue_watchers, {:watchers => :destroy}
88 end
88 end
89
89
90 map.project_module :time_tracking do |map|
90 map.project_module :time_tracking do |map|
91 map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
91 map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
92 map.permission :view_time_entries, :timelog => [:index, :report, :show]
92 map.permission :view_time_entries, :timelog => [:index, :report, :show]
93 map.permission :edit_time_entries, {:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
93 map.permission :edit_time_entries, {:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
94 map.permission :edit_own_time_entries, {:timelog => [:edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
94 map.permission :edit_own_time_entries, {:timelog => [:edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
95 map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
95 map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
96 end
96 end
97
97
98 map.project_module :news do |map|
98 map.project_module :news do |map|
99 map.permission :manage_news, {:news => [:new, :create, :edit, :update, :destroy], :comments => [:destroy]}, :require => :member
99 map.permission :manage_news, {:news => [:new, :create, :edit, :update, :destroy], :comments => [:destroy]}, :require => :member
100 map.permission :view_news, {:news => [:index, :show]}, :public => true
100 map.permission :view_news, {:news => [:index, :show]}, :public => true
101 map.permission :comment_news, {:comments => :create}
101 map.permission :comment_news, {:comments => :create}
102 end
102 end
103
103
104 map.project_module :documents do |map|
104 map.project_module :documents do |map|
105 map.permission :manage_documents, {:documents => [:new, :create, :edit, :update, :destroy, :add_attachment]}, :require => :loggedin
105 map.permission :manage_documents, {:documents => [:new, :create, :edit, :update, :destroy, :add_attachment]}, :require => :loggedin
106 map.permission :view_documents, :documents => [:index, :show, :download]
106 map.permission :view_documents, :documents => [:index, :show, :download]
107 end
107 end
108
108
109 map.project_module :files do |map|
109 map.project_module :files do |map|
110 map.permission :manage_files, {:files => [:new, :create]}, :require => :loggedin
110 map.permission :manage_files, {:files => [:new, :create]}, :require => :loggedin
111 map.permission :view_files, :files => :index, :versions => :download
111 map.permission :view_files, :files => :index, :versions => :download
112 end
112 end
113
113
114 map.project_module :wiki do |map|
114 map.project_module :wiki do |map|
115 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
115 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
116 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
116 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
117 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
117 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
118 map.permission :view_wiki_pages, :wiki => [:index, :show, :special, :date_index]
118 map.permission :view_wiki_pages, :wiki => [:index, :show, :special, :date_index]
119 map.permission :export_wiki_pages, :wiki => [:export]
119 map.permission :export_wiki_pages, :wiki => [:export]
120 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
120 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
121 map.permission :edit_wiki_pages, :wiki => [:edit, :update, :preview, :add_attachment]
121 map.permission :edit_wiki_pages, :wiki => [:edit, :update, :preview, :add_attachment]
122 map.permission :delete_wiki_pages_attachments, {}
122 map.permission :delete_wiki_pages_attachments, {}
123 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
123 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
124 end
124 end
125
125
126 map.project_module :repository do |map|
126 map.project_module :repository do |map|
127 map.permission :manage_repository, {:repositories => [:new, :create, :edit, :update, :committers, :destroy]}, :require => :member
127 map.permission :manage_repository, {:repositories => [:new, :create, :edit, :update, :committers, :destroy]}, :require => :member
128 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
128 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :raw, :annotate, :changes, :diff, :stats, :graph]
129 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
129 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
130 map.permission :commit_access, {}
130 map.permission :commit_access, {}
131 map.permission :manage_related_issues, {:repositories => [:add_related_issue, :remove_related_issue]}
131 map.permission :manage_related_issues, {:repositories => [:add_related_issue, :remove_related_issue]}
132 end
132 end
133
133
134 map.project_module :boards do |map|
134 map.project_module :boards do |map|
135 map.permission :manage_boards, {:boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
135 map.permission :manage_boards, {:boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
136 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
136 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
137 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
137 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
138 map.permission :edit_messages, {:messages => :edit}, :require => :member
138 map.permission :edit_messages, {:messages => :edit}, :require => :member
139 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
139 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
140 map.permission :delete_messages, {:messages => :destroy}, :require => :member
140 map.permission :delete_messages, {:messages => :destroy}, :require => :member
141 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
141 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
142 end
142 end
143
143
144 map.project_module :calendar do |map|
144 map.project_module :calendar do |map|
145 map.permission :view_calendar, :calendars => [:show, :update]
145 map.permission :view_calendar, :calendars => [:show, :update]
146 end
146 end
147
147
148 map.project_module :gantt do |map|
148 map.project_module :gantt do |map|
149 map.permission :view_gantt, :gantts => [:show, :update]
149 map.permission :view_gantt, :gantts => [:show, :update]
150 end
150 end
151 end
151 end
152
152
153 Redmine::MenuManager.map :top_menu do |menu|
153 Redmine::MenuManager.map :top_menu do |menu|
154 menu.push :home, :home_path
154 menu.push :home, :home_path
155 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
155 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
156 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
156 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
157 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
157 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
158 menu.push :help, Redmine::Info.help_url, :last => true
158 menu.push :help, Redmine::Info.help_url, :last => true
159 end
159 end
160
160
161 Redmine::MenuManager.map :account_menu do |menu|
161 Redmine::MenuManager.map :account_menu do |menu|
162 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
162 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
163 menu.push :register, { :controller => 'account', :action => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
163 menu.push :register, { :controller => 'account', :action => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
164 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
164 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
165 menu.push :logout, :signout_path, :if => Proc.new { User.current.logged? }
165 menu.push :logout, :signout_path, :if => Proc.new { User.current.logged? }
166 end
166 end
167
167
168 Redmine::MenuManager.map :application_menu do |menu|
168 Redmine::MenuManager.map :application_menu do |menu|
169 # Empty
169 # Empty
170 end
170 end
171
171
172 Redmine::MenuManager.map :admin_menu do |menu|
172 Redmine::MenuManager.map :admin_menu do |menu|
173 menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
173 menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
174 menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
174 menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
175 menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
175 menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
176 menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
176 menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
177 menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
177 menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
178 menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
178 menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
179 :html => {:class => 'issue_statuses'}
179 :html => {:class => 'issue_statuses'}
180 menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
180 menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
181 menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
181 menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
182 :html => {:class => 'custom_fields'}
182 :html => {:class => 'custom_fields'}
183 menu.push :enumerations, {:controller => 'enumerations'}
183 menu.push :enumerations, {:controller => 'enumerations'}
184 menu.push :settings, {:controller => 'settings'}
184 menu.push :settings, {:controller => 'settings'}
185 menu.push :ldap_authentication, {:controller => 'auth_sources', :action => 'index'},
185 menu.push :ldap_authentication, {:controller => 'auth_sources', :action => 'index'},
186 :html => {:class => 'server_authentication'}
186 :html => {:class => 'server_authentication'}
187 menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
187 menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
188 menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
188 menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
189 end
189 end
190
190
191 Redmine::MenuManager.map :project_menu do |menu|
191 Redmine::MenuManager.map :project_menu do |menu|
192 menu.push :overview, { :controller => 'projects', :action => 'show' }
192 menu.push :overview, { :controller => 'projects', :action => 'show' }
193 menu.push :activity, { :controller => 'activities', :action => 'index' }
193 menu.push :activity, { :controller => 'activities', :action => 'index' }
194 menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id,
194 menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id,
195 :if => Proc.new { |p| p.shared_versions.any? }
195 :if => Proc.new { |p| p.shared_versions.any? }
196 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
196 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
197 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
197 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
198 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
198 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
199 menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
199 menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
200 menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
200 menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
201 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
201 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
202 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
202 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
203 menu.push :wiki, { :controller => 'wiki', :action => 'show', :id => nil }, :param => :project_id,
203 menu.push :wiki, { :controller => 'wiki', :action => 'show', :id => nil }, :param => :project_id,
204 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
204 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
205 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
205 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
206 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
206 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
207 menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural, :param => :project_id
207 menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural, :param => :project_id
208 menu.push :repository, { :controller => 'repositories', :action => 'show', :repository_id => nil, :path => nil, :rev => nil },
208 menu.push :repository, { :controller => 'repositories', :action => 'show', :repository_id => nil, :path => nil, :rev => nil },
209 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
209 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
210 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
210 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
211 end
211 end
212
212
213 Redmine::Activity.map do |activity|
213 Redmine::Activity.map do |activity|
214 activity.register :issues, :class_name => %w(Issue Journal)
214 activity.register :issues, :class_name => %w(Issue Journal)
215 activity.register :changesets
215 activity.register :changesets
216 activity.register :news
216 activity.register :news
217 activity.register :documents, :class_name => %w(Document Attachment)
217 activity.register :documents, :class_name => %w(Document Attachment)
218 activity.register :files, :class_name => 'Attachment'
218 activity.register :files, :class_name => 'Attachment'
219 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
219 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
220 activity.register :messages, :default => false
220 activity.register :messages, :default => false
221 activity.register :time_entries, :default => false
221 activity.register :time_entries, :default => false
222 end
222 end
223
223
224 Redmine::Search.map do |search|
224 Redmine::Search.map do |search|
225 search.register :issues
225 search.register :issues
226 search.register :news
226 search.register :news
227 search.register :documents
227 search.register :documents
228 search.register :changesets
228 search.register :changesets
229 search.register :wiki_pages
229 search.register :wiki_pages
230 search.register :messages
230 search.register :messages
231 search.register :projects
231 search.register :projects
232 end
232 end
233
233
234 Redmine::WikiFormatting.map do |format|
234 Redmine::WikiFormatting.map do |format|
235 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
235 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
236 end
236 end
237
237
238 ActionView::Template.register_template_handler :rsb, Redmine::Views::ApiTemplateHandler
238 ActionView::Template.register_template_handler :rsb, Redmine::Views::ApiTemplateHandler
@@ -1,164 +1,163
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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 RepositoriesFilesystemControllerTest < ActionController::TestCase
20 class RepositoriesFilesystemControllerTest < ActionController::TestCase
21 tests RepositoriesController
21 tests RepositoriesController
22
22
23 fixtures :projects, :users, :roles, :members, :member_roles,
23 fixtures :projects, :users, :roles, :members, :member_roles,
24 :repositories, :enabled_modules
24 :repositories, :enabled_modules
25
25
26 REPOSITORY_PATH = Rails.root.join('tmp/test/filesystem_repository').to_s
26 REPOSITORY_PATH = Rails.root.join('tmp/test/filesystem_repository').to_s
27 PRJ_ID = 3
27 PRJ_ID = 3
28
28
29 def setup
29 def setup
30 @ruby19_non_utf8_pass =
30 @ruby19_non_utf8_pass =
31 (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
31 (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
32 User.current = nil
32 User.current = nil
33 Setting.enabled_scm << 'Filesystem' unless Setting.enabled_scm.include?('Filesystem')
33 Setting.enabled_scm << 'Filesystem' unless Setting.enabled_scm.include?('Filesystem')
34 @project = Project.find(PRJ_ID)
34 @project = Project.find(PRJ_ID)
35 @repository = Repository::Filesystem.create(
35 @repository = Repository::Filesystem.create(
36 :project => @project,
36 :project => @project,
37 :url => REPOSITORY_PATH,
37 :url => REPOSITORY_PATH,
38 :path_encoding => ''
38 :path_encoding => ''
39 )
39 )
40 assert @repository
40 assert @repository
41 end
41 end
42
42
43 if File.directory?(REPOSITORY_PATH)
43 if File.directory?(REPOSITORY_PATH)
44 def test_get_new
44 def test_get_new
45 @request.session[:user_id] = 1
45 @request.session[:user_id] = 1
46 @project.repository.destroy
46 @project.repository.destroy
47 get :new, :project_id => 'subproject1', :repository_scm => 'Filesystem'
47 get :new, :project_id => 'subproject1', :repository_scm => 'Filesystem'
48 assert_response :success
48 assert_response :success
49 assert_template 'new'
49 assert_template 'new'
50 assert_kind_of Repository::Filesystem, assigns(:repository)
50 assert_kind_of Repository::Filesystem, assigns(:repository)
51 assert assigns(:repository).new_record?
51 assert assigns(:repository).new_record?
52 end
52 end
53
53
54 def test_browse_root
54 def test_browse_root
55 @repository.fetch_changesets
55 @repository.fetch_changesets
56 @repository.reload
56 @repository.reload
57 get :show, :id => PRJ_ID
57 get :show, :id => PRJ_ID
58 assert_response :success
58 assert_response :success
59 assert_template 'show'
59 assert_template 'show'
60 assert_not_nil assigns(:entries)
60 assert_not_nil assigns(:entries)
61 assert assigns(:entries).size > 0
61 assert assigns(:entries).size > 0
62 assert_not_nil assigns(:changesets)
62 assert_not_nil assigns(:changesets)
63 assert assigns(:changesets).size == 0
63 assert assigns(:changesets).size == 0
64
64
65 assert_no_tag 'input', :attributes => {:name => 'rev'}
65 assert_no_tag 'input', :attributes => {:name => 'rev'}
66 assert_no_tag 'a', :content => 'Statistics'
66 assert_no_tag 'a', :content => 'Statistics'
67 assert_no_tag 'a', :content => 'Atom'
67 assert_no_tag 'a', :content => 'Atom'
68 end
68 end
69
69
70 def test_show_no_extension
70 def test_show_no_extension
71 get :entry, :id => PRJ_ID, :path => repository_path_hash(['test'])[:param]
71 get :entry, :id => PRJ_ID, :path => repository_path_hash(['test'])[:param]
72 assert_response :success
72 assert_response :success
73 assert_template 'entry'
73 assert_template 'entry'
74 assert_tag :tag => 'th',
74 assert_tag :tag => 'th',
75 :content => '1',
75 :content => '1',
76 :attributes => { :class => 'line-num' },
76 :attributes => { :class => 'line-num' },
77 :sibling => { :tag => 'td', :content => /TEST CAT/ }
77 :sibling => { :tag => 'td', :content => /TEST CAT/ }
78 end
78 end
79
79
80 def test_entry_download_no_extension
80 def test_entry_download_no_extension
81 get :entry, :id => PRJ_ID, :path => repository_path_hash(['test'])[:param],
81 get :raw, :id => PRJ_ID, :path => repository_path_hash(['test'])[:param]
82 :format => 'raw'
83 assert_response :success
82 assert_response :success
84 assert_equal 'application/octet-stream', @response.content_type
83 assert_equal 'application/octet-stream', @response.content_type
85 end
84 end
86
85
87 def test_show_non_ascii_contents
86 def test_show_non_ascii_contents
88 with_settings :repositories_encodings => 'UTF-8,EUC-JP' do
87 with_settings :repositories_encodings => 'UTF-8,EUC-JP' do
89 get :entry, :id => PRJ_ID,
88 get :entry, :id => PRJ_ID,
90 :path => repository_path_hash(['japanese', 'euc-jp.txt'])[:param]
89 :path => repository_path_hash(['japanese', 'euc-jp.txt'])[:param]
91 assert_response :success
90 assert_response :success
92 assert_template 'entry'
91 assert_template 'entry'
93 assert_tag :tag => 'th',
92 assert_tag :tag => 'th',
94 :content => '2',
93 :content => '2',
95 :attributes => { :class => 'line-num' },
94 :attributes => { :class => 'line-num' },
96 :sibling => { :tag => 'td', :content => /japanese/ }
95 :sibling => { :tag => 'td', :content => /japanese/ }
97 if @ruby19_non_utf8_pass
96 if @ruby19_non_utf8_pass
98 puts "TODO: show repository file contents test fails in Ruby 1.9 " +
97 puts "TODO: show repository file contents test fails in Ruby 1.9 " +
99 "and Encoding.default_external is not UTF-8. " +
98 "and Encoding.default_external is not UTF-8. " +
100 "Current value is '#{Encoding.default_external.to_s}'"
99 "Current value is '#{Encoding.default_external.to_s}'"
101 else
100 else
102 str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
101 str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
103 str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
102 str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
104 assert_tag :tag => 'th',
103 assert_tag :tag => 'th',
105 :content => '3',
104 :content => '3',
106 :attributes => { :class => 'line-num' },
105 :attributes => { :class => 'line-num' },
107 :sibling => { :tag => 'td', :content => /#{str_japanese}/ }
106 :sibling => { :tag => 'td', :content => /#{str_japanese}/ }
108 end
107 end
109 end
108 end
110 end
109 end
111
110
112 def test_show_utf16
111 def test_show_utf16
113 with_settings :repositories_encodings => 'UTF-16' do
112 with_settings :repositories_encodings => 'UTF-16' do
114 get :entry, :id => PRJ_ID,
113 get :entry, :id => PRJ_ID,
115 :path => repository_path_hash(['japanese', 'utf-16.txt'])[:param]
114 :path => repository_path_hash(['japanese', 'utf-16.txt'])[:param]
116 assert_response :success
115 assert_response :success
117 assert_tag :tag => 'th',
116 assert_tag :tag => 'th',
118 :content => '2',
117 :content => '2',
119 :attributes => { :class => 'line-num' },
118 :attributes => { :class => 'line-num' },
120 :sibling => { :tag => 'td', :content => /japanese/ }
119 :sibling => { :tag => 'td', :content => /japanese/ }
121 end
120 end
122 end
121 end
123
122
124 def test_show_text_file_should_send_if_too_big
123 def test_show_text_file_should_send_if_too_big
125 with_settings :file_max_size_displayed => 1 do
124 with_settings :file_max_size_displayed => 1 do
126 get :entry, :id => PRJ_ID,
125 get :entry, :id => PRJ_ID,
127 :path => repository_path_hash(['japanese', 'big-file.txt'])[:param]
126 :path => repository_path_hash(['japanese', 'big-file.txt'])[:param]
128 assert_response :success
127 assert_response :success
129 assert_equal 'text/plain', @response.content_type
128 assert_equal 'text/plain', @response.content_type
130 end
129 end
131 end
130 end
132
131
133 def test_destroy_valid_repository
132 def test_destroy_valid_repository
134 @request.session[:user_id] = 1 # admin
133 @request.session[:user_id] = 1 # admin
135
134
136 assert_difference 'Repository.count', -1 do
135 assert_difference 'Repository.count', -1 do
137 delete :destroy, :id => @repository.id
136 delete :destroy, :id => @repository.id
138 end
137 end
139 assert_response 302
138 assert_response 302
140 @project.reload
139 @project.reload
141 assert_nil @project.repository
140 assert_nil @project.repository
142 end
141 end
143
142
144 def test_destroy_invalid_repository
143 def test_destroy_invalid_repository
145 @request.session[:user_id] = 1 # admin
144 @request.session[:user_id] = 1 # admin
146 @project.repository.destroy
145 @project.repository.destroy
147 @repository = Repository::Filesystem.create!(
146 @repository = Repository::Filesystem.create!(
148 :project => @project,
147 :project => @project,
149 :url => "/invalid",
148 :url => "/invalid",
150 :path_encoding => ''
149 :path_encoding => ''
151 )
150 )
152
151
153 assert_difference 'Repository.count', -1 do
152 assert_difference 'Repository.count', -1 do
154 delete :destroy, :id => @repository.id
153 delete :destroy, :id => @repository.id
155 end
154 end
156 assert_response 302
155 assert_response 302
157 @project.reload
156 @project.reload
158 assert_nil @project.repository
157 assert_nil @project.repository
159 end
158 end
160 else
159 else
161 puts "Filesystem test repository NOT FOUND. Skipping functional tests !!!"
160 puts "Filesystem test repository NOT FOUND. Skipping functional tests !!!"
162 def test_fake; assert true end
161 def test_fake; assert true end
163 end
162 end
164 end
163 end
@@ -1,412 +1,411
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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 RepositoriesSubversionControllerTest < ActionController::TestCase
20 class RepositoriesSubversionControllerTest < ActionController::TestCase
21 tests RepositoriesController
21 tests RepositoriesController
22
22
23 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
23 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
24 :repositories, :issues, :issue_statuses, :changesets, :changes,
24 :repositories, :issues, :issue_statuses, :changesets, :changes,
25 :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers
25 :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers
26
26
27 PRJ_ID = 3
27 PRJ_ID = 3
28 NUM_REV = 11
28 NUM_REV = 11
29
29
30 def setup
30 def setup
31 Setting.default_language = 'en'
31 Setting.default_language = 'en'
32 User.current = nil
32 User.current = nil
33
33
34 @project = Project.find(PRJ_ID)
34 @project = Project.find(PRJ_ID)
35 @repository = Repository::Subversion.create(:project => @project,
35 @repository = Repository::Subversion.create(:project => @project,
36 :url => self.class.subversion_repository_url)
36 :url => self.class.subversion_repository_url)
37 assert @repository
37 assert @repository
38 end
38 end
39
39
40 if repository_configured?('subversion')
40 if repository_configured?('subversion')
41 def test_new
41 def test_new
42 @request.session[:user_id] = 1
42 @request.session[:user_id] = 1
43 @project.repository.destroy
43 @project.repository.destroy
44 get :new, :project_id => 'subproject1', :repository_scm => 'Subversion'
44 get :new, :project_id => 'subproject1', :repository_scm => 'Subversion'
45 assert_response :success
45 assert_response :success
46 assert_template 'new'
46 assert_template 'new'
47 assert_kind_of Repository::Subversion, assigns(:repository)
47 assert_kind_of Repository::Subversion, assigns(:repository)
48 assert assigns(:repository).new_record?
48 assert assigns(:repository).new_record?
49 end
49 end
50
50
51 def test_show
51 def test_show
52 assert_equal 0, @repository.changesets.count
52 assert_equal 0, @repository.changesets.count
53 @repository.fetch_changesets
53 @repository.fetch_changesets
54 @project.reload
54 @project.reload
55 assert_equal NUM_REV, @repository.changesets.count
55 assert_equal NUM_REV, @repository.changesets.count
56 get :show, :id => PRJ_ID
56 get :show, :id => PRJ_ID
57 assert_response :success
57 assert_response :success
58 assert_template 'show'
58 assert_template 'show'
59 assert_not_nil assigns(:entries)
59 assert_not_nil assigns(:entries)
60 assert_not_nil assigns(:changesets)
60 assert_not_nil assigns(:changesets)
61
61
62 entry = assigns(:entries).detect {|e| e.name == 'subversion_test'}
62 entry = assigns(:entries).detect {|e| e.name == 'subversion_test'}
63 assert_not_nil entry
63 assert_not_nil entry
64 assert_equal 'dir', entry.kind
64 assert_equal 'dir', entry.kind
65 assert_select 'tr.dir a[href=/projects/subproject1/repository/show/subversion_test]'
65 assert_select 'tr.dir a[href=/projects/subproject1/repository/show/subversion_test]'
66
66
67 assert_tag 'input', :attributes => {:name => 'rev'}
67 assert_tag 'input', :attributes => {:name => 'rev'}
68 assert_tag 'a', :content => 'Statistics'
68 assert_tag 'a', :content => 'Statistics'
69 assert_tag 'a', :content => 'Atom'
69 assert_tag 'a', :content => 'Atom'
70 assert_tag :tag => 'a',
70 assert_tag :tag => 'a',
71 :attributes => {:href => '/projects/subproject1/repository'},
71 :attributes => {:href => '/projects/subproject1/repository'},
72 :content => 'root'
72 :content => 'root'
73 end
73 end
74
74
75 def test_show_non_default
75 def test_show_non_default
76 Repository::Subversion.create(:project => @project,
76 Repository::Subversion.create(:project => @project,
77 :url => self.class.subversion_repository_url,
77 :url => self.class.subversion_repository_url,
78 :is_default => false, :identifier => 'svn')
78 :is_default => false, :identifier => 'svn')
79
79
80 get :show, :id => PRJ_ID, :repository_id => 'svn'
80 get :show, :id => PRJ_ID, :repository_id => 'svn'
81 assert_response :success
81 assert_response :success
82 assert_template 'show'
82 assert_template 'show'
83 assert_select 'tr.dir a[href=/projects/subproject1/repository/svn/show/subversion_test]'
83 assert_select 'tr.dir a[href=/projects/subproject1/repository/svn/show/subversion_test]'
84 # Repository menu should link to the main repo
84 # Repository menu should link to the main repo
85 assert_select '#main-menu a[href=/projects/subproject1/repository]'
85 assert_select '#main-menu a[href=/projects/subproject1/repository]'
86 end
86 end
87
87
88 def test_browse_directory
88 def test_browse_directory
89 assert_equal 0, @repository.changesets.count
89 assert_equal 0, @repository.changesets.count
90 @repository.fetch_changesets
90 @repository.fetch_changesets
91 @project.reload
91 @project.reload
92 assert_equal NUM_REV, @repository.changesets.count
92 assert_equal NUM_REV, @repository.changesets.count
93 get :show, :id => PRJ_ID, :path => repository_path_hash(['subversion_test'])[:param]
93 get :show, :id => PRJ_ID, :path => repository_path_hash(['subversion_test'])[:param]
94 assert_response :success
94 assert_response :success
95 assert_template 'show'
95 assert_template 'show'
96 assert_not_nil assigns(:entries)
96 assert_not_nil assigns(:entries)
97 assert_equal [
97 assert_equal [
98 '[folder_with_brackets]', 'folder', '.project',
98 '[folder_with_brackets]', 'folder', '.project',
99 'helloworld.c', 'textfile.txt'
99 'helloworld.c', 'textfile.txt'
100 ],
100 ],
101 assigns(:entries).collect(&:name)
101 assigns(:entries).collect(&:name)
102 entry = assigns(:entries).detect {|e| e.name == 'helloworld.c'}
102 entry = assigns(:entries).detect {|e| e.name == 'helloworld.c'}
103 assert_equal 'file', entry.kind
103 assert_equal 'file', entry.kind
104 assert_equal 'subversion_test/helloworld.c', entry.path
104 assert_equal 'subversion_test/helloworld.c', entry.path
105 assert_tag :a, :content => 'helloworld.c', :attributes => { :class => /text\-x\-c/ }
105 assert_tag :a, :content => 'helloworld.c', :attributes => { :class => /text\-x\-c/ }
106 end
106 end
107
107
108 def test_browse_at_given_revision
108 def test_browse_at_given_revision
109 assert_equal 0, @repository.changesets.count
109 assert_equal 0, @repository.changesets.count
110 @repository.fetch_changesets
110 @repository.fetch_changesets
111 @project.reload
111 @project.reload
112 assert_equal NUM_REV, @repository.changesets.count
112 assert_equal NUM_REV, @repository.changesets.count
113 get :show, :id => PRJ_ID, :path => repository_path_hash(['subversion_test'])[:param],
113 get :show, :id => PRJ_ID, :path => repository_path_hash(['subversion_test'])[:param],
114 :rev => 4
114 :rev => 4
115 assert_response :success
115 assert_response :success
116 assert_template 'show'
116 assert_template 'show'
117 assert_not_nil assigns(:entries)
117 assert_not_nil assigns(:entries)
118 assert_equal ['folder', '.project', 'helloworld.c', 'helloworld.rb', 'textfile.txt'],
118 assert_equal ['folder', '.project', 'helloworld.c', 'helloworld.rb', 'textfile.txt'],
119 assigns(:entries).collect(&:name)
119 assigns(:entries).collect(&:name)
120 end
120 end
121
121
122 def test_file_changes
122 def test_file_changes
123 assert_equal 0, @repository.changesets.count
123 assert_equal 0, @repository.changesets.count
124 @repository.fetch_changesets
124 @repository.fetch_changesets
125 @project.reload
125 @project.reload
126 assert_equal NUM_REV, @repository.changesets.count
126 assert_equal NUM_REV, @repository.changesets.count
127 get :changes, :id => PRJ_ID,
127 get :changes, :id => PRJ_ID,
128 :path => repository_path_hash(['subversion_test', 'folder', 'helloworld.rb'])[:param]
128 :path => repository_path_hash(['subversion_test', 'folder', 'helloworld.rb'])[:param]
129 assert_response :success
129 assert_response :success
130 assert_template 'changes'
130 assert_template 'changes'
131
131
132 changesets = assigns(:changesets)
132 changesets = assigns(:changesets)
133 assert_not_nil changesets
133 assert_not_nil changesets
134 assert_equal %w(6 3 2), changesets.collect(&:revision)
134 assert_equal %w(6 3 2), changesets.collect(&:revision)
135
135
136 # svn properties displayed with svn >= 1.5 only
136 # svn properties displayed with svn >= 1.5 only
137 if Redmine::Scm::Adapters::SubversionAdapter.client_version_above?([1, 5, 0])
137 if Redmine::Scm::Adapters::SubversionAdapter.client_version_above?([1, 5, 0])
138 assert_not_nil assigns(:properties)
138 assert_not_nil assigns(:properties)
139 assert_equal 'native', assigns(:properties)['svn:eol-style']
139 assert_equal 'native', assigns(:properties)['svn:eol-style']
140 assert_tag :ul,
140 assert_tag :ul,
141 :child => { :tag => 'li',
141 :child => { :tag => 'li',
142 :child => { :tag => 'b', :content => 'svn:eol-style' },
142 :child => { :tag => 'b', :content => 'svn:eol-style' },
143 :child => { :tag => 'span', :content => 'native' } }
143 :child => { :tag => 'span', :content => 'native' } }
144 end
144 end
145 end
145 end
146
146
147 def test_directory_changes
147 def test_directory_changes
148 assert_equal 0, @repository.changesets.count
148 assert_equal 0, @repository.changesets.count
149 @repository.fetch_changesets
149 @repository.fetch_changesets
150 @project.reload
150 @project.reload
151 assert_equal NUM_REV, @repository.changesets.count
151 assert_equal NUM_REV, @repository.changesets.count
152 get :changes, :id => PRJ_ID,
152 get :changes, :id => PRJ_ID,
153 :path => repository_path_hash(['subversion_test', 'folder'])[:param]
153 :path => repository_path_hash(['subversion_test', 'folder'])[:param]
154 assert_response :success
154 assert_response :success
155 assert_template 'changes'
155 assert_template 'changes'
156
156
157 changesets = assigns(:changesets)
157 changesets = assigns(:changesets)
158 assert_not_nil changesets
158 assert_not_nil changesets
159 assert_equal %w(10 9 7 6 5 2), changesets.collect(&:revision)
159 assert_equal %w(10 9 7 6 5 2), changesets.collect(&:revision)
160 end
160 end
161
161
162 def test_entry
162 def test_entry
163 assert_equal 0, @repository.changesets.count
163 assert_equal 0, @repository.changesets.count
164 @repository.fetch_changesets
164 @repository.fetch_changesets
165 @project.reload
165 @project.reload
166 assert_equal NUM_REV, @repository.changesets.count
166 assert_equal NUM_REV, @repository.changesets.count
167 get :entry, :id => PRJ_ID,
167 get :entry, :id => PRJ_ID,
168 :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
168 :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
169 assert_response :success
169 assert_response :success
170 assert_template 'entry'
170 assert_template 'entry'
171 end
171 end
172
172
173 def test_entry_should_send_if_too_big
173 def test_entry_should_send_if_too_big
174 assert_equal 0, @repository.changesets.count
174 assert_equal 0, @repository.changesets.count
175 @repository.fetch_changesets
175 @repository.fetch_changesets
176 @project.reload
176 @project.reload
177 assert_equal NUM_REV, @repository.changesets.count
177 assert_equal NUM_REV, @repository.changesets.count
178 # no files in the test repo is larger than 1KB...
178 # no files in the test repo is larger than 1KB...
179 with_settings :file_max_size_displayed => 0 do
179 with_settings :file_max_size_displayed => 0 do
180 get :entry, :id => PRJ_ID,
180 get :entry, :id => PRJ_ID,
181 :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
181 :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
182 assert_response :success
182 assert_response :success
183 assert_equal 'attachment; filename="helloworld.c"',
183 assert_equal 'attachment; filename="helloworld.c"',
184 @response.headers['Content-Disposition']
184 @response.headers['Content-Disposition']
185 end
185 end
186 end
186 end
187
187
188 def test_entry_at_given_revision
188 def test_entry_at_given_revision
189 assert_equal 0, @repository.changesets.count
189 assert_equal 0, @repository.changesets.count
190 @repository.fetch_changesets
190 @repository.fetch_changesets
191 @project.reload
191 @project.reload
192 assert_equal NUM_REV, @repository.changesets.count
192 assert_equal NUM_REV, @repository.changesets.count
193 get :entry, :id => PRJ_ID,
193 get :entry, :id => PRJ_ID,
194 :path => repository_path_hash(['subversion_test', 'helloworld.rb'])[:param],
194 :path => repository_path_hash(['subversion_test', 'helloworld.rb'])[:param],
195 :rev => 2
195 :rev => 2
196 assert_response :success
196 assert_response :success
197 assert_template 'entry'
197 assert_template 'entry'
198 # this line was removed in r3 and file was moved in r6
198 # this line was removed in r3 and file was moved in r6
199 assert_tag :tag => 'td', :attributes => { :class => /line-code/},
199 assert_tag :tag => 'td', :attributes => { :class => /line-code/},
200 :content => /Here's the code/
200 :content => /Here's the code/
201 end
201 end
202
202
203 def test_entry_not_found
203 def test_entry_not_found
204 assert_equal 0, @repository.changesets.count
204 assert_equal 0, @repository.changesets.count
205 @repository.fetch_changesets
205 @repository.fetch_changesets
206 @project.reload
206 @project.reload
207 assert_equal NUM_REV, @repository.changesets.count
207 assert_equal NUM_REV, @repository.changesets.count
208 get :entry, :id => PRJ_ID,
208 get :entry, :id => PRJ_ID,
209 :path => repository_path_hash(['subversion_test', 'zzz.c'])[:param]
209 :path => repository_path_hash(['subversion_test', 'zzz.c'])[:param]
210 assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
210 assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
211 :content => /The entry or revision was not found in the repository/
211 :content => /The entry or revision was not found in the repository/
212 end
212 end
213
213
214 def test_entry_download
214 def test_entry_download
215 assert_equal 0, @repository.changesets.count
215 assert_equal 0, @repository.changesets.count
216 @repository.fetch_changesets
216 @repository.fetch_changesets
217 @project.reload
217 @project.reload
218 assert_equal NUM_REV, @repository.changesets.count
218 assert_equal NUM_REV, @repository.changesets.count
219 get :entry, :id => PRJ_ID,
219 get :raw, :id => PRJ_ID,
220 :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param],
220 :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
221 :format => 'raw'
222 assert_response :success
221 assert_response :success
223 assert_equal 'attachment; filename="helloworld.c"', @response.headers['Content-Disposition']
222 assert_equal 'attachment; filename="helloworld.c"', @response.headers['Content-Disposition']
224 end
223 end
225
224
226 def test_directory_entry
225 def test_directory_entry
227 assert_equal 0, @repository.changesets.count
226 assert_equal 0, @repository.changesets.count
228 @repository.fetch_changesets
227 @repository.fetch_changesets
229 @project.reload
228 @project.reload
230 assert_equal NUM_REV, @repository.changesets.count
229 assert_equal NUM_REV, @repository.changesets.count
231 get :entry, :id => PRJ_ID,
230 get :entry, :id => PRJ_ID,
232 :path => repository_path_hash(['subversion_test', 'folder'])[:param]
231 :path => repository_path_hash(['subversion_test', 'folder'])[:param]
233 assert_response :success
232 assert_response :success
234 assert_template 'show'
233 assert_template 'show'
235 assert_not_nil assigns(:entry)
234 assert_not_nil assigns(:entry)
236 assert_equal 'folder', assigns(:entry).name
235 assert_equal 'folder', assigns(:entry).name
237 end
236 end
238
237
239 # TODO: this test needs fixtures.
238 # TODO: this test needs fixtures.
240 def test_revision
239 def test_revision
241 get :revision, :id => 1, :rev => 2
240 get :revision, :id => 1, :rev => 2
242 assert_response :success
241 assert_response :success
243 assert_template 'revision'
242 assert_template 'revision'
244 assert_tag :tag => 'ul',
243 assert_tag :tag => 'ul',
245 :child => { :tag => 'li',
244 :child => { :tag => 'li',
246 # link to the entry at rev 2
245 # link to the entry at rev 2
247 :child => { :tag => 'a',
246 :child => { :tag => 'a',
248 :attributes => {:href => '/projects/ecookbook/repository/revisions/2/entry/test/some/path/in/the/repo'},
247 :attributes => {:href => '/projects/ecookbook/repository/revisions/2/entry/test/some/path/in/the/repo'},
249 :content => 'repo',
248 :content => 'repo',
250 # link to partial diff
249 # link to partial diff
251 :sibling => { :tag => 'a',
250 :sibling => { :tag => 'a',
252 :attributes => { :href => '/projects/ecookbook/repository/revisions/2/diff/test/some/path/in/the/repo' }
251 :attributes => { :href => '/projects/ecookbook/repository/revisions/2/diff/test/some/path/in/the/repo' }
253 }
252 }
254 }
253 }
255 }
254 }
256 end
255 end
257
256
258 def test_invalid_revision
257 def test_invalid_revision
259 assert_equal 0, @repository.changesets.count
258 assert_equal 0, @repository.changesets.count
260 @repository.fetch_changesets
259 @repository.fetch_changesets
261 @project.reload
260 @project.reload
262 assert_equal NUM_REV, @repository.changesets.count
261 assert_equal NUM_REV, @repository.changesets.count
263 get :revision, :id => PRJ_ID, :rev => 'something_weird'
262 get :revision, :id => PRJ_ID, :rev => 'something_weird'
264 assert_response 404
263 assert_response 404
265 assert_error_tag :content => /was not found/
264 assert_error_tag :content => /was not found/
266 end
265 end
267
266
268 def test_invalid_revision_diff
267 def test_invalid_revision_diff
269 get :diff, :id => PRJ_ID, :rev => '1', :rev_to => 'something_weird'
268 get :diff, :id => PRJ_ID, :rev => '1', :rev_to => 'something_weird'
270 assert_response 404
269 assert_response 404
271 assert_error_tag :content => /was not found/
270 assert_error_tag :content => /was not found/
272 end
271 end
273
272
274 def test_empty_revision
273 def test_empty_revision
275 assert_equal 0, @repository.changesets.count
274 assert_equal 0, @repository.changesets.count
276 @repository.fetch_changesets
275 @repository.fetch_changesets
277 @project.reload
276 @project.reload
278 assert_equal NUM_REV, @repository.changesets.count
277 assert_equal NUM_REV, @repository.changesets.count
279 ['', ' ', nil].each do |r|
278 ['', ' ', nil].each do |r|
280 get :revision, :id => PRJ_ID, :rev => r
279 get :revision, :id => PRJ_ID, :rev => r
281 assert_response 404
280 assert_response 404
282 assert_error_tag :content => /was not found/
281 assert_error_tag :content => /was not found/
283 end
282 end
284 end
283 end
285
284
286 # TODO: this test needs fixtures.
285 # TODO: this test needs fixtures.
287 def test_revision_with_repository_pointing_to_a_subdirectory
286 def test_revision_with_repository_pointing_to_a_subdirectory
288 r = Project.find(1).repository
287 r = Project.find(1).repository
289 # Changes repository url to a subdirectory
288 # Changes repository url to a subdirectory
290 r.update_attribute :url, (r.url + '/test/some')
289 r.update_attribute :url, (r.url + '/test/some')
291
290
292 get :revision, :id => 1, :rev => 2
291 get :revision, :id => 1, :rev => 2
293 assert_response :success
292 assert_response :success
294 assert_template 'revision'
293 assert_template 'revision'
295 assert_tag :tag => 'ul',
294 assert_tag :tag => 'ul',
296 :child => { :tag => 'li',
295 :child => { :tag => 'li',
297 # link to the entry at rev 2
296 # link to the entry at rev 2
298 :child => { :tag => 'a',
297 :child => { :tag => 'a',
299 :attributes => {:href => '/projects/ecookbook/repository/revisions/2/entry/path/in/the/repo'},
298 :attributes => {:href => '/projects/ecookbook/repository/revisions/2/entry/path/in/the/repo'},
300 :content => 'repo',
299 :content => 'repo',
301 # link to partial diff
300 # link to partial diff
302 :sibling => { :tag => 'a',
301 :sibling => { :tag => 'a',
303 :attributes => { :href => '/projects/ecookbook/repository/revisions/2/diff/path/in/the/repo' }
302 :attributes => { :href => '/projects/ecookbook/repository/revisions/2/diff/path/in/the/repo' }
304 }
303 }
305 }
304 }
306 }
305 }
307 end
306 end
308
307
309 def test_revision_diff
308 def test_revision_diff
310 assert_equal 0, @repository.changesets.count
309 assert_equal 0, @repository.changesets.count
311 @repository.fetch_changesets
310 @repository.fetch_changesets
312 @project.reload
311 @project.reload
313 assert_equal NUM_REV, @repository.changesets.count
312 assert_equal NUM_REV, @repository.changesets.count
314 ['inline', 'sbs'].each do |dt|
313 ['inline', 'sbs'].each do |dt|
315 get :diff, :id => PRJ_ID, :rev => 3, :type => dt
314 get :diff, :id => PRJ_ID, :rev => 3, :type => dt
316 assert_response :success
315 assert_response :success
317 assert_template 'diff'
316 assert_template 'diff'
318 assert_tag :tag => 'h2',
317 assert_tag :tag => 'h2',
319 :content => / 3/
318 :content => / 3/
320 end
319 end
321 end
320 end
322
321
323 def test_revision_diff_raw_format
322 def test_revision_diff_raw_format
324 assert_equal 0, @repository.changesets.count
323 assert_equal 0, @repository.changesets.count
325 @repository.fetch_changesets
324 @repository.fetch_changesets
326 @project.reload
325 @project.reload
327 assert_equal NUM_REV, @repository.changesets.count
326 assert_equal NUM_REV, @repository.changesets.count
328
327
329 get :diff, :id => PRJ_ID, :rev => 3, :format => 'diff'
328 get :diff, :id => PRJ_ID, :rev => 3, :format => 'diff'
330 assert_response :success
329 assert_response :success
331 assert_equal 'text/x-patch', @response.content_type
330 assert_equal 'text/x-patch', @response.content_type
332 assert_equal 'Index: subversion_test/textfile.txt', @response.body.split(/\r?\n/).first
331 assert_equal 'Index: subversion_test/textfile.txt', @response.body.split(/\r?\n/).first
333 end
332 end
334
333
335 def test_directory_diff
334 def test_directory_diff
336 assert_equal 0, @repository.changesets.count
335 assert_equal 0, @repository.changesets.count
337 @repository.fetch_changesets
336 @repository.fetch_changesets
338 @project.reload
337 @project.reload
339 assert_equal NUM_REV, @repository.changesets.count
338 assert_equal NUM_REV, @repository.changesets.count
340 ['inline', 'sbs'].each do |dt|
339 ['inline', 'sbs'].each do |dt|
341 get :diff, :id => PRJ_ID, :rev => 6, :rev_to => 2,
340 get :diff, :id => PRJ_ID, :rev => 6, :rev_to => 2,
342 :path => repository_path_hash(['subversion_test', 'folder'])[:param],
341 :path => repository_path_hash(['subversion_test', 'folder'])[:param],
343 :type => dt
342 :type => dt
344 assert_response :success
343 assert_response :success
345 assert_template 'diff'
344 assert_template 'diff'
346
345
347 diff = assigns(:diff)
346 diff = assigns(:diff)
348 assert_not_nil diff
347 assert_not_nil diff
349 # 2 files modified
348 # 2 files modified
350 assert_equal 2, Redmine::UnifiedDiff.new(diff).size
349 assert_equal 2, Redmine::UnifiedDiff.new(diff).size
351 assert_tag :tag => 'h2', :content => /2:6/
350 assert_tag :tag => 'h2', :content => /2:6/
352 end
351 end
353 end
352 end
354
353
355 def test_annotate
354 def test_annotate
356 assert_equal 0, @repository.changesets.count
355 assert_equal 0, @repository.changesets.count
357 @repository.fetch_changesets
356 @repository.fetch_changesets
358 @project.reload
357 @project.reload
359 assert_equal NUM_REV, @repository.changesets.count
358 assert_equal NUM_REV, @repository.changesets.count
360 get :annotate, :id => PRJ_ID,
359 get :annotate, :id => PRJ_ID,
361 :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
360 :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
362 assert_response :success
361 assert_response :success
363 assert_template 'annotate'
362 assert_template 'annotate'
364 end
363 end
365
364
366 def test_annotate_at_given_revision
365 def test_annotate_at_given_revision
367 assert_equal 0, @repository.changesets.count
366 assert_equal 0, @repository.changesets.count
368 @repository.fetch_changesets
367 @repository.fetch_changesets
369 @project.reload
368 @project.reload
370 assert_equal NUM_REV, @repository.changesets.count
369 assert_equal NUM_REV, @repository.changesets.count
371 get :annotate, :id => PRJ_ID, :rev => 8,
370 get :annotate, :id => PRJ_ID, :rev => 8,
372 :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
371 :path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
373 assert_response :success
372 assert_response :success
374 assert_template 'annotate'
373 assert_template 'annotate'
375 assert_tag :tag => 'h2', :content => /@ 8/
374 assert_tag :tag => 'h2', :content => /@ 8/
376 end
375 end
377
376
378 def test_destroy_valid_repository
377 def test_destroy_valid_repository
379 @request.session[:user_id] = 1 # admin
378 @request.session[:user_id] = 1 # admin
380 assert_equal 0, @repository.changesets.count
379 assert_equal 0, @repository.changesets.count
381 @repository.fetch_changesets
380 @repository.fetch_changesets
382 assert_equal NUM_REV, @repository.changesets.count
381 assert_equal NUM_REV, @repository.changesets.count
383
382
384 assert_difference 'Repository.count', -1 do
383 assert_difference 'Repository.count', -1 do
385 delete :destroy, :id => @repository.id
384 delete :destroy, :id => @repository.id
386 end
385 end
387 assert_response 302
386 assert_response 302
388 @project.reload
387 @project.reload
389 assert_nil @project.repository
388 assert_nil @project.repository
390 end
389 end
391
390
392 def test_destroy_invalid_repository
391 def test_destroy_invalid_repository
393 @request.session[:user_id] = 1 # admin
392 @request.session[:user_id] = 1 # admin
394 @project.repository.destroy
393 @project.repository.destroy
395 @repository = Repository::Subversion.create!(
394 @repository = Repository::Subversion.create!(
396 :project => @project,
395 :project => @project,
397 :url => "file:///invalid")
396 :url => "file:///invalid")
398 @repository.fetch_changesets
397 @repository.fetch_changesets
399 assert_equal 0, @repository.changesets.count
398 assert_equal 0, @repository.changesets.count
400
399
401 assert_difference 'Repository.count', -1 do
400 assert_difference 'Repository.count', -1 do
402 delete :destroy, :id => @repository.id
401 delete :destroy, :id => @repository.id
403 end
402 end
404 assert_response 302
403 assert_response 302
405 @project.reload
404 @project.reload
406 assert_nil @project.repository
405 assert_nil @project.repository
407 end
406 end
408 else
407 else
409 puts "Subversion test repository NOT FOUND. Skipping functional tests !!!"
408 puts "Subversion test repository NOT FOUND. Skipping functional tests !!!"
410 def test_fake; assert true end
409 def test_fake; assert true end
411 end
410 end
412 end
411 end
@@ -1,409 +1,409
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 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 RoutingRepositoriesTest < ActionController::IntegrationTest
20 class RoutingRepositoriesTest < ActionController::IntegrationTest
21 def setup
21 def setup
22 @path_hash = repository_path_hash(%w[path to file.c])
22 @path_hash = repository_path_hash(%w[path to file.c])
23 assert_equal "path/to/file.c", @path_hash[:path]
23 assert_equal "path/to/file.c", @path_hash[:path]
24 assert_equal "path/to/file.c", @path_hash[:param]
24 assert_equal "path/to/file.c", @path_hash[:param]
25 end
25 end
26
26
27 def test_repositories_resources
27 def test_repositories_resources
28 assert_routing(
28 assert_routing(
29 { :method => 'get',
29 { :method => 'get',
30 :path => "/projects/redmine/repositories/new" },
30 :path => "/projects/redmine/repositories/new" },
31 { :controller => 'repositories', :action => 'new', :project_id => 'redmine' }
31 { :controller => 'repositories', :action => 'new', :project_id => 'redmine' }
32 )
32 )
33 assert_routing(
33 assert_routing(
34 { :method => 'post',
34 { :method => 'post',
35 :path => "/projects/redmine/repositories" },
35 :path => "/projects/redmine/repositories" },
36 { :controller => 'repositories', :action => 'create', :project_id => 'redmine' }
36 { :controller => 'repositories', :action => 'create', :project_id => 'redmine' }
37 )
37 )
38 assert_routing(
38 assert_routing(
39 { :method => 'get',
39 { :method => 'get',
40 :path => "/repositories/1/edit" },
40 :path => "/repositories/1/edit" },
41 { :controller => 'repositories', :action => 'edit', :id => '1' }
41 { :controller => 'repositories', :action => 'edit', :id => '1' }
42 )
42 )
43 assert_routing(
43 assert_routing(
44 { :method => 'put',
44 { :method => 'put',
45 :path => "/repositories/1" },
45 :path => "/repositories/1" },
46 { :controller => 'repositories', :action => 'update', :id => '1' }
46 { :controller => 'repositories', :action => 'update', :id => '1' }
47 )
47 )
48 assert_routing(
48 assert_routing(
49 { :method => 'delete',
49 { :method => 'delete',
50 :path => "/repositories/1" },
50 :path => "/repositories/1" },
51 { :controller => 'repositories', :action => 'destroy', :id => '1' }
51 { :controller => 'repositories', :action => 'destroy', :id => '1' }
52 )
52 )
53 ["get", "post"].each do |method|
53 ["get", "post"].each do |method|
54 assert_routing(
54 assert_routing(
55 { :method => method,
55 { :method => method,
56 :path => "/repositories/1/committers" },
56 :path => "/repositories/1/committers" },
57 { :controller => 'repositories', :action => 'committers', :id => '1' }
57 { :controller => 'repositories', :action => 'committers', :id => '1' }
58 )
58 )
59 end
59 end
60 end
60 end
61
61
62 def test_repositories_show
62 def test_repositories_show
63 assert_routing(
63 assert_routing(
64 { :method => 'get',
64 { :method => 'get',
65 :path => "/projects/redmine/repository" },
65 :path => "/projects/redmine/repository" },
66 { :controller => 'repositories', :action => 'show', :id => 'redmine' }
66 { :controller => 'repositories', :action => 'show', :id => 'redmine' }
67 )
67 )
68 end
68 end
69
69
70 def test_repositories
70 def test_repositories
71 assert_routing(
71 assert_routing(
72 { :method => 'get',
72 { :method => 'get',
73 :path => "/projects/redmine/repository/statistics" },
73 :path => "/projects/redmine/repository/statistics" },
74 { :controller => 'repositories', :action => 'stats', :id => 'redmine' }
74 { :controller => 'repositories', :action => 'stats', :id => 'redmine' }
75 )
75 )
76 assert_routing(
76 assert_routing(
77 { :method => 'get',
77 { :method => 'get',
78 :path => "/projects/redmine/repository/graph" },
78 :path => "/projects/redmine/repository/graph" },
79 { :controller => 'repositories', :action => 'graph', :id => 'redmine' }
79 { :controller => 'repositories', :action => 'graph', :id => 'redmine' }
80 )
80 )
81 end
81 end
82
82
83 def test_repositories_show_with_repository_id
83 def test_repositories_show_with_repository_id
84 assert_routing(
84 assert_routing(
85 { :method => 'get',
85 { :method => 'get',
86 :path => "/projects/redmine/repository/foo" },
86 :path => "/projects/redmine/repository/foo" },
87 { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo' }
87 { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo' }
88 )
88 )
89 end
89 end
90
90
91 def test_repositories_with_repository_id
91 def test_repositories_with_repository_id
92 assert_routing(
92 assert_routing(
93 { :method => 'get',
93 { :method => 'get',
94 :path => "/projects/redmine/repository/foo/statistics" },
94 :path => "/projects/redmine/repository/foo/statistics" },
95 { :controller => 'repositories', :action => 'stats', :id => 'redmine', :repository_id => 'foo' }
95 { :controller => 'repositories', :action => 'stats', :id => 'redmine', :repository_id => 'foo' }
96 )
96 )
97 assert_routing(
97 assert_routing(
98 { :method => 'get',
98 { :method => 'get',
99 :path => "/projects/redmine/repository/foo/graph" },
99 :path => "/projects/redmine/repository/foo/graph" },
100 { :controller => 'repositories', :action => 'graph', :id => 'redmine', :repository_id => 'foo' }
100 { :controller => 'repositories', :action => 'graph', :id => 'redmine', :repository_id => 'foo' }
101 )
101 )
102 end
102 end
103
103
104 def test_repositories_revisions
104 def test_repositories_revisions
105 empty_path_param = []
105 empty_path_param = []
106 assert_routing(
106 assert_routing(
107 { :method => 'get',
107 { :method => 'get',
108 :path => "/projects/redmine/repository/revisions" },
108 :path => "/projects/redmine/repository/revisions" },
109 { :controller => 'repositories', :action => 'revisions', :id => 'redmine' }
109 { :controller => 'repositories', :action => 'revisions', :id => 'redmine' }
110 )
110 )
111 assert_routing(
111 assert_routing(
112 { :method => 'get',
112 { :method => 'get',
113 :path => "/projects/redmine/repository/revisions.atom" },
113 :path => "/projects/redmine/repository/revisions.atom" },
114 { :controller => 'repositories', :action => 'revisions', :id => 'redmine',
114 { :controller => 'repositories', :action => 'revisions', :id => 'redmine',
115 :format => 'atom' }
115 :format => 'atom' }
116 )
116 )
117 assert_routing(
117 assert_routing(
118 { :method => 'get',
118 { :method => 'get',
119 :path => "/projects/redmine/repository/revisions/2457" },
119 :path => "/projects/redmine/repository/revisions/2457" },
120 { :controller => 'repositories', :action => 'revision', :id => 'redmine',
120 { :controller => 'repositories', :action => 'revision', :id => 'redmine',
121 :rev => '2457' }
121 :rev => '2457' }
122 )
122 )
123 assert_routing(
123 assert_routing(
124 { :method => 'get',
124 { :method => 'get',
125 :path => "/projects/redmine/repository/revisions/2457/show" },
125 :path => "/projects/redmine/repository/revisions/2457/show" },
126 { :controller => 'repositories', :action => 'show', :id => 'redmine',
126 { :controller => 'repositories', :action => 'show', :id => 'redmine',
127 :rev => '2457' }
127 :rev => '2457' }
128 )
128 )
129 assert_routing(
129 assert_routing(
130 { :method => 'get',
130 { :method => 'get',
131 :path => "/projects/redmine/repository/revisions/2457/show/#{@path_hash[:path]}" },
131 :path => "/projects/redmine/repository/revisions/2457/show/#{@path_hash[:path]}" },
132 { :controller => 'repositories', :action => 'show', :id => 'redmine',
132 { :controller => 'repositories', :action => 'show', :id => 'redmine',
133 :path => @path_hash[:param] , :rev => '2457'}
133 :path => @path_hash[:param] , :rev => '2457'}
134 )
134 )
135 assert_routing(
135 assert_routing(
136 { :method => 'get',
136 { :method => 'get',
137 :path => "/projects/redmine/repository/changes" },
137 :path => "/projects/redmine/repository/changes" },
138 { :controller => 'repositories', :action => 'changes', :id => 'redmine' }
138 { :controller => 'repositories', :action => 'changes', :id => 'redmine' }
139 )
139 )
140 ['2457', 'master', 'slash/slash'].each do |rev|
140 ['2457', 'master', 'slash/slash'].each do |rev|
141 assert_routing(
141 assert_routing(
142 { :method => 'get',
142 { :method => 'get',
143 :path => "/projects/redmine/repository/changes" },
143 :path => "/projects/redmine/repository/changes" },
144 { :controller => 'repositories', :action => 'changes', :id => 'redmine',
144 { :controller => 'repositories', :action => 'changes', :id => 'redmine',
145 :rev => rev },
145 :rev => rev },
146 {},
146 {},
147 { :rev => rev }
147 { :rev => rev }
148 )
148 )
149 end
149 end
150 ['2457', 'master', 'slash/slash'].each do |rev|
150 ['2457', 'master', 'slash/slash'].each do |rev|
151 assert_routing(
151 assert_routing(
152 { :method => 'get',
152 { :method => 'get',
153 :path => "/projects/redmine/repository/changes/#{@path_hash[:path]}" },
153 :path => "/projects/redmine/repository/changes/#{@path_hash[:path]}" },
154 { :controller => 'repositories', :action => 'changes', :id => 'redmine',
154 { :controller => 'repositories', :action => 'changes', :id => 'redmine',
155 :path => @path_hash[:param], :rev => rev },
155 :path => @path_hash[:param], :rev => rev },
156 {},
156 {},
157 { :rev => rev }
157 { :rev => rev }
158 )
158 )
159 end
159 end
160 assert_routing(
160 assert_routing(
161 { :method => 'get',
161 { :method => 'get',
162 :path => "/projects/redmine/repository/revisions/2457/diff" },
162 :path => "/projects/redmine/repository/revisions/2457/diff" },
163 { :controller => 'repositories', :action => 'diff', :id => 'redmine',
163 { :controller => 'repositories', :action => 'diff', :id => 'redmine',
164 :rev => '2457' }
164 :rev => '2457' }
165 )
165 )
166 assert_routing(
166 assert_routing(
167 { :method => 'get',
167 { :method => 'get',
168 :path => "/projects/redmine/repository/revisions/2457/diff.diff" },
168 :path => "/projects/redmine/repository/revisions/2457/diff.diff" },
169 { :controller => 'repositories', :action => 'diff', :id => 'redmine',
169 { :controller => 'repositories', :action => 'diff', :id => 'redmine',
170 :rev => '2457', :format => 'diff' }
170 :rev => '2457', :format => 'diff' }
171 )
171 )
172 assert_routing(
172 assert_routing(
173 { :method => 'get',
173 { :method => 'get',
174 :path => "/projects/redmine/repository/revisions/2/diff/#{@path_hash[:path]}" },
174 :path => "/projects/redmine/repository/revisions/2/diff/#{@path_hash[:path]}" },
175 { :controller => 'repositories', :action => 'diff', :id => 'redmine',
175 { :controller => 'repositories', :action => 'diff', :id => 'redmine',
176 :path => @path_hash[:param], :rev => '2' }
176 :path => @path_hash[:param], :rev => '2' }
177 )
177 )
178 assert_routing(
178 assert_routing(
179 { :method => 'get',
179 { :method => 'get',
180 :path => "/projects/redmine/repository/revisions/2/entry/#{@path_hash[:path]}" },
180 :path => "/projects/redmine/repository/revisions/2/entry/#{@path_hash[:path]}" },
181 { :controller => 'repositories', :action => 'entry', :id => 'redmine',
181 { :controller => 'repositories', :action => 'entry', :id => 'redmine',
182 :path => @path_hash[:param], :rev => '2' }
182 :path => @path_hash[:param], :rev => '2' }
183 )
183 )
184 assert_routing(
184 assert_routing(
185 { :method => 'get',
185 { :method => 'get',
186 :path => "/projects/redmine/repository/revisions/2/raw/#{@path_hash[:path]}" },
186 :path => "/projects/redmine/repository/revisions/2/raw/#{@path_hash[:path]}" },
187 { :controller => 'repositories', :action => 'entry', :id => 'redmine',
187 { :controller => 'repositories', :action => 'raw', :id => 'redmine',
188 :path => @path_hash[:param], :rev => '2', :format => 'raw' }
188 :path => @path_hash[:param], :rev => '2' }
189 )
189 )
190 assert_routing(
190 assert_routing(
191 { :method => 'get',
191 { :method => 'get',
192 :path => "/projects/redmine/repository/revisions/2/annotate/#{@path_hash[:path]}" },
192 :path => "/projects/redmine/repository/revisions/2/annotate/#{@path_hash[:path]}" },
193 { :controller => 'repositories', :action => 'annotate', :id => 'redmine',
193 { :controller => 'repositories', :action => 'annotate', :id => 'redmine',
194 :path => @path_hash[:param], :rev => '2' }
194 :path => @path_hash[:param], :rev => '2' }
195 )
195 )
196 end
196 end
197
197
198 def test_repositories_revisions_with_repository_id
198 def test_repositories_revisions_with_repository_id
199 empty_path_param = []
199 empty_path_param = []
200 assert_routing(
200 assert_routing(
201 { :method => 'get',
201 { :method => 'get',
202 :path => "/projects/redmine/repository/foo/revisions" },
202 :path => "/projects/redmine/repository/foo/revisions" },
203 { :controller => 'repositories', :action => 'revisions', :id => 'redmine', :repository_id => 'foo' }
203 { :controller => 'repositories', :action => 'revisions', :id => 'redmine', :repository_id => 'foo' }
204 )
204 )
205 assert_routing(
205 assert_routing(
206 { :method => 'get',
206 { :method => 'get',
207 :path => "/projects/redmine/repository/foo/revisions.atom" },
207 :path => "/projects/redmine/repository/foo/revisions.atom" },
208 { :controller => 'repositories', :action => 'revisions', :id => 'redmine', :repository_id => 'foo',
208 { :controller => 'repositories', :action => 'revisions', :id => 'redmine', :repository_id => 'foo',
209 :format => 'atom' }
209 :format => 'atom' }
210 )
210 )
211 assert_routing(
211 assert_routing(
212 { :method => 'get',
212 { :method => 'get',
213 :path => "/projects/redmine/repository/foo/revisions/2457" },
213 :path => "/projects/redmine/repository/foo/revisions/2457" },
214 { :controller => 'repositories', :action => 'revision', :id => 'redmine', :repository_id => 'foo',
214 { :controller => 'repositories', :action => 'revision', :id => 'redmine', :repository_id => 'foo',
215 :rev => '2457' }
215 :rev => '2457' }
216 )
216 )
217 assert_routing(
217 assert_routing(
218 { :method => 'get',
218 { :method => 'get',
219 :path => "/projects/redmine/repository/foo/revisions/2457/show" },
219 :path => "/projects/redmine/repository/foo/revisions/2457/show" },
220 { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo',
220 { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo',
221 :rev => '2457' }
221 :rev => '2457' }
222 )
222 )
223 assert_routing(
223 assert_routing(
224 { :method => 'get',
224 { :method => 'get',
225 :path => "/projects/redmine/repository/foo/revisions/2457/show/#{@path_hash[:path]}" },
225 :path => "/projects/redmine/repository/foo/revisions/2457/show/#{@path_hash[:path]}" },
226 { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo',
226 { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo',
227 :path => @path_hash[:param] , :rev => '2457'}
227 :path => @path_hash[:param] , :rev => '2457'}
228 )
228 )
229 assert_routing(
229 assert_routing(
230 { :method => 'get',
230 { :method => 'get',
231 :path => "/projects/redmine/repository/foo/changes" },
231 :path => "/projects/redmine/repository/foo/changes" },
232 { :controller => 'repositories', :action => 'changes', :id => 'redmine', :repository_id => 'foo' }
232 { :controller => 'repositories', :action => 'changes', :id => 'redmine', :repository_id => 'foo' }
233 )
233 )
234 ['2457', 'master', 'slash/slash'].each do |rev|
234 ['2457', 'master', 'slash/slash'].each do |rev|
235 assert_routing(
235 assert_routing(
236 { :method => 'get',
236 { :method => 'get',
237 :path => "/projects/redmine/repository/foo/changes" },
237 :path => "/projects/redmine/repository/foo/changes" },
238 { :controller => 'repositories', :action => 'changes', :id => 'redmine',
238 { :controller => 'repositories', :action => 'changes', :id => 'redmine',
239 :repository_id => 'foo', :rev => rev },
239 :repository_id => 'foo', :rev => rev },
240 {},
240 {},
241 { :rev => rev }
241 { :rev => rev }
242 )
242 )
243 end
243 end
244 ['2457', 'master', 'slash/slash'].each do |rev|
244 ['2457', 'master', 'slash/slash'].each do |rev|
245 assert_routing(
245 assert_routing(
246 { :method => 'get',
246 { :method => 'get',
247 :path => "/projects/redmine/repository/foo/changes/#{@path_hash[:path]}" },
247 :path => "/projects/redmine/repository/foo/changes/#{@path_hash[:path]}" },
248 { :controller => 'repositories', :action => 'changes', :id => 'redmine',
248 { :controller => 'repositories', :action => 'changes', :id => 'redmine',
249 :repository_id => 'foo', :path => @path_hash[:param], :rev => rev },
249 :repository_id => 'foo', :path => @path_hash[:param], :rev => rev },
250 {},
250 {},
251 { :rev => rev }
251 { :rev => rev }
252 )
252 )
253 end
253 end
254 assert_routing(
254 assert_routing(
255 { :method => 'get',
255 { :method => 'get',
256 :path => "/projects/redmine/repository/foo/revisions/2457/diff" },
256 :path => "/projects/redmine/repository/foo/revisions/2457/diff" },
257 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
257 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
258 :rev => '2457' }
258 :rev => '2457' }
259 )
259 )
260 assert_routing(
260 assert_routing(
261 { :method => 'get',
261 { :method => 'get',
262 :path => "/projects/redmine/repository/foo/revisions/2457/diff.diff" },
262 :path => "/projects/redmine/repository/foo/revisions/2457/diff.diff" },
263 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
263 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
264 :rev => '2457', :format => 'diff' }
264 :rev => '2457', :format => 'diff' }
265 )
265 )
266 assert_routing(
266 assert_routing(
267 { :method => 'get',
267 { :method => 'get',
268 :path => "/projects/redmine/repository/foo/revisions/2/diff/#{@path_hash[:path]}" },
268 :path => "/projects/redmine/repository/foo/revisions/2/diff/#{@path_hash[:path]}" },
269 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
269 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
270 :path => @path_hash[:param], :rev => '2' }
270 :path => @path_hash[:param], :rev => '2' }
271 )
271 )
272 assert_routing(
272 assert_routing(
273 { :method => 'get',
273 { :method => 'get',
274 :path => "/projects/redmine/repository/foo/revisions/2/entry/#{@path_hash[:path]}" },
274 :path => "/projects/redmine/repository/foo/revisions/2/entry/#{@path_hash[:path]}" },
275 { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
275 { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
276 :path => @path_hash[:param], :rev => '2' }
276 :path => @path_hash[:param], :rev => '2' }
277 )
277 )
278 assert_routing(
278 assert_routing(
279 { :method => 'get',
279 { :method => 'get',
280 :path => "/projects/redmine/repository/foo/revisions/2/raw/#{@path_hash[:path]}" },
280 :path => "/projects/redmine/repository/foo/revisions/2/raw/#{@path_hash[:path]}" },
281 { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
281 { :controller => 'repositories', :action => 'raw', :id => 'redmine', :repository_id => 'foo',
282 :path => @path_hash[:param], :rev => '2', :format => 'raw' }
282 :path => @path_hash[:param], :rev => '2' }
283 )
283 )
284 assert_routing(
284 assert_routing(
285 { :method => 'get',
285 { :method => 'get',
286 :path => "/projects/redmine/repository/foo/revisions/2/annotate/#{@path_hash[:path]}" },
286 :path => "/projects/redmine/repository/foo/revisions/2/annotate/#{@path_hash[:path]}" },
287 { :controller => 'repositories', :action => 'annotate', :id => 'redmine', :repository_id => 'foo',
287 { :controller => 'repositories', :action => 'annotate', :id => 'redmine', :repository_id => 'foo',
288 :path => @path_hash[:param], :rev => '2' }
288 :path => @path_hash[:param], :rev => '2' }
289 )
289 )
290 end
290 end
291
291
292 def test_repositories_non_revisions_path
292 def test_repositories_non_revisions_path
293 assert_routing(
293 assert_routing(
294 { :method => 'get',
294 { :method => 'get',
295 :path => "/projects/redmine/repository/diff/#{@path_hash[:path]}" },
295 :path => "/projects/redmine/repository/diff/#{@path_hash[:path]}" },
296 { :controller => 'repositories', :action => 'diff', :id => 'redmine',
296 { :controller => 'repositories', :action => 'diff', :id => 'redmine',
297 :path => @path_hash[:param] }
297 :path => @path_hash[:param] }
298 )
298 )
299 assert_routing(
299 assert_routing(
300 { :method => 'get',
300 { :method => 'get',
301 :path => "/projects/redmine/repository/browse/#{@path_hash[:path]}" },
301 :path => "/projects/redmine/repository/browse/#{@path_hash[:path]}" },
302 { :controller => 'repositories', :action => 'browse', :id => 'redmine',
302 { :controller => 'repositories', :action => 'browse', :id => 'redmine',
303 :path => @path_hash[:param] }
303 :path => @path_hash[:param] }
304 )
304 )
305 assert_routing(
305 assert_routing(
306 { :method => 'get',
306 { :method => 'get',
307 :path => "/projects/redmine/repository/entry/#{@path_hash[:path]}" },
307 :path => "/projects/redmine/repository/entry/#{@path_hash[:path]}" },
308 { :controller => 'repositories', :action => 'entry', :id => 'redmine',
308 { :controller => 'repositories', :action => 'entry', :id => 'redmine',
309 :path => @path_hash[:param] }
309 :path => @path_hash[:param] }
310 )
310 )
311 assert_routing(
311 assert_routing(
312 { :method => 'get',
312 { :method => 'get',
313 :path => "/projects/redmine/repository/raw/#{@path_hash[:path]}" },
313 :path => "/projects/redmine/repository/raw/#{@path_hash[:path]}" },
314 { :controller => 'repositories', :action => 'entry', :id => 'redmine',
314 { :controller => 'repositories', :action => 'raw', :id => 'redmine',
315 :path => @path_hash[:param], :format => 'raw' }
315 :path => @path_hash[:param] }
316 )
316 )
317 assert_routing(
317 assert_routing(
318 { :method => 'get',
318 { :method => 'get',
319 :path => "/projects/redmine/repository/annotate/#{@path_hash[:path]}" },
319 :path => "/projects/redmine/repository/annotate/#{@path_hash[:path]}" },
320 { :controller => 'repositories', :action => 'annotate', :id => 'redmine',
320 { :controller => 'repositories', :action => 'annotate', :id => 'redmine',
321 :path => @path_hash[:param] }
321 :path => @path_hash[:param] }
322 )
322 )
323 assert_routing(
323 assert_routing(
324 { :method => 'get',
324 { :method => 'get',
325 :path => "/projects/redmine/repository/changes/#{@path_hash[:path]}" },
325 :path => "/projects/redmine/repository/changes/#{@path_hash[:path]}" },
326 { :controller => 'repositories', :action => 'changes', :id => 'redmine',
326 { :controller => 'repositories', :action => 'changes', :id => 'redmine',
327 :path => @path_hash[:param] }
327 :path => @path_hash[:param] }
328 )
328 )
329 assert_routing(
329 assert_routing(
330 { :method => 'get',
330 { :method => 'get',
331 :path => "/projects/redmine/repository/revision" },
331 :path => "/projects/redmine/repository/revision" },
332 { :controller => 'repositories', :action => 'revision', :id => 'redmine' }
332 { :controller => 'repositories', :action => 'revision', :id => 'redmine' }
333 )
333 )
334 end
334 end
335
335
336 def test_repositories_non_revisions_path_with_repository_id
336 def test_repositories_non_revisions_path_with_repository_id
337 assert_routing(
337 assert_routing(
338 { :method => 'get',
338 { :method => 'get',
339 :path => "/projects/redmine/repository/foo/diff/#{@path_hash[:path]}" },
339 :path => "/projects/redmine/repository/foo/diff/#{@path_hash[:path]}" },
340 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
340 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
341 :path => @path_hash[:param] }
341 :path => @path_hash[:param] }
342 )
342 )
343 assert_routing(
343 assert_routing(
344 { :method => 'get',
344 { :method => 'get',
345 :path => "/projects/redmine/repository/foo/browse/#{@path_hash[:path]}" },
345 :path => "/projects/redmine/repository/foo/browse/#{@path_hash[:path]}" },
346 { :controller => 'repositories', :action => 'browse', :id => 'redmine', :repository_id => 'foo',
346 { :controller => 'repositories', :action => 'browse', :id => 'redmine', :repository_id => 'foo',
347 :path => @path_hash[:param] }
347 :path => @path_hash[:param] }
348 )
348 )
349 assert_routing(
349 assert_routing(
350 { :method => 'get',
350 { :method => 'get',
351 :path => "/projects/redmine/repository/foo/entry/#{@path_hash[:path]}" },
351 :path => "/projects/redmine/repository/foo/entry/#{@path_hash[:path]}" },
352 { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
352 { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
353 :path => @path_hash[:param] }
353 :path => @path_hash[:param] }
354 )
354 )
355 assert_routing(
355 assert_routing(
356 { :method => 'get',
356 { :method => 'get',
357 :path => "/projects/redmine/repository/foo/raw/#{@path_hash[:path]}" },
357 :path => "/projects/redmine/repository/foo/raw/#{@path_hash[:path]}" },
358 { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
358 { :controller => 'repositories', :action => 'raw', :id => 'redmine', :repository_id => 'foo',
359 :path => @path_hash[:param], :format => 'raw' }
359 :path => @path_hash[:param] }
360 )
360 )
361 assert_routing(
361 assert_routing(
362 { :method => 'get',
362 { :method => 'get',
363 :path => "/projects/redmine/repository/foo/annotate/#{@path_hash[:path]}" },
363 :path => "/projects/redmine/repository/foo/annotate/#{@path_hash[:path]}" },
364 { :controller => 'repositories', :action => 'annotate', :id => 'redmine', :repository_id => 'foo',
364 { :controller => 'repositories', :action => 'annotate', :id => 'redmine', :repository_id => 'foo',
365 :path => @path_hash[:param] }
365 :path => @path_hash[:param] }
366 )
366 )
367 assert_routing(
367 assert_routing(
368 { :method => 'get',
368 { :method => 'get',
369 :path => "/projects/redmine/repository/foo/changes/#{@path_hash[:path]}" },
369 :path => "/projects/redmine/repository/foo/changes/#{@path_hash[:path]}" },
370 { :controller => 'repositories', :action => 'changes', :id => 'redmine', :repository_id => 'foo',
370 { :controller => 'repositories', :action => 'changes', :id => 'redmine', :repository_id => 'foo',
371 :path => @path_hash[:param] }
371 :path => @path_hash[:param] }
372 )
372 )
373 assert_routing(
373 assert_routing(
374 { :method => 'get',
374 { :method => 'get',
375 :path => "/projects/redmine/repository/foo/revision" },
375 :path => "/projects/redmine/repository/foo/revision" },
376 { :controller => 'repositories', :action => 'revision', :id => 'redmine', :repository_id => 'foo'}
376 { :controller => 'repositories', :action => 'revision', :id => 'redmine', :repository_id => 'foo'}
377 )
377 )
378 end
378 end
379
379
380 def test_repositories_related_issues
380 def test_repositories_related_issues
381 assert_routing(
381 assert_routing(
382 { :method => 'post',
382 { :method => 'post',
383 :path => "/projects/redmine/repository/revisions/123/issues" },
383 :path => "/projects/redmine/repository/revisions/123/issues" },
384 { :controller => 'repositories', :action => 'add_related_issue',
384 { :controller => 'repositories', :action => 'add_related_issue',
385 :id => 'redmine', :rev => '123' }
385 :id => 'redmine', :rev => '123' }
386 )
386 )
387 assert_routing(
387 assert_routing(
388 { :method => 'delete',
388 { :method => 'delete',
389 :path => "/projects/redmine/repository/revisions/123/issues/25" },
389 :path => "/projects/redmine/repository/revisions/123/issues/25" },
390 { :controller => 'repositories', :action => 'remove_related_issue',
390 { :controller => 'repositories', :action => 'remove_related_issue',
391 :id => 'redmine', :rev => '123', :issue_id => '25' }
391 :id => 'redmine', :rev => '123', :issue_id => '25' }
392 )
392 )
393 end
393 end
394
394
395 def test_repositories_related_issues_with_repository_id
395 def test_repositories_related_issues_with_repository_id
396 assert_routing(
396 assert_routing(
397 { :method => 'post',
397 { :method => 'post',
398 :path => "/projects/redmine/repository/foo/revisions/123/issues" },
398 :path => "/projects/redmine/repository/foo/revisions/123/issues" },
399 { :controller => 'repositories', :action => 'add_related_issue',
399 { :controller => 'repositories', :action => 'add_related_issue',
400 :id => 'redmine', :repository_id => 'foo', :rev => '123' }
400 :id => 'redmine', :repository_id => 'foo', :rev => '123' }
401 )
401 )
402 assert_routing(
402 assert_routing(
403 { :method => 'delete',
403 { :method => 'delete',
404 :path => "/projects/redmine/repository/foo/revisions/123/issues/25" },
404 :path => "/projects/redmine/repository/foo/revisions/123/issues/25" },
405 { :controller => 'repositories', :action => 'remove_related_issue',
405 { :controller => 'repositories', :action => 'remove_related_issue',
406 :id => 'redmine', :repository_id => 'foo', :rev => '123', :issue_id => '25' }
406 :id => 'redmine', :repository_id => 'foo', :rev => '123', :issue_id => '25' }
407 )
407 )
408 end
408 end
409 end
409 end
General Comments 0
You need to be logged in to leave comments. Login now