diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb index 110f52dee5..dd6b20a3d3 100644 --- a/Library/Homebrew/cask/cask_loader.rb +++ b/Library/Homebrew/cask/cask_loader.rb @@ -14,7 +14,7 @@ module Cask # Loads a cask from a string. class FromContentLoader - attr_reader :content + attr_reader :content, :tap def self.can_load?(ref) return false unless ref.respond_to?(:to_str) @@ -32,8 +32,9 @@ module Cask content.match?(@regex) end - def initialize(content) + def initialize(content, tap: nil) @content = content.force_encoding("UTF-8") + @tap = tap end def load(config:) diff --git a/Library/Homebrew/dev-cmd/contributions.rb b/Library/Homebrew/dev-cmd/contributions.rb index 035c16a2f7..d9bd088f40 100755 --- a/Library/Homebrew/dev-cmd/contributions.rb +++ b/Library/Homebrew/dev-cmd/contributions.rb @@ -39,7 +39,7 @@ module Homebrew description: "A GitHub username or email address of a specific person to find contribution data for." switch "--csv", - description: "Print a CSV of a user's contributions across repositories over the time period." + description: "Print a CSV of contributions across repositories over the time period." end end @@ -48,6 +48,7 @@ module Homebrew args = contributions_args.parse results = {} + grand_totals = {} all_repos = args.repositories.nil? || args.repositories.include?("all") repos = if all_repos @@ -61,13 +62,13 @@ module Homebrew if args.user user = args.user results[user] = scan_repositories(repos, user, args) - puts "#{user} contributed #{total(results[user])} times #{time_period(args)}." - puts generate_csv(T.must(user), results[user]) if args.csv? + grand_totals[user] = total(results[user]) + + puts "#{user} contributed #{grand_totals[user].values.sum} times #{time_period(args)}." + puts generate_csv(T.must(user), results[user], grand_totals[user]) if args.csv? return end - odie "CSVs not yet supported for the full list of maintainers at once." if args.csv? - maintainers = GitHub.members_by_team("Homebrew", "maintainers") maintainers.each do |username, _| # TODO: Using the GitHub username to scan the `git log` undercounts some @@ -76,8 +77,12 @@ module Homebrew # TODO: Switch to using the GitHub APIs instead of `git log` if # they ever support trailers. results[username] = scan_repositories(repos, username, args) - puts "#{username} contributed #{total(results[username])} times #{time_period(args)}." + grand_totals[username] = total(results[username]) + + puts "#{username} contributed #{grand_totals[username].values.sum} times #{time_period(args)}." end + + puts generate_maintainers_csv(grand_totals) if args.csv? end sig { params(repo: String).returns(Pathname) } @@ -100,10 +105,21 @@ module Homebrew end end - sig { params(user: String, results: Hash).returns(String) } - def generate_csv(user, results) + sig { params(totals: Hash).returns(String) } + def generate_maintainers_csv(totals) CSV.generate do |csv| - csv << %w[user repo commits coauthorships signoffs total] + csv << %w[user repo commits coauthorships signoffs reviews total] + + totals.sort_by { |_, v| -v.values.sum }.each do |user, total| + csv << grand_total_row(user, total) + end + end + end + + sig { params(user: String, results: Hash, grand_total: Hash).returns(String) } + def generate_csv(user, results, grand_total) + CSV.generate do |csv| + csv << %w[user repo commits coauthorships signoffs reviews total] results.each do |repo, counts| csv << [ user, @@ -111,13 +127,27 @@ module Homebrew counts[:commits], counts[:coauthorships], counts[:signoffs], + counts[:reviews], counts.values.sum, ] end - csv << [user, "*", "*", "*", "*", total(results)] + csv << grand_total_row(user, grand_total) end end + sig { params(user: String, grand_total: Hash).returns(Array) } + def grand_total_row(user, grand_total) + [ + user, + "all", + grand_total[:commits], + grand_total[:coauthorships], + grand_total[:signoffs], + grand_total[:reviews], + grand_total.values.sum, + ] + end + def scan_repositories(repos, person, args) data = {} @@ -145,18 +175,28 @@ module Homebrew commits: GitHub.repo_commit_count_for_user(repo_full_name, person, args), coauthorships: git_log_trailers_cmd(T.must(repo_path), person, "Co-authored-by", args), signoffs: git_log_trailers_cmd(T.must(repo_path), person, "Signed-off-by", args), + reviews: GitHub.count_issues("", is: "pr", repo: repo_full_name, reviewed_by: person), } end data end - sig { params(results: Hash).returns(Integer) } + sig { params(results: Hash).returns(Hash) } def total(results) - results - .values # [{:commits=>1, :coauthorships=>0, :signoffs=>3}, {:commits=>500, :coauthorships=>2, :signoffs=>450}] - .map(&:values) # [[1, 0, 3], [500, 2, 450]] - .sum(&:sum) # 956 + totals = { commits: 0, coauthorships: 0, signoffs: 0, reviews: 0 } + + # { + # "brew"=>{:commits=>9,:coauthorships=>6,:signoffs=>3,:reviews=>1}, + # "core"=>{:commits=>15,:coauthorships=>10,:signoffs=>5,:reviews=>2} + # } + results.each_value do |counts| + counts.each do |kind, count| + totals[kind] += count + end + end + + totals # {:commits=>24,:coauthorships=>16,:signoffs=>8,:reviews=>3} end sig { params(repo_path: Pathname, person: String, trailer: String, args: Homebrew::CLI::Args).returns(Integer) } diff --git a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi index 1fcb39ee96..2416582555 100644 --- a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi +++ b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi @@ -5339,6 +5339,9 @@ class Object HOMEBREW_LOGS = ::T.let(nil, ::T.untyped) HOMEBREW_MACOS_ARM_DEFAULT_PREFIX = ::T.let(nil, ::T.untyped) HOMEBREW_MACOS_ARM_DEFAULT_REPOSITORY = ::T.let(nil, ::T.untyped) + HOMEBREW_MACOS_NEWEST_UNSUPPORTED = ::T.let(nil, ::T.untyped) + HOMEBREW_MACOS_OLDEST_ALLOWED = ::T.let(nil, ::T.untyped) + HOMEBREW_MACOS_OLDEST_SUPPORTED = ::T.let(nil, ::T.untyped) HOMEBREW_MAIN_TAP_CASK_REGEX = ::T.let(nil, ::T.untyped) HOMEBREW_OFFICIAL_REPO_PREFIXES_REGEX = ::T.let(nil, ::T.untyped) HOMEBREW_PHYSICAL_PROCESSOR = ::T.let(nil, ::T.untyped) diff --git a/Library/Homebrew/test/search_spec.rb b/Library/Homebrew/test/search_spec.rb index ef3f383919..6a37c77183 100644 --- a/Library/Homebrew/test/search_spec.rb +++ b/Library/Homebrew/test/search_spec.rb @@ -39,7 +39,7 @@ describe Homebrew::Search do ], } - allow(GitHub::API).to receive(:open_rest).and_yield(json_response) + allow(GitHub::API).to receive(:open_rest).and_return(json_response) expect(described_class.search_taps("some-formula")) .to match(formulae: ["homebrew/foo/some-formula"], casks: ["homebrew/bar/some-cask"]) diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb index 1ca085109b..3137393e6d 100644 --- a/Library/Homebrew/utils/github.rb +++ b/Library/Homebrew/utils/github.rb @@ -37,7 +37,11 @@ module GitHub end def search_issues(query, **qualifiers) - search("issues", query, **qualifiers) + search_results_items("issues", query, **qualifiers) + end + + def count_issues(query, **qualifiers) + search_results_count("issues", query, **qualifiers) end def create_gist(files, description, private:) @@ -57,7 +61,14 @@ module GitHub end def search_code(repo: nil, user: "Homebrew", path: ["Formula", "Casks", "."], filename: nil, extension: "rb") - matches = search("code", user: user, path: path, filename: filename, extension: extension, repo: repo) + matches = search_results_items( + "code", + user: user, + path: path, + filename: filename, + extension: extension, + repo: repo, + ) return matches if matches.blank? matches.map do |match| @@ -163,7 +174,7 @@ module GitHub params = main_params params += qualifiers.flat_map do |key, value| - Array(value).map { |v| "#{key}:#{v}" } + Array(value).map { |v| "#{key.to_s.tr("_", "-")}:#{v}" } end "q=#{URI.encode_www_form_component(params.join(" "))}&per_page=100" @@ -176,7 +187,17 @@ module GitHub def search(entity, *queries, **qualifiers) uri = url_to "search", entity uri.query = search_query_string(*queries, **qualifiers) - API.open_rest(uri) { |json| json.fetch("items", []) } + API.open_rest(uri) + end + + def search_results_items(entity, *queries, **qualifiers) + json = search(entity, *queries, **qualifiers) + json.fetch("items", []) + end + + def search_results_count(entity, *queries, **qualifiers) + json = search(entity, *queries, **qualifiers) + json.fetch("total_count", 0) end def approved_reviews(user, repo, pr, commit: nil) diff --git a/completions/fish/brew.fish b/completions/fish/brew.fish index 1fe3aa4422..9d88c13fab 100644 --- a/completions/fish/brew.fish +++ b/completions/fish/brew.fish @@ -537,7 +537,7 @@ __fish_brew_complete_arg 'config' -l verbose -d 'Make some output more verbose' __fish_brew_complete_cmd 'contributions' 'Contributions to Homebrew repos' -__fish_brew_complete_arg 'contributions' -l csv -d 'Print a CSV of a user\'s contributions across repositories over the time period' +__fish_brew_complete_arg 'contributions' -l csv -d 'Print a CSV of contributions across repositories over the time period' __fish_brew_complete_arg 'contributions' -l debug -d 'Display any debugging information' __fish_brew_complete_arg 'contributions' -l from -d 'Date (ISO-8601 format) to start searching contributions' __fish_brew_complete_arg 'contributions' -l help -d 'Show this message' diff --git a/completions/zsh/_brew b/completions/zsh/_brew index b4406ef039..8e5fb74f7e 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -666,7 +666,7 @@ _brew_config() { # brew contributions _brew_contributions() { _arguments \ - '--csv[Print a CSV of a user'\''s contributions across repositories over the time period]' \ + '--csv[Print a CSV of contributions across repositories over the time period]' \ '--debug[Display any debugging information]' \ '--from[Date (ISO-8601 format) to start searching contributions]' \ '--help[Show this message]' \ diff --git a/docs/Manpage.md b/docs/Manpage.md index c360f2b0b3..35bfa5bb30 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -1124,7 +1124,7 @@ Contributions to Homebrew repos. * `--user`: A GitHub username or email address of a specific person to find contribution data for. * `--csv`: - Print a CSV of a user's contributions across repositories over the time period. + Print a CSV of contributions across repositories over the time period. ### `create` [*`options`*] *`URL`* diff --git a/manpages/brew.1 b/manpages/brew.1 index f9722eccfc..5b0e63eb9c 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1619,7 +1619,7 @@ A GitHub username or email address of a specific person to find contribution dat . .TP \fB\-\-csv\fR -Print a CSV of a user\'s contributions across repositories over the time period\. +Print a CSV of contributions across repositories over the time period\. . .SS "\fBcreate\fR [\fIoptions\fR] \fIURL\fR" Generate a formula or, with \fB\-\-cask\fR, a cask for the downloadable file at \fIURL\fR and open it in the editor\. Homebrew will attempt to automatically derive the formula name and version, but if it fails, you\'ll have to make your own template\. The \fBwget\fR formula serves as a simple example\. For the complete API, see: \fIhttps://rubydoc\.brew\.sh/Formula\fR