git_statistics 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -33,7 +33,7 @@ module GitStatistics
33
33
  Dir.entries(path).reject { |file| %w[. ..].include?(file) }
34
34
  end
35
35
 
36
- def flush_commits(force = false)
36
+ def flush_commits(force=false)
37
37
  if size >= limit || force
38
38
  file_count = Utilities.number_of_matching_files(path, /\d+\.json/)
39
39
  save(File.join(path, "#{file_count}.json"), @pretty)
@@ -54,13 +54,18 @@ module GitStatistics
54
54
  # Identify authors and author type
55
55
  type = email ? :author_email : :author
56
56
 
57
- # For all the commit files created
58
- Dir.entries(path).each do |file|
59
- # Load commit file and extract the commits
60
- if file =~ /\d+\.json/
61
- load(File.join(path, file))
57
+ # Process the commits from file or memory
58
+ files = Dir.entries(path) - [".", ".."]
59
+ if files.size == 0
62
60
  process_commits(type, merge)
63
- clear
61
+ else
62
+ #Load commit file and extract the commits
63
+ files.each do |file|
64
+ if file =~ /\d+\.json/
65
+ load(File.join(path, file))
66
+ process_commits(type, merge)
67
+ clear
68
+ end
64
69
  end
65
70
  end
66
71
  end
@@ -112,8 +117,9 @@ module GitStatistics
112
117
  data[:languages][file[:language].to_sym][:additions] += file[:additions]
113
118
  data[:languages][file[:language].to_sym][:deletions] += file[:deletions]
114
119
 
120
+ # Keep count of languages status (i.e., added, deleted) and keep keys consistent (i.e., added_files, deleted_files)
115
121
  if file[:status] != nil
116
- data[:languages][file[:language].to_sym][file[:status].to_sym] += 1
122
+ data[:languages][file[:language].to_sym][(file[:status]+'_files').to_sym] += 1
117
123
  end
118
124
 
119
125
  return data
@@ -125,10 +131,8 @@ module GitStatistics
125
131
  data[:commits] += 1
126
132
  data[:additions] += commit[:additions]
127
133
  data[:deletions] += commit[:deletions]
128
- data[:create] += commit[:create] if commit[:create] != nil
129
- data[:delete] += commit[:delete] if commit[:delete] != nil
130
- data[:rename] += commit[:rename] if commit[:rename] != nil
131
- data[:copy] += commit[:copy] if commit[:copy] != nil
134
+ data[:added_files] += commit[:added_files] if !commit[:added_files].nil?
135
+ data[:deleted_files] += commit[:deleted_files] if !commit[:deleted_files].nil?
132
136
  return data
133
137
  end
134
138
 
@@ -142,9 +146,9 @@ module GitStatistics
142
146
  # Ensure the path to the file exists
143
147
  FileUtils.mkdir_p(File.dirname(file))
144
148
  # Save file in a simple or pretty format
145
- File.open(file, 'w') do |file|
149
+ File.open(file, 'w') do |f|
146
150
  json_content = pretty ? JSON.pretty_generate(self) : self.to_json
147
- file.write(json_content)
151
+ f.write(json_content)
148
152
  end
149
153
  end
150
154
  end
