gitalytics 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 440abf11cbc39d3544a6d226527dd29dfb4d2adf
4
- data.tar.gz: fc5393c1b3ea97dd5819f1d607b879d085a18fa5
3
+ metadata.gz: dfee4701c631f00b32ae513f27dd761e78bc90c9
4
+ data.tar.gz: 18dfec6a19254bd61de7ecb7a65b34b824f610f9
5
5
  SHA512:
6
- metadata.gz: 56972f5d972a6d17f5bb46c234d27ffa6865dc2be24d636a0159147be2753726331113a725cbbee862d3a83e3a11c4bf0b93f0d506fc0eecdb2b2878ee33f6e9
7
- data.tar.gz: 3e825ed9e7103ff3d543ce2c870d1ca153b7ba2389f6ae5047e3d124fc748bef25baca3199e4181acf19104251c04abc4474ff3756cb0be566d94b0fdec24688
6
+ metadata.gz: 22ab60c1cc856e08152c8893170c567b82831ff09910c7d4a7e7107cc06576042651ef0001a71a7533da5557b4d31a0ab3d515fe897fb07531e32b62ce1d45b1
7
+ data.tar.gz: f24764d467fd4e7df3f06a37804f3185d2e07157241e38764ff70c4e013ccef02c81377c1459998d1f75e1daf3f729d4c560d8395b8e26e8eff50f0a1c24b9b0
@@ -79,6 +79,18 @@
79
79
  /*-webkit-font-smoothing:antialiased;*/
80
80
  }
81
81
 
82
+ .dashboard-box {
83
+ background-color: #f3f3f3;
84
+ border-radius: 10px;
85
+ margin-bottom: 30px;
86
+ padding: 20px;
87
+ text-align: center;
88
+ }
89
+
90
+ .dashboard-box .glyphicon {
91
+ font-size: 48px;
92
+ }
93
+
82
94
  </style>
83
95
  </head>
84
96
 
@@ -101,9 +113,9 @@
101
113
  </div>
102
114
  <div class="collapse navbar-collapse">
103
115
  <ul class="nav navbar-nav">
104
- <li class="active"><a href="#">Users</a></li>
105
- <!-- <li><a href="#about">About</a></li>
106
- <li><a href="#contact">Contact</a></li> -->
116
+ <li class="active"><a href="#dashboard" data-toggle="tab">Dashboard</a></li>
117
+ <li><a href="#authors" data-toggle="tab">Authors</a></li>
118
+ <!-- <li><a href="#contact">Contact</a></li> -->
107
119
  </ul>
108
120
  </div><!--/.nav-collapse -->
109
121
  </div>
@@ -111,28 +123,84 @@
111
123
 
112
124
  <!-- Begin page content -->
113
125
  <div class="container">
