Skip to content

Commit

Permalink
Merge pull request #10635 from nandahkrishna/bump-cask-support
Browse files Browse the repository at this point in the history
dev-cmd/bump: add cask support
  • Loading branch information
nandahkrishna authored Feb 17, 2021
2 parents c454257 + 88f78c4 commit 53d840c
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 55 deletions.
127 changes: 90 additions & 37 deletions Library/Homebrew/dev-cmd/bump.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,77 +16,126 @@ def bump_args
Display out-of-date brew formulae and the latest version available.
Also displays whether a pull request has been opened with the URL.
EOS
switch "--no-pull-requests",
description: "Do not retrieve pull requests from GitHub."
switch "--formula", "--formulae",
description: "Check only formulae."
switch "--cask", "--casks",
description: "Check only casks."
flag "--limit=",
description: "Limit number of package results returned."

named_args :formula
conflicts "--cask", "--formula"

named_args [:formula, :cask]
end
end

def bump
args = bump_args.parse

requested_formulae = args.named.to_formulae.presence
requested_limit = args.limit.to_i if args.limit.present?
if args.limit.present? && !args.formula? && !args.cask?
raise UsageError, "`--limit` must be used with either `--formula` or `--cask`."
end

if requested_formulae
Livecheck.load_other_tap_strategies(requested_formulae)
formulae_and_casks = if args.formula?
args.named.to_formulae.presence
elsif args.cask?
args.named.to_casks.presence
else
args.named.to_formulae_and_casks.presence
end

requested_formulae.each_with_index do |formula, i|
limit = args.limit.to_i if args.limit.present?

if formulae_and_casks
Livecheck.load_other_tap_strategies(formulae_and_casks)

formulae_and_casks.each_with_index do |formula_or_cask, i|
puts if i.positive?

if formula.head_only?
ohai formula.name
puts "Formula is HEAD-only."
next
name = Livecheck.formula_or_cask_name(formula_or_cask)
repository = if formula_or_cask.is_a?(Formula)
if formula_or_cask.head_only?
ohai name
puts "Formula is HEAD-only."
next
end

Repology::HOMEBREW_CORE
else
Repology::HOMEBREW_CASK
end

package_data = Repology.single_package_query(formula.name)
retrieve_and_display_info(formula, package_data&.values&.first)
package_data = Repology.single_package_query(name, repository: repository)
retrieve_and_display_info(formula_or_cask, name, package_data&.values&.first, args: args)
end
else
outdated_packages = Repology.parse_api_response(requested_limit)
outdated_packages.each_with_index do |(_name, repositories), i|
puts if i.positive?
api_response = {}
unless args.cask?
api_response[:formulae] =
Repology.parse_api_response(limit, repository: Repology::HOMEBREW_CORE)
end
unless args.formula?
api_response[:casks] =
Repology.parse_api_response(limit, repository: Repology::HOMEBREW_CASK)
end

homebrew_repo = repositories.find do |repo|
repo["repo"] == "homebrew"
api_response.each do |package_type, outdated_packages|
repository = if package_type == :formulae
Repology::HOMEBREW_CORE
else
Repology::HOMEBREW_CASK
end

next if homebrew_repo.blank?
outdated_packages.each_with_index do |(_name, repositories), i|
homebrew_repo = repositories.find do |repo|
repo["repo"] == repository
end

formula = begin
Formula[homebrew_repo["srcname"]]
rescue
next
end
next if homebrew_repo.blank?

formula_or_cask = begin
if repository == Repology::HOMEBREW_CORE
Formula[homebrew_repo["srcname"]]
else
Cask::CaskLoader.load(homebrew_repo["srcname"])
end
rescue
next
end
name = Livecheck.formula_or_cask_name(formula_or_cask)

retrieve_and_display_info(formula, repositories)
puts if i.positive?
retrieve_and_display_info(formula_or_cask, name, repositories, args: args)

break if requested_limit && i >= requested_limit
break if limit && i >= limit
end
end
end
end

def livecheck_result(formula)
skip_result = Livecheck::SkipConditions.skip_information(formula)
def livecheck_result(formula_or_cask)
skip_result = Livecheck::SkipConditions.skip_information(formula_or_cask)
if skip_result.present?
return "#{skip_result[:status]}#{" - #{skip_result[:messages].join(", ")}" if skip_result[:messages].present?}"
end

version_info = Livecheck.latest_version(
formula,
formula_or_cask,
json: true, full_name: false, verbose: false, debug: false,
)
latest = version_info[:latest] if version_info.present?

return "unable to get versions" if latest.blank?

latest.to_s
rescue => e
"error: #{e}"
end

