git_ownership_insights 1.2.0 → 2.0.1

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
  SHA256:
3
- metadata.gz: 6d884a43cd70caba8943ba59a6ce05d46631cb6927ed0eefa74a1dccbc2d66f8
4
- data.tar.gz: 180007096b00a2978d8e6d6440c9214b1f8d59e41c841e665392db2c955fecd8
3
+ metadata.gz: 87339076047688d1452d5b7a1ca0455c9955cc580b9e472889d7dcf54f901fc7
4
+ data.tar.gz: cffcd3905dfd9dd500b92636c59301e7b7f640c594b3687f3770310d198eaa0b
5
5
  SHA512:
6
- metadata.gz: 27a2bc913215ffb0cee443be41b1a91128edc31998d0f3841ad0ac02fd03393529f41825c55645cfc007f0a0d478a439834568334e2bf81c89929d3eeb396f37
7
- data.tar.gz: e8d564d1734b023321027464ff86aea38463085681ef579297b69fc8f4bfd034b558d064e754bc0b142bf1a18171f4e959dd9c1af0d2a2ac34a375f01f5cbb88
6
+ metadata.gz: 71c488b0aff9354657f8a0b822490b9910b5082dfcbc9cf65ab521cb39f79f55a8441809101998166621b82a8dda5a0bc67c48adda796350fd8df6b5843ed0de
7
+ data.tar.gz: a41606244a1b77a1f62a08541cecadeec45f09f6eba2714d332f85359c6e670210b921e37854f64c445c0f42efd31def4d7f53a8804db989806f078f88bb5dd9
@@ -0,0 +1,2 @@
1
+ spec/fixtures/file1.swift @FIOS
2
+ spec/fixtures/file2.kt @FAND
data/.rubocop.yml ADDED
@@ -0,0 +1,14 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ # The behavior of RuboCop can be controlled via the .rubocop.yml
4
+ # configuration file. It makes it possible to enable/disable
5
+ # certain cops (checks) and to alter their behavior if they accept
6
+ # any parameters. The file can be placed either in your home
7
+ # directory or in some project directory.
8
+ #
9
+ # RuboCop will start looking for the configuration file in the directory
10
+ # where the inspected file is and continue its way up to the root directory.
11
+ #
12
+ # See https://docs.rubocop.org/rubocop/configuration
13
+ AllCops:
14
+ TargetRubyVersion: 3.2.1
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,65 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2024-01-30 15:39:52 UTC using RuboCop version 1.60.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 12
10
+ # Configuration parameters: AllowedMethods.
11
+ # AllowedMethods: enums
12
+ Lint/ConstantDefinitionInBlock:
13
+ Exclude:
14
+ - 'spec/git_ownership_insights_spec.rb'
15
+
16
+ # Offense count: 4
17
+ # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
18
+ Metrics/AbcSize:
19
+ Max: 181
20
+
21
+ # Offense count: 4
22
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
23
+ # AllowedMethods: refine
24
+ Metrics/BlockLength:
25
+ Max: 76
26
+
27
+ # Offense count: 1
28
+ # Configuration parameters: CountComments, CountAsOne.
29
+ Metrics/ClassLength:
30
+ Max: 200
31
+
32
+ # Offense count: 1
33
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
34
+ Metrics/CyclomaticComplexity:
35
+ Max: 28
36
+
37
+ # Offense count: 4
38
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
39
+ Metrics/MethodLength:
40
+ Max: 109
41
+
42
+ # Offense count: 1
43
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
44
+ Metrics/PerceivedComplexity:
45
+ Max: 29
46
+
47
+ # Offense count: 1
48
+ # Configuration parameters: AllowedConstants.
49
+ Style/Documentation:
50
+ Exclude:
51
+ - 'spec/**/*'
52
+ - 'test/**/*'
53
+ - 'lib/git_ownership_insights/git_ownership_insight.rb'
54
+
55
+ # Offense count: 1
56
+ Style/MultilineBlockChain:
57
+ Exclude:
58
+ - 'lib/git_ownership_insights/git_ownership_insight.rb'
59
+
60
+ # Offense count: 11
61
+ # This cop supports safe autocorrection (--autocorrect).
62
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
63
+ # URISchemes: http, https
64
+ Layout/LineLength:
65
+ Max: 229
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- git_ownership_insights (1.2.0)
4
+ git_ownership_insights (2.0.0)
5
5
  date
