git_team_stats 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5157e6d24bbac821867bd8c7dd0384a3202169db
4
+ data.tar.gz: 136c1b15bcf2263f886c67685dd5b95cc032dd53
5
+ SHA512:
6
+ metadata.gz: fdda33147352b1d66709a865b84e03428bb6a2068486cce3104d2fa00412f9b829d75d1eb7410a75200d470a4874cc694af657578f0987c9d5a00060df6d0f7b
7
+ data.tar.gz: 8d2d3ac426e201a568a222e7e923c637736d63e3839401b841bad95f6be34008031e83e849dcfc8b6ff2d4f6a6a9f7446a27a9c5579da58ea07c492bfd3fdbb1
@@ -0,0 +1,28 @@
1
+ {
2
+ "users" : [
3
+ {
4
+ "name" : "you",
5
+ "aliases" : ["Your Alias #1", "yourotheralias"],
6
+ "default" : true
7
+ },
8
+ {
9
+ "name" : "collaborator",
10
+ "aliases" : ["Their alias"]
11
+ }
12
+ ],
13
+ "projects" : [
14
+ {
15
+ "name" : "project 1",
16
+ "repos" : ["~/src/proj1", "~/src/dependencies/proj1-dep"],
17
+ "ignored_directories" : ["Some/directory/you/forgot/to/gitignore/"],
18
+ "default" : true,
19
+ "start_date" : 1369253382,
20
+ "end_date" : 1369356790
21
+ },
22
+ {
23
+ "name" : "Other project",
24
+ "repos" : ["~/src/OtherProject"],
25
+ "ignored_directories" : []
26
+ }
27
+ ]
28
+ }
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .git_team_stats.json
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in git_team_stats.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Simon Holroyd
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,206 @@
1
+ # GitTeamStats
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'git_team_stats'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install git_team_stats
18
+
19
+
20
+ ## Configure
21
+
22
+ Configuration uses ```.gitstatistics.json``` file. To start, add your own ```.gitstatistics.json``` based off of ```.gitstatistics.json.example``` and edit according to your needs.
23
+
24
+ ```json
25
+ {
26
+ "users" : [
27
+ {
28
+ "name" : "you",
29
+ "aliases" : ["Your Alias #1", "yourotheralias"],
30
+ "default" : true
31
+ },
32
+ {
33
+ "name" : "collaborator",
34
+ "aliases" : ["Their alias"]
35
+ }
36
+ ],
37
+ "projects" : [
38
+ {
39
+ "name" : "project 1",
40
+ "repos" : ["~/src/proj1", "~/src/dependencies/proj1-dep"],
41
+ "ignored_directories" : ["Some/directory/you/forgot/to/gitignore/"],
42
+ "default" : true,
43
+ "start_date" : 1369253382,
44
+ "end_date" : 1369356790
45
+ },
46
+ {
47
+ "name" : "Other project",
48
+ "repos" : ["~/src/OtherProject"],
49
+ "ignored_directories" : []
50
+ }
51
+ ]
52
+ }
53
+ ```
54
+
55
+ ### Defaults
56
+
57
+ If ```projects``` is left empty, the program will default to running on the current working directory
58
+
59
+ ## Usage
60
+
61
+ Basic usage is as follows
62
+
63
+ ```
64
+ $ git_team_stats [global options] command [command options] [arguments...]
65
+ ```
66
+
67
+ ### Options
68
+
69
+ **cache_path**: ```--cache_path=path```
70
+ - The path to your cache files (default: ./tmp)
71
+
72
+ **config_path**: ```--config_path=path```
73
+ - The path to your config file (default: ./.git_team_stats.json)
74
+
75
+ **project**: ```--project=name```
76
+ - The project name to run on (default: none). Make sure you have projects set in your config file.
77
+
78
+ **help**: ```--help```
79
+ - Show this message
80
+
81
+ **ignore_cache**: ```--ignore_cache```
82
+ - A switch to turn off loading from cache
83
+
84
+ **no_cache**: ```--no_cache```
85
+ - A switch to turn off writing to cache
86
+
87
+ ### Commands
88
+
89
+ ##### Count Commits
90
+
91
+ ```
92
+ $ git_team_stats count_commits
93
+ ```
94
+
95
+ Returns the total number of commits across all your repos in the given project
96
+
97
+
98
+ ##### Inspect Commits
99
+
100
+ ```
101
+ $ git_team_stats inspect_commits
102
+ ```
103
+
104
+ Runs the full inspection on your project repos
105
+
106
+
107
+ ##### Team Cumulative Commits
108
+
109
+ ```
110
+ $ git_team_stats team_cumulative_stats
111
+ ```
112
+
113
+ Gather cumulative statistics on the team. Example output:
114
+
115
+ ```
116
+ ~~~ Cumulative Team Statistics ~~~~~~~~
117
+ commits : 1641
118
+ lines : 73630
119
+ edits : 196752
120
+ languages:
121
+ Objective-C
122
+ edits : 127530
123
+ lines : 47940
124
+ Ruby
125
+ edits : 2810
126
+ lines : 2118
127
+ Markdown
128
+ edits : 3592
129
+ lines : 112
130
+ Shell
131
+ edits : 427
132
+ lines : 381
133
+ YAML
134
+ edits : 203
135
+ lines : 165
136
+ PHP
137
+ edits : 16206
138
+ lines : 10630
139
+ SCSS
140
+ edits : 4746
141
+ lines : 3164
142
+ JavaScript
143
+ edits : 12926
144
+ lines : 11672
145
+ JSON
146
+ edits : 7221
147
+ lines : 7183
148
+ ```
149
+
150
+
151
+ ##### User Cumulative Commits
152
+
153
+ ```
154
+ $ git_team_stats user_cumulative_stats [--user]
155
+ ```
156
+
157
+ Gather cumulative statistics on a team member. Note you should either have a default user in your config file or pass a user name in the CLI. Example output:
158
+
159
+ ```
160
+ ~~~ Cumulative User Statistics (Simon Holroyd) ~~~~~~~~
161
+ commits : 839
162
+ lines : 82525
163
+ edits : 110461
164
+ languages:
165
+ Objective-C
166
+ edits : 97762
167
+ lines : 75868
168
+ Markdown
169
+ edits : 1720
170
+ lines : 1696
171
+ PHP
172
+ edits : 1636
173
+ lines : 660
174
+ SCSS
175
+ edits : 1719
176
+ lines : 977
177
+ JavaScript
178
+ edits : 173
179
+ lines : 41
180
+ ```
181
+
182
+
183
+ ##### Team Most Productive Hour
184
+
185
+ Coming soon
186
+
187
+ ##### User Most Productive Hour
188
+
189
+ Coming soon
190
+
191
+ ##### Codebase over time
192
+
193
+ Coming soon
194
+
195
+ ##### User contribution over time
196
+
197
+ Coming soon
198
+
199
+
200
+ ## Contributing
201
+
202
+ 1. Fork it
203
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
204
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
205
+ 4. Push to the branch (`git push origin my-new-feature`)
206
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake'
4
+ require 'json'
5
+ require 'gli'
6
+ require 'progress_bar'
7
+ require 'language_sniffer'
8
+ require 'git_team_stats'
@@ -0,0 +1,207 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'json'
4
+ require 'progress_bar'
5
+ require 'language_sniffer'
6
+ require 'gli'
7
+ require 'git_team_stats'
8
+
9
+ include GLI::App
10
+
11
+ program_desc 'Analyze commits and committers in mulitple git repos and output project-level statistics'
12
+
13
+ desc "The path to your config file"
14
+ flag [:config_path], :default_value => File.join(Dir.pwd,'.git_team_stats.json')
15
+ desc "The path to your cache files"
16
+ flag [:cache_path], :default_value => File.join(Dir.pwd,'tmp')
17
+ desc "The time period to group values by"
18
+ flag [:time_period], :default_value => :week
19
+ desc "The project name to run on"
20
+ flag [:project], :default_value => :none
21
+ desc "A switch to turn off loading from cache"
22
+ switch [:ignore_cache]
23
+ desc "A switch to turn off writing to cache"
24
+ switch [:no_cache]
25
+
26
+ pre do |global_options,command,options,args|
27
+ $dir = Dir.pwd
28
+
29
+ $users = []
30
+ $projects = []
31
+ $project = nil
32
+
33
+ if File.exists? global_options[:config_path]
34
+ config = JSON.parse(File.read(global_options[:config_path]), {:symbolize_names => true})
35
+
36
+ $users = (config[:users].empty?) ? [] : config[:users]
37
+ $projects = (config[:projects].empty?) ? [] : config[:projects]
38
+
39
+ end
40
+
41
+
42
+ if $projects.empty?
43
+ $projects.push({
44
+ :name => "current",
45
+ :repos => [Dir.pwd],
46
+ :ignored_directories => [],
47
+ :default => true
48
+ })
49
+ end
50
+
51
+ true
52
+ end
53
+
54
+ def require_user(options)
55
+
56
+ if options[:user] == :none
57
+ if $users.select{ :default == true }.empty?
58
+ help_now!('user is required, either as a command line arg or a default in .git_team_stats.json')
59
+ else
60
+ $user = $users.select{ :default == true }[0]
61
+ end
62
+ else
63
+ $user = {
64
+ :name => options[:user].to_s,
65
+ :aliases => [options[:user].to_s]
66
+ }
67
+ end
68
+
69
+ end
70
+
71
+ def require_project(global_options)
72
+ if global_options[:project] == :none
73
+ if !$projects.select{ |proj| proj[:default] == true }.empty?
74
+ $project = $projects.select{ |proj| proj[:default] == true }[0]
75
+ end
76
+ else
77
+ if !$projects.select{ |proj| proj[:name] == global_options[:project] }.empty?
78
+ $project = $projects.select{ |proj| proj[:name] == global_options[:project] }[0]
79
+ end
80
+ end
81
+ if ($project == nil)
82
+ puts $projects
83
+ help_now!('project is required, either as a command line arg or a default in .git_team_stats.json')
84
+ end
85
+
86
+ GitTeamStats.start($project)
87
+
88
+ load_cache(global_options)
89
+
90
+ end
91
+
92
+ def load_cache(global_options)
93
+ if (global_options[:ignore_cache])
94
+ return
95
+ end
96
+
97
+ cache_file_path = File.join(global_options[:cache_path], GitTeamStats.get_cache_file_name() + '.json')
98
+
99
+ if (File.exist?(cache_file_path))
100
+ output = JSON.parse(File.open(cache_file_path, 'rb').read, {:symbolize_names => true})
101
+ puts "Loading data from cache".color(:yellow)
102
+ GitTeamStats.load_from_cache(output)
103
+ end
104
+
105
+ end
106
+
107
+
108
+ desc "Count the total commits in the project"
109
+ command :count_commits do |c|
110
+ c.action do |global_options,options,args|
111
+ require_project(global_options)
112
+
113
+ GitTeamStats.inspect_commits()
114
+ puts "Total commits : " + GitTeamStats.count_commits().to_s
115
+ end
116
+ end
117
+
118
+ desc "Run the standard project inspection"
119
+ command :inspect_commits do |c|
120
+ c.action do |global_options,options,args|
121
+ require_project(global_options)
122
+
123
+ puts GitTeamStats.inspect_commits()
124
+
125
+ end
126
+ end
127
+
128
+ desc "Gather cumulative statistics on the team"
129
+ command :team_cumulative_stats do |c|
130
+ c.action do |global_options,options,args|
131
+ require_project(global_options)
132
+
133
+ stats = GitTeamStats.team_cumulative_stats()
134
+ puts "~~~ Cumulative Team Statistics ~~~~~~~~".color(:green)
135
+ stats.each{ |key, value|
136
+ if (key == :file_types)
137
+ puts "languages: "
138
+ value.each{ |language, data|
139
+ puts " " + language.to_s
140
+ puts " edits : " + data[:edits].to_s
141
+ puts " lines : " + data[:lines].to_s
142
+ }
143
+ else
144
+ puts key.to_s + " : " + value.to_s
145
+ end
146
+ }
147
+
148
+ end
149
+ end
150
+
151
+ desc "Gather cumulative statistics on a specific user"
152
+ command :user_cumulative_stats do |c|
153
+ c.flag [:user], :default_value => :none
154
+ c.action do |global_options,options,args|
155
+ require_project(global_options)
156
+ require_user(options)
157
+
158
+ stats = GitTeamStats.user_cumulative_stats($user)
159
+ headline = "~~~ Cumulative User Statistics (%s) ~~~~~~~~" % $user[:name].to_s
160
+ puts headline.color(:green)
161
+ stats.each{ |key, value|
162
+ if (key == :file_types)
163
+ puts "languages: "
164
+ value.each{ |language, data|
165
+ puts " " + language.to_s
166
+ puts " edits : " + data[:edits].to_s
167
+ puts " lines : " + data[:lines].to_s
168
+ }
169
+ else
170
+ puts key.to_s + " : " + value.to_s
171
+ end
172
+ }
173
+ end
174
+ end
175
+
176
+
177
+ post do |global_options,command,options,args|
178
+ if (global_options[:no_cache])
179
+ return
180
+ end
181
+
182
+ if (Dir.exist?(global_options[:cache_path]))
183
+ output = GitTeamStats.get_cache_output()
184
+ cache_file_path = File.join(global_options[:cache_path], GitTeamStats.get_cache_file_name() + '.json')
185
+
186
+ if (File.exist?(cache_file_path))
187
+ f = File.open(cache_file_path, "w+")
188
+ else
189
+ f = File.new(cache_file_path, "w+")
190
+ end
191
+ f.write(output.to_json)
192
+ f.close()
193
+
194
+
195
+ else
196
+ puts "Could not cache results, could not write to cache directory".color(:yellow)
197
+ end
198
+
199
+ true
200
+ end
201
+
202
+ on_error do |exception|
203
+ puts exception
204
+ end
205
+
206
+
207
+ exit run(ARGV)
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'git_team_stats/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "git_team_stats"
8
+ spec.version = GitTeamStats::VERSION
9
+ spec.authors = ["Simon Holroyd"]
10
+ spec.email = ["sholroyd@gmail.com"]
11
+ spec.description = %q{git_team_stats is a gem that compiles contribution statistics for projects that span mulitple repos}
12
+ spec.summary = %q{git_team_stats is a gem that compiles contribution statistics for projects that span mulitple repos}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_dependency 'json'
25
+ spec.add_dependency 'progress_bar'
26
+ spec.add_dependency 'rainbow'
27
+ spec.add_dependency 'language_sniffer'
28
+ spec.add_dependency 'gli'
29
+
30
+
31
+ end
@@ -0,0 +1,138 @@
1
+ require "git_team_stats/version"
2
+ require "git_team_stats/git_parse"
3
+
4
+ module GitTeamStats
5
+
6
+ @project = nil
7
+
8
+ @inspected = false
9
+
10
+ def self.start(project)
11
+ @project = project
12
+
13
+ @commits_in_detail = []
14
+
15
+ @project[:parsers] = []
16
+
17
+ @project[:repos].each do |repo|
18
+ @project[:parsers].push(
19
+ GitParse.new(repo)
20
+ )
21
+ end
22
+
23
+ end
24
+
25
+ def self.count_commits
26
+ count = 0
27
+
28
+ if !@inspected
29
+ self.inspect_commits()
30
+ end
31
+
32
+ return @commits_in_detail.length
33
+ end
34
+
35
+ def self.collect_commits
36
+ unless @inspected
37
+
38
+ @project[:parsers].each do |parser|
39
+ parser.get_commits()
40
+ end
41
+ end
42
+ end
43
+
44
+ def self.inspect_commits
45
+ unless @inspected
46
+
47
+ self.collect_commits()
48
+
49
+ @project[:parsers].each do |parser|
50
+ @commits_in_detail += parser.get_commit_details()
51
+ end
52
+
53
+ @inspected = true
54
+ end
55
+ end
56
+
57
+ def self.team_cumulative_stats
58
+ self.inspect_commits()
59
+
60
+ team_cumulative = {
61
+ :commits => 0,
62
+ :lines => 0,
63
+ :edits => 0,
64
+ :file_types => {}
65
+ }
66
+ @commits_in_detail.each do |commit|
67
+ team_cumulative[:commits] += 1
68
+ team_cumulative[:lines] += commit[:lines]
69
+ team_cumulative[:edits] += commit[:edits]
70
+
71
+ commit[:file_types].each do |language, details|
72
+ if team_cumulative[:file_types].key? language
73
+ team_cumulative[:file_types][language][:lines] += details[:lines]
74
+ team_cumulative[:file_types][language][:edits] += details[:edits]
75
+ else
76
+ team_cumulative[:file_types][language] = {
77
+ :lines => details[:lines],
78
+ :edits => details[:edits]
79
+ }
80
+ end
81
+ end
82
+ end
83
+
84
+ return team_cumulative
85
+ end
86
+
87
+ def self.user_cumulative_stats(user)
88
+ self.inspect_commits()
89
+
90
+ user_cumulative = {
91
+ :commits => 0,
92
+ :lines => 0,
93
+ :edits => 0,
94
+ :file_types => {}
95
+ }
96
+ @commits_in_detail.each do |commit|
97
+ if user[:aliases].any?{ |name| name == commit[:committer] }
98
+ user_cumulative[:commits] += 1
99
+ user_cumulative[:lines] += commit[:lines]
100
+ user_cumulative[:edits] += commit[:edits]
101
+
102
+ commit[:file_types].each do |language, details|
103
+ if user_cumulative[:file_types].key? language
104
+ user_cumulative[:file_types][language][:lines] += details[:lines]
105
+ user_cumulative[:file_types][language][:edits] += details[:edits]
106
+ else
107
+ user_cumulative[:file_types][language] = {
108
+ :lines => details[:lines],
109
+ :edits => details[:edits]
110
+ }
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ return user_cumulative
117
+ end
118
+
119
+ def self.get_cache_output
120
+ return @commits_in_detail
121
+ end
122
+
123
+ def self.load_from_cache(data)
124
+ @commits_in_detail = data
125
+ @inspected = true
126
+ end
127
+
128
+ def self.get_cache_file_name
129
+ hash_str = ""
130
+ @project[:parsers].each{ |parser|
131
+ hash_str += parser.get_head_short_hash().to_s + "-"
132
+ }
133
+
134
+ return $project[:name].to_s + "-" + hash_str + @project[:start_date].to_s + '-' + @project[:end_date].to_s
135
+ end
136
+
137
+
138
+ end
@@ -0,0 +1,197 @@
1
+ require 'progress_bar'
2
+ require 'rainbow'
3
+ require 'language_sniffer'
4
+
5
+ class GitParse
6
+
7
+
8
+ def initialize(directory)
9
+ @commits = []
10
+
11
+ @ignored_directories = []
12
+ @start_date = nil
13
+ @end_date = nil
14
+
15
+ @directory = directory
16
+ end
17
+
18
+
19
+ def execute(command, directory = ".")
20
+ directory = `cd #{directory}; #{command}`
21
+ end
22
+
23
+
24
+ def get_commits
25
+
26
+ hash = ""
27
+
28
+ puts "finding commits in #{@directory}".color(:yellow)
29
+ rev_list = get_rev_list()
30
+ bar = ProgressBar.new(rev_list.lines.length, :bar, :percentage, :eta);
31
+ rev_list.lines.each do |line|
32
+ bar.increment!
33
+ if ( line =~ /^commit ([\w]+)/)
34
+ hash = $1
35
+ next
36
+ else hash != ""
37
+ if ( line =~ /^([\d]+)\s(.+)\s<(.+)>$/ )
38
+ timestamp = $1.to_i
39
+ committer = $2
40
+ email = $3
41
+ end
42
+
43
+ @commits.push({
44
+ :hash => hash,
45
+ :committer => committer,
46
+ :path => @directory,
47
+ :timestamp => timestamp,
48
+ })
49
+
50
+ hash = ""
51
+ end
52
+ end
53
+
54
+ return @commits
55
+ end
56
+
57
+
58
+
59
+ def count_commits
60
+ if @commits.empty?
61
+ get_commits()
62
+ end
63
+
64
+ return @commits.count
65
+ end
66
+
67
+ def get_authors
68
+ users = []
69
+ get_authors_from_shortlog().lines.each do |line|
70
+ if !users.any? {|user| user[:name] = line }
71
+ users.push({
72
+ :name => line.strip,
73
+ :aliases => [line.strip]
74
+ })
75
+ end
76
+ end
77
+ return users
78
+ end
79
+
80
+ def get_authors_from_shortlog
81
+ return execute("git shortlog -s | cut -c8-", @directory)
82
+ end
83
+
84
+ def get_head_short_hash
85
+ return execute("git rev-parse --short HEAD", @directory).strip
86
+ end
87
+
88
+ def get_rev_list
89
+ date_str = ""
90
+ if @start_date != nil
91
+ date_str += "--max-age=%s " % [@start_date.to_i.to_s]
92
+ end
93
+ if @end_date != nil
94
+ date_str += "--min-age=%s " % [@end_date.to_i.to_s]
95
+ end
96
+ return execute("git rev-list --reverse --pretty=format:\"%%at %%aN <%%aE>\" %s HEAD" % date_str, @directory)
97
+ end
98
+
99
+ def get_diff_tree(commit_hash)
100
+ return execute("git diff-tree %s --numstat" % commit_hash, @directory)
101
+ end
102
+
103
+ def get_file(commit_hash, file_name)
104
+ return execute("git show %s:%s 2>&1" % [commit_hash, file_name], @directory)
105
+ end
106
+
107
+ def parse_diff_tree(commit_hash)
108
+
109
+ total_lines = 0
110
+ total_edits = 0
111
+ file_types = {}
112
+
113
+ diff_tree = get_diff_tree(commit_hash)
114
+
115
+ diff_tree.lines.each do |line|
116
+
117
+ if ( line =~ /^([\d]+)\s([\d]+)(.*[^\w](\w+))$/)
118
+
119
+ insertions = $1.to_i
120
+ deletions = $2.to_i
121
+
122
+ lines = insertions - deletions
123
+ edits = insertions + deletions
124
+
125
+ file_name = $3.strip!
126
+
127
+ extension = $4
128
+
129
+ if (@ignored_directories.any?{ |obj| (file_name.index(obj) == 0) })
130
+ next
131
+ end
132
+
133
+ language = get_language_for_file(file_name, commit_hash)
134
+
135
+ if language == nil
136
+ next
137
+ end
138
+
139
+ if (file_types.key? language.name.to_sym)
140
+ file_types[language.name.to_sym][:lines] += lines
141
+ file_types[language.name.to_sym][:edits] += edits
142
+ else
143
+ file_types[language.name.to_sym] = {
144
+ :lines => lines,
145
+ :edits => edits
146
+ }
147
+ end
148
+
149
+ total_lines += lines
150
+ total_edits += edits
151
+
152
+
153
+ end
154
+ end
155
+
156
+ return {
157
+ :lines => total_lines,
158
+ :edits => total_edits,
159
+ :file_types => file_types
160
+ }
161
+
162
+ end
163
+
164
+ def get_language_for_file(file_name, commit_hash)
165
+ escaped_file_name = file_name.gsub(/([\[\(\)\]\{\}\*\?\\])/, '\\\\\1')
166
+
167
+ full_file_path = File.join(Dir.home, @directory.gsub(/^~/, ""), file_name)
168
+
169
+ if File.file? full_file_path
170
+ language = LanguageSniffer.detect(full_file_path).language;
171
+ else
172
+ language = LanguageSniffer.detect(full_file_path, :content => get_file(commit_hash, escaped_file_name), :path => full_file_path).language;
173
+ end
174
+
175
+ return language
176
+ end
177
+
178
+ def get_commit_details
179
+
180
+ puts "analyzing commits in #{@directory}".color(:yellow)
181
+
182
+ bar = ProgressBar.new(@commits.length, :bar, :percentage, :eta);
183
+
184
+ @commits.each { |commit|
185
+
186
+ bar.increment!
187
+
188
+ diff_tree = parse_diff_tree(commit[:hash])
189
+
190
+ commit.merge!(diff_tree)
191
+ }
192
+
193
+ return @commits
194
+
195
+ end
196
+
197
+ end
@@ -0,0 +1,3 @@
1
+ module GitTeamStats
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git_team_stats
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Simon Holroyd
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-28 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.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
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'
55
+ - !ruby/object:Gem::Dependency
56
+ name: progress_bar
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rainbow
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: language_sniffer
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: gli
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: git_team_stats is a gem that compiles contribution statistics for projects
112
+ that span mulitple repos
113
+ email:
114
+ - sholroyd@gmail.com
115
+ executables:
116
+ - git_team_stats
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - .git_team_stats.json.example
121
+ - .gitignore
122
+ - Gemfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - bin/git_team_stats
127
+ - git_team_stats.gemspec
128
+ - lib/git_team_stats.rb
129
+ - lib/git_team_stats/git_parse.rb
130
+ - lib/git_team_stats/version.rb
131
+ homepage: ''
132
+ licenses:
133
+ - MIT
134
+ metadata: {}
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ requirements: []
150
+ rubyforge_project:
151
+ rubygems_version: 2.0.0
152
+ signing_key:
153
+ specification_version: 4
154
+ summary: git_team_stats is a gem that compiles contribution statistics for projects
155
+ that span mulitple repos
156
+ test_files: []