114
- <div class="page-header">
115
- <h1>Users</h1>
116
- <p class="lead">Compare the quantity of commits made by each of your repository contributors.<br/> Check who is writing most of the code of your project and maybe give him/her a prize! ;)</p>
117
- <% @data[:users].each do |user| %>
118
- <a href="#" title="<%= user.name %> <small><%= user.email %></small>" class="user-avatar" data-content="<%= user.summary %>">
119
- <img class="dp img-circle" src="<%= "http://www.gravatar.com/avatar/#{user.gravatar}" %>" style="width: 100px; height:100px; border-color:<%= user.rgba %>"></a>
120
- <% end %>
121
- </div>
122
-
123
- <div class="row">
124
- <div class="col-md-6">
125
- <h2>Commits count per user</h2>
126
- <canvas id="usersPieChart" width="550" height="400"></canvas>
126
+ <div class="tab-content">
127
+ <div class="tab-pane active" id="dashboard">
128
+ <div class="page-header">
129
+ <h1>Dashboard</h1>
130
+ <p class="lead">A quick overview of the activity on your git repository.</p>
131
+ </div>
132
+ <div class="row">
133
+ <div class="col-md-4">
134
+ <div class="dashboard-box">
135
+ <span class="glyphicon glyphicon-user"></span><br>
136
+ <%= @users.count %>
137
+ authors
138
+ </div>
139
+ </div>
140
+ <div class="col-md-4">
141
+ <div class="dashboard-box">
142
+ <span class="glyphicon glyphicon-list"></span><br>
143
+ <%= @commits.count %>
144
+ commits
145
+ </div>
146
+ </div>
147
+ <div class="col-md-4">
148
+ <div class="dashboard-box">
149
+ <span class="glyphicon glyphicon-file"></span><br>
150
+ <%= @commits.map{ |c| c.files_committed }.flatten.uniq.compact.count %>
151
+ files committed
152
+ </div>
153
+ </div>
154
+ </div>
155
+ <div class="row">
156
+ <div class="col-md-4">
157
+ <div class="dashboard-box">
158
+ <span class="glyphicon glyphicon-plus"></span><br>
159
+ <%= @commits.map{ |c| c.insertions }.inject(0){ |total, current| total + current } %>
160
+ insertions
161
+ </div>
162
+ </div>
163
+ <div class="col-md-4">
164
+ <div class="dashboard-box">
165
+ <span class="glyphicon glyphicon-minus"></span><br>
166
+ <%= @commits.map{ |c| c.deletions }.inject(0){ |total, current| total + current } %>
167
+ deletions
168
+ </div>
169
+ </div>
170
+ <div class="col-md-4">
171
+ <div class="dashboard-box">
172
+ <span class="glyphicon glyphicon-calendar"></span><br>
173
+ <%= (@commits.max_by(&:date).date - @commits.min_by(&:date).date).to_i + 1 %>
174
+ days
175
+ </div>
176
+ </div>
177
+ </div>
127
178
  </div>
128
- <div class="col-md-6">
129
- <h2>Commits per weekday per user</h2>
130
- <canvas id="usersRadarChart" width="550" height="400"></canvas>
179
+ <div class="tab-pane" id="authors">
180
+ <div class="page-header">
181
+ <h1>Authors</h1>
182
+ <p class="lead">Compare the quantity of commits made by each of your repository contributors.<br/> Check who is writing most of the code of your project and maybe give him/her a prize! ;)</p>
183
+ <% @users.each do |user| %>
184
+ <a href="#" title="<%= user.name %> <small><%= user.email %></small>" class="user-avatar" data-content="<%= user.summary %>">
185
+ <img class="dp img-circle" src="<%= "http://www.gravatar.com/avatar/#{user.gravatar}" %>" style="width: 100px; height:100px; border-color:<%= user.rgba %>"></a>
186
+ <% end %>
187
+ </div>
188
+
189
+ <div class="row">
190
+ <div class="col-md-6">
191
+ <h2>Commits count per user</h2>
192
+ <canvas id="usersPieChart" width="550" height="400"></canvas>
193
+ </div>
194
+ <div class="col-md-6">
195
+ <h2>Commits per weekday per user</h2>
196
+ <canvas id="usersRadarChart" width="550" height="400"></canvas>
197
+ </div>
198
+ </div>
199
+ <hr>
200
+ <h2>Insertions vs. Deletions</h2>
201
+ <canvas id="usersBarChart" width="1100" height="400"></canvas>
131
202
  </div>
132
203
  </div>
133
- <hr>
134
- <h2>Insertions vs. Deletions</h2>
135
- <canvas id="usersBarChart" width="1100" height="400"></canvas>
136
204
  </div>
137
205
  </div>
138
206
 
@@ -155,21 +223,21 @@
155
223
  });
156
224
 
157
225
  // Data for Users Pie Chart
158
- var data = [<%= @data[:users].map{|d| "{ value: #{d.commits.count}, color: '#{d.rgba}' }" }.join(',') %>];
226
+ var data = [<%= @users.map{|d| "{ value: #{d.commits.count}, color: '#{d.rgba}' }" }.join(',') %>];
159
227
  var ctx = document.getElementById("usersPieChart").getContext("2d");
160
228
  var usersPieChart = new Chart(ctx).Pie(data);
161
229
 
162
230
  // Data for Insertions vs. Deletions Bar Chart
