11module GitStatistics
22 class CommitSummary < SimpleDelegator
3- def initialize ( commit )
3+ def initialize ( repo , commit )
44 super ( commit )
5+ @repo = repo
6+ @diff = diff ( commit . parents . first )
7+ @patches = @diff . patches
58 end
69
710 # A Git commit is a merge if it has more than one parent
@@ -10,13 +13,18 @@ def merge?
1013 end
1114
1215 # How many files were removed in this commit
13- def removed_files
14- cached_show . select { |diff | diff . deleted_file == true } . count
16+ def deleted_files
17+ file_stats . select { |file | file . status == :deleted } . count
1518 end
1619
1720 # How many files were added in this commit
18- def new_files
19- cached_show . select { |diff | diff . new_file == true } . count
21+ def added_files
22+ file_stats . select { |file | file . status == :added } . count
23+ end
24+
25+ # How many files were modified (not added/deleted) in this commit
26+ def modified_files
27+ file_stats . select { |file | file . status == :modified } . count
2028 end
2129
2230 # How many total additions in this commit?
@@ -35,18 +43,18 @@ def net
3543 end
3644
3745 def file_stats
38- @cached_file_stats ||= diffstats . map { |diff | DiffSummary . new ( diff , current_tree ) }
46+ @cached_file_stats ||= diffstats . map { |diff | DiffSummary . new ( @repo , diff ) }
3947 end
4048
41- LanguageSummary = Struct . new ( :name , :additions , :deletions , :net )
49+ LanguageSummary = Struct . new ( :name , :additions , :deletions , :net , :added_files , :deleted_files , :modified_files )
4250
4351 # Array of LanguageSummary objects (one for each language) for simple calculations
4452 def languages
4553 grouped_language_files . collect do |language , stats |
4654 additions = summarize ( stats , :additions )
4755 deletions = summarize ( stats , :deletions )
4856 net = summarize ( stats , :net )
49- LanguageSummary . new ( language , additions , deletions , net )
57+ LanguageSummary . new ( language , additions , deletions , net , added_files , deleted_files , modified_files )
5058 end
5159 end
5260
@@ -55,72 +63,13 @@ def grouped_language_files
5563 file_stats . group_by ( &:language )
5664 end
5765
58- FileSummary = Struct . new ( :name , :language , :additions , :deletions , :net , :filestatus )
59-
60- # Array of FileSummary objects (one for each file) for simple calculations
61- def files
62- file_stats . collect { |stats | determine_file_summary ( stats ) }
63- end
64-
65- def cached_show
66- @cached_commit_show ||= show
67- end
68-
6966 # Files touched in this commit
70- def file_names
71- diffstats . map ( &:filename )
72- end
73-
74- # Fetch the current Grit::Repo tree from this commit
75- def current_tree
76- @current_tree ||= repo . tree ( sha )
67+ def filenames
68+ file_stats . map ( &:filename )
7769 end
7870
7971 private
8072
81- def determine_file_summary ( stats )
82- filestatus = :modified
83- language = stats . language
84-
85- # Determine if this file could be a new or deleted file
86- if ( stats . additions > 0 && stats . deletions == 0 ) || ( stats . additions == 0 && stats . deletions > 0 )
87- # Extract file status from commit's diff object
88- cached_show . each do |diff |
89- if stats . filename == diff . b_path
90- filestatus = :create if diff . new_file
91- filestatus = :delete if diff . deleted_file
92- break
93- end
94- end
95- end
96-
97- # Determine language of blob
98- if stats . tree?
99- # Trees have no language (the tree's blobs are still processed via the remainder diffstats)
100- language = "Unknown"
101- elsif stats . submodule?
102- language = "Submodule"
103- elsif stats . blob . nil?
104- # If blob is nil (i.e., deleted file) grab the previous version of this blob using the parents of the current commit
105- blob = BlobFinder . get_blob ( self . parents . first , stats . filename )
106- blob = BlobFinder . get_blob ( self . parents . last , stats . filename ) if blob . nil?
107-
108- # Determine language of newly found blob
109- if blob . kind_of? Grit ::Tree
110- language = "Unknown"
111- elsif blob . kind_of? Grit ::Submodule
112- language = "Submodule"
113- elsif blob . nil? || blob . language . nil?
114- language = "Unknown"
115- else
116- language = blob . language . to_s
117- end
118- end
119-
120- # TODO Converts file summary into hash to keep json compatibility (for now)
121- Hash [ FileSummary . new ( stats . filename , language , stats . additions , stats . deletions , stats . net , filestatus ) . each_pair . to_a ]
122- end
123-
12473 def summarize ( stats , what )
12574 stats . map ( &what ) . inject ( 0 , :+ )
12675 end
@@ -130,19 +79,7 @@ def commit_summary(what)
13079 end
13180
13281 def diffstats
133- if merge?
134- merge_diffstats
135- else
136- stats . to_diffstat
137- end
138- end
139-
140- # Hackery coming...
141- DIFFSTAT_REGEX = /([-|\d ]+)\s +([-|\d ]+)\s +(.+)/i
142- def merge_diffstats
143- native_diff = repo . git . native ( :diff , { numstat : true } , parents . join ( "..." ) )
144- per_file_info = native_diff . scan ( DIFFSTAT_REGEX )
145- per_file_info . map { |add , del , file | Grit ::DiffStat . new ( file , add . to_i , del . to_i ) }
82+ @patches
14683 end
14784
14885 end
0 commit comments