git_stats 1.0.11 → 1.0.12
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/.gitmodules +3 -0
- data/README.md +16 -10
- data/config/locales/de.yml +2 -0
- data/config/locales/en.yml +4 -1
- data/lib/git_stats/base.rb +3 -1
- data/lib/git_stats/cli.rb +5 -3
- data/lib/git_stats/core_extensions/enumerable.rb +10 -0
- data/lib/git_stats/generator.rb +4 -4
- data/lib/git_stats/git_data/comment_stat.rb +38 -0
- data/lib/git_stats/git_data/commit.rb +8 -4
- data/lib/git_stats/git_data/repo.rb +46 -13
- data/lib/git_stats/git_data/short_stat.rb +1 -1
- data/lib/git_stats/git_data/tree.rb +23 -0
- data/lib/git_stats/i18n.rb +1 -0
- data/lib/git_stats/stats_view/charts/authors_charts.rb +6 -4
- data/lib/git_stats/stats_view/charts/charts.rb +1 -1
- data/lib/git_stats/stats_view/charts/repo_charts.rb +10 -0
- data/lib/git_stats/stats_view/view.rb +2 -1
- data/lib/git_stats/version.rb +1 -1
- data/spec/factories.rb +8 -0
- data/spec/git_data/commit_range_spec.rb +2 -2
- data/spec/git_data/commit_spec.rb +1 -1
- data/spec/git_data/generator_spec.rb +5 -7
- data/spec/git_data/repo_spec.rb +5 -5
- data/spec/git_data/short_stat_spec.rb +1 -1
- data/spec/git_data/tree_spec.rb +41 -0
- data/spec/integration/author_spec.rb +2 -2
- data/spec/integration/file_spec.rb +2 -2
- data/spec/integration/shared.rb +91 -0
- data/spec/integration/tree_spec.rb +197 -0
- data/templates/author_details/_author_details.haml +4 -4
- data/templates/authors/_authors.haml +5 -5
- data/templates/comments/_comments.haml +11 -0
- data/templates/comments/by_date.haml +1 -0
- data/templates/general.haml +3 -0
- metadata +31 -25
- data/lib/git_stats/by_field_finder.rb +0 -7
- data/spec/by_field_finder_spec.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2fdf7c3f12067e71e3eddbd26ece408572f6d0bf
|
4
|
+
data.tar.gz: 79b20aeae19c213893f447432a34bd81bb89880e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3286e2ccc323720aa0532f0112d77ff103136646ac14f64e425c7787e3c9b67bc91eee7e0f23e22cfe15a0d0ca02796a61f9e7aa8fab0fae5cc23f4aa9194a7d
|
7
|
+
data.tar.gz: 87b139080a6f5420c7267cc858d73ba4494c745e40b60e599fe2ac2f763a615b08e28d67f89c235c7f85bad73a6b3891ec3148c7b3542035fedf7129edb4d1bb
|
data/.gitmodules
CHANGED
@@ -1,3 +1,6 @@
|
|
1
1
|
[submodule "spec/integration/test_repo"]
|
2
2
|
path = spec/integration/test_repo
|
3
3
|
url = git://github.com/tomgi/git_stats_test_repo.git
|
4
|
+
[submodule "spec/integration/test_repo_tree"]
|
5
|
+
path = spec/integration/test_repo_tree
|
6
|
+
url = git://github.com/irevert/git_stats_test_repo_tree
|
data/README.md
CHANGED
@@ -34,16 +34,22 @@ It browses the repository and outputs html page with statistics.
|
|
34
34
|
git_stats generate
|
35
35
|
|
36
36
|
Options:
|
37
|
-
p, [--path=PATH]
|
38
|
-
|
39
|
-
o, [--
|
40
|
-
|
41
|
-
l, [--language=LANGUAGE]
|
42
|
-
|
43
|
-
f, [--from=FROM]
|
44
|
-
t, [--to=TO]
|
45
|
-
|
46
|
-
s, [--silent]
|
37
|
+
p, [--path=PATH] # Path to repository from which statistics should be generated.
|
38
|
+
# Default: .
|
39
|
+
o, [--out-path=OUT_PATH] # Output path where statistics should be written.
|
40
|
+
# Default: ./git_stats
|
41
|
+
l, [--language=LANGUAGE] # Language of written statistics.
|
42
|
+
# Default: en
|
43
|
+
f, [--from=FROM] # Commit from where statistics should start.
|
44
|
+
t, [--to=TO] # Commit where statistics should stop.
|
45
|
+
# Default: HEAD
|
46
|
+
s, [--silent], [--no-silent] # Silent mode. Don't output anything.
|
47
|
+
d, [--tree=TREE] # Tree where statistics should be generated.
|
48
|
+
# Default: .
|
49
|
+
c, [--comment=COMMENT] # The string which is used for comments.
|
50
|
+
# Default: //
|
51
|
+
|
52
|
+
|
47
53
|
|
48
54
|
#### Start generator with default settings
|
49
55
|
|
data/config/locales/de.yml
CHANGED
@@ -12,8 +12,10 @@ de:
|
|
12
12
|
commits_by_hour: Commits in der Stunde
|
13
13
|
files: Dateien
|
14
14
|
lines: Zeilen
|
15
|
+
comments: Kommentare
|
15
16
|
files_by_date: Dateien nach Datum
|
16
17
|
lines_by_date: Zeilen nach Datum
|
18
|
+
comments_by_date: Kommentare nach Datum
|
17
19
|
files_by_extension: Dateien nach Erweiterungen
|
18
20
|
lines_by_extension: Zeilen nach Erweiterungen
|
19
21
|
hour_of_day: Tagesstunden
|
data/config/locales/en.yml
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
en:
|
2
2
|
project_name: Project name
|
3
3
|
project_version: Project version
|
4
|
+
tree_path: Tree path
|
4
5
|
generated_at: Generated at
|
5
6
|
generator: Generator
|
6
7
|
report_period: Report period
|
@@ -12,8 +13,10 @@ en:
|
|
12
13
|
commits_by_hour: Commits by hour
|
13
14
|
files: Files
|
14
15
|
lines: Lines
|
16
|
+
comments: Comments
|
15
17
|
files_by_date: Files by date
|
16
18
|
lines_by_date: Lines by date
|
19
|
+
comments_by_date: Comments by date
|
17
20
|
files_by_extension: Files by extension
|
18
21
|
lines_by_extension: Lines by extension
|
19
22
|
hour_of_day: Hour of day
|
@@ -57,4 +60,4 @@ en:
|
|
57
60
|
details: Details
|
58
61
|
insertions_by_date: Lines added by date
|
59
62
|
deletions_by_date: Lines deleted by date
|
60
|
-
changed_lines_by_date: Changed lines by date
|
63
|
+
changed_lines_by_date: Changed lines by date
|
data/lib/git_stats/base.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
require 'git_stats/core_extensions/hash'
|
3
3
|
require 'git_stats/core_extensions/string'
|
4
4
|
require 'git_stats/core_extensions/symbol'
|
5
|
+
require 'git_stats/core_extensions/enumerable'
|
5
6
|
|
6
7
|
require 'git_stats/version'
|
7
8
|
require 'git_stats/i18n'
|
8
|
-
require 'git_stats/by_field_finder'
|
9
9
|
require 'git_stats/cli'
|
10
10
|
require 'git_stats/generator'
|
11
11
|
require 'git_stats/validator'
|
@@ -18,6 +18,8 @@ require 'git_stats/git_data/command_runner'
|
|
18
18
|
require 'git_stats/git_data/commit'
|
19
19
|
require 'git_stats/git_data/repo'
|
20
20
|
require 'git_stats/git_data/short_stat'
|
21
|
+
require 'git_stats/git_data/comment_stat'
|
22
|
+
require 'git_stats/git_data/tree'
|
21
23
|
|
22
24
|
require 'git_stats/stats_view/template'
|
23
25
|
require 'git_stats/stats_view/view'
|
data/lib/git_stats/cli.rb
CHANGED
@@ -4,16 +4,18 @@ require "thor"
|
|
4
4
|
|
5
5
|
class GitStats::CLI < Thor
|
6
6
|
option :path, :aliases => :p, :default => '.', :desc => 'Path to repository from which statistics should be generated.'
|
7
|
-
option :
|
7
|
+
option :out_path, :aliases => :o, :default => './git_stats', :desc => 'Output path where statistics should be written.'
|
8
8
|
option :language, :aliases => :l, :default => 'en', :desc => 'Language of written statistics.'
|
9
9
|
option :from, :aliases => :f, :desc => 'Commit from where statistics should start.'
|
10
10
|
option :to, :aliases => :t, :default => 'HEAD', :desc => 'Commit where statistics should stop.'
|
11
11
|
option :silent, :aliases => :s, :type => :boolean, :desc => 'Silent mode. Don\'t output anything.'
|
12
|
-
|
12
|
+
option :tree, :aliases => :d, :default => '.', :desc => 'Tree where statistics should be generated.'
|
13
|
+
option :comment, :aliases => :c, :default => '//', :desc => 'The string which is used for comments.'
|
14
|
+
|
13
15
|
desc 'generate', 'Generates the statistics of a repository'
|
14
16
|
def generate
|
15
17
|
I18n.locale = options[:language]
|
16
|
-
GitStats::Generator.new(options
|
18
|
+
GitStats::Generator.new(options) { |g|
|
17
19
|
g.add_command_observer { |command, result| puts "#{command}" } unless options[:silent]
|
18
20
|
}.render_all
|
19
21
|
end
|
data/lib/git_stats/generator.rb
CHANGED
@@ -4,12 +4,12 @@ module GitStats
|
|
4
4
|
delegate :add_command_observer, to: :@repo
|
5
5
|
delegate :render_all, to: :@view
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
validate_repo_path(
|
7
|
+
def initialize(options)
|
8
|
+
validate_repo_path(options[:path])
|
9
9
|
|
10
|
-
@repo = GitData::Repo.new(
|
10
|
+
@repo = GitData::Repo.new(options)
|
11
11
|
view_data = StatsView::ViewData.new(@repo)
|
12
|
-
@view = StatsView::View.new(view_data, out_path)
|
12
|
+
@view = StatsView::View.new(view_data, options[:out_path])
|
13
13
|
|
14
14
|
yield self if block_given?
|
15
15
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module GitStats
|
3
|
+
module GitData
|
4
|
+
class CommentStat
|
5
|
+
attr_reader :commit, :insertions, :deletions
|
6
|
+
|
7
|
+
def initialize(commit)
|
8
|
+
@commit = commit
|
9
|
+
calculate_stat
|
10
|
+
end
|
11
|
+
|
12
|
+
def changed_lines
|
13
|
+
insertions + deletions
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"#{self.class} #@commit"
|
18
|
+
end
|
19
|
+
|
20
|
+
def escape_characters_in_string(string)
|
21
|
+
pattern = /(\'|\"|\.|\*|\/|\-|\\)/
|
22
|
+
string.gsub(pattern){|match|"\\" + match}
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def calculate_stat
|
27
|
+
escaped_string = escape_characters_in_string(commit.repo.comment_string)
|
28
|
+
stat_line = commit.repo.run("git show #{commit.sha} | awk 'BEGIN {adds=0; dels=0} {if ($0 ~ /^\\+#{escaped_string}/) adds++; if ($0 ~ /^\-#{escaped_string}/) dels++} END {print adds \" insertions \" dels \" deletes\"}'").lines.to_a[0]
|
29
|
+
if stat_line.blank?
|
30
|
+
@insertions = @deletions = 0
|
31
|
+
else
|
32
|
+
@insertions = stat_line[/(\d+) insertions?/, 1].to_i
|
33
|
+
@deletions = stat_line[/(\d+) deletes?/, 1].to_i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -9,9 +9,9 @@ module GitStats
|
|
9
9
|
attr_reader :repo, :sha, :stamp, :date, :author
|
10
10
|
|
11
11
|
def files
|
12
|
-
@files ||= repo.run_and_parse("git ls-tree -r #{self.sha}").map do |file|
|
12
|
+
@files ||= repo.run_and_parse("git ls-tree -r #{self.sha} -- #{repo.tree_path}").map do |file|
|
13
13
|
Blob.new(repo: repo, filename: file[:filename], sha: file[:sha])
|
14
|
-
end
|
14
|
+
end
|
15
15
|
end
|
16
16
|
|
17
17
|
def binary_files
|
@@ -37,11 +37,11 @@ module GitStats
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def files_count
|
40
|
-
@files_count ||= repo.run("git ls-tree -r --name-only #{self.sha} | wc -l").to_i
|
40
|
+
@files_count ||= repo.run("git ls-tree -r --name-only #{self.sha} -- #{repo.tree_path}| wc -l").to_i
|
41
41
|
end
|
42
42
|
|
43
43
|
def lines_count
|
44
|
-
@lines_count ||= repo.run("git diff --shortstat `git hash-object -t tree /dev/null` #{self.sha}").lines.map do |line|
|
44
|
+
@lines_count ||= repo.run("git diff --shortstat `git hash-object -t tree /dev/null` #{self.sha} -- #{repo.tree_path}").lines.map do |line|
|
45
45
|
line[/(\d+) insertions?/, 1].to_i
|
46
46
|
end.sum
|
47
47
|
end
|
@@ -50,6 +50,10 @@ module GitStats
|
|
50
50
|
@short_stat ||= ShortStat.new(self)
|
51
51
|
end
|
52
52
|
|
53
|
+
def comment_stat
|
54
|
+
@comment_stat ||= CommentStat.new(self)
|
55
|
+
end
|
56
|
+
|
53
57
|
def to_s
|
54
58
|
"#{self.class} #@sha"
|
55
59
|
end
|
@@ -6,32 +6,51 @@ module GitStats
|
|
6
6
|
class Repo
|
7
7
|
include HashInitializable
|
8
8
|
|
9
|
-
attr_reader :path, :first_commit_sha, :last_commit_sha
|
10
|
-
|
11
9
|
delegate :files, :files_by_extension, :files_by_extension_count, :lines_by_extension,
|
12
|
-
:files_count, :binary_files, :text_files, :lines_count, to: :last_commit
|
10
|
+
:files_count, :binary_files, :text_files, :lines_count, :comments_count, to: :last_commit
|
13
11
|
|
14
12
|
def initialize(params)
|
15
13
|
super(params)
|
16
14
|
@path = File.expand_path(@path)
|
15
|
+
@tree_path ||= "."
|
16
|
+
end
|
17
|
+
|
18
|
+
def path
|
19
|
+
@path ||= '.'
|
20
|
+
end
|
21
|
+
|
22
|
+
def first_commit_sha
|
23
|
+
@first_commit_sha
|
24
|
+
end
|
25
|
+
|
26
|
+
def last_commit_sha
|
27
|
+
@last_commit_sha ||= 'HEAD'
|
28
|
+
end
|
29
|
+
|
30
|
+
def tree_path
|
31
|
+
@tree_path ||= '.'
|
32
|
+
end
|
33
|
+
|
34
|
+
def comment_string
|
35
|
+
@comment_string ||= '//'
|
17
36
|
end
|
18
37
|
|
19
38
|
def authors
|
20
|
-
@authors ||= run_and_parse("git shortlog -se #{commit_range}").map do |author|
|
39
|
+
@authors ||= run_and_parse("git shortlog -se #{commit_range} #{tree_path}").map do |author|
|
21
40
|
Author.new(repo: self, name: author[:name], email: author[:email])
|
22
|
-
end
|
41
|
+
end
|
23
42
|
end
|
24
43
|
|
25
44
|
def commits
|
26
|
-
@commits ||= run_and_parse("git rev-list --pretty=format:'%h|%at|%ai|%aE' #{commit_range} | grep -v commit").map do |commit_line|
|
45
|
+
@commits ||= run_and_parse("git rev-list --pretty=format:'%h|%at|%ai|%aE' #{commit_range} #{tree_path} | grep -v commit").map do |commit_line|
|
27
46
|
Commit.new(
|
28
47
|
repo: self,
|
29
48
|
sha: commit_line[:sha],
|
30
49
|
stamp: commit_line[:stamp],
|
31
50
|
date: DateTime.parse(commit_line[:date]),
|
32
|
-
author: authors.
|
51
|
+
author: authors.first! { |a| a.email == commit_line[:author_email] }
|
33
52
|
)
|
34
|
-
end.sort_by! { |e| e.date }
|
53
|
+
end.sort_by! { |e| e.date }
|
35
54
|
end
|
36
55
|
|
37
56
|
def commits_period
|
@@ -63,6 +82,15 @@ module GitStats
|
|
63
82
|
}]
|
64
83
|
end
|
65
84
|
|
85
|
+
def comments_count_by_date
|
86
|
+
sum = 0
|
87
|
+
@comment_count_each_day ||= Hash[commits.map { |commit|
|
88
|
+
sum += commit.comment_stat.insertions
|
89
|
+
sum -= commit.comment_stat.deletions
|
90
|
+
[commit.date.to_date, sum]
|
91
|
+
}].fill_empty_days!(aggregated: true)
|
92
|
+
end
|
93
|
+
|
66
94
|
def last_commit
|
67
95
|
commits.last
|
68
96
|
end
|
@@ -71,14 +99,14 @@ module GitStats
|
|
71
99
|
@first_commit_sha.blank? ? last_commit_sha : "#@first_commit_sha..#{last_commit_sha}"
|
72
100
|
end
|
73
101
|
|
74
|
-
def last_commit_sha
|
75
|
-
@last_commit_sha ||= 'HEAD'
|
76
|
-
end
|
77
|
-
|
78
102
|
def short_stats
|
79
103
|
@short_stats ||= commits.map(&:short_stat)
|
80
104
|
end
|
81
105
|
|
106
|
+
def comment_stats
|
107
|
+
@comment_stats ||= commits.map(&:comment_stat)
|
108
|
+
end
|
109
|
+
|
82
110
|
def activity
|
83
111
|
@activity ||= Activity.new(commits)
|
84
112
|
end
|
@@ -87,8 +115,12 @@ module GitStats
|
|
87
115
|
@project_version ||= run("git rev-parse --short #{commit_range}").strip
|
88
116
|
end
|
89
117
|
|
118
|
+
def tree
|
119
|
+
@tree ||= Tree.new(repo: self, relative_path: @tree_path)
|
120
|
+
end
|
121
|
+
|
90
122
|
def project_name
|
91
|
-
@project_name ||= File.basename(path)
|
123
|
+
@project_name ||= (File.expand_path(File.join(path, tree_path)).sub(File.dirname(File.expand_path(path))+File::SEPARATOR,"") || File.basename(path))
|
92
124
|
end
|
93
125
|
|
94
126
|
def run(command)
|
@@ -132,6 +164,7 @@ module GitStats
|
|
132
164
|
command_observers.each { |o| o.call(command, result) }
|
133
165
|
end
|
134
166
|
|
167
|
+
|
135
168
|
end
|
136
169
|
end
|
137
170
|
end
|
@@ -19,7 +19,7 @@ module GitStats
|
|
19
19
|
|
20
20
|
private
|
21
21
|
def calculate_stat
|
22
|
-
stat_line = commit.repo.run("git show --shortstat --oneline #{commit.sha}").lines.to_a[1]
|
22
|
+
stat_line = commit.repo.run("git show --shortstat --oneline #{commit.sha} -- #{commit.repo.tree_path}").lines.to_a[1]
|
23
23
|
if stat_line.blank?
|
24
24
|
@files_changed = @insertions = @deletions = 0
|
25
25
|
else
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'git_stats/hash_initializable'
|
3
|
+
|
4
|
+
module GitStats
|
5
|
+
module GitData
|
6
|
+
class Tree
|
7
|
+
include HashInitializable
|
8
|
+
|
9
|
+
attr_reader :repo, :relative_path
|
10
|
+
|
11
|
+
def authors
|
12
|
+
@authors ||= run_and_parse("git shortlog -se #{commit_range}").map do |author|
|
13
|
+
Author.new(repo: self, name: author[:name], email: author[:email])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def ==(other)
|
18
|
+
((self.repo == other.repo) && (self.relative_path == other.relative_path))
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/git_stats/i18n.rb
CHANGED
@@ -3,14 +3,16 @@ module GitStats
|
|
3
3
|
module StatsView
|
4
4
|
module Charts
|
5
5
|
class AuthorsCharts
|
6
|
+
AUTHORS_ON_CHART_LIMIT = 4
|
7
|
+
|
6
8
|
def initialize(authors)
|
7
9
|
@authors = authors
|
8
10
|
end
|
9
11
|
|
10
|
-
def commits_sum_by_author_by_date(
|
12
|
+
def commits_sum_by_author_by_date(authors = nil)
|
11
13
|
Chart.new do |f|
|
12
14
|
f.multi_date_chart(
|
13
|
-
data: (authors || @authors.sort_by { |author| -author.commits.size }[0..
|
15
|
+
data: (authors || @authors.sort_by { |author| -author.commits.size }[0..AUTHORS_ON_CHART_LIMIT]).map { |author| {name: author.name, data: author.commits_sum_by_date} },
|
14
16
|
title: :lines_by_date.t,
|
15
17
|
y_text: :lines.t
|
16
18
|
)
|
@@ -18,10 +20,10 @@ module GitStats
|
|
18
20
|
end
|
19
21
|
|
20
22
|
[:insertions, :deletions, :changed_lines].each do |method|
|
21
|
-
define_method "#{method}_by_author_by_date" do |
|
23
|
+
define_method "#{method}_by_author_by_date" do |authors = nil|
|
22
24
|
Chart.new do |f|
|
23
25
|
f.multi_date_chart(
|
24
|
-
data: (authors || @authors.sort_by { |author| -author.send(method) }[0..
|
26
|
+
data: (authors || @authors.sort_by { |author| -author.send(method) }[0..AUTHORS_ON_CHART_LIMIT]).map { |author| {name: author.name, data: author.send("#{method}_by_date")} },
|
25
27
|
title: :lines_by_date.t,
|
26
28
|
y_text: :lines.t
|
27
29
|
)
|
@@ -3,7 +3,7 @@ module GitStats
|
|
3
3
|
module StatsView
|
4
4
|
module Charts
|
5
5
|
class All
|
6
|
-
delegate :files_by_extension, :lines_by_extension, :files_by_date, :lines_by_date, to: :repo_charts
|
6
|
+
delegate :files_by_extension, :lines_by_extension, :files_by_date, :lines_by_date, :comments_by_date, to: :repo_charts
|
7
7
|
|
8
8
|
delegate :commits_sum_by_author_by_date, :changed_lines_by_author_by_date,
|
9
9
|
:insertions_by_author_by_date, :deletions_by_author_by_date, to: :authors_charts
|