163
231
  var data = {
164
- labels: [<%= @data[:users].map{|d| "'#{d.name}'" }.join(',') %>],
232
+ labels: [<%= @users.map{|d| "'#{d.name}'" }.join(',') %>],
165
233
  datasets: [
166
234
  {
167
- data: [<%= @data[:users].map{|d| "#{d.total_insertions}" }.join(',') %>],
235
+ data: [<%= @users.map{|d| "#{d.total_insertions}" }.join(',') %>],
168
236
  fillColor: 'rgba(196, 234, 44, 0.5)',
169
237
  strokeColor: 'rgba(196, 234, 44, 1)'
170
238
  },
171
239
  {
172
- data: [<%= @data[:users].map{|d| "#{d.total_deletions}" }.join(',') %>],
240
+ data: [<%= @users.map{|d| "#{d.total_deletions}" }.join(',') %>],
173
241
  fillColor: 'rgba(234, 80, 44, 0.5)',
174
242
  strokeColor: 'rgba(234, 80, 44, 1)'
175
243
  }
@@ -182,14 +250,14 @@
182
250
  var data = {
183
251
  labels: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
184
252
  datasets: [
185
- <% @data[:users].each_with_index do |user, i| %>
253
+ <% @users.each_with_index do |user, i| %>
186
254
  {
187
255
  fillColor : "<%= user.rgba('0.5') %>",
188
256
  strokeColor : "<%= user.rgba %>",
189
257
  pointColor : "<%= user.rgba %>",
190
258
  pointStrokeColor : "#fff",
191
259
  data : [<%= user.weekday_commits.join(', ') %>]
192
- }<%= ',' unless i + 1 == @data[:users].count %>
260
+ }<%= ',' unless i + 1 == @users.count %>
193
261
  <% end %>
194
262
  ]
195
263
  };
@@ -2,13 +2,15 @@
2
2
  # encoding: UTF-8
3
3
 
4
4
  Encoding.default_external = Encoding::UTF_8
5
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
5
6
 
6
7
  require 'optparse'
7
- require File.expand_path("../../lib/gitalytics.rb", __FILE__)
8
+ require 'gitalytics'
8
9
 
9
10
  options = {
10
11
  format: 'cli'
11
12
  }
13
+
12
14
  OptionParser.new do |opts|
13
15
  opts.banner = "Usage: gitalytics [options]"
14
16
 
@@ -17,8 +19,14 @@ OptionParser.new do |opts|
17
19
  exit
18
20
  end
19
21
 
20
- opts.on("-h", "--html", "Outputs html report") do |v|
22
+ opts.on("-h", "--html", "Outputs html report and displays it in default web browser") do |v|
23
+ options[:format] = 'html'
24
+ options[:browser] = true
25
+ end
26
+
27
+ opts.on("-n", "--no-browser", "Do not open html report in browser") do |v|
21
28
  options[:format] = 'html'
29
+ options[:browser] = false
22
30
  end
23
31
  end.parse!
24
32
 
@@ -4,144 +4,54 @@ require 'date'
4
4
  require 'erb'
5
5
  require 'digest/md5'
6
6
 
7
- class Gitalytics
8
-
9
- VERSION = '1.1.1'
7
+ require 'gitlog'
8
+ require 'user'
9
+ require 'commit'
10
10
 
11
- attr_accessor :data
11
+ class Gitalytics
12
12
 
13
- def initialize
14
- @data = { commits: [], users: [] }
15
- end
13
+ VERSION = '1.2.0'
16
14
 
17
15
  def analyze(options)
18
- parse_git_log
16
+ data = GitLog.parse_git_log
17
+
19
18
  case options[:format]
20
19
  when 'html'
21
- output_html_report
20
+ output_html_report(data, options[:browser])
22
21
  else
23
- output_cli_report
22
+ output_cli_report(data[:users])
24
23
  end
25
24
  end
26
25
 
27
26
  private
28
- def parse_git_log
29
- result = `git log --stat --format=`
30
-
31
- result.each_line do |line|
32
- line.encode!('UTF-8', 'UTF8-MAC') if defined?(Encoding::UTF8_MAC)
33
27
 
34
- if match = line.match(/^commit ([0-9a-z]*)$/)
35
- @data[:commits] << Commit.new(match[1])
36
- elsif match = line.match(/^Author: ([[:alpha:] ]*) <(.*)>$/)
37
- user = get_user(match[1], match[2])
38
- @data[:commits].last.author = user
39
- user.commits << @data[:commits].last
40
- elsif match = line.match(/^Date: (.*)$/)
41
- @data[:commits].last.date = Date.parse(match[1])
42
- elsif match = line.match(/^ (.*)$/)
43
- @data[:commits].last.subject = match[1]
44
- elsif match = line.match(/^ ([^ ]+)[ ]+\|[ ]+([\d]+) ([\+]*)([-]*)$/)
45
- @data[:commits].last.summary << { filename: match[1], changes: match[2], insertions: match[3], deletions: match[4] }
46
- end
47
- end
48
-
49
- end
50
-
51
- def output_cli_report
52
- @data[:users].each do |user|
28
+ def output_cli_report(users)
29
+ users.each do |user|
53
30
  puts user.summary
54
31
  end
55
32
  end
56
33
 
57
- def output_html_report
34
+ def output_html_report(data, open_in_browser)
58
35
  template_file = File.read(File.join(File.dirname(__FILE__), "..", "assets", "gitalytics.html.erb"))
59
36
  erb = ERB.new(template_file)
60
- File.open("gitalytics_result.html", 'w+') { |file| file.write(erb.result(binding)) }
61
- end
62
-
63
- def get_user(name, email)
64
- @data[:users].each do |u|
65
- return u if u.email == email
37
+ output_file = "gitalytics_result.html"
38
+ File.open(output_file, 'w+') do |file|
39
+ @users = data[:users]
40
+ @commits = data[:commits]
41
+ file.write(erb.result(binding))
66
42
  end
67
- @data[:users] << new_user = User.new(name, email)
68
- new_user
69
- end
70
-
71
- end
72
-
73
- class User
74
-
75
- attr_accessor :name, :email, :commits, :colors
76
-
77
- def initialize(name, email)
78
- self.name = name
79
- self.email = email
80
- self.commits = []
81
- self.colors = [rand(255), rand(255), rand(255)].join(', ')
82
- end
83
-
84
- def gravatar
85
- Digest::MD5.hexdigest(email)
86
- end
87
-
88
- def first_commit
89
- commits.min_by(&:date)
90
- end
91
-
92
- def last_commit
93
- commits.max_by(&:date)
94
- end
95
-
96
- def commits_period
97
- (last_commit.date - first_commit.date).to_i + 1
98
- end
99
-
100
- def working_days
101
- commits.map(&:date).uniq.count
102
- end
103
-
104
- def total_insertions
105
- commits.map(&:insertions).inject(0) { |total, current| total + current }
106
- end
107
-
108
- def total_deletions
109
- commits.map(&:deletions).inject(0) { |total, current| total + current }
43
+ open_report_in_browser(output_file) if open_in_browser
110
44
  end
111
45
 
112
- def summary
113
- "#{name} has made #{commits.count} commits between #{commits_period} days. He/she did something useful on #{working_days} of those days."
114
- end
115
-
116
- def rgba(opacity = 1)
117
- "rgba(#{colors}, #{opacity})"
118
- end
119
-
120
- def weekday_commits
121
- days = Array.new(7) {0}
122
- commits.each do |c|
123
- days[c.date.wday] += 1
46
+ def open_report_in_browser(filename)
47
+ host = RbConfig::CONFIG['host_os']
48
+ if host =~ /mswin|mingw|cygwin/
49
+ system "start #{filename}"
50
+ elsif host =~ /darwin/
51
+ system "open #{filename}"
52
+ elsif host =~ /linux|bsd/
53
+ system "xdg-open #{filename}"
124
54
  end
125
- days
126
- end
127
-
128
- end
129
-
130
- class Commit
131
-
132
- attr_accessor :hash, :author, :date, :subject, :summary
133
-
134
- def initialize(hash)
135
- self.hash = hash
136
- self.summary = []
137
- end
138
-
139
- def insertions
140
- summary.map{ |s| s[:insertions].length }.inject(0){ |total, current| total + current }
141
- end
142
-
143
- def deletions
144
- summary.map{ |s| s[:deletions].length }.inject(0){ |total, current| total + current }
145
55
  end
146
56
 
147
57
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitalytics
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gonzalo Robaina
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-07 00:00:00.000000000 Z
11
+ date: 2014-01-18 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Get usefull analytics from your git log
14
14
  email: gonzalor@gmail.com