def retrieve_pull_requests(formula)
pull_requests = GitHub.fetch_pull_requests(formula.name, formula.tap&.full_name, state: "open")
def retrieve_pull_requests(formula_or_cask, name)
pull_requests = GitHub.fetch_pull_requests(name, formula_or_cask.tap&.full_name, state: "open")
if pull_requests.try(:any?)
pull_requests = pull_requests.map { |pr| "#{pr["title"]} (#{Formatter.url(pr["html_url"])})" }.join(", ")
end
Expand All @@ -96,31 +145,35 @@ def retrieve_pull_requests(formula)
pull_requests
end

def retrieve_and_display_info(formula, repositories)
current_version = formula.stable.version.to_s
def retrieve_and_display_info(formula_or_cask, name, repositories, args:)
current_version = if formula_or_cask.is_a?(Formula)
formula_or_cask.stable.version
else
Version.new(formula_or_cask.version)
end

repology_latest = if repositories.present?
Repology.latest_version(repositories)
else
"not found"
end

livecheck_latest = livecheck_result(formula)
pull_requests = retrieve_pull_requests(formula)
livecheck_latest = livecheck_result(formula_or_cask)
pull_requests = retrieve_pull_requests(formula_or_cask, name) unless args.no_pull_requests?

title = if current_version == repology_latest &&
current_version == livecheck_latest
"#{formula} is up to date!"
"#{name} is up to date!"
else
formula.name
name
end

ohai title
puts <<~EOS
Current formula version: #{current_version}
Latest Repology version: #{repology_latest}
Latest livecheck version: #{livecheck_latest}
Open pull requests: #{pull_requests}
EOS
puts "Open pull requests: #{pull_requests}" unless args.no_pull_requests?
end
end
6 changes: 3 additions & 3 deletions Library/Homebrew/test/utils/repology_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
describe Repology do
describe "single_package_query", :needs_network do
it "returns nil for non-existent package" do
response = described_class.single_package_query("invalidName")
response = described_class.single_package_query("invalidName", repository: "homebrew")

expect(response).to be_nil
end

it "returns a hash for existing package" do
response = described_class.single_package_query("openclonk")
response = described_class.single_package_query("openclonk", repository: "homebrew")

expect(response).not_to be_nil
expect(response).to be_a(Hash)
Expand All @@ -22,7 +22,7 @@
describe "parse_api_response", :needs_network do
it "returns a hash of data" do
limit = 1
response = described_class.parse_api_response(limit)
response = described_class.parse_api_response(limit, repository: "homebrew")

expect(response).not_to be_nil
expect(response).to be_a(Hash)
Expand Down
35 changes: 23 additions & 12 deletions Library/Homebrew/utils/repology.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@
#
# @api private
module Repology
HOMEBREW_CORE = "homebrew"
HOMEBREW_CASK = "homebrew_casks"

module_function

MAX_PAGINATION = 15
private_constant :MAX_PAGINATION

def query_api(last_package_in_response = "")
def query_api(last_package_in_response = "", repository:)
last_package_in_response += "/" if last_package_in_response.present?
url = "https://repology.org/api/v1/projects/#{last_package_in_response}?inrepo=homebrew&outdated=1"
url = "https://repology.org/api/v1/projects/#{last_package_in_response}?inrepo=#{repository}&outdated=1"

output, _errors, _status = curl_output(url.to_s)
JSON.parse(output)
end

def single_package_query(name)
url = "https://repology.org/tools/project-by?repo=homebrew&" \
def single_package_query(name, repository:)
url = "https://repology.org/tools/project-by?repo=#{repository}&" \
"name_type=srcname&target_page=api_v1_project&name=#{name}"

output, _errors, _status = curl_output("--location", url.to_s)
Expand All @@ -34,26 +37,34 @@ def single_package_query(name)
end
end

def parse_api_response(limit = nil)
ohai "Querying outdated packages from Repology"
def parse_api_response(limit = nil, repository:)
package_term = case repository
when HOMEBREW_CORE
"formula"
when HOMEBREW_CASK
"cask"
else
"package"
end

ohai "Querying outdated #{package_term.pluralize} from Repology"

page_no = 1
outdated_packages = {}
last_package_index = ""
last_package = ""

while page_no <= MAX_PAGINATION
odebug "Paginating Repology API page: #{page_no}"

response = query_api(last_package_index.to_s)
response_size = response.size
response = query_api(last_package, repository: repository)
outdated_packages.merge!(response)
last_package_index = outdated_packages.size - 1
last_package = response.keys.last

page_no += 1
break if limit && outdated_packages.size >= limit || response_size <= 1
break if limit && outdated_packages.size >= limit || response.size <= 1
end

puts "#{outdated_packages.size} outdated #{"package".pluralize(outdated_packages.size)} found"
puts "#{outdated_packages.size} outdated #{package_term.pluralize(outdated_packages.size)} found"
puts

