##// END OF EJS Templates
scm: set mime type in downloading file....
Toshi MARUYAMA -
r5090:f15b12556f01
parent child
Show More
@@ -1,356 +1,359
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
2 # Copyright (C) 2006-2009 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
21
22 class ChangesetNotFound < Exception; end
22 class ChangesetNotFound < Exception; end
23 class InvalidRevisionParam < Exception; end
23 class InvalidRevisionParam < Exception; end
24
24
25 class RepositoriesController < ApplicationController
25 class RepositoriesController < ApplicationController
26 menu_item :repository
26 menu_item :repository
27 menu_item :settings, :only => :edit
27 menu_item :settings, :only => :edit
28 default_search_scope :changesets
28 default_search_scope :changesets
29
29
30 before_filter :find_repository, :except => :edit
30 before_filter :find_repository, :except => :edit
31 before_filter :find_project, :only => :edit
31 before_filter :find_project, :only => :edit
32 before_filter :authorize
32 before_filter :authorize
33 accept_key_auth :revisions
33 accept_key_auth :revisions
34
34
35 rescue_from Redmine::Scm::Adapters::CommandFailed, :with => :show_error_command_failed
35 rescue_from Redmine::Scm::Adapters::CommandFailed, :with => :show_error_command_failed
36
36
37 def edit
37 def edit
38 @repository = @project.repository
38 @repository = @project.repository
39 if !@repository
39 if !@repository
40 @repository = Repository.factory(params[:repository_scm])
40 @repository = Repository.factory(params[:repository_scm])
41 @repository.project = @project if @repository
41 @repository.project = @project if @repository
42 end
42 end
43 if request.post? && @repository
43 if request.post? && @repository
44 @repository.attributes = params[:repository]
44 @repository.attributes = params[:repository]
45 @repository.save
45 @repository.save
46 end
46 end
47 render(:update) do |page|
47 render(:update) do |page|
48 page.replace_html "tab-content-repository", :partial => 'projects/settings/repository'
48 page.replace_html "tab-content-repository", :partial => 'projects/settings/repository'
49 if @repository && !@project.repository
49 if @repository && !@project.repository
50 @project.reload #needed to reload association
50 @project.reload #needed to reload association
51 page.replace_html "main-menu", render_main_menu(@project)
51 page.replace_html "main-menu", render_main_menu(@project)
52 end
52 end
53 end
53 end
54 end
54 end
55
55
56 def committers
56 def committers
57 @committers = @repository.committers
57 @committers = @repository.committers
58 @users = @project.users
58 @users = @project.users
59 additional_user_ids = @committers.collect(&:last).collect(&:to_i) - @users.collect(&:id)
59 additional_user_ids = @committers.collect(&:last).collect(&:to_i) - @users.collect(&:id)
60 @users += User.find_all_by_id(additional_user_ids) unless additional_user_ids.empty?
60 @users += User.find_all_by_id(additional_user_ids) unless additional_user_ids.empty?
61 @users.compact!
61 @users.compact!
62 @users.sort!
62 @users.sort!
63 if request.post? && params[:committers].is_a?(Hash)
63 if request.post? && params[:committers].is_a?(Hash)
64 # Build a hash with repository usernames as keys and corresponding user ids as values
64 # Build a hash with repository usernames as keys and corresponding user ids as values
65 @repository.committer_ids = params[:committers].values.inject({}) {|h, c| h[c.first] = c.last; h}
65 @repository.committer_ids = params[:committers].values.inject({}) {|h, c| h[c.first] = c.last; h}
66 flash[:notice] = l(:notice_successful_update)
66 flash[:notice] = l(:notice_successful_update)
67 redirect_to :action => 'committers', :id => @project
67 redirect_to :action => 'committers', :id => @project
68 end
68 end
69 end
69 end
70
70
71 def destroy
71 def destroy
72 @repository.destroy
72 @repository.destroy
73 redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'repository'
73 redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'repository'
74 end
74 end
75
75
76 def show
76 def show
77 @repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty?
77 @repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty?
78
78
79 @entries = @repository.entries(@path, @rev)
79 @entries = @repository.entries(@path, @rev)
80 @changeset = @repository.find_changeset_by_name(@rev)
80 @changeset = @repository.find_changeset_by_name(@rev)
81 if request.xhr?
81 if request.xhr?
82 @entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
82 @entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
83 else
83 else
84 (show_error_not_found; return) unless @entries
84 (show_error_not_found; return) unless @entries
85 @changesets = @repository.latest_changesets(@path, @rev)
85 @changesets = @repository.latest_changesets(@path, @rev)
86 @properties = @repository.properties(@path, @rev)
86 @properties = @repository.properties(@path, @rev)
87 render :action => 'show'
87 render :action => 'show'
88 end
88 end
89 end
89 end
90
90
91 alias_method :browse, :show
91 alias_method :browse, :show
92
92
93 def changes
93 def changes
94 @entry = @repository.entry(@path, @rev)
94 @entry = @repository.entry(@path, @rev)
95 (show_error_not_found; return) unless @entry
95 (show_error_not_found; return) unless @entry
96 @changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i)
96 @changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i)
97 @properties = @repository.properties(@path, @rev)
97 @properties = @repository.properties(@path, @rev)
98 @changeset = @repository.find_changeset_by_name(@rev)
98 @changeset = @repository.find_changeset_by_name(@rev)
99 end
99 end
100
100
101 def revisions
101 def revisions
102 @changeset_count = @repository.changesets.count
102 @changeset_count = @repository.changesets.count
103 @changeset_pages = Paginator.new self, @changeset_count,
103 @changeset_pages = Paginator.new self, @changeset_count,
104 per_page_option,
104 per_page_option,
105 params['page']
105 params['page']
106 @changesets = @repository.changesets.find(:all,
106 @changesets = @repository.changesets.find(:all,
107 :limit => @changeset_pages.items_per_page,
107 :limit => @changeset_pages.items_per_page,
108 :offset => @changeset_pages.current.offset,
108 :offset => @changeset_pages.current.offset,
109 :include => [:user, :repository])
109 :include => [:user, :repository])
110
110
111 respond_to do |format|
111 respond_to do |format|
112 format.html { render :layout => false if request.xhr? }
112 format.html { render :layout => false if request.xhr? }
113 format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") }
113 format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") }
114 end
114 end
115 end
115 end
116
116
117 def entry
117 def entry
118 @entry = @repository.entry(@path, @rev)
118 @entry = @repository.entry(@path, @rev)
119 (show_error_not_found; return) unless @entry
119 (show_error_not_found; return) unless @entry
120
120
121 # If the entry is a dir, show the browser
121 # If the entry is a dir, show the browser
122 (show; return) if @entry.is_dir?
122 (show; return) if @entry.is_dir?
123
123
124 @content = @repository.cat(@path, @rev)
124 @content = @repository.cat(@path, @rev)
125 (show_error_not_found; return) unless @content
125 (show_error_not_found; return) unless @content
126 if 'raw' == params[:format] ||
126 if 'raw' == params[:format] ||
127 (@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) ||
127 (@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) ||
128 ! is_entry_text_data?(@content, @path)
128 ! is_entry_text_data?(@content, @path)
129 # Force the download
129 # Force the download
130 send_data @content, :filename => filename_for_content_disposition(@path.split('/').last)
130 send_opt = { :filename => filename_for_content_disposition(@path.split('/').last) }
131 send_type = Redmine::MimeType.of(@path)
132 send_opt[:type] = send_type.to_s if send_type
133 send_data @content, send_opt
131 else
134 else
132 # Prevent empty lines when displaying a file with Windows style eol
135 # Prevent empty lines when displaying a file with Windows style eol
133 # TODO: UTF-16
136 # TODO: UTF-16
134 # Is this needs? AttachmentsController reads file simply.
137 # Is this needs? AttachmentsController reads file simply.
135 @content.gsub!("\r\n", "\n")
138 @content.gsub!("\r\n", "\n")
136 @changeset = @repository.find_changeset_by_name(@rev)
139 @changeset = @repository.find_changeset_by_name(@rev)
137 end
140 end
138 end
141 end
139
142
140 def is_entry_text_data?(ent, path)
143 def is_entry_text_data?(ent, path)
141 # UTF-16 contains "\x00".
144 # UTF-16 contains "\x00".
142 # It is very strict that file contains less than 30% of ascii symbols
145 # It is very strict that file contains less than 30% of ascii symbols
143 # in non Western Europe.
146 # in non Western Europe.
144 return true if Redmine::MimeType.is_type?('text', path)
147 return true if Redmine::MimeType.is_type?('text', path)
145 # Ruby 1.8.6 has a bug of integer divisions.
148 # Ruby 1.8.6 has a bug of integer divisions.
146 # http://apidock.com/ruby/v1_8_6_287/String/is_binary_data%3F
149 # http://apidock.com/ruby/v1_8_6_287/String/is_binary_data%3F
147 return false if ent.is_binary_data?
150 return false if ent.is_binary_data?
148 true
151 true
149 end
152 end
150 private :is_entry_text_data?
153 private :is_entry_text_data?
151
154
152 def annotate
155 def annotate
153 @entry = @repository.entry(@path, @rev)
156 @entry = @repository.entry(@path, @rev)
154 (show_error_not_found; return) unless @entry
157 (show_error_not_found; return) unless @entry
155
158
156 @annotate = @repository.scm.annotate(@path, @rev)
159 @annotate = @repository.scm.annotate(@path, @rev)
157 (render_error l(:error_scm_annotate); return) if @annotate.nil? || @annotate.empty?
160 (render_error l(:error_scm_annotate); return) if @annotate.nil? || @annotate.empty?
158 @changeset = @repository.find_changeset_by_name(@rev)
161 @changeset = @repository.find_changeset_by_name(@rev)
159 end
162 end
160
163
161 def revision
164 def revision
162 raise ChangesetNotFound if @rev.blank?
165 raise ChangesetNotFound if @rev.blank?
163 @changeset = @repository.find_changeset_by_name(@rev)
166 @changeset = @repository.find_changeset_by_name(@rev)
164 raise ChangesetNotFound unless @changeset
167 raise ChangesetNotFound unless @changeset
165
168
166 respond_to do |format|
169 respond_to do |format|
167 format.html
170 format.html
168 format.js {render :layout => false}
171 format.js {render :layout => false}
169 end
172 end
170 rescue ChangesetNotFound
173 rescue ChangesetNotFound
171 show_error_not_found
174 show_error_not_found
172 end
175 end
173
176
174 def diff
177 def diff
175 if params[:format] == 'diff'
178 if params[:format] == 'diff'
176 @diff = @repository.diff(@path, @rev, @rev_to)
179 @diff = @repository.diff(@path, @rev, @rev_to)
177 (show_error_not_found; return) unless @diff
180 (show_error_not_found; return) unless @diff
178 filename = "changeset_r#{@rev}"
181 filename = "changeset_r#{@rev}"
179 filename << "_r#{@rev_to}" if @rev_to
182 filename << "_r#{@rev_to}" if @rev_to
180 send_data @diff.join, :filename => "#{filename}.diff",
183 send_data @diff.join, :filename => "#{filename}.diff",
181 :type => 'text/x-patch',
184 :type => 'text/x-patch',
182 :disposition => 'attachment'
185 :disposition => 'attachment'
183 else
186 else
184 @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
187 @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
185 @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
188 @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
186
189
187 # Save diff type as user preference
190 # Save diff type as user preference
188 if User.current.logged? && @diff_type != User.current.pref[:diff_type]
191 if User.current.logged? && @diff_type != User.current.pref[:diff_type]
189 User.current.pref[:diff_type] = @diff_type
192 User.current.pref[:diff_type] = @diff_type
190 User.current.preference.save
193 User.current.preference.save
191 end
194 end
192
195
193 @cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
196 @cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
194 unless read_fragment(@cache_key)
197 unless read_fragment(@cache_key)
195 @diff = @repository.diff(@path, @rev, @rev_to)
198 @diff = @repository.diff(@path, @rev, @rev_to)
196 show_error_not_found unless @diff
199 show_error_not_found unless @diff
197 end
200 end
198
201
199 @changeset = @repository.find_changeset_by_name(@rev)
202 @changeset = @repository.find_changeset_by_name(@rev)
200 @changeset_to = @rev_to ? @repository.find_changeset_by_name(@rev_to) : nil
203 @changeset_to = @rev_to ? @repository.find_changeset_by_name(@rev_to) : nil
201 @diff_format_revisions = @repository.diff_format_revisions(@changeset, @changeset_to)
204 @diff_format_revisions = @repository.diff_format_revisions(@changeset, @changeset_to)
202 end
205 end
203 end
206 end
204
207
205 def stats
208 def stats
206 end
209 end
207
210
208 def graph
211 def graph
209 data = nil
212 data = nil
210 case params[:graph]
213 case params[:graph]
211 when "commits_per_month"
214 when "commits_per_month"
212 data = graph_commits_per_month(@repository)
215 data = graph_commits_per_month(@repository)
213 when "commits_per_author"
216 when "commits_per_author"
214 data = graph_commits_per_author(@repository)
217 data = graph_commits_per_author(@repository)
215 end
218 end
216 if data
219 if data
217 headers["Content-Type"] = "image/svg+xml"
220 headers["Content-Type"] = "image/svg+xml"
218 send_data(data, :type => "image/svg+xml", :disposition => "inline")
221 send_data(data, :type => "image/svg+xml", :disposition => "inline")
219 else
222 else
220 render_404
223 render_404
221 end
224 end
222 end
225 end
223
226
224 private
227 private
225
228
226 REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
229 REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
227
230
228 def find_repository
231 def find_repository
229 @project = Project.find(params[:id])
232 @project = Project.find(params[:id])
230 @repository = @project.repository
233 @repository = @project.repository
231 (render_404; return false) unless @repository
234 (render_404; return false) unless @repository
232 @path = params[:path].join('/') unless params[:path].nil?
235 @path = params[:path].join('/') unless params[:path].nil?
233 @path ||= ''
236 @path ||= ''
234 @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].strip
237 @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].strip
235 @rev_to = params[:rev_to]
238 @rev_to = params[:rev_to]
236
239
237 unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE)
240 unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE)
238 if @repository.branches.blank?
241 if @repository.branches.blank?
239 raise InvalidRevisionParam
242 raise InvalidRevisionParam
240 end
243 end
241 end
244 end
242 rescue ActiveRecord::RecordNotFound
245 rescue ActiveRecord::RecordNotFound
243 render_404
246 render_404
244 rescue InvalidRevisionParam
247 rescue InvalidRevisionParam
245 show_error_not_found
248 show_error_not_found
246 end
249 end
247
250
248 def show_error_not_found
251 def show_error_not_found
249 render_error :message => l(:error_scm_not_found), :status => 404
252 render_error :message => l(:error_scm_not_found), :status => 404
250 end
253 end
251
254
252 # Handler for Redmine::Scm::Adapters::CommandFailed exception
255 # Handler for Redmine::Scm::Adapters::CommandFailed exception
253 def show_error_command_failed(exception)
256 def show_error_command_failed(exception)
254 render_error l(:error_scm_command_failed, exception.message)
257 render_error l(:error_scm_command_failed, exception.message)
255 end
258 end
256
259
257 def graph_commits_per_month(repository)
260 def graph_commits_per_month(repository)
258 @date_to = Date.today
261 @date_to = Date.today
259 @date_from = @date_to << 11
262 @date_from = @date_to << 11
260 @date_from = Date.civil(@date_from.year, @date_from.month, 1)
263 @date_from = Date.civil(@date_from.year, @date_from.month, 1)
261 commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
264 commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
262 commits_by_month = [0] * 12
265 commits_by_month = [0] * 12
263 commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
266 commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
264
267
265 changes_by_day = repository.changes.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
268 changes_by_day = repository.changes.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
266 changes_by_month = [0] * 12
269 changes_by_month = [0] * 12
267 changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
270 changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
268
271
269 fields = []
272 fields = []
270 12.times {|m| fields << month_name(((Date.today.month - 1 - m) % 12) + 1)}
273 12.times {|m| fields << month_name(((Date.today.month - 1 - m) % 12) + 1)}
271
274
272 graph = SVG::Graph::Bar.new(
275 graph = SVG::Graph::Bar.new(
273 :height => 300,
276 :height => 300,
274 :width => 800,
277 :width => 800,
275 :fields => fields.reverse,
278 :fields => fields.reverse,
276 :stack => :side,
279 :stack => :side,
277 :scale_integers => true,
280 :scale_integers => true,
278 :step_x_labels => 2,
281 :step_x_labels => 2,
279 :show_data_values => false,
282 :show_data_values => false,
280 :graph_title => l(:label_commits_per_month),
283 :graph_title => l(:label_commits_per_month),
281 :show_graph_title => true
284 :show_graph_title => true
282 )
285 )
283
286
284 graph.add_data(
287 graph.add_data(
285 :data => commits_by_month[0..11].reverse,
288 :data => commits_by_month[0..11].reverse,
286 :title => l(:label_revision_plural)
289 :title => l(:label_revision_plural)
287 )
290 )
288
291
289 graph.add_data(
292 graph.add_data(
290 :data => changes_by_month[0..11].reverse,
293 :data => changes_by_month[0..11].reverse,
291 :title => l(:label_change_plural)
294 :title => l(:label_change_plural)
292 )
295 )
293
296
294 graph.burn
297 graph.burn
295 end
298 end
296
299
297 def graph_commits_per_author(repository)
300 def graph_commits_per_author(repository)
298 commits_by_author = repository.changesets.count(:all, :group => :committer)
301 commits_by_author = repository.changesets.count(:all, :group => :committer)
299 commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}
302 commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}
300
303
301 changes_by_author = repository.changes.count(:all, :group => :committer)
304 changes_by_author = repository.changes.count(:all, :group => :committer)
302 h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
305 h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
303
306
304 fields = commits_by_author.collect {|r| r.first}
307 fields = commits_by_author.collect {|r| r.first}
305 commits_data = commits_by_author.collect {|r| r.last}
308 commits_data = commits_by_author.collect {|r| r.last}
306 changes_data = commits_by_author.collect {|r| h[r.first] || 0}
309 changes_data = commits_by_author.collect {|r| h[r.first] || 0}
307
310
308 fields = fields + [""]*(10 - fields.length) if fields.length<10
311 fields = fields + [""]*(10 - fields.length) if fields.length<10
309 commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
312 commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
310 changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
313 changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
311
314
312 # Remove email adress in usernames
315 # Remove email adress in usernames
313 fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') }
316 fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') }
314
317
315 graph = SVG::Graph::BarHorizontal.new(
318 graph = SVG::Graph::BarHorizontal.new(
316 :height => 400,
319 :height => 400,
317 :width => 800,
320 :width => 800,
318 :fields => fields,
321 :fields => fields,
319 :stack => :side,
322 :stack => :side,
320 :scale_integers => true,
323 :scale_integers => true,
321 :show_data_values => false,
324 :show_data_values => false,
322 :rotate_y_labels => false,
325 :rotate_y_labels => false,
323 :graph_title => l(:label_commits_per_author),
326 :graph_title => l(:label_commits_per_author),
324 :show_graph_title => true
327 :show_graph_title => true
325 )
328 )
326
329
327 graph.add_data(
330 graph.add_data(
328 :data => commits_data,
331 :data => commits_data,
329 :title => l(:label_revision_plural)
332 :title => l(:label_revision_plural)
330 )
333 )
331
334
332 graph.add_data(
335 graph.add_data(
333 :data => changes_data,
336 :data => changes_data,
334 :title => l(:label_change_plural)
337 :title => l(:label_change_plural)
335 )
338 )
336
339
337 graph.burn
340 graph.burn
338 end
341 end
339
342
340 end
343 end
341
344
342 class Date
345 class Date
343 def months_ago(date = Date.today)
346 def months_ago(date = Date.today)
344 (date.year - self.year)*12 + (date.month - self.month)
347 (date.year - self.year)*12 + (date.month - self.month)
345 end
348 end
346
349
347 def weeks_ago(date = Date.today)
350 def weeks_ago(date = Date.today)
348 (date.year - self.year)*52 + (date.cweek - self.cweek)
351 (date.year - self.year)*52 + (date.cweek - self.cweek)
349 end
352 end
350 end
353 end
351
354
352 class String
355 class String
353 def with_leading_slash
356 def with_leading_slash
354 starts_with?('/') ? self : "/#{self}"
357 starts_with?('/') ? self : "/#{self}"
355 end
358 end
356 end
359 end
@@ -1,109 +1,108
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 require 'repositories_controller'
19 require 'repositories_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class RepositoriesController; def rescue_action(e) raise e end; end
22 class RepositoriesController; def rescue_action(e) raise e end; end
23
23
24 class RepositoriesFilesystemControllerTest < ActionController::TestCase
24 class RepositoriesFilesystemControllerTest < ActionController::TestCase
25 fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules
25 fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules
26
26
27 # No '..' in the repository path
27 # No '..' in the repository path
28 REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/filesystem_repository'
28 REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/filesystem_repository'
29 PRJ_ID = 3
29 PRJ_ID = 3
30
30
31 def setup
31 def setup
32 @controller = RepositoriesController.new
32 @controller = RepositoriesController.new
33 @request = ActionController::TestRequest.new
33 @request = ActionController::TestRequest.new
34 @response = ActionController::TestResponse.new
34 @response = ActionController::TestResponse.new
35 User.current = nil
35 User.current = nil
36 Setting.enabled_scm << 'Filesystem' unless Setting.enabled_scm.include?('Filesystem')
36 Setting.enabled_scm << 'Filesystem' unless Setting.enabled_scm.include?('Filesystem')
37 @repository = Repository::Filesystem.create(
37 @repository = Repository::Filesystem.create(
38 :project => Project.find(PRJ_ID),
38 :project => Project.find(PRJ_ID),
39 :url => REPOSITORY_PATH,
39 :url => REPOSITORY_PATH,
40 :path_encoding => ''
40 :path_encoding => ''
41 )
41 )
42 assert @repository
42 assert @repository
43 end
43 end
44
44
45 if File.directory?(REPOSITORY_PATH)
45 if File.directory?(REPOSITORY_PATH)
46 def test_browse_root
46 def test_browse_root
47 @repository.fetch_changesets
47 @repository.fetch_changesets
48 @repository.reload
48 @repository.reload
49 get :show, :id => PRJ_ID
49 get :show, :id => PRJ_ID
50 assert_response :success
50 assert_response :success
51 assert_template 'show'
51 assert_template 'show'
52 assert_not_nil assigns(:entries)
52 assert_not_nil assigns(:entries)
53 assert assigns(:entries).size > 0
53 assert assigns(:entries).size > 0
54 assert_not_nil assigns(:changesets)
54 assert_not_nil assigns(:changesets)
55 assert assigns(:changesets).size == 0
55 assert assigns(:changesets).size == 0
56 end
56 end
57
57
58 def test_show_no_extension
58 def test_show_no_extension
59 get :entry, :id => PRJ_ID, :path => ['test']
59 get :entry, :id => PRJ_ID, :path => ['test']
60 assert_response :success
60 assert_response :success
61 assert_template 'entry'
61 assert_template 'entry'
62 assert_tag :tag => 'th',
62 assert_tag :tag => 'th',
63 :content => '1',
63 :content => '1',
64 :attributes => { :class => 'line-num' },
64 :attributes => { :class => 'line-num' },
65 :sibling => { :tag => 'td', :content => /TEST CAT/ }
65 :sibling => { :tag => 'td', :content => /TEST CAT/ }
66 end
66 end
67
67
68 def test_entry_download_no_extension
68 def test_entry_download_no_extension
69 get :entry, :id => PRJ_ID, :path => ['test'], :format => 'raw'
69 get :entry, :id => PRJ_ID, :path => ['test'], :format => 'raw'
70 assert_response :success
70 assert_response :success
71 assert_equal 'application/octet-stream', @response.content_type
71 assert_equal 'application/octet-stream', @response.content_type
72 end
72 end
73
73
74 def test_show_non_ascii_contents
74 def test_show_non_ascii_contents
75 with_settings :repositories_encodings => 'UTF-8,EUC-JP' do
75 with_settings :repositories_encodings => 'UTF-8,EUC-JP' do
76 get :entry, :id => PRJ_ID, :path => ['japanese', 'euc-jp.txt']
76 get :entry, :id => PRJ_ID, :path => ['japanese', 'euc-jp.txt']
77 assert_response :success
77 assert_response :success
78 assert_template 'entry'
78 assert_template 'entry'
79 assert_tag :tag => 'th',
79 assert_tag :tag => 'th',
80 :content => '2',
80 :content => '2',
81 :attributes => { :class => 'line-num' },
81 :attributes => { :class => 'line-num' },
82 :sibling => { :tag => 'td', :content => /japanese/ }
82 :sibling => { :tag => 'td', :content => /japanese/ }
83 end
83 end
84 end
84 end
85
85
86 def test_show_utf16
86 def test_show_utf16
87 with_settings :repositories_encodings => 'UTF-16' do
87 with_settings :repositories_encodings => 'UTF-16' do
88 get :entry, :id => PRJ_ID, :path => ['japanese', 'utf-16.txt']
88 get :entry, :id => PRJ_ID, :path => ['japanese', 'utf-16.txt']
89 assert_response :success
89 assert_response :success
90 assert_tag :tag => 'th',
90 assert_tag :tag => 'th',
91 :content => '2',
91 :content => '2',
92 :attributes => { :class => 'line-num' },
92 :attributes => { :class => 'line-num' },
93 :sibling => { :tag => 'td', :content => /japanese/ }
93 :sibling => { :tag => 'td', :content => /japanese/ }
94 end
94 end
95 end
95 end
96
96
97 def test_show_text_file_should_send_if_too_big
97 def test_show_text_file_should_send_if_too_big
98 with_settings :file_max_size_displayed => 1 do
98 with_settings :file_max_size_displayed => 1 do
99 get :entry, :id => PRJ_ID, :path => ['japanese', 'big-file.txt']
99 get :entry, :id => PRJ_ID, :path => ['japanese', 'big-file.txt']
100 assert_response :success
100 assert_response :success
101 # TODO: 'text/plain'
101 assert_equal 'text/plain', @response.content_type
102 assert_equal 'application/octet-stream', @response.content_type
103 end
102 end
104 end
103 end
105 else
104 else
106 puts "Filesystem test repository NOT FOUND. Skipping functional tests !!!"
105 puts "Filesystem test repository NOT FOUND. Skipping functional tests !!!"
107 def test_fake; assert true end
106 def test_fake; assert true end
108 end
107 end
109 end
108 end
@@ -1,373 +1,372
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 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 require 'repositories_controller'
19 require 'repositories_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class RepositoriesController; def rescue_action(e) raise e end; end
22 class RepositoriesController; def rescue_action(e) raise e end; end
23
23
24 class RepositoriesMercurialControllerTest < ActionController::TestCase
24 class RepositoriesMercurialControllerTest < ActionController::TestCase
25 fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules
25 fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules
26
26
27 # No '..' in the repository path
27 # No '..' in the repository path
28 REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/mercurial_repository'
28 REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/mercurial_repository'
29 CHAR_1_HEX = "\xc3\x9c"
29 CHAR_1_HEX = "\xc3\x9c"
30 PRJ_ID = 3
30 PRJ_ID = 3
31
31
32 ruby19_non_utf8_pass = (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
32 ruby19_non_utf8_pass = (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
33
33
34 def setup
34 def setup
35 @controller = RepositoriesController.new
35 @controller = RepositoriesController.new
36 @request = ActionController::TestRequest.new
36 @request = ActionController::TestRequest.new
37 @response = ActionController::TestResponse.new
37 @response = ActionController::TestResponse.new
38 User.current = nil
38 User.current = nil
39 @repository = Repository::Mercurial.create(
39 @repository = Repository::Mercurial.create(
40 :project => Project.find(PRJ_ID),
40 :project => Project.find(PRJ_ID),
41 :url => REPOSITORY_PATH,
41 :url => REPOSITORY_PATH,
42 :path_encoding => 'ISO-8859-1'
42 :path_encoding => 'ISO-8859-1'
43 )
43 )
44 assert @repository
44 assert @repository
45 @diff_c_support = true
45 @diff_c_support = true
46 @char_1 = CHAR_1_HEX.dup
46 @char_1 = CHAR_1_HEX.dup
47 @tag_char_1 = "tag-#{CHAR_1_HEX}-00"
47 @tag_char_1 = "tag-#{CHAR_1_HEX}-00"
48 @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
48 @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
49 @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
49 @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
50 if @char_1.respond_to?(:force_encoding)
50 if @char_1.respond_to?(:force_encoding)
51 @char_1.force_encoding('UTF-8')
51 @char_1.force_encoding('UTF-8')
52 @tag_char_1.force_encoding('UTF-8')
52 @tag_char_1.force_encoding('UTF-8')
53 @branch_char_0.force_encoding('UTF-8')
53 @branch_char_0.force_encoding('UTF-8')
54 @branch_char_1.force_encoding('UTF-8')
54 @branch_char_1.force_encoding('UTF-8')
55 end
55 end
56 end
56 end
57
57
58 if ruby19_non_utf8_pass
58 if ruby19_non_utf8_pass
59 puts "TODO: Mercurial functional test fails in Ruby 1.9 " +
59 puts "TODO: Mercurial functional test fails in Ruby 1.9 " +
60 "and Encoding.default_external is not UTF-8. " +
60 "and Encoding.default_external is not UTF-8. " +
61 "Current value is '#{Encoding.default_external.to_s}'"
61 "Current value is '#{Encoding.default_external.to_s}'"
62 def test_fake; assert true end
62 def test_fake; assert true end
63 elsif File.directory?(REPOSITORY_PATH)
63 elsif File.directory?(REPOSITORY_PATH)
64 def test_show_root
64 def test_show_root
65 @repository.fetch_changesets
65 @repository.fetch_changesets
66 @repository.reload
66 @repository.reload
67 get :show, :id => PRJ_ID
67 get :show, :id => PRJ_ID
68 assert_response :success
68 assert_response :success
69 assert_template 'show'
69 assert_template 'show'
70 assert_not_nil assigns(:entries)
70 assert_not_nil assigns(:entries)
71 assert_equal 4, assigns(:entries).size
71 assert_equal 4, assigns(:entries).size
72 assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
72 assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
73 assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
73 assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
74 assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
74 assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
75 assert_not_nil assigns(:changesets)
75 assert_not_nil assigns(:changesets)
76 assigns(:changesets).size > 0
76 assigns(:changesets).size > 0
77 end
77 end
78
78
79 def test_show_directory
79 def test_show_directory
80 @repository.fetch_changesets
80 @repository.fetch_changesets
81 @repository.reload
81 @repository.reload
82 get :show, :id => PRJ_ID, :path => ['images']
82 get :show, :id => PRJ_ID, :path => ['images']
83 assert_response :success
83 assert_response :success
84 assert_template 'show'
84 assert_template 'show'
85 assert_not_nil assigns(:entries)
85 assert_not_nil assigns(:entries)
86 assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
86 assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
87 entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
87 entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
88 assert_not_nil entry
88 assert_not_nil entry
89 assert_equal 'file', entry.kind
89 assert_equal 'file', entry.kind
90 assert_equal 'images/edit.png', entry.path
90 assert_equal 'images/edit.png', entry.path
91 assert_not_nil assigns(:changesets)
91 assert_not_nil assigns(:changesets)
92 assigns(:changesets).size > 0
92 assigns(:changesets).size > 0
93 end
93 end
94
94
95 def test_show_at_given_revision
95 def test_show_at_given_revision
96 @repository.fetch_changesets
96 @repository.fetch_changesets
97 @repository.reload
97 @repository.reload
98 [0, '0', '0885933ad4f6'].each do |r1|
98 [0, '0', '0885933ad4f6'].each do |r1|
99 get :show, :id => PRJ_ID, :path => ['images'], :rev => r1
99 get :show, :id => PRJ_ID, :path => ['images'], :rev => r1
100 assert_response :success
100 assert_response :success
101 assert_template 'show'
101 assert_template 'show'
102 assert_not_nil assigns(:entries)
102 assert_not_nil assigns(:entries)
103 assert_equal ['delete.png'], assigns(:entries).collect(&:name)
103 assert_equal ['delete.png'], assigns(:entries).collect(&:name)
104 assert_not_nil assigns(:changesets)
104 assert_not_nil assigns(:changesets)
105 assigns(:changesets).size > 0
105 assigns(:changesets).size > 0
106 end
106 end
107 end
107 end
108
108
109 def test_show_directory_sql_escape_percent
109 def test_show_directory_sql_escape_percent
110 @repository.fetch_changesets
110 @repository.fetch_changesets
111 @repository.reload
111 @repository.reload
112 [13, '13', '3a330eb32958'].each do |r1|
112 [13, '13', '3a330eb32958'].each do |r1|
113 get :show, :id => PRJ_ID, :path => ['sql_escape', 'percent%dir'], :rev => r1
113 get :show, :id => PRJ_ID, :path => ['sql_escape', 'percent%dir'], :rev => r1
114 assert_response :success
114 assert_response :success
115 assert_template 'show'
115 assert_template 'show'
116
116
117 assert_not_nil assigns(:entries)
117 assert_not_nil assigns(:entries)
118 assert_equal ['percent%file1.txt', 'percentfile1.txt'], assigns(:entries).collect(&:name)
118 assert_equal ['percent%file1.txt', 'percentfile1.txt'], assigns(:entries).collect(&:name)
119 changesets = assigns(:changesets)
119 changesets = assigns(:changesets)
120 assert_not_nil changesets
120 assert_not_nil changesets
121 assigns(:changesets).size > 0
121 assigns(:changesets).size > 0
122 assert_equal %w(13 11 10 9), changesets.collect(&:revision)
122 assert_equal %w(13 11 10 9), changesets.collect(&:revision)
123 end
123 end
124 end
124 end
125
125
126 def test_show_directory_latin_1
126 def test_show_directory_latin_1
127 @repository.fetch_changesets
127 @repository.fetch_changesets
128 @repository.reload
128 @repository.reload
129 [21, '21', 'adf805632193'].each do |r1|
129 [21, '21', 'adf805632193'].each do |r1|
130 get :show, :id => PRJ_ID, :path => ['latin-1-dir'], :rev => r1
130 get :show, :id => PRJ_ID, :path => ['latin-1-dir'], :rev => r1
131 assert_response :success
131 assert_response :success
132 assert_template 'show'
132 assert_template 'show'
133
133
134 assert_not_nil assigns(:entries)
134 assert_not_nil assigns(:entries)
135 assert_equal ["make-latin-1-file.rb",
135 assert_equal ["make-latin-1-file.rb",
136 "test-#{@char_1}-1.txt",
136 "test-#{@char_1}-1.txt",
137 "test-#{@char_1}-2.txt",
137 "test-#{@char_1}-2.txt",
138 "test-#{@char_1}.txt"], assigns(:entries).collect(&:name)
138 "test-#{@char_1}.txt"], assigns(:entries).collect(&:name)
139 changesets = assigns(:changesets)
139 changesets = assigns(:changesets)
140 assert_not_nil changesets
140 assert_not_nil changesets
141 assert_equal %w(21 20 19 18 17), changesets.collect(&:revision)
141 assert_equal %w(21 20 19 18 17), changesets.collect(&:revision)
142 end
142 end
143 end
143 end
144
144
145 def test_show_branch
145 def test_show_branch
146 @repository.fetch_changesets
146 @repository.fetch_changesets
147 @repository.reload
147 @repository.reload
148 [
148 [
149 'default',
149 'default',
150 @branch_char_1,
150 @branch_char_1,
151 'branch (1)[2]&,%.-3_4',
151 'branch (1)[2]&,%.-3_4',
152 @branch_char_0,
152 @branch_char_0,
153 'test_branch.latin-1',
153 'test_branch.latin-1',
154 'test-branch-00',
154 'test-branch-00',
155 ].each do |bra|
155 ].each do |bra|
156 get :show, :id => PRJ_ID, :rev => bra
156 get :show, :id => PRJ_ID, :rev => bra
157 assert_response :success
157 assert_response :success
158 assert_template 'show'
158 assert_template 'show'
159 assert_not_nil assigns(:entries)
159 assert_not_nil assigns(:entries)
160 assert assigns(:entries).size > 0
160 assert assigns(:entries).size > 0
161 assert_not_nil assigns(:changesets)
161 assert_not_nil assigns(:changesets)
162 assigns(:changesets).size > 0
162 assigns(:changesets).size > 0
163 end
163 end
164 end
164 end
165
165
166 def test_show_tag
166 def test_show_tag
167 @repository.fetch_changesets
167 @repository.fetch_changesets
168 @repository.reload
168 @repository.reload
169 [
169 [
170 @tag_char_1,
170 @tag_char_1,
171 'tag_test.00',
171 'tag_test.00',
172 'tag-init-revision'
172 'tag-init-revision'
173 ].each do |tag|
173 ].each do |tag|
174 get :show, :id => PRJ_ID, :rev => tag
174 get :show, :id => PRJ_ID, :rev => tag
175 assert_response :success
175 assert_response :success
176 assert_template 'show'
176 assert_template 'show'
177 assert_not_nil assigns(:entries)
177 assert_not_nil assigns(:entries)
178 assert assigns(:entries).size > 0
178 assert assigns(:entries).size > 0
179 assert_not_nil assigns(:changesets)
179 assert_not_nil assigns(:changesets)
180 assigns(:changesets).size > 0
180 assigns(:changesets).size > 0
181 end
181 end
182 end
182 end
183
183
184 def test_changes
184 def test_changes
185 get :changes, :id => PRJ_ID, :path => ['images', 'edit.png']
185 get :changes, :id => PRJ_ID, :path => ['images', 'edit.png']
186 assert_response :success
186 assert_response :success
187 assert_template 'changes'
187 assert_template 'changes'
188 assert_tag :tag => 'h2', :content => 'edit.png'
188 assert_tag :tag => 'h2', :content => 'edit.png'
189 end
189 end
190
190
191 def test_entry_show
191 def test_entry_show
192 get :entry, :id => PRJ_ID, :path => ['sources', 'watchers_controller.rb']
192 get :entry, :id => PRJ_ID, :path => ['sources', 'watchers_controller.rb']
193 assert_response :success
193 assert_response :success
194 assert_template 'entry'
194 assert_template 'entry'
195 # Line 10
195 # Line 10
196 assert_tag :tag => 'th',
196 assert_tag :tag => 'th',
197 :content => '10',
197 :content => '10',
198 :attributes => { :class => 'line-num' },
198 :attributes => { :class => 'line-num' },
199 :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
199 :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
200 end
200 end
201
201
202 def test_entry_show_latin_1
202 def test_entry_show_latin_1
203 [21, '21', 'adf805632193'].each do |r1|
203 [21, '21', 'adf805632193'].each do |r1|
204 get :entry, :id => PRJ_ID, :path => ['latin-1-dir', "test-#{@char_1}-2.txt"], :rev => r1
204 get :entry, :id => PRJ_ID, :path => ['latin-1-dir', "test-#{@char_1}-2.txt"], :rev => r1
205 assert_response :success
205 assert_response :success
206 assert_template 'entry'
206 assert_template 'entry'
207 assert_tag :tag => 'th',
207 assert_tag :tag => 'th',
208 :content => '1',
208 :content => '1',
209 :attributes => { :class => 'line-num' },
209 :attributes => { :class => 'line-num' },
210 :sibling => { :tag => 'td',
210 :sibling => { :tag => 'td',
211 :content => /Mercurial is a distributed version control system/ }
211 :content => /Mercurial is a distributed version control system/ }
212 end
212 end
213 end
213 end
214
214
215 def test_entry_download
215 def test_entry_download
216 get :entry, :id => PRJ_ID, :path => ['sources', 'watchers_controller.rb'], :format => 'raw'
216 get :entry, :id => PRJ_ID, :path => ['sources', 'watchers_controller.rb'], :format => 'raw'
217 assert_response :success
217 assert_response :success
218 # File content
218 # File content
219 assert @response.body.include?('WITHOUT ANY WARRANTY')
219 assert @response.body.include?('WITHOUT ANY WARRANTY')
220 end
220 end
221
221
222 def test_entry_binary_force_download
222 def test_entry_binary_force_download
223 get :entry, :id => PRJ_ID, :rev => 1, :path => ['images', 'edit.png']
223 get :entry, :id => PRJ_ID, :rev => 1, :path => ['images', 'edit.png']
224 assert_response :success
224 assert_response :success
225 # TODO: 'image/png'
225 assert_equal 'image/png', @response.content_type
226 assert_equal 'application/octet-stream', @response.content_type
227 end
226 end
228
227
229 def test_directory_entry
228 def test_directory_entry
230 get :entry, :id => PRJ_ID, :path => ['sources']
229 get :entry, :id => PRJ_ID, :path => ['sources']
231 assert_response :success
230 assert_response :success
232 assert_template 'show'
231 assert_template 'show'
233 assert_not_nil assigns(:entry)
232 assert_not_nil assigns(:entry)
234 assert_equal 'sources', assigns(:entry).name
233 assert_equal 'sources', assigns(:entry).name
235 end
234 end
236
235
237 def test_diff
236 def test_diff
238 @repository.fetch_changesets
237 @repository.fetch_changesets
239 @repository.reload
238 @repository.reload
240 [4, '4', 'def6d2f1254a'].each do |r1|
239 [4, '4', 'def6d2f1254a'].each do |r1|
241 # Full diff of changeset 4
240 # Full diff of changeset 4
242 get :diff, :id => PRJ_ID, :rev => r1
241 get :diff, :id => PRJ_ID, :rev => r1
243 assert_response :success
242 assert_response :success
244 assert_template 'diff'
243 assert_template 'diff'
245 if @diff_c_support
244 if @diff_c_support
246 # Line 22 removed
245 # Line 22 removed
247 assert_tag :tag => 'th',
246 assert_tag :tag => 'th',
248 :content => '22',
247 :content => '22',
249 :sibling => { :tag => 'td',
248 :sibling => { :tag => 'td',
250 :attributes => { :class => /diff_out/ },
249 :attributes => { :class => /diff_out/ },
251 :content => /def remove/ }
250 :content => /def remove/ }
252 assert_tag :tag => 'h2', :content => /4:def6d2f1254a/
251 assert_tag :tag => 'h2', :content => /4:def6d2f1254a/
253 end
252 end
254 end
253 end
255 end
254 end
256
255
257 def test_diff_two_revs
256 def test_diff_two_revs
258 @repository.fetch_changesets
257 @repository.fetch_changesets
259 @repository.reload
258 @repository.reload
260 [2, '400bb8672109', '400', 400].each do |r1|
259 [2, '400bb8672109', '400', 400].each do |r1|
261 [4, 'def6d2f1254a'].each do |r2|
260 [4, 'def6d2f1254a'].each do |r2|
262 get :diff, :id => PRJ_ID, :rev => r1,
261 get :diff, :id => PRJ_ID, :rev => r1,
263 :rev_to => r2
262 :rev_to => r2
264 assert_response :success
263 assert_response :success
265 assert_template 'diff'
264 assert_template 'diff'
266
265
267 diff = assigns(:diff)
266 diff = assigns(:diff)
268 assert_not_nil diff
267 assert_not_nil diff
269 assert_tag :tag => 'h2', :content => /4:def6d2f1254a 2:400bb8672109/
268 assert_tag :tag => 'h2', :content => /4:def6d2f1254a 2:400bb8672109/
270 end
269 end
271 end
270 end
272 end
271 end
273
272
274 def test_diff_latin_1
273 def test_diff_latin_1
275 [21, 'adf805632193'].each do |r1|
274 [21, 'adf805632193'].each do |r1|
276 get :diff, :id => PRJ_ID, :rev => r1
275 get :diff, :id => PRJ_ID, :rev => r1
277 assert_response :success
276 assert_response :success
278 assert_template 'diff'
277 assert_template 'diff'
279 assert_tag :tag => 'th',
278 assert_tag :tag => 'th',
280 :content => '2',
279 :content => '2',
281 :sibling => { :tag => 'td',
280 :sibling => { :tag => 'td',
282 :attributes => { :class => /diff_in/ },
281 :attributes => { :class => /diff_in/ },
283 :content => /It is written in Python/ }
282 :content => /It is written in Python/ }
284 end
283 end
285 end
284 end
286
285
287 def test_annotate
286 def test_annotate
288 get :annotate, :id => PRJ_ID, :path => ['sources', 'watchers_controller.rb']
287 get :annotate, :id => PRJ_ID, :path => ['sources', 'watchers_controller.rb']
289 assert_response :success
288 assert_response :success
290 assert_template 'annotate'
289 assert_template 'annotate'
291 # Line 23, revision 4:def6d2f1254a
290 # Line 23, revision 4:def6d2f1254a
292 assert_tag :tag => 'th',
291 assert_tag :tag => 'th',
293 :content => '23',
292 :content => '23',
294 :attributes => { :class => 'line-num' },
293 :attributes => { :class => 'line-num' },
295 :sibling =>
294 :sibling =>
296 {
295 {
297 :tag => 'td',
296 :tag => 'td',
298 :attributes => { :class => 'revision' },
297 :attributes => { :class => 'revision' },
299 :child => { :tag => 'a', :content => '4:def6d2f1254a' }
298 :child => { :tag => 'a', :content => '4:def6d2f1254a' }
300 }
299 }
301 assert_tag :tag => 'th',
300 assert_tag :tag => 'th',
302 :content => '23',
301 :content => '23',
303 :attributes => { :class => 'line-num' },
302 :attributes => { :class => 'line-num' },
304 :sibling =>
303 :sibling =>
305 {
304 {
306 :tag => 'td' ,
305 :tag => 'td' ,
307 :content => 'jsmith' ,
306 :content => 'jsmith' ,
308 :attributes => { :class => 'author' },
307 :attributes => { :class => 'author' },
309 }
308 }
310 assert_tag :tag => 'th',
309 assert_tag :tag => 'th',
311 :content => '23',
310 :content => '23',
312 :attributes => { :class => 'line-num' },
311 :attributes => { :class => 'line-num' },
313 :sibling => { :tag => 'td', :content => /watcher =/ }
312 :sibling => { :tag => 'td', :content => /watcher =/ }
314 end
313 end
315
314
316 def test_annotate_at_given_revision
315 def test_annotate_at_given_revision
317 @repository.fetch_changesets
316 @repository.fetch_changesets
318 @repository.reload
317 @repository.reload
319 [2, '400bb8672109', '400', 400].each do |r1|
318 [2, '400bb8672109', '400', 400].each do |r1|
320 get :annotate, :id => PRJ_ID, :rev => r1, :path => ['sources', 'watchers_controller.rb']
319 get :annotate, :id => PRJ_ID, :rev => r1, :path => ['sources', 'watchers_controller.rb']
321 assert_response :success
320 assert_response :success
322 assert_template 'annotate'
321 assert_template 'annotate'
323 assert_tag :tag => 'h2', :content => /@ 2:400bb8672109/
322 assert_tag :tag => 'h2', :content => /@ 2:400bb8672109/
324 end
323 end
325 end
324 end
326
325
327 def test_annotate_latin_1
326 def test_annotate_latin_1
328 [21, '21', 'adf805632193'].each do |r1|
327 [21, '21', 'adf805632193'].each do |r1|
329 get :annotate, :id => PRJ_ID, :path => ['latin-1-dir', "test-#{@char_1}-2.txt"], :rev => r1
328 get :annotate, :id => PRJ_ID, :path => ['latin-1-dir', "test-#{@char_1}-2.txt"], :rev => r1
330 assert_response :success
329 assert_response :success
331 assert_template 'annotate'
330 assert_template 'annotate'
332 assert_tag :tag => 'th',
331 assert_tag :tag => 'th',
333 :content => '1',
332 :content => '1',
334 :attributes => { :class => 'line-num' },
333 :attributes => { :class => 'line-num' },
335 :sibling =>
334 :sibling =>
336 {
335 {
337 :tag => 'td',
336 :tag => 'td',
338 :attributes => { :class => 'revision' },
337 :attributes => { :class => 'revision' },
339 :child => { :tag => 'a', :content => '20:709858aafd1b' }
338 :child => { :tag => 'a', :content => '20:709858aafd1b' }
340 }
339 }
341 assert_tag :tag => 'th',
340 assert_tag :tag => 'th',
342 :content => '1',
341 :content => '1',
343 :attributes => { :class => 'line-num' },
342 :attributes => { :class => 'line-num' },
344 :sibling =>
343 :sibling =>
345 {
344 {
346 :tag => 'td' ,
345 :tag => 'td' ,
347 :content => 'jsmith' ,
346 :content => 'jsmith' ,
348 :attributes => { :class => 'author' },
347 :attributes => { :class => 'author' },
349
348
350 }
349 }
351 assert_tag :tag => 'th',
350 assert_tag :tag => 'th',
352 :content => '1',
351 :content => '1',
353 :attributes => { :class => 'line-num' },
352 :attributes => { :class => 'line-num' },
354 :sibling => { :tag => 'td',
353 :sibling => { :tag => 'td',
355 :content => /Mercurial is a distributed version control system/ }
354 :content => /Mercurial is a distributed version control system/ }
356
355
357 end
356 end
358 end
357 end
359
358
360 def test_empty_revision
359 def test_empty_revision
361 @repository.fetch_changesets
360 @repository.fetch_changesets
362 @repository.reload
361 @repository.reload
363 ['', ' ', nil].each do |r|
362 ['', ' ', nil].each do |r|
364 get :revision, :id => PRJ_ID, :rev => r
363 get :revision, :id => PRJ_ID, :rev => r
365 assert_response 404
364 assert_response 404
366 assert_error_tag :content => /was not found/
365 assert_error_tag :content => /was not found/
367 end
366 end
368 end
367 end
369 else
368 else
370 puts "Mercurial test repository NOT FOUND. Skipping functional tests !!!"
369 puts "Mercurial test repository NOT FOUND. Skipping functional tests !!!"
371 def test_fake; assert true end
370 def test_fake; assert true end
372 end
371 end
373 end
372 end
General Comments 0
You need to be logged in to leave comments. Login now