Skip to content

Commit

Permalink
Merge pull request Homebrew#15552 from MikeMcQuaid/info_github_packag…
Browse files Browse the repository at this point in the history
…es_downloads

cmd/info: add (undocumented) --github-packages-downloads option.
  • Loading branch information
MikeMcQuaid committed Jun 16, 2023
2 parents 2c95aa4 + cd313ad commit 0606b63
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 3 deletions.
3 changes: 3 additions & 0 deletions Library/Homebrew/cmd/info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ def info_args
"The value for <category> must be `install`, `install-on-request` or `build-error`; " \
"`cask-install` or `os-version` may be specified if <formula> is not. " \
"The default is `install`."
switch "--github-packages-downloads",
description: "Scrape GitHub Packages download counts from HTML for a core formula.",
hidden: true
switch "--github",
description: "Open the GitHub source page for <formula> and <cask> in a browser. " \
"To view the history locally: `brew log -p` <formula> or <cask>"
Expand Down
51 changes: 48 additions & 3 deletions Library/Homebrew/utils/analytics.rb
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def output(args:, filter: nil)
table_output(category, days, results, os_version: os_version, cask_install: cask_install)
end

def get_analytics(json, args:)
def output_analytics(json, args:)
full_analytics = args.analytics? || verbose?

ohai "Analytics"
Expand All @@ -207,13 +207,58 @@ def get_analytics(json, args:)
end
end

# This method is undocumented because it is not intended for general use.
# It relies on screen scraping some GitHub HTML that's not available as an API.
# This seems very likely to break in the future.
# That said, it's the only way to get the data we want right now.
def output_github_packages_downloads(formula, args:)
return unless args.github_packages_downloads?
return unless formula.core_formula?

escaped_formula_name = GitHubPackages.image_formula_name(formula.name)
formula_url_suffix = "container/core%2F#{escaped_formula_name}/"
formula_url = "https://github.com/Homebrew/homebrew-core/pkgs/#{formula_url_suffix}"
output = Utils::Curl.curl_output("--fail", formula_url)
return unless output.success?

formula_version_urls = output.stdout
.scan(%r{/orgs/Homebrew/packages/#{formula_url_suffix}\d+\?tag=[^"]+})
.map do |url|
url.sub("/orgs/Homebrew/packages/", "/Homebrew/homebrew-core/pkgs/")
end
return if formula_version_urls.empty?

thirty_day_download_count = 0
formula_version_urls.each do |formula_version_url_suffix|
formula_version_url = "https://github.com#{formula_version_url_suffix}"
output = Utils::Curl.curl_output("--fail", formula_version_url)
next unless output.success?

last_thirty_days_match = output.stdout.match(
%r{<span class="[\s\-a-z]*">Last 30 days</span>\s*<span class="[\s\-a-z]*">([\d.M,]+)</span>}m,
)
next if last_thirty_days_match.blank?

last_thirty_days_downloads = last_thirty_days_match.captures.first.tr(",", "")
thirty_day_download_count += if (millions_match = last_thirty_days_downloads.match(/(\d+\.\d+)M/).presence)
millions_match.captures.first.to_i * 1_000_000
else
last_thirty_days_downloads.to_i
end
end

ohai "GitHub Packages Downloads"
puts "#{number_readable(thirty_day_download_count)} (30 days)"
end

def formula_output(formula, args:)
return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api?

json = Homebrew::API::Formula.fetch formula.name
return if json.blank? || json["analytics"].blank?

get_analytics(json, args: args)
output_analytics(json, args: args)
output_github_packages_downloads(formula, args: args)
rescue ArgumentError
# Ignore failed API requests
nil
Expand All @@ -225,7 +270,7 @@ def cask_output(cask, args:)
json = Homebrew::API::Cask.fetch cask.token
return if json.blank? || json["analytics"].blank?

get_analytics(json, args: args)
output_analytics(json, args: args)
rescue ArgumentError
# Ignore failed API requests
nil
Expand Down

0 comments on commit 0606b63

Please sign in to comment.