outdated_packages
Expand Down
4 changes: 4 additions & 0 deletions completions/bash/brew
Original file line number Diff line number Diff line change
Expand Up @@ -427,16 +427,20 @@ _brew_bump() {
case "$cur" in
-*)
__brewcomp "
--cask
--debug
--formula
--help
--limit
--no-pull-requests
--quiet
--verbose
"
return
;;
esac
__brew_complete_formulae
__brew_complete_casks
}

_brew_bump_cask_pr() {
Expand Down
4 changes: 4 additions & 0 deletions completions/fish/brew.fish
Original file line number Diff line number Diff line change
Expand Up @@ -387,12 +387,16 @@ __fish_brew_complete_arg 'bottle' -a '(__fish_brew_suggest_formulae_installed)'


__fish_brew_complete_cmd 'bump' 'Display out-of-date brew formulae and the latest version available'
__fish_brew_complete_arg 'bump' -l cask -d 'Check only casks'
__fish_brew_complete_arg 'bump' -l debug -d 'Display any debugging information'
__fish_brew_complete_arg 'bump' -l formula -d 'Check only formulae'
__fish_brew_complete_arg 'bump' -l help -d 'Show this message'
__fish_brew_complete_arg 'bump' -l limit -d 'Limit number of package results returned'
__fish_brew_complete_arg 'bump' -l no-pull-requests -d 'Do not retrieve pull requests from GitHub'
__fish_brew_complete_arg 'bump' -l quiet -d 'Make some output more quiet'
__fish_brew_complete_arg 'bump' -l verbose -d 'Make some output more verbose'
__fish_brew_complete_arg 'bump' -a '(__fish_brew_suggest_formulae_all)'
__fish_brew_complete_arg 'bump' -a '(__fish_brew_suggest_casks_all)'


__fish_brew_complete_cmd 'bump-cask-pr' 'Create a pull request to update cask with a new version'
Expand Down
6 changes: 5 additions & 1 deletion completions/zsh/_brew
Original file line number Diff line number Diff line change
Expand Up @@ -469,12 +469,16 @@ _brew_bottle() {
# brew bump
_brew_bump() {
_arguments \
'(--formula)--cask[Check only casks]' \
'--debug[Display any debugging information]' \
'(--cask)--formula[Check only formulae]' \
'--help[Show this message]' \
'--limit[Limit number of package results returned]' \
'--no-pull-requests[Do not retrieve pull requests from GitHub]' \
'--quiet[Make some output more quiet]' \
'--verbose[Make some output more verbose]' \
'::formula:__brew_formulae'
'::formula:__brew_formulae' \
'::cask:__brew_casks'
}

# brew bump-cask-pr
Expand Down
8 changes: 7 additions & 1 deletion docs/Manpage.md
Original file line number Diff line number Diff line change
Expand Up @@ -826,11 +826,17 @@ value, while `--no-rebuild` will remove it.
* `--root-url`:
Use the specified *`URL`* as the root of the bottle's URL instead of Homebrew's default.

### `bump` [*`--limit`*`=`] [*`formula`* ...]
### `bump` [*`options`*] [*`formula`*|*`cask`* ...]

Display out-of-date brew formulae and the latest version available.
Also displays whether a pull request has been opened with the URL.

* `--no-pull-requests`:
Do not retrieve pull requests from GitHub.
* `--formula`:
Check only formulae.
* `--cask`:
Check only casks.
* `--limit`:
Limit number of package results returned.

Expand Down
14 changes: 13 additions & 1 deletion manpages/brew.1
Original file line number Diff line number Diff line change
Expand Up @@ -1132,10 +1132,22 @@ When passed with \fB\-\-write\fR, a new commit will not generated after writing
\fB\-\-root\-url\fR
Use the specified \fIURL\fR as the root of the bottle\'s URL instead of Homebrew\'s default\.
.
.SS "\fBbump\fR [\fI\-\-limit\fR\fB=\fR] [\fIformula\fR \.\.\.]"
.SS "\fBbump\fR [\fIoptions\fR] [\fIformula\fR|\fIcask\fR \.\.\.]"
Display out\-of\-date brew formulae and the latest version available\. Also displays whether a pull request has been opened with the URL\.
.
.TP
\fB\-\-no\-pull\-requests\fR
Do not retrieve pull requests from GitHub\.
.
.TP
\fB\-\-formula\fR
Check only formulae\.
.
.TP
\fB\-\-cask\fR
Check only casks\.
.
.TP
\fB\-\-limit\fR
Limit number of package results returned\.
.
Expand Down

0 comments on commit 53d840c

Please sign in to comment.