##// END OF EJS Templates
Fixed: nil error on 'commits per month' graph....
Jean-Philippe Lang -
r639:5b35bfd4344e
parent child
Show More
@@ -1,231 +1,232
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 RepositoriesController < ApplicationController
22 class RepositoriesController < ApplicationController
23 layout 'base'
23 layout 'base'
24 before_filter :find_project, :except => [:update_form]
24 before_filter :find_project, :except => [:update_form]
25 before_filter :authorize, :except => [:update_form, :stats, :graph]
25 before_filter :authorize, :except => [:update_form, :stats, :graph]
26 before_filter :check_project_privacy, :only => [:stats, :graph]
26 before_filter :check_project_privacy, :only => [:stats, :graph]
27
27
28 def show
28 def show
29 # check if new revisions have been committed in the repository
29 # check if new revisions have been committed in the repository
30 @repository.fetch_changesets if Setting.autofetch_changesets?
30 @repository.fetch_changesets if Setting.autofetch_changesets?
31 # get entries for the browse frame
31 # get entries for the browse frame
32 @entries = @repository.entries('')
32 @entries = @repository.entries('')
33 # latest changesets
33 # latest changesets
34 @changesets = @repository.changesets.find(:all, :limit => 10, :order => "committed_on DESC")
34 @changesets = @repository.changesets.find(:all, :limit => 10, :order => "committed_on DESC")
35 show_error and return unless @entries || @changesets.any?
35 show_error and return unless @entries || @changesets.any?
36 end
36 end
37
37
38 def browse
38 def browse
39 @entries = @repository.entries(@path, @rev)
39 @entries = @repository.entries(@path, @rev)
40 show_error and return unless @entries
40 show_error and return unless @entries
41 end
41 end
42
42
43 def changes
43 def changes
44 @entry = @repository.scm.entry(@path, @rev)
44 @entry = @repository.scm.entry(@path, @rev)
45 show_error and return unless @entry
45 show_error and return unless @entry
46 @changes = Change.find(:all, :include => :changeset,
46 @changes = Change.find(:all, :include => :changeset,
47 :conditions => ["repository_id = ? AND path = ?", @repository.id, @path.with_leading_slash],
47 :conditions => ["repository_id = ? AND path = ?", @repository.id, @path.with_leading_slash],
48 :order => "committed_on DESC")
48 :order => "committed_on DESC")
49 end
49 end
50
50
51 def revisions
51 def revisions
52 @changeset_count = @repository.changesets.count
52 @changeset_count = @repository.changesets.count
53 @changeset_pages = Paginator.new self, @changeset_count,
53 @changeset_pages = Paginator.new self, @changeset_count,
54 25,
54 25,
55 params['page']
55 params['page']
56 @changesets = @repository.changesets.find(:all,
56 @changesets = @repository.changesets.find(:all,
57 :limit => @changeset_pages.items_per_page,
57 :limit => @changeset_pages.items_per_page,
58 :offset => @changeset_pages.current.offset)
58 :offset => @changeset_pages.current.offset)
59
59
60 render :action => "revisions", :layout => false if request.xhr?
60 render :action => "revisions", :layout => false if request.xhr?
61 end
61 end
62
62
63 def entry
63 def entry
64 @content = @repository.scm.cat(@path, @rev)
64 @content = @repository.scm.cat(@path, @rev)
65 show_error and return unless @content
65 show_error and return unless @content
66 if 'raw' == params[:format]
66 if 'raw' == params[:format]
67 send_data @content, :filename => @path.split('/').last
67 send_data @content, :filename => @path.split('/').last
68 end
68 end
69 end
69 end
70
70
71 def revision
71 def revision
72 @changeset = @repository.changesets.find_by_revision(@rev)
72 @changeset = @repository.changesets.find_by_revision(@rev)
73 show_error and return unless @changeset
73 show_error and return unless @changeset
74 @changes_count = @changeset.changes.size
74 @changes_count = @changeset.changes.size
75 @changes_pages = Paginator.new self, @changes_count, 150, params['page']
75 @changes_pages = Paginator.new self, @changes_count, 150, params['page']
76 @changes = @changeset.changes.find(:all,
76 @changes = @changeset.changes.find(:all,
77 :limit => @changes_pages.items_per_page,
77 :limit => @changes_pages.items_per_page,
78 :offset => @changes_pages.current.offset)
78 :offset => @changes_pages.current.offset)
79
79
80 render :action => "revision", :layout => false if request.xhr?
80 render :action => "revision", :layout => false if request.xhr?
81 end
81 end
82
82
83 def diff
83 def diff
84 @rev_to = params[:rev_to] ? params[:rev_to].to_i : (@rev - 1)
84 @rev_to = params[:rev_to] ? params[:rev_to].to_i : (@rev - 1)
85 @diff_type = ('sbs' == params[:type]) ? 'sbs' : 'inline'
85 @diff_type = ('sbs' == params[:type]) ? 'sbs' : 'inline'
86
86
87 @cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
87 @cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
88 unless read_fragment(@cache_key)
88 unless read_fragment(@cache_key)
89 @diff = @repository.diff(@path, @rev, @rev_to, type)
89 @diff = @repository.diff(@path, @rev, @rev_to, type)
90 show_error and return unless @diff
90 show_error and return unless @diff
91 end
91 end
92 end
92 end
93
93
94 def stats
94 def stats
95 end
95 end
96
96
97 def graph
97 def graph
98 data = nil
98 data = nil
99 case params[:graph]
99 case params[:graph]
100 when "commits_per_month"
100 when "commits_per_month"
101 data = graph_commits_per_month(@repository)
101 data = graph_commits_per_month(@repository)
102 when "commits_per_author"
102 when "commits_per_author"
103 data = graph_commits_per_author(@repository)
103 data = graph_commits_per_author(@repository)
104 end
104 end
105 if data
105 if data
106 headers["Content-Type"] = "image/svg+xml"
106 headers["Content-Type"] = "image/svg+xml"
107 send_data(data, :type => "image/svg+xml", :disposition => "inline")
107 send_data(data, :type => "image/svg+xml", :disposition => "inline")
108 else
108 else
109 render_404
109 render_404
110 end
110 end
111 end
111 end
112
112
113 def update_form
113 def update_form
114 @repository = Repository.factory(params[:repository_scm])
114 @repository = Repository.factory(params[:repository_scm])
115 render :partial => 'projects/repository', :locals => {:repository => @repository}
115 render :partial => 'projects/repository', :locals => {:repository => @repository}
116 end
116 end
117
117
118 private
118 private
119 def find_project
119 def find_project
120 @project = Project.find(params[:id])
120 @project = Project.find(params[:id])
121 @repository = @project.repository
121 @repository = @project.repository
122 render_404 and return false unless @repository
122 render_404 and return false unless @repository
123 @path = params[:path].squeeze('/') if params[:path]
123 @path = params[:path].squeeze('/') if params[:path]
124 @path ||= ''
124 @path ||= ''
125 @rev = params[:rev].to_i if params[:rev]
125 @rev = params[:rev].to_i if params[:rev]
126 rescue ActiveRecord::RecordNotFound
126 rescue ActiveRecord::RecordNotFound
127 render_404
127 render_404
128 end
128 end
129
129
130 def show_error
130 def show_error
131 flash.now[:error] = l(:notice_scm_error)
131 flash.now[:error] = l(:notice_scm_error)
132 render :nothing => true, :layout => true
132 render :nothing => true, :layout => true
133 end
133 end
134
134
135 def graph_commits_per_month(repository)
135 def graph_commits_per_month(repository)
136 @date_to = Date.today
136 @date_to = Date.today
137 @date_from = @date_to << 12
137 @date_from = @date_to << 11
138 @date_from = Date.civil(@date_from.year, @date_from.month, 1)
138 commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
139 commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
139 commits_by_month = [0] * 12
140 commits_by_month = [0] * 12
140 commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
141 commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
141
142
142 changes_by_day = repository.changes.count(:all, :group => :commit_date)
143 changes_by_day = repository.changes.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
143 changes_by_month = [0] * 12
144 changes_by_month = [0] * 12
144 changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
145 changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
145
146
146 fields = []
147 fields = []
147 month_names = l(:actionview_datehelper_select_month_names_abbr).split(',')
148 month_names = l(:actionview_datehelper_select_month_names_abbr).split(',')
148 12.times {|m| fields << month_names[((Date.today.month - 1 - m) % 12)]}
149 12.times {|m| fields << month_names[((Date.today.month - 1 - m) % 12)]}
149
150
150 graph = SVG::Graph::Bar.new(
151 graph = SVG::Graph::Bar.new(
151 :height => 300,
152 :height => 300,
152 :width => 500,
153 :width => 500,
153 :fields => fields.reverse,
154 :fields => fields.reverse,
154 :stack => :side,
155 :stack => :side,
155 :scale_integers => true,
156 :scale_integers => true,
156 :step_x_labels => 2,
157 :step_x_labels => 2,
157 :show_data_values => false,
158 :show_data_values => false,
158 :graph_title => l(:label_commits_per_month),
159 :graph_title => l(:label_commits_per_month),
159 :show_graph_title => true
160 :show_graph_title => true
160 )
161 )
161
162
162 graph.add_data(
163 graph.add_data(
163 :data => commits_by_month[0..11].reverse,
164 :data => commits_by_month[0..11].reverse,
164 :title => l(:label_revision_plural)
165 :title => l(:label_revision_plural)
165 )
166 )
166
167
167 graph.add_data(
168 graph.add_data(
168 :data => changes_by_month[0..11].reverse,
169 :data => changes_by_month[0..11].reverse,
169 :title => l(:label_change_plural)
170 :title => l(:label_change_plural)
170 )
171 )
171
172
172 graph.burn
173 graph.burn
173 end
174 end
174
175
175 def graph_commits_per_author(repository)
176 def graph_commits_per_author(repository)
176 commits_by_author = repository.changesets.count(:all, :group => :committer)
177 commits_by_author = repository.changesets.count(:all, :group => :committer)
177 commits_by_author.sort! {|x, y| x.last <=> y.last}
178 commits_by_author.sort! {|x, y| x.last <=> y.last}
178
179
179 changes_by_author = repository.changes.count(:all, :group => :committer)
180 changes_by_author = repository.changes.count(:all, :group => :committer)
180 h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
181 h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
181
182
182 fields = commits_by_author.collect {|r| r.first}
183 fields = commits_by_author.collect {|r| r.first}
183 commits_data = commits_by_author.collect {|r| r.last}
184 commits_data = commits_by_author.collect {|r| r.last}
184 changes_data = commits_by_author.collect {|r| h[r.first] || 0}
185 changes_data = commits_by_author.collect {|r| h[r.first] || 0}
185
186
186 fields = fields + [""]*(10 - fields.length) if fields.length<10
187 fields = fields + [""]*(10 - fields.length) if fields.length<10
187 commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
188 commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
188 changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
189 changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
189
190
190 graph = SVG::Graph::BarHorizontal.new(
191 graph = SVG::Graph::BarHorizontal.new(
191 :height => 300,
192 :height => 300,
192 :width => 500,
193 :width => 500,
193 :fields => fields,
194 :fields => fields,
194 :stack => :side,
195 :stack => :side,
195 :scale_integers => true,
196 :scale_integers => true,
196 :show_data_values => false,
197 :show_data_values => false,
197 :rotate_y_labels => false,
198 :rotate_y_labels => false,
198 :graph_title => l(:label_commits_per_author),
199 :graph_title => l(:label_commits_per_author),
199 :show_graph_title => true
200 :show_graph_title => true
200 )
201 )
201
202
202 graph.add_data(
203 graph.add_data(
203 :data => commits_data,
204 :data => commits_data,
204 :title => l(:label_revision_plural)
205 :title => l(:label_revision_plural)
205 )
206 )
206
207
207 graph.add_data(
208 graph.add_data(
208 :data => changes_data,
209 :data => changes_data,
209 :title => l(:label_change_plural)
210 :title => l(:label_change_plural)
210 )
211 )
211
212
212 graph.burn
213 graph.burn
213 end
214 end
214
215
215 end
216 end
216
217
217 class Date
218 class Date
218 def months_ago(date = Date.today)
219 def months_ago(date = Date.today)
219 (date.year - self.year)*12 + (date.month - self.month)
220 (date.year - self.year)*12 + (date.month - self.month)
220 end
221 end
221
222
222 def weeks_ago(date = Date.today)
223 def weeks_ago(date = Date.today)
223 (date.year - self.year)*52 + (date.cweek - self.cweek)
224 (date.year - self.year)*52 + (date.cweek - self.cweek)
224 end
225 end
225 end
226 end
226
227
227 class String
228 class String
228 def with_leading_slash
229 def with_leading_slash
229 starts_with?('/') ? self : "/#{self}"
230 starts_with?('/') ? self : "/#{self}"
230 end
231 end
231 end
232 end
General Comments 0
You need to be logged in to leave comments. Login now