##// END OF EJS Templates
Fixed: empty lines when displaying repository files with Windows style eol....
Jean-Philippe Lang -
r980:38b185f1dc4d
parent child
Show More
@@ -1,277 +1,280
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 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
22 class ChangesetNotFound < Exception
23 end
23 end
24
24
25 class RepositoriesController < ApplicationController
25 class RepositoriesController < ApplicationController
26 layout 'base'
26 layout 'base'
27 before_filter :find_repository, :except => :edit
27 before_filter :find_repository, :except => :edit
28 before_filter :find_project, :only => :edit
28 before_filter :find_project, :only => :edit
29 before_filter :authorize
29 before_filter :authorize
30 accept_key_auth :revisions
30 accept_key_auth :revisions
31
31
32 def edit
32 def edit
33 @repository = @project.repository
33 @repository = @project.repository
34 if !@repository
34 if !@repository
35 @repository = Repository.factory(params[:repository_scm])
35 @repository = Repository.factory(params[:repository_scm])
36 @repository.project = @project
36 @repository.project = @project
37 end
37 end
38 if request.post?
38 if request.post?
39 @repository.attributes = params[:repository]
39 @repository.attributes = params[:repository]
40 @repository.save
40 @repository.save
41 end
41 end
42 render(:update) {|page| page.replace_html "tab-content-repository", :partial => 'projects/settings/repository'}
42 render(:update) {|page| page.replace_html "tab-content-repository", :partial => 'projects/settings/repository'}
43 end
43 end
44
44
45 def destroy
45 def destroy
46 @repository.destroy
46 @repository.destroy
47 redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'repository'
47 redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'repository'
48 end
48 end
49
49
50 def show
50 def show
51 # check if new revisions have been committed in the repository
51 # check if new revisions have been committed in the repository
52 @repository.fetch_changesets if Setting.autofetch_changesets?
52 @repository.fetch_changesets if Setting.autofetch_changesets?
53 # get entries for the browse frame
53 # get entries for the browse frame
54 @entries = @repository.entries('')
54 @entries = @repository.entries('')
55 # latest changesets
55 # latest changesets
56 @changesets = @repository.changesets.find(:all, :limit => 10, :order => "committed_on DESC")
56 @changesets = @repository.changesets.find(:all, :limit => 10, :order => "committed_on DESC")
57 show_error and return unless @entries || @changesets.any?
57 show_error and return unless @entries || @changesets.any?
58 end
58 end
59
59
60 def browse
60 def browse
61 @entries = @repository.entries(@path, @rev)
61 @entries = @repository.entries(@path, @rev)
62 if request.xhr?
62 if request.xhr?
63 @entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
63 @entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
64 else
64 else
65 show_error unless @entries
65 show_error unless @entries
66 end
66 end
67 end
67 end
68
68
69 def changes
69 def changes
70 @entry = @repository.scm.entry(@path, @rev)
70 @entry = @repository.scm.entry(@path, @rev)
71 show_error and return unless @entry
71 show_error and return unless @entry
72 @changesets = @repository.changesets_for_path(@path)
72 @changesets = @repository.changesets_for_path(@path)
73 end
73 end
74
74
75 def revisions
75 def revisions
76 @changeset_count = @repository.changesets.count
76 @changeset_count = @repository.changesets.count
77 @changeset_pages = Paginator.new self, @changeset_count,
77 @changeset_pages = Paginator.new self, @changeset_count,
78 25,
78 25,
79 params['page']
79 params['page']
80 @changesets = @repository.changesets.find(:all,
80 @changesets = @repository.changesets.find(:all,
81 :limit => @changeset_pages.items_per_page,
81 :limit => @changeset_pages.items_per_page,
82 :offset => @changeset_pages.current.offset)
82 :offset => @changeset_pages.current.offset)
83
83
84 respond_to do |format|
84 respond_to do |format|
85 format.html { render :layout => false if request.xhr? }
85 format.html { render :layout => false if request.xhr? }
86 format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") }
86 format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") }
87 end
87 end
88 end
88 end
89
89
90 def entry
90 def entry
91 @content = @repository.scm.cat(@path, @rev)
91 @content = @repository.scm.cat(@path, @rev)
92 show_error and return unless @content
92 show_error and return unless @content
93 if 'raw' == params[:format]
93 if 'raw' == params[:format]
94 send_data @content, :filename => @path.split('/').last
94 send_data @content, :filename => @path.split('/').last
95 else
96 # Prevent empty lines when displaying a file with Windows style eol
97 @content.gsub!("\r\n", "\n")
95 end
98 end
96 end
99 end
97
100
98 def annotate
101 def annotate
99 @annotate = @repository.scm.annotate(@path, @rev)
102 @annotate = @repository.scm.annotate(@path, @rev)
100 show_error and return if @annotate.nil? || @annotate.empty?
103 show_error and return if @annotate.nil? || @annotate.empty?
101 end
104 end
102
105
103 def revision
106 def revision
104 @changeset = @repository.changesets.find_by_revision(@rev)
107 @changeset = @repository.changesets.find_by_revision(@rev)
105 raise ChangesetNotFound unless @changeset
108 raise ChangesetNotFound unless @changeset
106 @changes_count = @changeset.changes.size
109 @changes_count = @changeset.changes.size
107 @changes_pages = Paginator.new self, @changes_count, 150, params['page']
110 @changes_pages = Paginator.new self, @changes_count, 150, params['page']
108 @changes = @changeset.changes.find(:all,
111 @changes = @changeset.changes.find(:all,
109 :limit => @changes_pages.items_per_page,
112 :limit => @changes_pages.items_per_page,
110 :offset => @changes_pages.current.offset)
113 :offset => @changes_pages.current.offset)
111
114
112 respond_to do |format|
115 respond_to do |format|
113 format.html
116 format.html
114 format.js {render :layout => false}
117 format.js {render :layout => false}
115 end
118 end
116 rescue ChangesetNotFound
119 rescue ChangesetNotFound
117 show_error
120 show_error
118 end
121 end
119
122
120 def diff
123 def diff
121 @rev_to = params[:rev_to] ? params[:rev_to].to_i : (@rev - 1)
124 @rev_to = params[:rev_to] ? params[:rev_to].to_i : (@rev - 1)
122 @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
125 @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
123 @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
126 @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
124
127
125 # Save diff type as user preference
128 # Save diff type as user preference
126 if User.current.logged? && @diff_type != User.current.pref[:diff_type]
129 if User.current.logged? && @diff_type != User.current.pref[:diff_type]
127 User.current.pref[:diff_type] = @diff_type
130 User.current.pref[:diff_type] = @diff_type
128 User.current.preference.save
131 User.current.preference.save
129 end
132 end
130
133
131 @cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
134 @cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
132 unless read_fragment(@cache_key)
135 unless read_fragment(@cache_key)
133 @diff = @repository.diff(@path, @rev, @rev_to, @diff_type)
136 @diff = @repository.diff(@path, @rev, @rev_to, @diff_type)
134 show_error and return unless @diff
137 show_error and return unless @diff
135 end
138 end
136 end
139 end
137
140
138 def stats
141 def stats
139 end
142 end
140
143
141 def graph
144 def graph
142 data = nil
145 data = nil
143 case params[:graph]
146 case params[:graph]
144 when "commits_per_month"
147 when "commits_per_month"
145 data = graph_commits_per_month(@repository)
148 data = graph_commits_per_month(@repository)
146 when "commits_per_author"
149 when "commits_per_author"
147 data = graph_commits_per_author(@repository)
150 data = graph_commits_per_author(@repository)
148 end
151 end
149 if data
152 if data
150 headers["Content-Type"] = "image/svg+xml"
153 headers["Content-Type"] = "image/svg+xml"
151 send_data(data, :type => "image/svg+xml", :disposition => "inline")
154 send_data(data, :type => "image/svg+xml", :disposition => "inline")
152 else
155 else
153 render_404
156 render_404
154 end
157 end
155 end
158 end
156
159
157 private
160 private
158 def find_project
161 def find_project
159 @project = Project.find(params[:id])
162 @project = Project.find(params[:id])
160 rescue ActiveRecord::RecordNotFound
163 rescue ActiveRecord::RecordNotFound
161 render_404
164 render_404
162 end
165 end
163
166
164 def find_repository
167 def find_repository
165 @project = Project.find(params[:id])
168 @project = Project.find(params[:id])
166 @repository = @project.repository
169 @repository = @project.repository
167 render_404 and return false unless @repository
170 render_404 and return false unless @repository
168 @path = params[:path].join('/') unless params[:path].nil?
171 @path = params[:path].join('/') unless params[:path].nil?
169 @path ||= ''
172 @path ||= ''
170 @rev = params[:rev].to_i if params[:rev]
173 @rev = params[:rev].to_i if params[:rev]
171 rescue ActiveRecord::RecordNotFound
174 rescue ActiveRecord::RecordNotFound
172 render_404
175 render_404
173 end
176 end
174
177
175 def show_error
178 def show_error
176 flash.now[:error] = l(:notice_scm_error)
179 flash.now[:error] = l(:notice_scm_error)
177 render :nothing => true, :layout => true
180 render :nothing => true, :layout => true
178 end
181 end
179
182
180 def graph_commits_per_month(repository)
183 def graph_commits_per_month(repository)
181 @date_to = Date.today
184 @date_to = Date.today
182 @date_from = @date_to << 11
185 @date_from = @date_to << 11
183 @date_from = Date.civil(@date_from.year, @date_from.month, 1)
186 @date_from = Date.civil(@date_from.year, @date_from.month, 1)
184 commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
187 commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
185 commits_by_month = [0] * 12
188 commits_by_month = [0] * 12
186 commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
189 commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
187
190
188 changes_by_day = repository.changes.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
191 changes_by_day = repository.changes.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
189 changes_by_month = [0] * 12
192 changes_by_month = [0] * 12
190 changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
193 changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
191
194
192 fields = []
195 fields = []
193 month_names = l(:actionview_datehelper_select_month_names_abbr).split(',')
196 month_names = l(:actionview_datehelper_select_month_names_abbr).split(',')
194 12.times {|m| fields << month_names[((Date.today.month - 1 - m) % 12)]}
197 12.times {|m| fields << month_names[((Date.today.month - 1 - m) % 12)]}
195
198
196 graph = SVG::Graph::Bar.new(
199 graph = SVG::Graph::Bar.new(
197 :height => 300,
200 :height => 300,
198 :width => 500,
201 :width => 500,
199 :fields => fields.reverse,
202 :fields => fields.reverse,
200 :stack => :side,
203 :stack => :side,
201 :scale_integers => true,
204 :scale_integers => true,
202 :step_x_labels => 2,
205 :step_x_labels => 2,
203 :show_data_values => false,
206 :show_data_values => false,
204 :graph_title => l(:label_commits_per_month),
207 :graph_title => l(:label_commits_per_month),
205 :show_graph_title => true
208 :show_graph_title => true
206 )
209 )
207
210
208 graph.add_data(
211 graph.add_data(
209 :data => commits_by_month[0..11].reverse,
212 :data => commits_by_month[0..11].reverse,
210 :title => l(:label_revision_plural)
213 :title => l(:label_revision_plural)
211 )
214 )
212
215
213 graph.add_data(
216 graph.add_data(
214 :data => changes_by_month[0..11].reverse,
217 :data => changes_by_month[0..11].reverse,
215 :title => l(:label_change_plural)
218 :title => l(:label_change_plural)
216 )
219 )
217
220
218 graph.burn
221 graph.burn
219 end
222 end
220
223
221 def graph_commits_per_author(repository)
224 def graph_commits_per_author(repository)
222 commits_by_author = repository.changesets.count(:all, :group => :committer)
225 commits_by_author = repository.changesets.count(:all, :group => :committer)
223 commits_by_author.sort! {|x, y| x.last <=> y.last}
226 commits_by_author.sort! {|x, y| x.last <=> y.last}
224
227
225 changes_by_author = repository.changes.count(:all, :group => :committer)
228 changes_by_author = repository.changes.count(:all, :group => :committer)
226 h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
229 h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
227
230
228 fields = commits_by_author.collect {|r| r.first}
231 fields = commits_by_author.collect {|r| r.first}
229 commits_data = commits_by_author.collect {|r| r.last}
232 commits_data = commits_by_author.collect {|r| r.last}
230 changes_data = commits_by_author.collect {|r| h[r.first] || 0}
233 changes_data = commits_by_author.collect {|r| h[r.first] || 0}
231
234
232 fields = fields + [""]*(10 - fields.length) if fields.length<10
235 fields = fields + [""]*(10 - fields.length) if fields.length<10
233 commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
236 commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
234 changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
237 changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
235
238
236 graph = SVG::Graph::BarHorizontal.new(
239 graph = SVG::Graph::BarHorizontal.new(
237 :height => 300,
240 :height => 300,
238 :width => 500,
241 :width => 500,
239 :fields => fields,
242 :fields => fields,
240 :stack => :side,
243 :stack => :side,
241 :scale_integers => true,
244 :scale_integers => true,
242 :show_data_values => false,
245 :show_data_values => false,
243 :rotate_y_labels => false,
246 :rotate_y_labels => false,
244 :graph_title => l(:label_commits_per_author),
247 :graph_title => l(:label_commits_per_author),
245 :show_graph_title => true
248 :show_graph_title => true
246 )
249 )
247
250
248 graph.add_data(
251 graph.add_data(
249 :data => commits_data,
252 :data => commits_data,
250 :title => l(:label_revision_plural)
253 :title => l(:label_revision_plural)
251 )
254 )
252
255
253 graph.add_data(
256 graph.add_data(
254 :data => changes_data,
257 :data => changes_data,
255 :title => l(:label_change_plural)
258 :title => l(:label_change_plural)
256 )
259 )
257
260
258 graph.burn
261 graph.burn
259 end
262 end
260
263
261 end
264 end
262
265
263 class Date
266 class Date
264 def months_ago(date = Date.today)
267 def months_ago(date = Date.today)
265 (date.year - self.year)*12 + (date.month - self.month)
268 (date.year - self.year)*12 + (date.month - self.month)
266 end
269 end
267
270
268 def weeks_ago(date = Date.today)
271 def weeks_ago(date = Date.today)
269 (date.year - self.year)*52 + (date.cweek - self.cweek)
272 (date.year - self.year)*52 + (date.cweek - self.cweek)
270 end
273 end
271 end
274 end
272
275
273 class String
276 class String
274 def with_leading_slash
277 def with_leading_slash
275 starts_with?('/') ? self : "/#{self}"
278 starts_with?('/') ? self : "/#{self}"
276 end
279 end
277 end
280 end
General Comments 0
You need to be logged in to leave comments. Login now