git_statistics 0.7.0 → 0.8.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: ac2c8d9e4ff4611dfa6c6b2f9f664fb874a7201f
4
- data.tar.gz: 9da9f644f174806900bd8b2a2921906bfc3e3989
3
+ metadata.gz: 73f7fc388f1d121e11c2699b107138fee200da9b
4
+ data.tar.gz: b87b3b4c7cfbc545df2e7d933142289d0665c1e5
5
5
  SHA512:
6
- metadata.gz: 381f1532eee3178c8a1459ec2f5ca37f1429786c56e4bae54c6139e2e9ed4fea6253fc4960d6b426e360e777c6adad1c48bffac53b1ce4fe9f93b5de27f5e51f
7
- data.tar.gz: b7bb4f77e58b6f1bf73cfd09219651c0256a59a8a9b3de25a50c11948063a66c3df88856b14210709a6353f1fd0bf97d5eeaafea95f3d36d0a7587bf4d5fd7cf
6
+ metadata.gz: 6c531508caedd57a36a3c0ef0ecb40db56483b17e28d765967496e3220b1752ff2091f349da6058f88ecdf41d6cb98cb97b1b7585c25c2db6da5520dbb2ad27e
7
+ data.tar.gz: 80370289c3c487d77af7b89bba761311654c622786f7b3326fa7ca97c6250514278a33977fc89b4ab890f353ca18f4d295bd36dcc034e27577f8abd0842e598a
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $:.unshift File.expand_path("../../lib", __FILE__)
3
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
4
  require 'git_statistics'
5
5
 
6
6
  GitStatistics::CLI.new(Dir.pwd).execute
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $:.unshift File.expand_path("../../lib", __FILE__)
3
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
4
  require 'git_statistics'
5
5
 
6
6
  GitStatistics::CLI.new(Dir.pwd).execute
@@ -4,11 +4,10 @@ module GitStatistics
4
4
  class CLI
5
5
  attr_reader :repository, :options
6
6
 
7
- DEFAULT_BRANCH = "master"
7
+ DEFAULT_BRANCH = 'master'
8
8
 
9
9
  def initialize(dir)
10
- repository_location = dir.nil? ? Rugged::Repository.discover(Dir.pwd) : Rugged::Repository.discover(dir)
11
- @repository = Rugged::Repository.new(repository_location)
10
+ @repository = dir.nil? ? Rugged::Repository.discover(Dir.pwd) : Rugged::Repository.discover(dir)
12
11
  @collected = false
13
12
  @collector = nil
