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