git_statistics 0.6.0 → 0.7.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.
@@ -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