6
6
  pry
7
7
 
@@ -134,5 +134,5 @@ end
134
134
  system("git checkout #{DEFAULT_BRANCH}", [:out] => File::NULL)
135
135
  system('git pull', %i[out err] => File::NULL)
136
136
 
137
- GitOwnershipInsights.contribution_message(duration_in_days: options[:duration_in_days] || 30, directory_path: REPO_PATH,
138
- begin_time: DateTime.now, steps: options[:steps].to_i, debug: options[:debug])
137
+ GitOwnershipInsights.new(duration_in_days: options[:duration_in_days] || 30, directory_path: REPO_PATH,
138
+ begin_time: DateTime.now, steps: options[:steps].to_i, debug: options[:debug]).contribution_message
@@ -1,11 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module GitOwnershipInsights
4
- def self.true?(obj)
3
+ require 'pry'
4
+ require 'date'
5
+
6
+ class GitOwnershipInsights
7
+ def initialize(directory_path:, duration_in_days:, begin_time:, debug: nil, steps: 1)
8
+ @directory_path = directory_path
9
+ @duration_in_days = duration_in_days
10
+ @begin_time = begin_time
11
+ @debug = debug
12
+ @steps = steps
13
+ end
14
+
15
+ def true?(obj)
5
16
  obj.to_s.downcase == 'true'
6
17
  end
7
18
 
8
- def self.read_codeowners_file
19
+ def read_codeowners_file
9
20
  raise "CODEOWNERS file does not exist under #{CODEOWNERS_PATH}" unless File.exist?(CODEOWNERS_PATH)
10
21
 
11
22
  codeowners = {}
@@ -20,7 +31,7 @@ module GitOwnershipInsights
20
31
  codeowners
21
32
  end
22
33
 
23
- def self.find_owners(file_path, codeowners)
34
+ def find_owners(file_path, codeowners)
24
35
  matching_patterns = codeowners.keys.select do |pattern|
25
36
  pattern_regex = Regexp.new("^#{Regexp.escape(pattern.sub(%r{^/+}, '').chomp('/')).gsub('\*', '.*').gsub('**',
26
37
  '.*?')}")
@@ -42,7 +53,7 @@ module GitOwnershipInsights
42
53
  codeowners[best_match].split(' ')
43
54
  end
44
55
 
45
- def self.count_big_files(directory_path, size: BIG_FILE_SIZE)
56
+ def count_big_files(directory_path, size: BIG_FILE_SIZE)
46
57
  size = size.to_i
47
58
  # Get a list of all files in the specified directory
48
59
  files = Dir.glob(File.join(directory_path, '**', '*')).select { |file| File.file?(file) }
@@ -65,7 +76,7 @@ module GitOwnershipInsights
65
76
  puts " *Current(*) total number of code files longer than #{size} lines:* #{count}"
66
77
  end
67
78
 
68
- def self.count_hotspot_lines(files)
79
+ def count_hotspot_lines(files)
69
80
  code_files = files.select do |f|
70
81
  extension = File.extname(f)
71
82
  valid_extensions = CODE_EXTENSIONS
@@ -83,55 +94,57 @@ module GitOwnershipInsights
83
94
  puts " *Total lines of hotspot code:* #{count}"
84
95
  end
85
96
 
86
- def self.filter_existing_code_files(files)
97
+ def filter_existing_code_files(files)
87
98
  files.select do |f|
88
99
  next unless File.exist?(f)
89
100
 
101
+ if EXCLUDED_FILES
102
+ excluded_patterns = EXCLUDED_FILES.split(',')
103
+ next if excluded_patterns.any? { |pattern| f.include?(pattern) }
104
+ end
105
+
90
106
  extension = File.extname(f)
91
107
  valid_extensions = CODE_EXTENSIONS
92
108
  valid_extensions.include?(extension)
93
109
  end
94
110
  end
95
111
 
96
- def self.git_files(directory_path:)
112
+ def git_files(directory_path:)
97
113
  `git ls-tree -r --name-only $(git rev-list -1 HEAD) -- "#{directory_path}"`
