Port Homebrew::DevCmd::Contributions

This commit is contained in:
Douglas Eichelberger 2024-03-19 11:57:54 -07:00
parent 777ee12258
commit 0373e0dc29
2 changed files with 189 additions and 188 deletions

View File

@ -5,8 +5,8 @@ require "cli/parser"
require "csv" require "csv"
module Homebrew module Homebrew
module_function module DevCmd
class Contributions < AbstractCommand
PRIMARY_REPOS = %w[brew core cask].freeze PRIMARY_REPOS = %w[brew core cask].freeze
SUPPORTED_REPOS = [ SUPPORTED_REPOS = [
PRIMARY_REPOS, PRIMARY_REPOS,
@ -15,9 +15,7 @@ module Homebrew
].flatten.freeze ].flatten.freeze
MAX_REPO_COMMITS = 1000 MAX_REPO_COMMITS = 1000
sig { returns(CLI::Parser) } cmd_args do
def contributions_args
Homebrew::CLI::Parser.new do
usage_banner "`contributions` [--user=<email|username>] [<--repositories>`=`] [<--csv>]" usage_banner "`contributions` [--user=<email|username>] [<--repositories>`=`] [<--csv>]"
description <<~EOS description <<~EOS
Summarise contributions to Homebrew repositories. Summarise contributions to Homebrew repositories.
@ -43,18 +41,15 @@ module Homebrew
switch "--csv", switch "--csv",
description: "Print a CSV of contributions across repositories over the time period." description: "Print a CSV of contributions across repositories over the time period."
end end
end
sig { void }
def contributions
args = contributions_args.parse
sig { override.void }
def run
results = {} results = {}
grand_totals = {} grand_totals = {}
repos = if args.repositories.blank? || args.repositories.include?("primary") repos = if args.repositories.blank? || T.must(args.repositories).include?("primary")
PRIMARY_REPOS PRIMARY_REPOS
elsif args.repositories.include?("all") elsif T.must(args.repositories).include?("all")
SUPPORTED_REPOS SUPPORTED_REPOS
else else
args.repositories args.repositories
@ -71,7 +66,7 @@ module Homebrew
# committer details to match the ones on GitHub. # committer details to match the ones on GitHub.
# TODO: Switch to using the GitHub APIs instead of `git log` if # TODO: Switch to using the GitHub APIs instead of `git log` if
# they ever support trailers. # they ever support trailers.
results[username] = scan_repositories(repos, username, args, from:) results[username] = scan_repositories(repos, username, from:)
grand_totals[username] = total(results[username]) grand_totals[username] = total(results[username])
contributions = contribution_types.filter_map do |type| contributions = contribution_types.filter_map do |type|
@ -80,7 +75,8 @@ module Homebrew
"#{Utils.pluralize("time", type_count, include_count: true)} (#{type})" "#{Utils.pluralize("time", type_count, include_count: true)} (#{type})"
end end
contributions << "#{Utils.pluralize("time", grand_totals[username].values.sum, include_count: true)} (total)" contributions << "#{Utils.pluralize("time", grand_totals[username].values.sum,
include_count: true)} (total)"
puts [ puts [
"#{username} contributed", "#{username} contributed",
@ -95,6 +91,8 @@ module Homebrew
puts generate_csv(grand_totals) puts generate_csv(grand_totals)
end end
private
sig { params(repo: String).returns(Pathname) } sig { params(repo: String).returns(Pathname) }
def find_repo_path_for_repo(repo) def find_repo_path_for_repo(repo)
return HOMEBREW_REPOSITORY if repo == "brew" return HOMEBREW_REPOSITORY if repo == "brew"
@ -139,7 +137,7 @@ module Homebrew
] ]
end end
def scan_repositories(repos, person, args, from:) def scan_repositories(repos, person, from:)
data = {} data = {}
repos.each do |repo| repos.each do |repo|
@ -168,7 +166,7 @@ module Homebrew
author: author_commits, author: author_commits,
committer: committer_commits, committer: committer_commits,
coauthorship: git_log_trailers_cmd(T.must(repo_path), person, "Co-authored-by", from:, to: args.to), coauthorship: git_log_trailers_cmd(T.must(repo_path), person, "Co-authored-by", from:, to: args.to),
review: count_reviews(repo_full_name, person, args), review: count_reviews(repo_full_name, person),
} }
end end
@ -201,8 +199,8 @@ module Homebrew
Utils.safe_popen_read(*cmd).lines.count { |l| l.include?(person) } Utils.safe_popen_read(*cmd).lines.count { |l| l.include?(person) }
end end
sig { params(repo_full_name: String, person: String, args: Homebrew::CLI::Args).returns(Integer) } sig { params(repo_full_name: String, person: String).returns(Integer) }
def count_reviews(repo_full_name, person, args) def count_reviews(repo_full_name, person)
GitHub.count_issues("", is: "pr", repo: repo_full_name, reviewed_by: person, review: "approved", args:) GitHub.count_issues("", is: "pr", repo: repo_full_name, reviewed_by: person, review: "approved", args:)
rescue GitHub::API::ValidationFailedError rescue GitHub::API::ValidationFailedError
if args.verbose? if args.verbose?
@ -211,3 +209,5 @@ module Homebrew
0 # Users who have made their contributions private are not searchable to determine counts. 0 # Users who have made their contributions private are not searchable to determine counts.
end end
end end
end
end

View File

@ -1,7 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cmd/shared_examples/args_parse" require "cmd/shared_examples/args_parse"
require "dev-cmd/contributions"
RSpec.describe "brew contributions" do RSpec.describe Homebrew::DevCmd::Contributions do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
end end