14
13
  @options = OpenStruct.new(
@@ -16,7 +15,7 @@ module GitStatistics
16
15
  merges: false,
17
16
  pretty: false,
18
17
  update: false,
19
- sort: "commits",
18
+ sort: 'commits',
20
19
  top: 0,
21
20
  branch: DEFAULT_BRANCH,
22
21
  verbose: false,
@@ -35,19 +34,19 @@ module GitStatistics
35
34
  end
36
35
 
37
36
  def collect_and_only_update
38
- if options.update
39
- # Ensure commit directory is present
40
- @collector = Collector.new(repository, options.limit, false, options.pretty)
41
- commits_directory = repository.workdir + ".git_statistics/"
42
- FileUtils.mkdir_p(commits_directory)
43
- file_count = Utilities.number_of_matching_files(commits_directory, /\d+\.json/) - 1
37
+ return unless options.update
44
38
 
45
- if file_count >= 0
46
- time_since = Utilities.get_modified_time(commits_directory + "#{file_count}.json").to_s
47
- @collector.collect({:branch => options.branch, :time_since => time_since})
48
- @collected = true
49
- end
50
- end
39
+ # Ensure commit directory is present
40
+ @collector = Collector.new(repository, options.limit, false, options.pretty)
41
+ commits_directory = repository.workdir + '.git_statistics/'
42
+ FileUtils.mkdir_p(commits_directory)
43
+ file_count = Utilities.number_of_matching_files(commits_directory, /\d+\.json/) - 1
44
+
45
+ return unless file_count >= 0
46
+
47
+ time_since = Utilities.get_modified_time(commits_directory + "#{file_count}.json").to_s
48
+ @collector.collect(branch: options.branch, time_since: time_since)
49
+ @collected = true
51
50
  end
52
51
 
53
52
  def calculate!
@@ -61,40 +60,40 @@ module GitStatistics
61
60
 
62
61
  def fresh_collect!
63
62
  @collector = Collector.new(repository, options.limit, true, options.pretty)
64
- @collector.collect({:branch => options.branch})
63
+ @collector.collect(branch: options.branch)
65
64
  end
66
65
 
67
66
  def parse_options
68
67
  OptionParser.new do |opt|
69
68
  opt.version = VERSION
70
- opt.on "-e", "--email", "Use author's email instead of name" do
69
+ opt.on '-e', '--email', "Use author's email instead of name" do
71
70
  options.email = true
72
71
  end
73
- opt.on "-m", "--merges", "Factor in merges when calculating statistics" do
72
+ opt.on '-m', '--merges', 'Factor in merges when calculating statistics' do
74
73
  options.merges = true
75
74
  end
76
- opt.on "-p", "--pretty", "Save the commits in git_repo/.git_statistics in pretty print (larger file size)" do
75
+ opt.on '-p', '--pretty', 'Save the commits in git_repo/.git_statistics in pretty print (larger file size)' do
77
76
  options.pretty = true
78
77
  end
79
- opt.on "-u", "--update", "Update saved commits with new data" do
78
+ opt.on '-u', '--update', 'Update saved commits with new data' do
80
79
  options.update = true
81
80
  end
82
- opt.on "-s", "--sort TYPE", "Sort authors by {commits, additions, deletions, create, delete, rename, copy, merges}" do |type|
81
+ opt.on '-s', '--sort TYPE', 'Sort authors by {commits, additions, deletions, create, delete, rename, copy, merges}' do |type|
83
82
  options.sort = type
84
83
  end
85
- opt.on "-t", "--top N", Float,"Show the top N authors in results" do |value|
84
+ opt.on '-t', '--top N', Float, 'Show the top N authors in results' do |value|
86
85
  options.top = value
87
86
  end
88
- opt.on "-b", "--branch BRANCH", "Use the specified branch for statistics (otherwise the master branch is used)" do |branch|
87
+ opt.on '-b', '--branch BRANCH', 'Use the specified branch for statistics (otherwise the master branch is used)' do |branch|
89
88
  options.branch = branch
90
89
  end
91
- opt.on "-v", "--verbose", "Verbose output (shows INFO level log statements)" do
90
+ opt.on '-v', '--verbose', 'Verbose output (shows INFO level log statements)' do
92
91
  options.verbose = true
93
92
  end
94
- opt.on "-d", "--debug", "Debug output (shows DEBUG level log statements)" do
93
+ opt.on '-d', '--debug', 'Debug output (shows DEBUG level log statements)' do
95
94
  options.debug = true
96
95
  end
97
- opt.on "-l", "--limit MAX_COMMITS", Float, "The maximum limit of commits to hold in memory at a time" do |number|
96
+ opt.on '-l', '--limit MAX_COMMITS', Float, 'The maximum limit of commits to hold in memory at a time' do |number|
98
97
  options.limit = number
99
98
  end
100
99
  end.parse!
@@ -102,14 +101,13 @@ module GitStatistics
102
101
 
103
102
  private
104
103
 
105
- def determine_log_level
106
- if options.debug
107
- Log.level = Logger::DEBUG
108
- Log.use_debug
109
- elsif options.verbose
110
- Log.level = Logger::INFO
111
- end
104
+ def determine_log_level
105
+ if options.debug
106
+ Log.level = Logger::DEBUG
107
+ Log.use_debug
108
+ elsif options.verbose
109
+ Log.level = Logger::INFO
112
110
  end
113
-
111
+ end
114
112
  end
115
113
  end
@@ -1,41 +1,39 @@
1
1
  module GitStatistics
2
2
  class Collector
3
-
4
3
  attr_accessor :repo, :commits_path, :commits
5
4
 
6
5
  def initialize(repo, limit, fresh, pretty)
7
6
  @repo = repo
8
- @commits_path = repo.workdir + ".git_statistics"
7
+ @commits_path = repo.workdir + '.git_statistics'
9
8
  @commits = Commits.new(@commits_path, fresh, limit, pretty)
10
9
  end
11
10
 
12
11
  def collect(options = {})
13
- branch = options[:branch] ? options[:branch] : CLI::DEFAULT_BRANCH
14
- branch_head = Rugged::Branch.lookup(repo, branch).tip
12
+ branch_name = options[:branch] ? options[:branch] : CLI::DEFAULT_BRANCH
15
13
 
16
14
  walker = Rugged::Walker.new(repo)
17
- walker.push(branch_head)
15
+ walker.push(repo.branches[branch_name].target)
18
16
 
19
17
  walker.each_with_index do |commit, count|
20
- if valid_commit?(commit, options)
21
- extract_commit(commit, count + 1)
22
- @commits.flush_commits
23
- end
18
+ next unless valid_commit?(commit, options)
19
+
20
+ extract_commit(commit, count + 1)
21
+ @commits.flush_commits
24
22
  end
25
23
 
26
24
  @commits.flush_commits(true)
27
25
  end
28
26
 
29
27
  def valid_commit?(commit, options)
30
- if !options[:time_since].nil?
28
+ unless options[:time_since].nil?
31
29
  return false unless commit.author[:time] > DateTime.parse(options[:time_since].to_s).to_time
32
30
  end
33
31
 
34
- if !options[:time_until].nil?
32
+ unless options[:time_until].nil?
35
33
  return false unless commit.author[:time] < DateTime.parse(options[:time_until].to_s).to_time
36
34
  end
37
35
 
38
- return true
36
+ true
39
37
  end
40
38
 
41
39
  def acquire_commit_meta(commit_summary)
@@ -52,9 +50,9 @@ module GitStatistics
52
50
  data[:added_files] = commit_summary.added_files
53
51
  data[:deleted_files] = commit_summary.deleted_files
54
52
  data[:modified_files] = commit_summary.modified_files
55
- data[:files] = commit_summary.file_stats.map{ |file| file.to_json }
53
+ data[:files] = commit_summary.file_stats.map(&:to_json)
56
54
 
57
- return data
55
+ data
58
56
  end
59
57
 
60
58
  def extract_commit(commit, count)
@@ -64,8 +62,7 @@ module GitStatistics
64
62
  # Acquire meta information about commit
65
63
  commit_data = acquire_commit_meta(commit_summary)
66
64
 
67
- return commit_data
65
+ commit_data
68
66
  end
69
-
70
67
  end
71
68
  end
@@ -1,5 +1,7 @@
1
1
  module GitStatistics
2
2
  class CommitSummary < SimpleDelegator
3
+ attr_reader :patches
4
+
3
5
  def initialize(repo, commit)
4
6
  super(commit)
5
7
  @repo = repo
@@ -14,17 +16,17 @@ module GitStatistics
14
16
 
15
17
  # How many files were removed in this commit
16
18
  def deleted_files
17
- file_stats.select { |file| file.status == :deleted }.count
19
+ file_stats.count { |file| file.status == :deleted }
18
20
  end
19
21
 
20
22
  # How many files were added in this commit
21
23
  def added_files
22
- file_stats.select { |file| file.status == :added }.count
24
+ file_stats.count { |file| file.status == :added }
23
25
  end
24
26
 
25
27
  # How many files were modified (not added/deleted) in this commit
26
28
  def modified_files
27
- file_stats.select { |file| file.status == :modified }.count
29
+ file_stats.count { |file| file.status == :modified }
28
30
  end
29
31
 
30
32
  # How many total additions in this commit?
@@ -43,14 +45,14 @@ module GitStatistics
43
45
  end
44
46
 
45
47
  def file_stats
46
- @cached_file_stats ||= diffstats.map { |diff| DiffSummary.new(@repo, diff) }
48
+ @cached_file_stats ||= @patches.map { |diff| DiffSummary.new(@repo, diff) }
47
49
  end
48
50
 
49
51
  LanguageSummary = Struct.new(:name, :additions, :deletions, :net, :added_files, :deleted_files, :modified_files)
50
52
 
51
53
  # Array of LanguageSummary objects (one for each language) for simple calculations
52
54
  def languages
53
- grouped_language_files.collect do |language, stats|
55
+ grouped_language_files.map do |language, stats|
54
56
  additions = summarize(stats, :additions)
55
57
  deletions = summarize(stats, :deletions)
56
58
  net = summarize(stats, :net)
@@ -70,17 +72,12 @@ module GitStatistics
70
72
 
71
73
  private
72
74
 
73
- def summarize(stats, what)
74
- stats.map(&what).inject(0, :+)
75
- end
76
-
77
- def commit_summary(what)
78
- summarize(file_stats, what)
79
- end
80
-
81
- def diffstats
82
- @patches
83
- end
75
+ def summarize(stats, what)
76
+ stats.map(&what).inject(0, :+)
77
+ end
84
78
 
79
+ def commit_summary(what)
80
+ summarize(file_stats, what)
81
+ end
85
82
  end
86
83
  end
@@ -1,6 +1,5 @@
1
1
  module GitStatistics
2
2
  class Commits < Hash
3
-
4
3
  attr_accessor :stats, :totals, :path, :fresh, :limit, :pretty
5
4
 
6
5
  def initialize(path, fresh, limit, pretty)
@@ -30,23 +29,23 @@ module GitStatistics
30
29
  end
31
30
 
32
31
  def files_in_path
33
- Dir.entries(path).reject { |file| %w[. ..].include?(file) }
32
+ Dir.entries(path).reject { |file| %w(. ..).include?(file) }
34
33
  end
35
34
 
36
- def flush_commits(force=false)
37
- if size >= limit || force
38
- file_count = Utilities.number_of_matching_files(path, /\d+\.json/)
39
- save(File.join(path, "#{file_count}.json"), @pretty)
40
- clear
41
- end
35
+ def flush_commits(force = false)
36
+ return unless size >= limit || force
37
+
38
+ file_count = Utilities.number_of_matching_files(path, /\d+\.json/)
39
+ save(File.join(path, "#{file_count}.json"), @pretty)
40
+ clear
42
41
  end
43
42
 
44
43
  def author_top_n_type(type, top_n = 0)
45
44
  top_n = 0 if top_n < 0
46
- if @stats.empty? || !@stats.first[1].has_key?(type)
45
+ if @stats.empty? || !@stats.first[1].key?(type)
47
46
  nil
48
47
  else
49
- Hash[*@stats.sorted_hash {|a,b| b[1][type.to_sym] <=> a[1][type]}.to_a[0..top_n-1].flatten]
48
+ Hash[*@stats.sorted_hash { |a, b| b[1][type.to_sym] <=> a[1][type] }.to_a[0..top_n - 1].flatten]
50
49
  end
51
50
  end
52
51
 
@@ -55,24 +54,24 @@ module GitStatistics
55
54
  type = email ? :author_email : :author
56
55
 
57
56
  # Process the commits from file or memory
58
- files = Dir.entries(path) - [".", ".."]
57
+ files = Dir.entries(path) - ['.', '..']
59
58
  if files.size == 0
60
- process_commits(type, merge)
59
+ process_commits(type, merge)
61
60
  else
62
- #Load commit file and extract the commits
61
+ # Load commit file and extract the commits
63
62
  files.each do |file|
64
- if file =~ /\d+\.json/
65
- load(File.join(path, file))
66
- process_commits(type, merge)
67
- clear
68
- end
63
+ next unless file =~ /\d+\.json/
64
+
65
+ load(File.join(path, file))
66
+ process_commits(type, merge)
67
+ clear
69
68
  end
70
69
  end
71
70
  end
72
71
 
73
72
  def process_commits(type, merge)
74
73
  # Collect the stats from each commit
75
- each do |key,value|
74
+ each do |key, value|
76
75
  next if !merge && value[:merge]
77
76
  # If there are no changed files move to next commit
78
77
  next if value[:files].empty?
@@ -88,7 +87,6 @@ module GitStatistics
88
87
 
89
88
  # Collect language stats
90
89
  value[:files].each do |file|
91
-
92
90
  # Add to author's languages
93
91
  add_language_stats(author, file)
94
92
 
@@ -118,11 +116,11 @@ module GitStatistics
118
116
  data[:languages][file[:language].to_sym][:deletions] += file[:deletions]
119
117
 
120
118
  # Keep count of languages status (i.e., added, deleted) and keep keys consistent (i.e., added_files, deleted_files)
121
- if file[:status] != nil
122
- data[:languages][file[:language].to_sym][(file[:status]+'_files').to_sym] += 1
119
+ unless file[:status].nil?
120
+ data[:languages][file[:language].to_sym][(file[:status] + '_files').to_sym] += 1
123
121
  end
124
122
 
125
- return data
123
+ data
126
124
  end
127
125
 
128
126
  def add_commit_stats(data, commit)
@@ -131,25 +129,25 @@ module GitStatistics
131
129
  data[:commits] += 1
132
130
  data[:additions] += commit[:additions]
133
131
  data[:deletions] += commit[:deletions]
134
- data[:added_files] += commit[:added_files] if !commit[:added_files].nil?
135
- data[:deleted_files] += commit[:deleted_files] if !commit[:deleted_files].nil?
136
- return data
132
+ data[:added_files] += commit[:added_files] unless commit[:added_files].nil?
133
+ data[:deleted_files] += commit[:deleted_files] unless commit[:deleted_files].nil?
134
+ data
137
135
  end
138
136
 
139
137
  def load(file)
140
- merge!(JSON.parse(File.read(file), :symbolize_names => true))
138
+ merge!(JSON.parse(File.read(file), symbolize_names: true))
141
139
  end
142
140
 
143
141
  def save(file, pretty)
144
- # Don't save if there is no information (i.e., using updates)
145
- unless empty?
146
- # Ensure the path to the file exists
147
- FileUtils.mkdir_p(File.dirname(file))
148
- # Save file in a simple or pretty format
149
- File.open(file, 'w') do |f|
150
- json_content = pretty ? JSON.pretty_generate(self) : self.to_json
151
- f.write(json_content)
152
- end
142
+ return if empty?
143
+
144
+ # Ensure the path to the file exists
145
+ FileUtils.mkdir_p(File.dirname(file))
146
+
147
+ # Save file in a simple or pretty format
148
+ File.open(file, 'w') do |f|
149
+ json_content = pretty ? JSON.pretty_generate(self) : to_json
150
+ f.write(json_content)
153
151
  end
154
152
  end
155
153
  end
@@ -35,7 +35,7 @@ module GitStatistics
35
35
  end
36
36
 
37
37
  def filename
38
- if (status == :deleted)
38
+ if status == :deleted
39
39
  delta.old_file[:path]
40
40
  else
41
41
  delta.new_file[:path]
@@ -44,34 +44,30 @@ module GitStatistics
44
44
 
45
45
  # We flip these around since we are diffing in the opposite direction -- new.diff(old)
46
46
  def blob
47
- begin
48
- if (status == :deleted)
49
- blob = @repo.lookup(delta.new_file[:oid]) # Look at new instead of old
50
- else
51
- blob = @repo.lookup(delta.old_file[:oid]) # Look at old instead of new
52
- end
53
- rescue Rugged::OdbError
54
- Log.warn "Could not find object (most likely a submodule)"
55
- blob = nil
47
+ if status == :deleted
48
+ @repo.lookup(delta.new_file[:oid]) # Look at new instead of old
49
+ else
50
+ @repo.lookup(delta.old_file[:oid]) # Look at old instead of new
56
51
  end
52
+ rescue Rugged::OdbError
53
+ Log.warn 'Could not find object (most likely a submodule)'
54
+ nil
57
55
  end
58
56
 
59
57
  def inspect
60
- %Q{<GitStatistics::FileStat @filename=#{filename} @status=#{status} @similarity=#{similarity} @language=#{language} @additions=#{additions}, @deletions=#{deletions}, @net=#{net}>}
58
+ "<GitStatistics::FileStat @filename=#{filename} @status=#{status} @similarity=#{similarity} @language=#{language} @additions=#{additions}, @deletions=#{deletions}, @net=#{net}>"
61
59
  end
62
60
 
63
61
  def to_json
64
- { filename: filename, status: status, similarity: similarity, language: language, additions: additions, deletions: deletions, net: net}
62
+ { filename: filename, status: status, similarity: similarity, language: language, additions: additions, deletions: deletions, net: net }
65
63
  end
66
64
 
67
65
  # Determine the language of the file from the blob
68
66
  def language
69
- language = "Unknown"
67
+ language = 'Unknown'
70
68
  unless blob.nil?
71
- detected_language = LanguageSniffer.detect(filename, :content => blob.content).language
72
- unless detected_language.nil?
73
- language = detected_language.name
74
- end
69
+ detected_language = LanguageSniffer.detect(filename, content: blob.content).language
70
+ language = detected_language.name unless detected_language.nil?
75
71
  end
76
72
  language
77
73
  end