98
114
  end
99
115
 
100
- def self.files_with_changes(directory_path:, start_date:, end_date:)
116
+ def files_with_changes(directory_path:, start_date:, end_date:)
101
117
  `git log --name-only --pretty=format:"" --since="#{start_date}" --until="#{end_date}" "#{directory_path}"`
102
118
  end
103
119
 
104
- def self.git_commit_count(file:, start_date:, end_date:)
120
+ def git_commit_count(file:, start_date:, end_date:)
105
121
  `git log --since="#{start_date}" --until="#{end_date}" --follow -- "#{file}" | grep -c '^commit'`
106
122
  end
107
123
 
108
- def self.contribution_message(directory_path:, duration_in_days:, begin_time:, debug: nil, steps: nil)
109
- duration_in_days = duration_in_days.to_i
124
+ def git_commit_info(file:, start_date:, end_date:)
125
+ `git log --pretty=format:"%s" --since="#{start_date}" --until="#{end_date}" --follow -- "#{file}"`
126
+ end
127
+
128
+ def contribution_message
129
+ duration_in_days = @duration_in_days.to_i
110
130
  all_teams = []
111
131
  cross_teams_count = 0
112
132
  single_ownership_teams_count = 0
113
133
  files_changed_by_many_teams = 0
114
134
  total_changes = 0
115
- start_date = begin_time.to_time.to_i - duration_in_days * 86_400 - 30 * 86_400
116
- end_date = begin_time.to_time.to_i - 30 * 86_400
117
- git_ls = git_files(directory_path:)
135
+ start_date = @begin_time.to_time.to_i - duration_in_days * 86_400 - 30 * 86_400
136
+ end_date = @begin_time.to_time.to_i - 30 * 86_400
137
+ git_ls = git_files(directory_path: @directory_path)
118
138
  file_count = filter_existing_code_files(git_ls.split).count
119
- all_files_with_changes = files_with_changes(directory_path:, start_date:, end_date:).split.sort
139
+ all_files_with_changes = files_with_changes(directory_path: @directory_path, start_date:, end_date:).split.sort
120
140
  code_files_with_changes = filter_existing_code_files(all_files_with_changes)
121
141
  uniq_code_files_with_changes = code_files_with_changes.uniq
122
142
 
123
- if EXCLUDED_FILES
124
- excluded_patterns = EXCLUDED_FILES.split(',')
125
- uniq_code_files_with_changes = uniq_code_files_with_changes.reject do |file|
126
- excluded_patterns.any? { |pattern| file.include?(pattern) }
127
- end
128
- end
129
-
130
143
  file_team_map = {}
131
144
  uniq_code_files_with_changes.each do |file|
132
145
  filename = File.basename(file)
133
146
  commit_count = git_commit_count(file:, start_date:, end_date:).to_i
134
- git_log = `git log --pretty=format:"%s" --since="#{start_date}" --until="#{end_date}" --follow -- "#{file}"`.split("\n")
147
+ git_log = git_commit_info(file:, start_date:, end_date:).split("\n")
135
148
  teams = git_log.map do |team|
