gitalytics 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/.gitignore +14 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +31 -0
- data/Gemfile +9 -0
- data/README.md +65 -0
- data/Rakefile +8 -0
- data/assets/gitalytics.html.erb +286 -47
- data/bin/gitalytics +8 -2
- data/gitalytics.gemspec +28 -0
- data/lib/gitalytics.rb +13 -7
- data/lib/{commit.rb → gitalytics/commit.rb} +0 -0
- data/lib/{gitlog.rb → gitalytics/gitlog.rb} +18 -12
- data/lib/{user.rb → gitalytics/user.rb} +12 -11
- data/lib/gitalytics/version.rb +3 -0
- data/test/lib/test_commit.rb +42 -0
- data/test/lib/test_gitlog.rb +105 -0
- data/test/lib/test_user.rb +86 -0
- data/test/test_helper.rb +2 -0
- metadata +72 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3f105e2f5f0c549981b100e5ebfa66d22c86fef
|
4
|
+
data.tar.gz: 432428efcdfea8e4dc3c3eec59ece71a39092692
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90fcb57c95019c47583cb0f6c9cc909d12addb5db13e430e118dc8f5ea2028adde466c9ac16ba7b862344ca93eb003a97d6ce5869edc33810a68d9269572f935
|
7
|
+
data.tar.gz: ffb1ecd259992afa952df44a83d5c01f2492e3c855084d85a27068cd0366390f63ab622383f701ee0b08e7de9a06aa92412e55af3af7ab5cc21ae9bbb549af84
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
## Gitalytics Changelog
|
2
|
+
|
3
|
+
#### v.1.3.0
|
4
|
+
* Changed CLI output text.
|
5
|
+
* Re-structure of gem's source code.
|
6
|
+
* Authors are now grouped by name.
|
7
|
+
* Added CLI option -e to group authors by email (old behavior).
|
8
|
+
* Updated Chart.js version.
|
9
|
+
* Updated Bootstrap version.
|
10
|
+
* Updated HTML report design.
|
11
|
+
|
12
|
+
#### v.1.2.1
|
13
|
+
* Fixed bug that prevented gitalytics to initialize correctly. (Thanks @willyschwindt)
|
14
|
+
|
15
|
+
#### v.1.2.0
|
16
|
+
* Git log parser totally refactored. (Thanks @grilix)
|
17
|
+
* Gitalytics now open html report in browser automatically. (Thanks @surendrans)
|
18
|
+
* Moved classes and modules to external files.
|
19
|
+
* Added CLI option -n that prevents report to load automatically in web browser.
|
20
|
+
* Dashboard added with some quick stats for your git repository.
|
21
|
+
|
22
|
+
#### v1.1.1
|
23
|
+
* Add Changelog :)
|
24
|
+
* Update Readme.
|
25
|
+
* Fix bug which preventing authors with special characters to be shown on the report. (thanks @afrojas)
|
26
|
+
* Fix bug which may result in a broken report if the user uses a default format for git log. (thanks @dgiunta)
|
27
|
+
|
28
|
+
#### v1.1.0
|
29
|
+
* Add Insertions vs. Deletions graph for Users.
|
30
|
+
* Add weekday commits count graph for Users.
|
31
|
+
* Change the way it shows the authors information.
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
## Gitalytics
|
2
|
+
|
3
|
+
Get commits statistics for your git repository
|
4
|
+
Based on gist by Tobin Harris: https://gist.github.com/tobinharris/396634
|
5
|
+
|
6
|
+
[](https://codeclimate.com/github/pepito2k/gitalytics)
|
7
|
+
[](http://badge.fury.io/rb/gitalytics)
|
8
|
+
[](https://gemnasium.com/pepito2k/gitalytics)
|
9
|
+
[](https://travis-ci.org/pepito2k/gitalytics)
|
10
|
+
[](https://coveralls.io/r/pepito2k/gitalytics?branch=master)
|
11
|
+
|
12
|
+

|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
### Manual installation
|
17
|
+
|
18
|
+
gem install gitalytics
|
19
|
+
|
20
|
+
### Using bundler
|
21
|
+
Add gitalytics to your Gemfile
|
22
|
+
|
23
|
+
gem "gitalytics"
|
24
|
+
|
25
|
+
Install the gem
|
26
|
+
|
27
|
+
bundle install
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
Open a terminal window pointing to your git repository and just run the gitalytics command:
|
31
|
+
|
32
|
+
$ gitalytics
|
33
|
+
|
34
|
+
If you'd like to get a fancy html report like the one in the screenshot above, you will need to run the following command:
|
35
|
+
|
36
|
+
$ gitalytics -h
|
37
|
+
|
38
|
+
If you want to have the html report but don't want it to be opened right away just write:
|
39
|
+
|
40
|
+
$ gitalytics -n
|
41
|
+
|
42
|
+
Note that gitalytics groups authors by name, you can change that and group by email using:
|
43
|
+
|
44
|
+
$ gitalytics -e
|
45
|
+
|
46
|
+
## License
|
47
|
+
Copyright (c) 2016 Gonzalo Robaina
|
48
|
+
|
49
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
50
|
+
of this software and associated documentation files (the "Software"), to deal
|
51
|
+
in the Software without restriction, including without limitation the rights
|
52
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
53
|
+
copies of the Software, and to permit persons to whom the Software is
|
54
|
+
furnished to do so, subject to the following conditions:
|
55
|
+
|
56
|
+
The above copyright notice and this permission notice shall be included in
|
57
|
+
all copies or substantial portions of the Software.
|
58
|
+
|
59
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
60
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
61
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
62
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
63
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
64
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
65
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
data/assets/gitalytics.html.erb
CHANGED
@@ -4,13 +4,14 @@
|
|
4
4
|
<meta charset="utf-8">
|
5
5
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
-
<meta name="description" content="">
|
8
|
-
<meta name="author" content="">
|
7
|
+
<meta name="description" content="Gitalytics Report">
|
8
|
+
<meta name="author" content="Gonzalo Robaina">
|
9
9
|
|
10
10
|
<title>Gitalytics report</title>
|
11
11
|
|
12
12
|
<!-- Bootstrap core CSS -->
|
13
|
-
<link href="
|
13
|
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
14
|
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
|
14
15
|
|
15
16
|
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
16
17
|
<!--[if lt IE 9]>
|
@@ -40,10 +41,115 @@
|
|
40
41
|
|
41
42
|
/* Set the fixed height of the footer here */
|
42
43
|
#footer {
|
43
|
-
height: 60px;
|
44
44
|
background-color: #f5f5f5;
|
45
|
+
height: 60px;
|
46
|
+
margin-top: 60px;
|
45
47
|
}
|
46
48
|
|
49
|
+
/* Twitter Profile styles
|
50
|
+
-------------------------------------------------- */
|
51
|
+
.twPc-div {
|
52
|
+
background: #fff none repeat scroll 0 0;
|
53
|
+
border: 1px solid #e1e8ed;
|
54
|
+
border-radius: 6px;
|
55
|
+
height: 150px;
|
56
|
+
max-width: 340px;
|
57
|
+
margin-bottom: 40px;
|
58
|
+
}
|
59
|
+
.twPc-bg {
|
60
|
+
border-bottom: 1px solid #e1e8ed;
|
61
|
+
border-radius: 4px 4px 0 0;
|
62
|
+
height: 40px;
|
63
|
+
width: 100%;
|
64
|
+
}
|
65
|
+
.twPc-block {
|
66
|
+
display: block !important;
|
67
|
+
}
|
68
|
+
.twPc-button {
|
69
|
+
margin: -35px -10px 0;
|
70
|
+
text-align: right;
|
71
|
+
width: 100%;
|
72
|
+
}
|
73
|
+
.twPc-avatarLink {
|
74
|
+
background-color: #fff;
|
75
|
+
border-radius: 6px;
|
76
|
+
display: inline-block !important;
|
77
|
+
float: left;
|
78
|
+
margin: -30px 5px 0 8px;
|
79
|
+
max-width: 100%;
|
80
|
+
padding: 1px;
|
81
|
+
vertical-align: bottom;
|
82
|
+
}
|
83
|
+
.twPc-avatarImg {
|
84
|
+
border: 2px solid #fff;
|
85
|
+
border-radius: 7px;
|
86
|
+
box-sizing: border-box;
|
87
|
+
color: #fff;
|
88
|
+
height: 72px;
|
89
|
+
width: 72px;
|
90
|
+
}
|
91
|
+
.twPc-divUser {
|
92
|
+
margin: 5px 0 0;
|
93
|
+
}
|
94
|
+
.twPc-divName {
|
95
|
+
font-size: 18px;
|
96
|
+
font-weight: 700;
|
97
|
+
line-height: 21px;
|
98
|
+
white-space: nowrap;
|
99
|
+
overflow: hidden;
|
100
|
+
text-overflow: ellipsis
|
101
|
+
}
|
102
|
+
.twPc-divName a {
|
103
|
+
color: inherit !important;
|
104
|
+
}
|
105
|
+
.twPc-divStats {
|
106
|
+
margin-left: 11px;
|
107
|
+
padding: 10px 0;
|
108
|
+
}
|
109
|
+
.twPc-Arrange {
|
110
|
+
box-sizing: border-box;
|
111
|
+
display: table;
|
112
|
+
margin: 0;
|
113
|
+
min-width: 100%;
|
114
|
+
padding: 0;
|
115
|
+
table-layout: auto;
|
116
|
+
}
|
117
|
+
ul.twPc-Arrange {
|
118
|
+
list-style: outside none none;
|
119
|
+
margin: 0;
|
120
|
+
padding: 0;
|
121
|
+
}
|
122
|
+
.twPc-ArrangeSizeFit {
|
123
|
+
display: table-cell;
|
124
|
+
padding: 0;
|
125
|
+
vertical-align: top;
|
126
|
+
}
|
127
|
+
.twPc-ArrangeSizeFit a:hover {
|
128
|
+
text-decoration: none;
|
129
|
+
}
|
130
|
+
.twPc-StatValue {
|
131
|
+
display: block;
|
132
|
+
font-size: 18px;
|
133
|
+
font-weight: 500;
|
134
|
+
transition: color 0.15s ease-in-out 0s;
|
135
|
+
}
|
136
|
+
.twPc-StatValue.commits {
|
137
|
+
color: #a650c0;
|
138
|
+
}
|
139
|
+
.twPc-StatValue.insertions {
|
140
|
+
color: #539734;
|
141
|
+
}
|
142
|
+
.twPc-StatValue.deletions {
|
143
|
+
color: #c03c24;
|
144
|
+
}
|
145
|
+
.twPc-StatLabel {
|
146
|
+
color: #8899a6;
|
147
|
+
font-size: 10px;
|
148
|
+
letter-spacing: 0.02em;
|
149
|
+
overflow: hidden;
|
150
|
+
text-transform: uppercase;
|
151
|
+
transition: color 0.15s ease-in-out 0s;
|
152
|
+
}
|
47
153
|
|
48
154
|
/* Custom page CSS
|
49
155
|
-------------------------------------------------- */
|
@@ -96,6 +202,14 @@
|
|
96
202
|
font-size: 48px;
|
97
203
|
}
|
98
204
|
|
205
|
+
#authors li {
|
206
|
+
list-style: none;
|
207
|
+
}
|
208
|
+
|
209
|
+
.usersColorLegend {
|
210
|
+
vertical-align: middle;
|
211
|
+
}
|
212
|
+
|
99
213
|
</style>
|
100
214
|
</head>
|
101
215
|
|
@@ -120,6 +234,8 @@
|
|
120
234
|
<ul class="nav navbar-nav">
|
121
235
|
<li class="active"><a href="#dashboard" data-toggle="tab">Dashboard</a></li>
|
122
236
|
<li><a href="#authors" data-toggle="tab">Authors</a></li>
|
237
|
+
<li><a href="#commits" data-toggle="tab">Commits</a></li>
|
238
|
+
<li><a href="#dates" data-toggle="tab">Dates</a></li>
|
123
239
|
<!-- <li><a href="#contact">Contact</a></li> -->
|
124
240
|
</ul>
|
125
241
|
</div><!--/.nav-collapse -->
|
@@ -129,6 +245,7 @@
|
|
129
245
|
<!-- Begin page content -->
|
130
246
|
<div class="container">
|
131
247
|
<div class="tab-content">
|
248
|
+
<!-- Start Dashboard -->
|
132
249
|
<div class="tab-pane active" id="dashboard">
|
133
250
|
<div class="page-header">
|
134
251
|
<h1>Dashboard</h1>
|
@@ -183,30 +300,136 @@
|
|
183
300
|
</div>
|
184
301
|
</div>
|
185
302
|
</div>
|
303
|
+
<!-- End Dashboard -->
|
304
|
+
<!-- Start Authors -->
|
186
305
|
<div class="tab-pane" id="authors">
|
187
306
|
<div class="page-header">
|
188
307
|
<h1>Authors</h1>
|
189
308
|
<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>
|
309
|
+
</div>
|
310
|
+
<div class="row">
|
311
|
+
<p>So far, <%= @users.size %> contributors commited something to your project.</p>
|
190
312
|
<% @users.each do |user| %>
|
191
|
-
<
|
192
|
-
|
313
|
+
<div class="col-md-4">
|
314
|
+
<!-- Twitter Profile start -->
|
315
|
+
<div class="twPc-div">
|
316
|
+
<a class="twPc-bg twPc-block" style="background-color: <%= user.rgba %>"></a>
|
317
|
+
<div>
|
318
|
+
|
319
|
+
<a title="<%= user.name %>" href="#" class="twPc-avatarLink">
|
320
|
+
<img alt="<%= user.name %>" src="<%= "http://www.gravatar.com/avatar/#{user.gravatar}?d=mm" %>" class="twPc-avatarImg">
|
321
|
+
</a>
|
322
|
+
|
323
|
+
<div class="twPc-divUser">
|
324
|
+
<div class="twPc-divName">
|
325
|
+
<a href="#"><%= user.name %></a>
|
326
|
+
</div>
|
327
|
+
<span>
|
328
|
+
<a href="mailto:<%= user.email %>"><span><%= user.email %></span></a>
|
329
|
+
</span>
|
330
|
+
</div>
|
331
|
+
|
332
|
+
<div class="twPc-divStats">
|
333
|
+
<ul class="twPc-Arrange">
|
334
|
+
<li class="twPc-ArrangeSizeFit">
|
335
|
+
<span class="twPc-StatLabel twPc-block">Commits</span>
|
336
|
+
<span class="twPc-StatValue commits"><%= user.commits.size %></span>
|
337
|
+
</li>
|
338
|
+
<li class="twPc-ArrangeSizeFit">
|
339
|
+
<span class="twPc-StatLabel twPc-block">Inserts</span>
|
340
|
+
<span class="twPc-StatValue insertions"><%= user.total_insertions %></span>
|
341
|
+
</li>
|
342
|
+
<li class="twPc-ArrangeSizeFit">
|
343
|
+
<span class="twPc-StatLabel twPc-block">Deletes</span>
|
344
|
+
<span class="twPc-StatValue deletions"><%= user.total_deletions %></span>
|
345
|
+
</li>
|
346
|
+
</ul>
|
347
|
+
</div>
|
348
|
+
</div>
|
349
|
+
</div>
|
350
|
+
<!-- Twitter Profile end -->
|
351
|
+
</div>
|
193
352
|
<% end %>
|
194
353
|
</div>
|
195
354
|
|
196
355
|
<div class="row">
|
356
|
+
<h2>Commits count per user</h2>
|
197
357
|
<div class="col-md-6">
|
198
|
-
<h2>Commits count per user</h2>
|
199
358
|
<canvas id="usersPieChart" width="550" height="400"></canvas>
|
200
359
|
</div>
|
201
360
|
<div class="col-md-6">
|
202
|
-
<
|
203
|
-
|
361
|
+
<ul>
|
362
|
+
<% @users.each do |u| %>
|
363
|
+
<li>
|
364
|
+
<canvas class="usersColorLegend" width="30" height="15" style="background-color: <%= u.rgba %>"></canvas>
|
365
|
+
<%= u.name %>
|
366
|
+
</li>
|
367
|
+
<% end %>
|
368
|
+
<ul>
|
204
369
|
</div>
|
205
370
|
</div>
|
206
|
-
<hr>
|
371
|
+
<!-- <hr>
|
207
372
|
<h2>Insertions vs. Deletions</h2>
|
208
|
-
<canvas id="usersBarChart" width="1100" height="400"></canvas>
|
373
|
+
<canvas id="usersBarChart" width="1100" height="400"></canvas> -->
|
374
|
+
</div>
|
375
|
+
<!-- End Authors -->
|
376
|
+
<!-- Start Commits -->
|
377
|
+
<div class="tab-pane" id="commits">
|
378
|
+
<div class="page-header">
|
379
|
+
<h1>Commits</h1>
|
380
|
+
<p class="lead">A few basic stats on single commits.</p>
|
381
|
+
</div>
|
382
|
+
|
383
|
+
<% shortest_commit = @commits.min_by { |c| c.subject.length } %>
|
384
|
+
<% longest_commit = @commits.max_by { |c| c.subject.length } %>
|
385
|
+
|
386
|
+
<h2>Shortest commit message</h2>
|
387
|
+
<blockquote>
|
388
|
+
<p><%=shortest_commit.subject %></p>
|
389
|
+
<footer><%=shortest_commit.author.name %> <cite><%=shortest_commit.date.strftime('%a %-d, %B %Y') %></cite></footer>
|
390
|
+
</blockquote>
|
391
|
+
|
392
|
+
<hr/>
|
393
|
+
|
394
|
+
<h2>Longest commit message</h2>
|
395
|
+
<blockquote>
|
396
|
+
<p><%=longest_commit.subject %></p>
|
397
|
+
<footer><%=longest_commit.author.name %> <cite><%=longest_commit.date.strftime('%a %-d, %B %Y') %></cite></footer>
|
398
|
+
</blockquote>
|
399
|
+
|
209
400
|
</div>
|
401
|
+
<!-- End Commits -->
|
402
|
+
<!-- Start Dates -->
|
403
|
+
<div class="tab-pane" id="dates">
|
404
|
+
<div class="page-header">
|
405
|
+
<h1>Dates</h1>
|
406
|
+
<p class="lead">When are those commits happening?</p>
|
407
|
+
</div>
|
408
|
+
|
409
|
+
<% first_commit = @commits.min_by(&:date) %>
|
410
|
+
<% last_commit = @commits.max_by(&:date) %>
|
411
|
+
|
412
|
+
<h2>First Commit Ever</h2>
|
413
|
+
<blockquote>
|
414
|
+
<p><%=first_commit.subject %></p>
|
415
|
+
<footer><%=first_commit.author.name %> <cite><%=first_commit.date.strftime('%a %-d, %B %Y') %></cite></footer>
|
416
|
+
</blockquote>
|
417
|
+
|
418
|
+
<hr/>
|
419
|
+
|
420
|
+
<h2>Last Commit</h2>
|
421
|
+
<blockquote>
|
422
|
+
<p><%=last_commit.subject %></p>
|
423
|
+
<footer><%=last_commit.author.name %> <cite><%=last_commit.date.strftime('%a %-d, %B %Y') %></cite></footer>
|
424
|
+
</blockquote>
|
425
|
+
|
426
|
+
<hr/>
|
427
|
+
|
428
|
+
<h2>Most Busy Days</h2>
|
429
|
+
<canvas id="daysBarChart" width="1100" height="400"></canvas>
|
430
|
+
|
431
|
+
</div>
|
432
|
+
<!-- End Dates -->
|
210
433
|
</div>
|
211
434
|
</div>
|
212
435
|
</div>
|
@@ -218,63 +441,79 @@
|
|
218
441
|
</div>
|
219
442
|
|
220
443
|
|
221
|
-
<!--
|
444
|
+
<!-- External JavaScript Files
|
222
445
|
================================================== -->
|
223
|
-
|
224
|
-
<script src="https://
|
225
|
-
<script src="
|
226
|
-
<script src="http://cdnjs.cloudflare.com/ajax/libs/Chart.js/0.2.0/Chart.min.js"></script>
|
446
|
+
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
|
447
|
+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
|
448
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.min.js"></script>
|
227
449
|
<script>
|
228
450
|
$('.user-avatar').popover({ trigger: 'hover', html: true }).click(function(e){
|
229
451
|
e.preventDefault();
|
230
452
|
});
|
231
453
|
|
232
454
|
// Data for Users Pie Chart
|
233
|
-
var data = [<%= @users.map{|d| "{ value: #{d.commits.count}, color: '#{d.rgba}' }" }.join(',') %>];
|
234
|
-
var ctx = document.getElementById("usersPieChart").getContext("2d");
|
235
|
-
var usersPieChart = new Chart(ctx).Pie(data);
|
236
|
-
|
237
|
-
// Data for Insertions vs. Deletions Bar Chart
|
238
455
|
var data = {
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
},
|
246
|
-
{
|
247
|
-
data: [<%= @users.map{|d| "#{d.total_deletions}" }.join(',') %>],
|
248
|
-
fillColor: 'rgba(234, 80, 44, 0.5)',
|
249
|
-
strokeColor: 'rgba(234, 80, 44, 1)'
|
250
|
-
}
|
251
|
-
]
|
456
|
+
datasets: [{
|
457
|
+
data: [<%= @users.map{|u| "#{u.commits.count}" }.join(', ') %>],
|
458
|
+
backgroundColor: [<%= @users.map{|u| "'#{u.rgba}'" }.join(', ') %>]
|
459
|
+
}],
|
460
|
+
labels: [<%= @users.map{|u| "'#{u.name}'" }.join(', ') %>
|
461
|
+
]
|
252
462
|
};
|
253
|
-
var ctx = document.getElementById("
|
254
|
-
var
|
463
|
+
var ctx = document.getElementById("usersPieChart").getContext("2d");
|
464
|
+
var usersPieChart = new Chart(ctx,{
|
465
|
+
type: 'pie',
|
466
|
+
data: data,
|
467
|
+
options: {
|
468
|
+
legend: {
|
469
|
+
display: false
|
470
|
+
}
|
471
|
+
}
|
472
|
+
});
|
473
|
+
|
474
|
+
// // Data for Insertions vs. Deletions Bar Chart
|
475
|
+
// var data = {
|
476
|
+
// labels: [<%= @users.map{|d| "'#{d.name}'" }.join(',') %>],
|
477
|
+
// datasets: [
|
478
|
+
// {
|
479
|
+
// data: [<%= @users.map{|d| "#{d.total_insertions}" }.join(',') %>],
|
480
|
+
// fillColor: 'rgba(196, 234, 44, 0.5)',
|
481
|
+
// strokeColor: 'rgba(196, 234, 44, 1)'
|
482
|
+
// },
|
483
|
+
// {
|
484
|
+
// data: [<%= @users.map{|d| "#{d.total_deletions}" }.join(',') %>],
|
485
|
+
// fillColor: 'rgba(234, 80, 44, 0.5)',
|
486
|
+
// strokeColor: 'rgba(234, 80, 44, 1)'
|
487
|
+
// }
|
488
|
+
// ]
|
489
|
+
// };
|
490
|
+
// var ctx = document.getElementById("usersBarChart").getContext("2d");
|
491
|
+
// var usersBarChart = new Chart(ctx).Bar(data);
|
255
492
|
|
256
493
|
// Data for Weekday commits per user
|
257
494
|
var data = {
|
258
495
|
labels: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
259
496
|
datasets: [
|
260
|
-
<% @users.each_with_index do |user, i| %>
|
261
497
|
{
|
262
|
-
|
263
|
-
|
264
|
-
pointColor : "<%= user.rgba %>",
|
265
|
-
pointStrokeColor : "#fff",
|
266
|
-
data : [<%= user.weekday_commits.join(', ') %>]
|
267
|
-
}<%= ',' unless i + 1 == @users.count %>
|
268
|
-
<% end %>
|
498
|
+
data : [<%= @weekday_commits.join(', ') %>]
|
499
|
+
}
|
269
500
|
]
|
270
501
|
};
|
271
|
-
var ctx = document.getElementById("
|
272
|
-
var
|
502
|
+
var ctx = document.getElementById("daysBarChart").getContext("2d");
|
503
|
+
var myBarChart = new Chart(ctx, {
|
504
|
+
type: 'bar',
|
505
|
+
data: data,
|
506
|
+
options: {
|
507
|
+
legend: {
|
508
|
+
display: false
|
509
|
+
}
|
510
|
+
}
|
511
|
+
});
|
273
512
|
|
274
513
|
// Makes dashboard items link to tabs
|
275
514
|
$('a[data-open-tab]').click(function(e) {
|
276
515
|
e.preventDefault();
|
277
|
-
$('a[href="#' + $(this).attr('data-open-tab') + '"]').click();
|
516
|
+
$('.navbar-nav').find('a[href="#' + $(this).attr('data-open-tab') + '"]').click();
|
278
517
|
});
|
279
518
|
</script>
|
280
519
|
</body>
|
data/bin/gitalytics
CHANGED
@@ -8,7 +8,9 @@ require 'optparse'
|
|
8
8
|
require 'gitalytics'
|
9
9
|
|
10
10
|
options = {
|
11
|
-
|
11
|
+
browser: false,
|
12
|
+
format: 'cli',
|
13
|
+
group_by: 'name'
|
12
14
|
}
|
13
15
|
|
14
16
|
OptionParser.new do |opts|
|
@@ -28,7 +30,11 @@ OptionParser.new do |opts|
|
|
28
30
|
options[:format] = 'html'
|
29
31
|
options[:browser] = false
|
30
32
|
end
|
33
|
+
|
34
|
+
opts.on("-e", "--group-email", "Group commits by author's email address") do |v|
|
35
|
+
options[:group_by] = 'email'
|
36
|
+
end
|
31
37
|
end.parse!
|
32
38
|
|
33
39
|
Dir.chdir($1 || '.')
|
34
|
-
Gitalytics.
|
40
|
+
Gitalytics.analyze(options)
|
data/gitalytics.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gitalytics/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "gitalytics"
|
8
|
+
spec.version = Gitalytics::VERSION
|
9
|
+
|
10
|
+
spec.authors = ["Gonzalo Robaina"]
|
11
|
+
spec.email = "gonzalor@gmail.com"
|
12
|
+
|
13
|
+
spec.summary = "Git Analytics"
|
14
|
+
spec.description = "Get usefull analytics from your git log"
|
15
|
+
spec.homepage = "http://gonza.uy/gitalytics"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0")
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.required_ruby_version = '>= 1.9.3'
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_dependency "color-generator"
|
28
|
+
end
|
data/lib/gitalytics.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
3
|
require 'erb'
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
require '
|
4
|
+
require 'matrix'
|
5
|
+
require 'gitalytics/commit'
|
6
|
+
require 'gitalytics/gitlog'
|
7
|
+
require 'gitalytics/user'
|
8
|
+
require 'gitalytics/version'
|
7
9
|
|
8
|
-
|
10
|
+
module Gitalytics
|
9
11
|
|
10
|
-
|
12
|
+
module_function
|
11
13
|
|
12
14
|
def analyze(options)
|
13
|
-
data = GitLog.parse_git_log
|
15
|
+
data = GitLog.parse_git_log(options[:group_by])
|
14
16
|
|
15
17
|
case options[:format]
|
16
18
|
when 'html'
|
@@ -22,6 +24,8 @@ class Gitalytics
|
|
22
24
|
|
23
25
|
private
|
24
26
|
|
27
|
+
module_function
|
28
|
+
|
25
29
|
def output_cli_report(users)
|
26
30
|
users.each do |user|
|
27
31
|
puts user.summary
|
@@ -37,6 +41,9 @@ class Gitalytics
|
|
37
41
|
y.commits.length <=> x.commits.length
|
38
42
|
end
|
39
43
|
@commits = data[:commits]
|
44
|
+
weekday_commits = @users.map(&:weekday_commits)
|
45
|
+
@weekday_commits = weekday_commits.map { |a| Vector[*a] }.inject(:+).to_a
|
46
|
+
|
40
47
|
file.write(erb.result(binding))
|
41
48
|
end
|
42
49
|
open_report_in_browser(output_file) if open_in_browser
|
@@ -52,5 +59,4 @@ class Gitalytics
|
|
52
59
|
system "xdg-open #{filename}"
|
53
60
|
end
|
54
61
|
end
|
55
|
-
|
56
62
|
end
|
File without changes
|
@@ -1,22 +1,22 @@
|
|
1
|
-
require 'commit'
|
2
|
-
require 'user'
|
1
|
+
require 'gitalytics/commit'
|
2
|
+
require 'gitalytics/user'
|
3
3
|
require 'date'
|
4
4
|
|
5
5
|
module GitLog
|
6
6
|
|
7
7
|
module_function
|
8
8
|
|
9
|
-
def parse_git_log
|
9
|
+
def parse_git_log(group_by)
|
10
10
|
users, commits = [], []
|
11
11
|
|
12
12
|
log = get_log
|
13
13
|
blocks = get_blocks(log)
|
14
14
|
|
15
15
|
blocks.each do |(hash, block_string)|
|
16
|
-
commits << parse_block(hash, block_string, users)
|
16
|
+
commits << parse_block(hash, block_string, users, group_by)
|
17
17
|
end
|
18
18
|
|
19
|
-
{
|
19
|
+
{users: users, commits: commits}
|
20
20
|
end
|
21
21
|
|
22
22
|
def get_log
|
@@ -31,7 +31,7 @@ module GitLog
|
|
31
31
|
commits.zip(blocks)
|
32
32
|
end
|
33
33
|
|
34
|
-
def parse_block(hash, block_string, users)
|
34
|
+
def parse_block(hash, block_string, users, group_by)
|
35
35
|
commit = Commit.new(hash)
|
36
36
|
|
37
37
|
block_string.encode!('UTF-8', 'UTF8-MAC') if defined?(Encoding::UTF8_MAC)
|
@@ -41,7 +41,7 @@ module GitLog
|
|
41
41
|
commit.subject = data[:subject]
|
42
42
|
commit.date = Date.parse(data[:date])
|
43
43
|
|
44
|
-
get_commit_author(data, commit, users)
|
44
|
+
get_commit_author(data, commit, users, group_by)
|
45
45
|
get_commit_summary(block_string, commit)
|
46
46
|
|
47
47
|
commit
|
@@ -57,16 +57,22 @@ module GitLog
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
def get_commit_author(data, commit, users)
|
61
|
-
user = get_user(data[:name], data[:email], users)
|
60
|
+
def get_commit_author(data, commit, users, group_by)
|
61
|
+
user = get_user(data[:name], data[:email], users, group_by)
|
62
62
|
|
63
63
|
commit.author = user
|
64
64
|
user.commits << commit
|
65
65
|
end
|
66
66
|
|
67
|
-
def get_user(name, email, users)
|
68
|
-
|
69
|
-
|
67
|
+
def get_user(name, email, users, group_by)
|
68
|
+
if group_by == 'name'
|
69
|
+
users.each do |user|
|
70
|
+
return user if user.name == name
|
71
|
+
end
|
72
|
+
elsif group_by == 'email'
|
73
|
+
users.each do |user|
|
74
|
+
return user if user.email == email
|
75
|
+
end
|
70
76
|
end
|
71
77
|
users << new_user = User.new(name, email)
|
72
78
|
new_user
|
@@ -1,19 +1,15 @@
|
|
1
|
+
require 'color-generator'
|
1
2
|
require 'digest/md5'
|
2
|
-
require 'CGI'
|
3
3
|
|
4
4
|
class User
|
5
5
|
|
6
6
|
attr_accessor :name, :email, :commits, :colors
|
7
7
|
|
8
8
|
def initialize(name, email)
|
9
|
-
self.name
|
10
|
-
self.email
|
9
|
+
self.name = name
|
10
|
+
self.email = email
|
11
11
|
self.commits = []
|
12
|
-
self.colors
|
13
|
-
end
|
14
|
-
|
15
|
-
def escaped_name
|
16
|
-
CGI.escapeHTML(name)
|
12
|
+
self.colors = ColorGenerator.new(saturation: 0.3, lightness: 0.75).create_rgb.join(', ')
|
17
13
|
end
|
18
14
|
|
19
15
|
def gravatar
|
@@ -44,8 +40,12 @@ class User
|
|
44
40
|
commits.map(&:deletions).inject(0) { |total, current| total + current }
|
45
41
|
end
|
46
42
|
|
43
|
+
def total_changes
|
44
|
+
total_insertions + total_deletions
|
45
|
+
end
|
46
|
+
|
47
47
|
def summary
|
48
|
-
"#{name} has made #{commits.count} commits
|
48
|
+
"#{name} has made #{commits.count} commits on #{working_days} separate days during a span of #{commits_period} days."
|
49
49
|
end
|
50
50
|
|
51
51
|
def rgba(opacity = 1)
|
@@ -54,8 +54,9 @@ class User
|
|
54
54
|
|
55
55
|
def weekday_commits
|
56
56
|
days = Array.new(7) {0}
|
57
|
-
commits.each
|
57
|
+
commits.each do |c|
|
58
|
+
days[c.date.wday] += 1
|
59
|
+
end
|
58
60
|
days
|
59
61
|
end
|
60
|
-
|
61
62
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper.rb')
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'gitalytics/commit'
|
4
|
+
|
5
|
+
class TestCommit < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@commit = Commit.new('abcdef0123456789')
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_commit(commit)
|
12
|
+
commit.summary << {
|
13
|
+
insertions: 3,
|
14
|
+
deletions: 2,
|
15
|
+
filename: 'a.rb'
|
16
|
+
}
|
17
|
+
commit.summary << {
|
18
|
+
insertions: 4,
|
19
|
+
deletions: 3,
|
20
|
+
filename: 'b.rb'
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_that_count_insertions
|
25
|
+
build_commit(@commit)
|
26
|
+
|
27
|
+
assert_equal(7, @commit.insertions)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_that_count_deletions
|
31
|
+
build_commit(@commit)
|
32
|
+
|
33
|
+
assert_equal(5, @commit.deletions)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_that_count_files_committed
|
37
|
+
build_commit(@commit)
|
38
|
+
|
39
|
+
assert_equal(['a.rb', 'b.rb'], @commit.files_committed)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper.rb')
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'gitalytics/gitlog'
|
4
|
+
|
5
|
+
class TestCommit < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def git_log
|
8
|
+
|
9
|
+
%q(bea63e76c7c6d5afd42ac5b24a911b36e5c261f9 2013-02-13 23:11:16 -0200 Gonzalo Robaina <gonzalor@gmail.com> Print basic commit report on the console
|
10
|
+
|
11
|
+
6 1 bin/gitalytics
|
12
|
+
33 6 lib/gitalytics.rb
|
13
|
+
d392710a9e657c72e73ca87df3ed2c8c802441e4 2012-12-19 06:04:59 -0800 Gonzalo Robaina <gonzalor@gmail.com> Initial commit
|
14
|
+
|
15
|
+
16 0 .gitignore
|
16
|
+
4 0 README.md
|
17
|
+
9a99ae5dbc1eaadf268ca925cce9b68d10216151 2012-12-06 10:29:49 -0200 Gonzalo Robaina <gonzalor@gmail.com> initial commit
|
18
|
+
|
19
|
+
1 0 README.md
|
20
|
+
3 0 bin/gitalytics
|
21
|
+
13 0 gitalytics.gemspec
|
22
|
+
49 0 lib/gist.rb
|
23
|
+
11 0 lib/gitalytics.rb
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_get_blocks
|
28
|
+
expected_blocks = [
|
29
|
+
%q(2013-02-13 23:11:16 -0200 Gonzalo Robaina <gonzalor@gmail.com> Print basic commit report on the console
|
30
|
+
|
31
|
+
6 1 bin/gitalytics
|
32
|
+
33 6 lib/gitalytics.rb),
|
33
|
+
|
34
|
+
%q(2012-12-19 06:04:59 -0800 Gonzalo Robaina <gonzalor@gmail.com> Initial commit
|
35
|
+
|
36
|
+
16 0 .gitignore
|
37
|
+
4 0 README.md),
|
38
|
+
|
39
|
+
%q(2012-12-06 10:29:49 -0200 Gonzalo Robaina <gonzalor@gmail.com> initial commit
|
40
|
+
|
41
|
+
1 0 README.md
|
42
|
+
3 0 bin/gitalytics
|
43
|
+
13 0 gitalytics.gemspec
|
44
|
+
49 0 lib/gist.rb
|
45
|
+
11 0 lib/gitalytics.rb)
|
46
|
+
]
|
47
|
+
|
48
|
+
expected_commits = [
|
49
|
+
'bea63e76c7c6d5afd42ac5b24a911b36e5c261f9',
|
50
|
+
'd392710a9e657c72e73ca87df3ed2c8c802441e4',
|
51
|
+
'9a99ae5dbc1eaadf268ca925cce9b68d10216151',
|
52
|
+
]
|
53
|
+
blocks = GitLog.get_blocks(git_log)
|
54
|
+
|
55
|
+
assert_equal(expected_commits, blocks.map(&:first))
|
56
|
+
assert_equal(expected_blocks, blocks.map(&:last))
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_parse_block
|
60
|
+
blocks = GitLog.get_blocks(git_log)
|
61
|
+
hash, block = blocks.last
|
62
|
+
|
63
|
+
users = []
|
64
|
+
commit = GitLog.parse_block(hash, block, users, 'email')
|
65
|
+
|
66
|
+
assert_equal(
|
67
|
+
['README.md', 'bin/gitalytics', 'gitalytics.gemspec', 'lib/gist.rb', 'lib/gitalytics.rb'],
|
68
|
+
commit.files_committed
|
69
|
+
)
|
70
|
+
assert_equal(77, commit.insertions)
|
71
|
+
assert_equal(0, commit.deletions)
|
72
|
+
assert_equal('Gonzalo Robaina', commit.author.name)
|
73
|
+
assert_equal('gonzalor@gmail.com', commit.author.email)
|
74
|
+
assert_equal('initial commit', commit.subject)
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_get_user_creates_the_user
|
78
|
+
users = []
|
79
|
+
user = GitLog.get_user('name', 'email@example.com', users, 'name')
|
80
|
+
|
81
|
+
assert_equal(1, users.count)
|
82
|
+
assert_equal(user, users.last)
|
83
|
+
assert_equal('name', user.name)
|
84
|
+
assert_equal('email@example.com', user.email)
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_get_user_returns_the_user
|
88
|
+
users = [User.new('name', 'email@example.com')]
|
89
|
+
|
90
|
+
user = GitLog.get_user('name', 'email@example.com', users, 'email')
|
91
|
+
assert_equal(user, users.last)
|
92
|
+
assert_equal('name', user.name)
|
93
|
+
assert_equal('email@example.com', user.email)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_get_commit_author_links_user_and_commit
|
97
|
+
data = { name: 'test', email: 'test@email.com' }
|
98
|
+
commit = Commit.new(hash)
|
99
|
+
users = []
|
100
|
+
|
101
|
+
GitLog.get_commit_author(data, commit, users, 'name')
|
102
|
+
assert_equal(users.last, commit.author)
|
103
|
+
assert_equal(users.last.commits.last, commit)
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper.rb')
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'gitalytics/user'
|
4
|
+
require 'gitalytics/commit'
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
class TestUser < MiniTest::Unit::TestCase
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@user = User.new('John Doe', 'john@doe.com')
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_commit(hash, date, summary_data)
|
14
|
+
Commit.new(hash).tap do |commit|
|
15
|
+
commit.date = Date.parse(date)
|
16
|
+
summary_data.each { |summary| commit.summary << summary }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_commits(user)
|
21
|
+
user.commits << create_commit('abcdef', '2000-01-10', [{ # weekday: 1
|
22
|
+
filename: 'a.rb',
|
23
|
+
insertions: 1,
|
24
|
+
deletions: 0,
|
25
|
+
}])
|
26
|
+
user.commits << create_commit('abcdef', '2000-01-01', [{ # weekday: 6
|
27
|
+
filename: 'c.rb',
|
28
|
+
insertions: 0,
|
29
|
+
deletions: 1,
|
30
|
+
}])
|
31
|
+
user.commits << create_commit('abcdef', '2000-01-01', [{ # weekday: 6
|
32
|
+
filename: 'd.rb',
|
33
|
+
insertions: 4,
|
34
|
+
deletions: 5
|
35
|
+
}])
|
36
|
+
user.commits << create_commit('abcdef', '2000-01-08', [{ # weekday: 6
|
37
|
+
filename: 'e.rb',
|
38
|
+
insertions: 1,
|
39
|
+
deletions: 1
|
40
|
+
}])
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_initial_color
|
44
|
+
assert_match(/\d{1,3}, \d{1,3}, \d{1,3}/, @user.colors)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_gravatar_is_md5
|
48
|
+
assert_match(/[a-f0-9]{32}/, @user.gravatar)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_first_commit
|
52
|
+
create_commits(@user)
|
53
|
+
|
54
|
+
assert_equal(Date.parse('2000-1-1'), @user.first_commit.date)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_last_commit
|
58
|
+
create_commits(@user)
|
59
|
+
|
60
|
+
assert_equal(Date.parse('2000-1-10'), @user.last_commit.date)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_working_days
|
64
|
+
create_commits(@user)
|
65
|
+
|
66
|
+
assert_equal(3, @user.working_days)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_weekday_commits
|
70
|
+
create_commits(@user)
|
71
|
+
|
72
|
+
assert_equal([0, 1, 0, 0, 0, 0, 3], @user.weekday_commits)
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_total_insertions
|
76
|
+
create_commits(@user)
|
77
|
+
|
78
|
+
assert_equal(6, @user.total_insertions)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_total_deletions
|
82
|
+
create_commits(@user)
|
83
|
+
|
84
|
+
assert_equal(7, @user.total_deletions)
|
85
|
+
end
|
86
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,15 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitalytics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.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:
|
12
|
-
dependencies:
|
11
|
+
date: 2016-07-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: color-generator
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
13
55
|
description: Get usefull analytics from your git log
|
14
56
|
email: gonzalor@gmail.com
|
15
57
|
executables:
|
@@ -17,13 +59,27 @@ executables:
|
|
17
59
|
extensions: []
|
18
60
|
extra_rdoc_files: []
|
19
61
|
files:
|
62
|
+
- ".coveralls.yml"
|
63
|
+
- ".gitignore"
|
64
|
+
- ".travis.yml"
|
65
|
+
- CHANGELOG.md
|
66
|
+
- Gemfile
|
67
|
+
- Gemfile.lock
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
20
70
|
- assets/gitalytics.html.erb
|
21
71
|
- bin/gitalytics
|
22
|
-
-
|
72
|
+
- gitalytics.gemspec
|
23
73
|
- lib/gitalytics.rb
|
24
|
-
- lib/
|
25
|
-
- lib/
|
26
|
-
|
74
|
+
- lib/gitalytics/commit.rb
|
75
|
+
- lib/gitalytics/gitlog.rb
|
76
|
+
- lib/gitalytics/user.rb
|
77
|
+
- lib/gitalytics/version.rb
|
78
|
+
- test/lib/test_commit.rb
|
79
|
+
- test/lib/test_gitlog.rb
|
80
|
+
- test/lib/test_user.rb
|
81
|
+
- test/test_helper.rb
|
82
|
+
homepage: http://gonza.uy/gitalytics
|
27
83
|
licenses:
|
28
84
|
- MIT
|
29
85
|
metadata: {}
|
@@ -33,18 +89,22 @@ require_paths:
|
|
33
89
|
- lib
|
34
90
|
required_ruby_version: !ruby/object:Gem::Requirement
|
35
91
|
requirements:
|
36
|
-
- -
|
92
|
+
- - ">="
|
37
93
|
- !ruby/object:Gem::Version
|
38
|
-
version:
|
94
|
+
version: 1.9.3
|
39
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
96
|
requirements:
|
41
|
-
- -
|
97
|
+
- - ">="
|
42
98
|
- !ruby/object:Gem::Version
|
43
99
|
version: '0'
|
44
100
|
requirements: []
|
45
101
|
rubyforge_project:
|
46
|
-
rubygems_version: 2.4.
|
102
|
+
rubygems_version: 2.4.3
|
47
103
|
signing_key:
|
48
104
|
specification_version: 4
|
49
105
|
summary: Git Analytics
|
50
|
-
test_files:
|
106
|
+
test_files:
|
107
|
+
- test/lib/test_commit.rb
|
108
|
+
- test/lib/test_gitlog.rb
|
109
|
+
- test/lib/test_user.rb
|
110
|
+
- test/test_helper.rb
|