git_statistics 0.7.0 → 0.8.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 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