136
149
  team.match(/#{TEAM_REGEX}/)[0].upcase
137
150
  end.reject { |e| EXCLUSIONS&.include?(e) }
@@ -148,7 +161,7 @@ module GitOwnershipInsights
148
161
  single_ownership_teams_count += 1
149
162
  end
150
163
 
151
- puts "\n#{filename} [#{commit_count}]:#{teams}\n" if debug
164
+ puts "\n#{filename} [#{commit_count}]:#{teams}\n" if @debug
152
165
  end
153
166
 
154
167
  occurrences = all_teams.flatten.compact.tally
@@ -169,7 +182,7 @@ module GitOwnershipInsights
169
182
  filtered_top_touched_files = filtered_files.sort_by { |element, count| [-count.last, element] }
170
183
 
171
184
  puts ''
172
- puts "*Timeframe:* #{(begin_time - duration_in_days).strftime('%Y-%m-%d')} to #{begin_time.strftime('%Y-%m-%d')}"
185
+ puts "*Timeframe:* #{(@begin_time - duration_in_days).strftime('%Y-%m-%d')} to #{@begin_time.strftime('%Y-%m-%d')}"
173
186
  puts " *Code files with a single contributor:* #{(100 - ((files_changed_by_many_teams.to_f / file_count) * 100)).round(2)}%"
174
187
  puts " *Existing files changed by many teams:* #{files_changed_by_many_teams}"
175
188
  puts " *Current existing #{CODE_EXTENSIONS} files:* #{file_count}"
@@ -184,7 +197,7 @@ module GitOwnershipInsights
184
197
  puts " *#{CODE_EXTENSIONS} files exceeding #{BIG_FILE_SIZE} lines with multiple contributors:* #{filtered_top_touched_files.count}"
185
198
  puts " *Total amount of commits to #{CODE_EXTENSIONS} files:* #{total_changes}"
186
199
  puts " *Total #{CODE_EXTENSIONS} files changed:* #{uniq_code_files_with_changes.count}"
187
- count_big_files(directory_path)
200
+ count_big_files(@directory_path)
188
201
  puts " *Current(*) total of #{CODE_EXTENSIONS} files in the folder:* #{file_count}"
189
202
  puts " *Contributors:* #{contributors}"
190
203
  puts "* means that it the current(instant) repository value, all the other metrics are done over #{duration_in_days} days period"
@@ -193,7 +206,7 @@ module GitOwnershipInsights
193
206
  puts "\n"
194
207
  puts ' Hotspot changes:'
195
208
  filtered_top_touched_files.each do |line|
196
- puts " #{line.first.gsub(directory_path, '')} Contributors: #{line.last.first} Commits: #{line.last.last}"
209
+ puts " #{line.first.gsub(@directory_path, '')} Contributors: #{line.last.first} Commits: #{line.last.last}"
197
210
  end
198
211
  end
199
212
 
@@ -240,13 +253,13 @@ module GitOwnershipInsights
240
253
  end
241
254
  end
242
255
  end
243
- steps -= 1
256
+ @steps -= 1
244
257
 
245
- return unless steps.positive?
258
+ return unless @steps.positive?
246
259
 
247
- system("git checkout `git rev-list -1 --before='#{(begin_time - duration_in_days).strftime('%B %d %Y')}' HEAD`",
260
+ system("git checkout `git rev-list -1 --before='#{(@begin_time - duration_in_days).strftime('%B %d %Y')}' HEAD`",
248
261
  %i[out err] => File::NULL)
249
- contribution_message(duration_in_days:, directory_path:,
250
- begin_time: begin_time - duration_in_days, steps:, debug:)
262
+ @begin_time -= duration_in_days
263
+ contribution_message
251
264
  end
252
265
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module GitOwnershipInsights
4
- VERSION = '1.2.0'
3
+ class GitOwnershipInsights
4
+ VERSION = '2.0.1'
5
5
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative 'git_ownership_insights/version'
4
4
 
5
- module GitOwnershipInsights
5
+ class GitOwnershipInsights
6
6
  class Error < StandardError; end
7
7
  # Your code goes here...
8
8
  end
@@ -1,4 +1,4 @@
1
- module GitOwnershipInsights
1
+ class GitOwnershipInsights
2
2
  VERSION: String
3
3
  # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
4
  end
File without changes
@@ -0,0 +1,333 @@
1
+ line
2
+ line
3
+ line
4
+ line
5
+ line
6
+ line
7
+ line
8
+ line
9
+ line
10
+ line
11
+ line
12
+ line
13
+ line
14
+ line
15
+ line
16
+ line
17
+ line
18
+ line
19
+ line
20
+ line
21
+ line
22
+ line
23
+ line
24
+ line
25
+ line
26
+ line
27
+ line
28
+ line
29
+ line
30
+ line
31
+ line
32
+ line
33
+ line
34
+ line
35
+ line
36
+ line
37
+ line
38
+ line
39
+ line
40
+ line
41
+ line
42
+ line
43
+ line
44
+ line
45
+ line
46
+ line
47
+ line
48
+ line
49
+ line
50
+ line
51
+ line
52
+ line
53
+ line
54
+ line
55
+ line
56
+ line
57
+ line
58
+ line
59
+ line
60
+ line
61
+ line
62
+ line
63
+ line
64
+ line
65
+ line
66
+ line
67
+ line
68
+ line
69
+ line
70
+ line
71
+ line
72
+ line
73
+ line
74
+ line
75
+ line
76
+ line
77
+ line
78
+ line
79
+ line
80
+ line
81
+ line
82
+ line
83
+ line
84
+ line
85
+ line
86
+ line
87
+ line
88
+ line
89
+ line
90
+ line
91
+ line
92
+ line
93
+ line
94
+ line
95
+ line
96
+ line
97
+ line
98
+ line
99
+ line
100
+ line
101
+ line
102
+ line
103
+ line
104
+ line
105
+ line
106
+ line
107
+ line
108
+ line
109
+ line
110
+ line
111
+ line
112
+ line
113
+ line
114
+ line
115
+ line
116
+ line
117
+ line
118
+ line
119
+ line
120
+ line
121
+ line
122
+ line
123
+ line
124
+ line
125
+ line
126
+ line
127
+ line
128
+ line
129
+ line
130
+ line
131
+ line
132
+ line
133
+ line
134
+ line
135
+ line
136
+ line
137
+ line
138
+ line
139
+ line
140
+ line
141
+ line
142
+ line
143
+ line
144
+ line
145
+ line
146
+ line
147
+ line
148
+ line
149
+ line
150
+ line
151
+ line
152
+ line
153
+ line
154
+ line
155
+ line
156
+ line
157
+ line
158
+ line
159
+ line
160
+ line
161
+ line
162
+ line
163
+ line
164
+ line
165
+ line
166
+ line
167
+ line
168
+ line
169
+ line
170
+ line
171
+ line
172
+ line
173
+ line
174
+ line
175
+ line
176
+ line
177
+ line
178
+ line
179
+ line
180
+ line
181
+ line
182
+ line
183
+ line
184
+ line
185
+ line
186
+ line
187
+ line
188
+ line
189
+ line
190
+ line
191
+ line
192
+ line
193
+ line
194
+ line
195
+ line
196
+ line
197
+ line
198
+ line
199
+ line
200
+ line
201
+ line
202
+ line
203
+ line
204
+ line
205
+ line
206
+ line
207
+ line
208
+ line
209
+ line
210
+ line
211
+ line
212
+ line
213
+ line
214
+ line
215
+ line
216
+ line
217
+ line
218
+ line
219
+ line
220
+ line
221
+ line
222
+ line
223
+ line
224
+ line
225
+ line
226
+ line
227
+ line
228
+ line
229
+ line
230
+ line
231
+ line
232
+ line
233
+ line
234
+ line
235
+ line
236
+ line
237
+ line
238
+ line
239
+ line
240
+ line
241
+ line
242
+ line
243
+ line
244
+ line
245
+ line
246
+ line
247
+ line
248
+ line
249
+ line
250
+ line
251
+ line
252
+ line
253
+ line
254
+ line
255
+ line
256
+ line
257
+ line
258
+ line
259
+ line
260
+ line
261
+ line
262
+ line
263
+ line
264
+ line
265
+ line
266
+ line
267
+ line
268
+ line
269
+ line
270
+ line
271
+ line
272
+ line
273
+ line
274
+ line
275
+ line
276
+ line
277
+ line
278
+ line
279
+ line
280
+ line
281
+ line
282
+ line
283
+ line
284
+ line
285
+ line
286
+ line
287
+ line
288
+ line
289
+ line
290
+ line
291
+ line
292
+ line
293
+ line
294
+ line
295
+ line
296
+ line
297
+ line
298
+ line
299
+ line
300
+ line
301
+ line
302
+ line
303
+ line
304
+ line
305
+ line
306
+ line
307
+ line
308
+ line
309
+ line
310
+ line
311
+ line
312
+ line
313
+ line
314
+ line
315
+ line
316
+ line
317
+ line
318
+ line
319
+ line
320
+ line
321
+ line
322
+ // comment
323
+
324
+
325
+ line
326
+ line
327
+ line
328
+ line
329
+ line
330
+ line
331
+ line
332
+ line
333
+ line