This repository was archived by the owner on Jan 8, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun.rb
More file actions
105 lines (87 loc) · 3.01 KB
/
Copy pathrun.rb
File metadata and controls
105 lines (87 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
require 'digest'
require 'progress_bar'
require_relative './src/Stats'
require_relative './src/git/Repository'
require_relative './src/storage/Storage'
require_relative './src/table/Table'
repository = Git::Repository.new(ARGV[0])
storage = Storage::Storage.new("#{Dir.getwd}/tmp", Digest::MD5.hexdigest("#{repository.path}#{repository.hash}"))
stats = Stats.new(JSON.parse(storage.safe_read('stats.json', '{}')))
puts "Storing all data in '#{storage.path}'"
files = repository.tracked_files
processed_files = storage.safe_read('parsed_files.txt', '').split("\n").to_h { |file| [file, file] }
progress = ProgressBar.new(files.size)
def skip_file?(file)
# Ignore media files
['.mmdb', '.wav', '.mp3', '.mp4', '.jpg', '.jpeg', '.png', '.gif', '.woff', '.woff2', '.ttf', '.eot', '.svg', '.ico', '.pdf'].any? { file.end_with?(_1) } ||
# Ignore lock files
file.end_with?('.lock') ||
# Ignore aut-generated files
['.graphql'].any? { file.end_with?(_1) } ||
# Ignore rails schema
file == 'db/schema.rb' ||
# Ignore vendor files
file.include?('/vendor/') || file.start_with?('vendor/')
end
uniq_extensions = {}
# Filter files that need processing
files_to_process = files.reject do |file|
skip_file?(file) || processed_files.key?(file)
end
# Update progress bar to reflect skipped files
progress = ProgressBar.new(files_to_process.size)
# Process files in parallel with a thread pool
require 'concurrent'
thread_count = [Concurrent.processor_count, 8].min
pool = Concurrent::FixedThreadPool.new(thread_count)
mutex = Mutex.new
files_to_process.each_slice(100) do |files_slice|
# Track extensions for all files (not just processed ones)
files_slice.each do |file|
unless (extension = File.extname(file)).empty?
mutex.synchronize do
uniq_extensions[extension] ||= 0
uniq_extensions[extension] += 1
end
end
end
# Process files in parallel
promises = files_slice.map do |file|
Concurrent::Promise.execute(executor: pool) do
begin
blame_data = repository.per_author_blame(file)
[file, blame_data]
rescue => error
mutex.synchronize do
puts error
puts "File: #{file}"
end
nil
end
end
end
# Wait for all files in this slice to complete
results = promises.map(&:value)
# Update stats with the results
mutex.synchronize do
results.compact.each do |file, blame_data|
blame_data.each do |author, lines_count|
stats.bump_author(author, file, increase: lines_count)
end
processed_files[file] = file
progress.increment!
end
# Save progress after each slice
storage.store('parsed_files.txt', processed_files.keys.join("\n"))
storage.store('stats.json', stats.to_json)
storage.store('table.txt', Table::Table.new(stats))
end
end
pool.shutdown
pool.wait_for_termination
Table::Table.new(stats).print
puts "\n--------------------"
puts "Extensions:"
uniq_extensions.sort_by { |extension, count| -count }.each do |extension, count|
puts "> #{extension}: #{count}"
end