git_ownership_insights 1.2.0 → 2.0.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
  SHA256:
3
- metadata.gz: 6d884a43cd70caba8943ba59a6ce05d46631cb6927ed0eefa74a1dccbc2d66f8
4
- data.tar.gz: 180007096b00a2978d8e6d6440c9214b1f8d59e41c841e665392db2c955fecd8
3
+ metadata.gz: e323781f21d5b045b9fe23e6790f53739fe6bd99e917a9ad2b88c544a9aa3428
4
+ data.tar.gz: 0c23bd13ad86a4edc00f38a77e5219d18ebd81af84dc8e76764762611780fb1e
5
5
  SHA512:
6
- metadata.gz: 27a2bc913215ffb0cee443be41b1a91128edc31998d0f3841ad0ac02fd03393529f41825c55645cfc007f0a0d478a439834568334e2bf81c89929d3eeb396f37
7
- data.tar.gz: e8d564d1734b023321027464ff86aea38463085681ef579297b69fc8f4bfd034b558d064e754bc0b142bf1a18171f4e959dd9c1af0d2a2ac34a375f01f5cbb88
6
+ metadata.gz: 7302774074f86ca8f5ebd3288f47150a7cc9adf642b2dfe3bc60f0f0ff087a38f9645789b256e923fc578b5d445293be72dcc143d07906a86c6a678e8742a1c4
7
+ data.tar.gz: 97f58091878d741eac46b1c0a0eb8263cbe7cc7abdba5f8db2c70bf2d12fe4dc0f089496a8e8b7b87531c9bfa4bdb4577820b75afa50576eec9e30184bbdd723
@@ -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,58 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2024-01-30 07:43:06 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: 4
10
+ # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
11
+ Metrics/AbcSize:
12
+ Max: 187
13
+
14
+ # Offense count: 1
15
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
16
+ # AllowedMethods: refine
17
+ Metrics/BlockLength:
18
+ Max: 69
19
+
20
+ # Offense count: 1
21
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
22
+ Metrics/CyclomaticComplexity:
23
+ Max: 31
24
+
25
+ # Offense count: 4
26
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
27
+ Metrics/MethodLength:
28
+ Max: 115
29
+
30
+ # Offense count: 1
31
+ # Configuration parameters: CountComments, CountAsOne.
32
+ Metrics/ModuleLength:
33
+ Max: 192
34
+
35
+ # Offense count: 1
36
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
37
+ Metrics/PerceivedComplexity:
38
+ Max: 32
39
+
40
+ # Offense count: 1
41
+ # Configuration parameters: AllowedConstants.
42
+ Style/Documentation:
43
+ Exclude:
44
+ - 'spec/**/*'
45
+ - 'test/**/*'
46
+ - 'lib/git_ownership_insights/git_ownership_insight.rb'
47
+
48
+ # Offense count: 1
49
+ Style/MultilineBlockChain:
50
+ Exclude:
51
+ - 'lib/git_ownership_insights/git_ownership_insight.rb'
52
+
53
+ # Offense count: 7
54
+ # This cop supports safe autocorrection (--autocorrect).
55
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
56
+ # URISchemes: http, https
57
+ Layout/LineLength:
58
+ Max: 150
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.0'
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