@@ -0,0 +1,79 @@
1
+ module GitStatistics
2
+ class DiffSummary < SimpleDelegator
3
+ def initialize(repo, patch)
4
+ @repo = repo
5
+ super(patch)
6
+ end
7
+
8
+ # We flip these around since we are diffing in the opposite direction -- new.diff(old)
9
+ def additions
10
+ __getobj__.deletions
11
+ end
12
+
13
+ # We flip these around since we are diffing in the opposite direction -- new.diff(old)
14
+ def deletions
15
+ __getobj__.additions
16
+ end
17
+
18
+ def net
19
+ additions - deletions
20
+ end
21
+
22
+ # We flip these around since we are diffing in the opposite direction -- new.diff(old)
23
+ def status
24
+ if delta.status == :deleted
25
+ return :added
26
+ elsif delta.status == :added
27
+ return :deleted
28
+ else
29
+ return delta.status
30
+ end
31
+ end
32
+
33
+ def similarity
34
+ delta.similarity
35
+ end
36
+
37
+ def filename
38
+ if (status == :deleted)
39
+ delta.old_file[:path]
40
+ else
41
+ delta.new_file[:path]
42
+ end
43
+ end
44
+
45
+ # We flip these around since we are diffing in the opposite direction -- new.diff(old)
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
56
+ end
57
+ end
58
+
59
+ def inspect
60
+ %Q{<GitStatistics::FileStat @filename=#{filename} @status=#{status} @similarity=#{similarity} @language=#{language} @additions=#{additions}, @deletions=#{deletions}, @net=#{net}>}
61
+ end
62
+
63
+ def to_json
64
+ { filename: filename, status: status, similarity: similarity, language: language, additions: additions, deletions: deletions, net: net}
65
+ end
66
+
67
+ # Determine the language of the file from the blob
68
+ def language
69
+ language = "Unknown"
70
+ 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
75
+ end
76
+ language
77
+ end
78
+ end
79
+ end
@@ -2,10 +2,13 @@ module GitStatistics
2
2
  module Formatters
3
3
  class Console
4
4
 
5
+ attr_reader :output
5
6
  attr_accessor :commits, :config
6
7
 
7
8
  def initialize(commits)
8
9
  @commits = commits
10
+ @config = {}
11
+ @output = []
9
12
  end
10
13
 
11
14
  def prepare_result_summary(sort, email, top_n = 0)
@@ -26,7 +29,7 @@ module GitStatistics
26
29
 
27
30
  # Acquire formatting pattern for output
28
31
  @pattern = "| %-#{config[:author_length]}s | %-#{config[:language_length]}s | %7s | %9s | %9s | %7s | %7s | %7s | %6s | %6s |"
29
- config
32
+ @config
30
33
  end
31
34
 
32
35
  def print_summary(sort, email, top_n = 0)
@@ -35,47 +38,45 @@ module GitStatistics
35
38
  config = prepare_result_summary(sort, email, top_n)
36
39
 
37
40
  # Print query/header information
38
- output = print_header
39
-
41
+ print_header
40
42
  # Print per author information
41
43
  config[:data].each do |name, commit_data|
42
- output << print_row(name, commit_data)
43
- output << print_language_data(commit_data)
44
+ print_row(name, commit_data)
45
+ print_language_data(commit_data)
44
46
  end
45
- output << separator
46
- output << print_row("Repository Totals", commit_totals)
47
- output << print_language_data(commit_totals)
48
- output.flatten.join("\n")
47
+ add_row separator
48
+ print_row("Repository Totals", commit_totals)
49
+ print_language_data(commit_totals)
50
+ display!
51
+ end
52
+
53
+ def display!
54
+ output.join("\n")
49
55
  end
50
56
 
51
57
  def print_language_data(data)
52
- output = []
53
58
  # Print information of each language for the data
54
59
  data[:languages].each do |language, commit_data|
55
- output << print_row("", commit_data, language)
60
+ print_row("", commit_data, language)
56
61
  end
57
62
  output
58
63
  end
59
64
 
60
65
  def print_row(name, commit_info, language = '')
61
- format_for_row(name, language, commit_info[:commits],
62
- commit_info[:additions], commit_info[:deletions], commit_info[:create],
63
- commit_info[:delete], commit_info[:rename], commit_info[:copy], commit_info[:merges])
66
+ add_row format_for_row(name, language, commit_info[:commits],
67
+ commit_info[:additions], commit_info[:deletions], commit_info[:added_files],
68
+ commit_info[:deleted_files], commit_info[:renamed_files], commit_info[:copied_files], commit_info[:merges])
64
69
  end
65
70
 
66
71
  def print_header
67
- output = []
68
- output << get_author_info(@commits.stats.size)
69
- output << get_header_info
70
- output
72
+ get_author_info(@commits.stats.size)
73
+ get_header_info
71
74
  end
72
75
 
73
76
  def get_header_info
74
- headers = []
75
- headers << separator
76
- headers << format_for_row('Name/Email', 'Language', 'Commits', 'Additions', 'Deletions', 'Creates', 'Deletes', 'Renames', 'Copies', 'Merges')
77
- headers << separator
78
- headers
77
+ add_row separator
78
+ add_row format_for_row('Name/Email', 'Language', 'Commits', 'Additions', 'Deletions', 'Creates', 'Deletes', 'Renames', 'Copies', 'Merges')
79
+ add_row separator
79
80
  end
80
81
 
81
82
  def format_for_row(*columns)
@@ -83,15 +84,19 @@ module GitStatistics
83
84
  end
84
85
 
85
86
  def separator
86
- "-" * 89 + "-"*config[:author_length] + "-"*config[:language_length]
87
+ ("-" * 89) + ("-" * config[:author_length]) + ("-" * config[:language_length])
87
88
  end
88
89
 
89
90
  def get_author_info(total_authors)
90
91
  if config[:top_n] > 0 && config[:top_n] < total_authors
91
- return "Top #{config[:top_n]} authors(#{total_authors}) sorted by #{config[:sort]}"
92
+ add_row "Top #{config[:top_n]} authors(#{total_authors}) sorted by #{config[:sort]}"
93
+ else
94
+ add_row "All authors(#{total_authors}) sorted by #{config[:sort]}"
92
95
  end
96
+ end
93
97
 
94
- "All authors(#{total_authors}) sorted by #{config[:sort]}"
98
+ def add_row(string_or_array)
99
+ output.concat Array(string_or_array)
95
100
  end
96
101
  end
97
102
  end
@@ -1,10 +1,11 @@
1
1
  require 'json'
2
- require 'grit'
3
- require 'linguist'
4
2
  require 'pathname'
3
+ require 'ostruct'
4
+ require 'optparse'
5
+ require 'delegate'
6
+ require 'fileutils'
5
7
 
6
- # Must be required before all other files
7
- require 'git_statistics/blob'
8
- require 'git_statistics/regex_matcher'
8
+ require 'rugged'
9
+ require 'language_sniffer'
9
10
 
10
- Dir.glob(File.dirname(__FILE__) + '/**/*.rb') {|file| require file}
11
+ Dir.glob(File.dirname(__FILE__) + '/**/*.rb') { |file| require file }
@@ -3,7 +3,7 @@ module GitStatistics
3
3
  include Enumerable
4
4
 
5
5
  def initialize(command)
6
- @command = command
6
+ @command = command
7
7
  end
8
8
 
9
9
  def command
@@ -3,103 +3,35 @@ require 'rbconfig'
3
3
  module GitStatistics
4
4
  module Utilities
5
5
 
6
- class NotInRepository < StandardError; end
7
-
8
- def self.get_repository(path = Dir.pwd)
9
- ascender = Pathname.new(path).to_enum(:ascend)
10
- repo_path = ascender.detect { |path| (path + '.git').exist? }
11
- raise NotInRepository unless repo_path
12
- Grit::Repo.new(repo_path.to_s)
13
- rescue NotInRepository
14
- Log.error "You must be within a Git project to run git-statistics."
15
- exit 0
16
- end
17
-
18
- def self.max_length_in_list(list, max = nil)
19
- return nil if list.nil?
20
- list.each do |key,value|
21
- max = key.length if max.nil? || key.length > max
22
- end
23
- max
6
+ def self.max_length_in_list(list, min_length = nil)
7
+ list ||= []
8
+ min_length = min_length.to_i
9
+ list_max = list.map { |k,_| k.length }.max || 0
10
+ list_max >= min_length ? list_max : min_length
24
11
  end
25
12
 
26
- def self.split_old_new_file(old, new)
27
- # Split the old and new chunks up (separted by the =>)
28
- split_old = old.split('{')
29
- split_new = new.split('}')
30
-
31
- # Handle recombine the file splits into their whole paths)
32
- if split_old.one? && split_new.one?
33
- old_file = split_old[0]
34
- new_file = split_new[0]
35
- elsif split_new.one?
36
- old_file = split_old[0] + split_old[1]
37
- new_file = split_old[0] + split_new[0]
38
- elsif split_old.one?
39
- old_file = split_old[0] + split_new[1]
40
- new_file = split_old[0] + split_new[0] + split_new[1]
41
- else
42
- old_file = split_old[0] + split_old[1] + split_new[1]
43
- new_file = split_old[0] + split_new[0] + split_new[1]
44
- end
45
-
46
- # Return files, yet remove the '//' if present from combining splits
47
- return {:old_file => old_file.gsub('//', '/'),
48
- :new_file => new_file.gsub('//', '/')}
49
- end
50
-
51
- def self.find_blob_in_tree(tree, file)
52
- # Check If cannot find tree in commit or if we found a submodule as the changed file
53
- if tree.nil? || file.nil?
54
- return nil
55
- elsif tree.instance_of?(Grit::Submodule)
56
- return tree
57
- end
58
-
59
- # If the blob is within the current directory (tree)
60
- if file.one?
61
- blob = tree / file.first
62
-
63
- # Check if blob is nil (could not find changed file in tree)
64
- if blob.nil?
65
-
66
- # Try looking for submodules as they cannot be found using tree / file notation
67
- tree.contents.each do |content|
68
- if file.first == content.name
69
- return tree
70
- end
71
- end
72
-
73
- # Exit through recusion with the base case of a nil tree/blob
74
- return find_blob_in_tree(blob, file)
75
- end
76
- return blob
77
- else
78
- # Explore deeper in the tree to find the blob of the changed file
79
- return find_blob_in_tree(tree / file.first, file[1..-1])
80
- end
81
- end
13
+ COMMANDS = {
14
+ :windows => ->{ raise "`stat` is not supported on Windows" },
15
+ :mac => ->{ "-f %m" }
16
+ }
17
+ COMMANDS.default = ->{ "-c %Y" }
82
18
 
83
19
  def self.get_modified_time(file)
84
- if os == :windows
85
- raise "`stat` is not supported on the Windows operating system"
86
- end
87
- flags = os == :mac ? "-f %m" : "-c %Y"
20
+ flags = COMMANDS[os].()
88
21
  time_at("stat #{flags} #{file}")
89
22
  end
90
23
 
91
- def os
92
- case RbConfig::CONFIG['host_os']
93
- when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
94
- :windows
95
- when /darwin|mac os/
96
- :mac
97
- when /linux/
98
- :linux
99
- when /solaris|bsd/
100
- :unix
101
- else
102
- :unknown
24
+ class OperatingSystem
25
+ OPERATING_SYSTEMS = {
26
+ /mswin|msys|mingw|cygwin|bccwin|wince|emc/ => :windows,
27
+ /darwin|mac os/ => :mac,
28
+ /linux/ => :linux,
29
+ /solaris|bsd/ => :unix
30
+ }
31
+ OPERATING_SYSTEMS.default = :unknown
32
+
33
+ def self.determine(os_name)
34
+ OPERATING_SYSTEMS.select { |k,_| k =~ os_name }.first
103
35
  end
104
36
  end
105
37
 
@@ -107,11 +39,16 @@ module GitStatistics
107
39
  Time.at(%x{#{cmd}}.to_i)
108
40
  end
109
41
 
42
+ def self.os
43
+ OperatingSystem.determine(RbConfig::CONFIG['host_os'])
44
+ end
45
+
110
46
  def self.number_of_matching_files(directory, pattern)
111
47
  Dir.entries(directory).grep(pattern).size
112
48
  rescue SystemCallError
113
- warn "No such directory #{File.expand_path(directory)}"
49
+ Log.error "No such directory #{File.expand_path(directory)}"
114
50
  0
115
51
  end
52
+
116
53
  end
117
54
  end
@@ -1,3 +1,3 @@
1
1
  module GitStatistics
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -5,33 +5,29 @@ describe Collector do
5
5
  let(:limit) {100}
6
6
  let(:fresh) {true}
7
7
  let(:pretty) {false}
8
- let(:collector) {Collector.new(limit, fresh, pretty)}
9
-
10
- # Create buffer which is an array of cleaned lines
11
- let(:buffer) {
12
- fixture(fixture_file).lines
13
- }
8
+ let(:repo) { GIT_REPO }
9
+ let(:collector) {Collector.new(repo, limit, fresh, pretty)}
14
10
 
15
11
  describe "#collect" do
16
- let(:branch) {""}
12
+ let(:branch) {CLI::DEFAULT_BRANCH}
17
13
  let(:email) {false}
18
14
  let(:merge) {true}
19
- let(:time_since) {"--since \"Tue Sep 25 14:15:44 2012 -0400\""}
20
- let(:time_until) {"--until \"Tue Sep 25 14:45:05 2012 -0400\""}
15
+ let(:time_since) {"Tue Sep 24 14:15:44 2012 -0400"}
16
+ let(:time_until) {"Tue Sep 26 14:45:05 2012 -0400"}
21
17
  let(:author) {"Kevin Jalbert"}
22
18
 
23
19
  let(:setup) {
24
- collector.collect(branch, time_since, time_until)
20
+ collector.collect({:branch => branch, :time_since => time_since, :time_until => time_until})
25
21
  collector.commits.calculate_statistics(email, merge)
26
22
  @subject = collector.commits.stats[author]
27
23
  }
28
24
 
29
25
  context "with no merge commits" do
30
26
  let(:merge) {false}
31
- let(:time_since) {"--since \"Tue Sep 10 14:15:44 2012 -0400\""}
32
- let(:time_until) {"--until \"Tue Sep 11 14:45:05 2012 -0400\""}
27
+ let(:time_since) {"Tue Sep 10 14:15:44 2012 -0400"}
28
+ let(:time_until) {"Tue Sep 11 14:45:05 2012 -0400"}
33
29
 
34
- before(:all) {setup}
30
+ before(:all) { setup }
35
31
 
36
32
  it{@subject[:additions].should == 276}
37
33
  it{@subject[:deletions].should == 99}
@@ -40,279 +36,89 @@ describe Collector do
40
36
 
41
37
  it{@subject[:languages][:Ruby][:additions].should == 270}
42
38
  it{@subject[:languages][:Ruby][:deletions].should == 99}
43
- it{@subject[:languages][:Ruby][:create].should == 2}
44
- it{@subject[:languages][:Unknown][:additions].should == 6}
45
- it{@subject[:languages][:Unknown][:deletions].should == 0}
46
- it{@subject[:languages][:Unknown][:create].should == 1}
39
+ it{@subject[:languages][:Ruby][:added_files].should == 2}
40
+ it{@subject[:languages][:Text][:additions].should == 6}
41
+ it{@subject[:languages][:Text][:deletions].should == 0}
42
+ it{@subject[:languages][:Text][:added_files].should == 1}
47
43
  end
48
44
 
49
45
  context "with merge commits and merge option" do
50
- before(:all) {setup}
46
+ before(:all) { setup }
51
47
 
52
- it{@subject[:additions].should == 667}
53
- it{@subject[:deletions].should == 483}
54
- it{@subject[:commits].should == 3}
48
+ it{@subject[:additions].should == 1240}
49
+ it{@subject[:deletions].should == 934}
50
+ it{@subject[:commits].should == 9}
55
51
  it{@subject[:merges].should == 1}
56
52
 
57
53
  it{@subject[:languages][:Markdown][:additions].should == 1}
58
54
  it{@subject[:languages][:Markdown][:deletions].should == 0}
59
- it{@subject[:languages][:Ruby][:additions].should == 654}
60
- it{@subject[:languages][:Ruby][:deletions].should == 483}
55
+ it{@subject[:languages][:Ruby][:additions].should == 1227}
56
+ it{@subject[:languages][:Ruby][:deletions].should == 934}
61
57
  it{@subject[:languages][:Unknown][:additions].should == 12}
62
58
  it{@subject[:languages][:Unknown][:deletions].should == 0}
63
59
  end
64
60
 
65
61
  context "with merge commits and no merge option" do
66
62
  let(:merge) {false}
67
- before(:all) {setup}
63
+ before(:all) { setup }
68
64
 
69
- it{@subject[:additions].should == 8}
70
- it{@subject[:deletions].should == 1}
71
- it{@subject[:commits].should == 2}
65
+ it{@subject[:additions].should == 581}
66
+ it{@subject[:deletions].should == 452}
67
+ it{@subject[:commits].should == 8}
72
68
  it{@subject[:merges].should == 0}
73
69
 
74
70
  it{@subject[:languages][:Markdown][:additions].should == 1}
75
71
  it{@subject[:languages][:Markdown][:deletions].should == 0}
76
- it{@subject[:languages][:Ruby][:additions].should == 1}
77
- it{@subject[:languages][:Ruby][:deletions].should == 1}
72
+ it{@subject[:languages][:Ruby][:additions].should == 574}
73
+ it{@subject[:languages][:Ruby][:deletions].should == 452}
78
74
  it{@subject[:languages][:Unknown][:additions].should == 6}
79
75
  it{@subject[:languages][:Unknown][:deletions].should == 0}
80
76
  end
81
77
  end
82
78
 
83
- describe "#acquire_commit_data" do
84
- let(:data) {collector.acquire_commit_data(buffer.first)}
85
-
86
- context "no parent, first commit" do
87
- let(:fixture_file) {"commit_buffer_information_first.txt"}
88
- it {data[:sha].should == "111111aa111a11111a11aa11aaaa11a111111a11"}
89
- it {data[:data][:author].should == "Test Author"}
90
- it {data[:data][:author_email].should == "author@test.com"}
91
- it {data[:data][:time].should == "2011-01-11 11:11:11 +0000"}
92
- it {data[:data][:merge].should be_false}
93
- end
94
-
95
- context "without merge, one parent" do
96
- let(:fixture_file) {"commit_buffer_information.txt"}
97
- it {data[:sha].should == "111111aa111a11111a11aa11aaaa11a111111a11"}
98
- it {data[:data][:author].should == "Test Author"}
99
- it {data[:data][:author_email].should == "author@test.com"}
100
- it {data[:data][:time].should == "2011-01-11 11:11:11 +0000"}
101
- it {data[:data][:merge].should be_false}
102
- end
103
-
104
- context "with merge, two parents" do
105
- let(:fixture_file) {"commit_buffer_information_with_merge.txt"}
106
- it {data[:sha].should == "111111aa111a11111a11aa11aaaa11a111111a11"}
107
- it {data[:data][:author].should == "Test Author"}
108
- it {data[:data][:author_email].should == "author@test.com"}
109
- it {data[:data][:time].should == "2011-01-11 11:11:11 +0000"}
110
- it {data[:data][:merge].should be_true}
111
- end
112
- end
113
-
114
- describe "#identify_changed_files" do
115
- let(:files) {collector.identify_changed_files(buffer)}
116
- let(:fixture_file) {"commit_buffer_changes.txt"}
117
-
118
- context "with no changes" do
119
- let(:buffer) {[]}
120
- it {files.size.should == 0}
121
- it {files[0].should.nil?}
122
- end
123
-
124
- context "with all types (create,delete,rename,copy) of files" do
125
- it {files.size.should == 5}
126
-
127
- it {files[0][:additions].should == 45}
128
- it {files[0][:deletions].should == 1}
129
- it {files[0][:file].should == "dir/README"}
130
-
131
- it {files[1][:additions].should == 6}
132
- it {files[1][:deletions].should == 5}
133
- it {files[1][:old_file].should == "dir/lib/old_dir/copy_file.rb"}
134
- it {files[1][:file].should == "dir/lib/new_dir/copy_file.rb"}
135
- it {files[1][:status].should == "copy"}
136
-
137
- it {files[2][:additions].should == 0}
138
- it {files[2][:deletions].should == 0}
139
- it {files[2][:old_file].should == "dir/lib/rename/old_file.rb"}
140
- it {files[2][:file].should == "dir/lib/rename/new_file.rb"}
141
- it {files[2][:status].should == "rename"}
142
-
143
- it {files[3][:additions].should == 0}
144
- it {files[3][:deletions].should == 127}
145
- it {files[3][:file].should == "dir/lib/delete_file.rb"}
146
- it {files[3][:status].should == "delete"}
147
-
148
- it {files[4][:additions].should == 60}
149
- it {files[4][:deletions].should == 0}
150
- it {files[4][:file].should == "dir/lib/create_file.rb"}
151
- it {files[4][:status].should == "create"}
152
- end
153
- end
154
-
155
79
  describe "#extract_commit" do
156
- let(:data) {collector.extract_commit(buffer)}
157
-
158
- context "with valid buffer" do
159
- let(:fixture_file) {"commit_buffer_whole.txt"}
80
+ let(:commit) {repo.lookup(sha)}
81
+ let(:data) {collector.extract_commit(commit, nil)}
160
82
 
83
+ context "with valid commit" do
84
+ let(:sha) {"260bc61e2c42930d91f3503c5849b0a2351275cf"}
161
85
  it {data[:author].should == "Kevin Jalbert"}
162
86
  it {data[:author_email].should == "kevin.j.jalbert@gmail.com"}
163
- it {data[:time].should == "2012-04-12 14:13:56 -0400"}
87
+ it {data[:time].should match /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-|+]\d{4}/}
164
88
 
165
89
  it {data[:merge].should == false}
166
90
  it {data[:additions].should == 30}
167
91
  it {data[:deletions].should == 2}
168
- it {data[:create].should == 1}
92
+ it {data[:added_files].should == 1}
93
+ it {data[:deleted_files].should == 0}
169
94
 
170
- it {data[:files][0][:name].should == "Gemfile"}
95
+ it {data[:files][0][:filename].should == "Gemfile"}
171
96
  it {data[:files][0][:additions].should == 0}
172
97
  it {data[:files][0][:deletions].should == 1}
173
98
  it {data[:files][0][:status].should.nil?}
174
- it {data[:files][0][:binary].should == false}
175
- it {data[:files][0][:image].should == false}
176
- it {data[:files][0][:vendored].should == false}
177
- it {data[:files][0][:generated].should == false}
178
99
  it {data[:files][0][:language].should == "Ruby"}
179
100
 
180
- it {data[:files][1][:name].should == "Gemfile.lock"}
101
+ it {data[:files][1][:filename].should == "Gemfile.lock"}
181
102
  it {data[:files][1][:additions].should == 30}
182
103
  it {data[:files][1][:deletions].should == 0}
183
- it {data[:files][1][:status].should == "create"}
184
- it {data[:files][1][:binary].should == false}
185
- it {data[:files][1][:image].should == false}
186
- it {data[:files][1][:vendored].should == false}
187
- it {data[:files][1][:generated].should == true}
104
+ it {data[:files][1][:status].should eq(:added)}
188
105
  it {data[:files][1][:language].should == "Unknown"}
189
106
 
190
- it {data[:files][2][:name].should == "lib/git_statistics/initialize.rb"}
107
+ it {data[:files][2][:filename].should == "lib/git_statistics/initialize.rb"}
191
108
  it {data[:files][2][:additions].should == 0}
192
109
  it {data[:files][2][:deletions].should == 1}
193
110
  it {data[:files][2][:status].should.nil?}
194
- it {data[:files][2][:binary].should == false}
195
- it {data[:files][2][:image].should == false}
196
- it {data[:files][2][:vendored].should == false}
197
- it {data[:files][2][:generated].should == false}
198
111
  it {data[:files][2][:language].should == "Ruby"}
199
112
  end
200
113
 
201
- context "with buffer that has no file changes" do
202
- let(:fixture_file) {"commit_buffer_information.txt"}
203
- it {data.should.nil?}
204
- end
205
-
206
- context "with invalid buffer" do
207
- let(:buffer) {"invalid input"}
208
- it {data.should.nil?}
209
- end
210
- end
211
-
212
- describe "#fall_back_collect_commit" do
213
- subject { collector.fall_back_collect_commit(sha) }
214
- context "with valid sha" do
215
- let(:fixture_file) { "commit_buffer_whole.txt" }
216
- let(:sha) { "260bc61e2c42930d91f3503c5849b0a2351275cf" }
217
- it { should == buffer }
114
+ context "with invalid commit" do
115
+ let(:sha) {"111111aa111a11111a11aa11aaaa11a111111a11"}
116
+ it { expect {data}.to raise_error(Rugged::OdbError) }
218
117
  end
219
118
 
220
119
  context "with invalid sha" do
221
- let(:sha) { "111111aa111a11111a11aa11aaaa11a111111a11" }
222
- it { should be_empty }
223
- end
224
- end
225
-
226
- describe "#get_blob" do
227
- let(:sha) { "695b487432e8a1ede765b4e3efda088ab87a77f8" } # Commit within repository
228
- subject { collector.get_blob(sha, file) }
229
-
230
- context "with valid blob" do
231
- let(:file) {{:file => "Gemfile.lock"}}
232
- it { should be_a Grit::Blob }
233
- its(:name) { should == File.basename(file[:file]) }
234
- end
235
-
236
- context "with deleted file" do
237
- let(:file) {{:file => "spec/collector_spec.rb"}}
238
- it { should be_a Grit::Blob }
239
- its(:name) { should == File.basename(file[:file]) }
240
- end
241
-
242
- context "with invalid blob" do
243
- let(:file) {{:file => "dir/nothing.rb"}}
244
- it { should be_nil }
245
- end
246
- end
247
-
248
- describe "#process_blob" do
249
- let(:sha) {"695b487432e8a1ede765b4e3efda088ab87a77f8"} # Commit within repository
250
- let(:blob) {collector.get_blob(sha, file)}
251
- let(:data) {
252
- data = Hash.new(0)
253
- data[:files] = []
254
- collector.process_blob(data, blob, file)
255
- }
256
- let(:data_file) {data_file = data[:files].first}
257
-
258
- context "with status (delete) blob" do
259
- let(:file) {{:file => "spec/collector_spec.rb",
260
- :additions => 0,
261
- :deletions => 6,
262
- :status => "delete"}}
263
-
264
- it {data[:additions].should == file[:additions]}
265
- it {data[:deletions].should == file[:deletions]}
266
-
267
- it {data_file[:name].should == file[:file]}
268
- it {data_file[:additions].should == file[:additions]}
269
- it {data_file[:deletions].should == file[:deletions]}
270
- it {data_file[:status].should == file[:status]}
271
- it {data_file[:binary].should == false}
272
- it {data_file[:image].should == false}
273
- it {data_file[:vendored].should == false}
274
- it {data_file[:generated].should == false}
275
- it {data_file[:language].should == "Ruby"}
276
- end
277
-
278
- context "with invalid language blob" do
279
- let(:file) {{:file => "Gemfile.lock",
280
- :additions => 33,
281
- :deletions => 11,
282
- :status => nil}}
283
-
284
- it {data[:additions].should == file[:additions]}
285
- it {data[:deletions].should == file[:deletions]}
286
-
287
- it {data_file[:name].should == file[:file]}
288
- it {data_file[:additions].should == file[:additions]}
289
- it {data_file[:deletions].should == file[:deletions]}
290
- it {data_file[:status].should.nil?}
291
- it {data_file[:binary].should == false}
292
- it {data_file[:image].should == false}
293
- it {data_file[:vendored].should == false}
294
- it {data_file[:generated].should == true}
295
- it {data_file[:language].should == "Unknown"}
296
- end
297
-
298
- context "with valid language blob" do
299
- let(:file) {{:file => "README.md",
300
- :additions => 7,
301
- :deletions => 3,
302
- :status => nil}}
303
-
304
- it {data[:additions].should == file[:additions]}
305
- it {data[:deletions].should == file[:deletions]}
306
-
307
- it {data_file[:name].should == file[:file]}
308
- it {data_file[:additions].should == file[:additions]}
309
- it {data_file[:deletions].should == file[:deletions]}
310
- it {data_file[:status].should.nil?}
311
- it {data_file[:binary].should == false}
312
- it {data_file[:image].should == false}
313
- it {data_file[:vendored].should == false}
314
- it {data_file[:generated].should == false}
315
- it {data_file[:language].should == "Markdown"}
120
+ let(:sha) {"invalid input"}
121
+ it { expect {data}.to raise_error(Rugged::InvalidError) }
316
122
  end
317
123
  end
318
124