Merge branch 'master' into delay-loading-from-cask-source-api
This commit is contained in:
		
						commit
						fdc2e9f3f5
					
				@ -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:)
 | 
			
		||||
 | 
			
		||||
@ -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) }
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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"])
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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'
 | 
			
		||||
 | 
			
		||||
@ -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]' \
 | 
			
		||||
 | 
			
		||||
@ -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`*
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user