diff --git a/Library/Homebrew/dev-cmd/bump.rb b/Library/Homebrew/dev-cmd/bump.rb index ffbc2feab4..b6e4979e4c 100644 --- a/Library/Homebrew/dev-cmd/bump.rb +++ b/Library/Homebrew/dev-cmd/bump.rb @@ -16,66 +16,107 @@ module Homebrew 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 + + "homebrew" + else + "homebrew_casks" 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 = {} + api_response[:formulae] = Repology.parse_api_response(limit, repository: "homebrew") unless args.cask? + api_response[:casks] = Repology.parse_api_response(limit, repository: "homebrew_casks") unless args.formula? - homebrew_repo = repositories.find do |repo| - repo["repo"] == "homebrew" + api_response.each do |package_type, outdated_packages| + repository = if package_type == :formulae + "homebrew" + else + "homebrew_casks" 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 + next if homebrew_repo.blank? + + formula_or_cask = begin + if repository == "homebrew" + Formula[homebrew_repo["srcname"]] + else + Cask::CaskLoader.load(homebrew_repo["srcname"]) + end + rescue + next + end + name = Livecheck.formula_or_cask_name(formula_or_cask) + + puts if i.positive? + retrieve_and_display_info(formula_or_cask, name, repositories, args: args) + + break if limit && i >= limit end - - retrieve_and_display_info(formula, repositories) - - break if requested_limit && i >= requested_limit 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? @@ -85,8 +126,8 @@ module Homebrew latest.to_s 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 @@ -96,8 +137,12 @@ module Homebrew 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) @@ -105,14 +150,14 @@ module Homebrew "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 @@ -120,7 +165,7 @@ module Homebrew 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 diff --git a/Library/Homebrew/test/utils/repology_spec.rb b/Library/Homebrew/test/utils/repology_spec.rb index 87fd550eef..c72096eedf 100644 --- a/Library/Homebrew/test/utils/repology_spec.rb +++ b/Library/Homebrew/test/utils/repology_spec.rb @@ -6,13 +6,13 @@ require "utils/repology" 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) @@ -22,7 +22,7 @@ describe Repology do 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) diff --git a/Library/Homebrew/utils/repology.rb b/Library/Homebrew/utils/repology.rb index 9e80e455cc..fa63c922ca 100644 --- a/Library/Homebrew/utils/repology.rb +++ b/Library/Homebrew/utils/repology.rb @@ -12,16 +12,16 @@ module Repology 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) @@ -34,26 +34,34 @@ module Repology 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" + "formula" + when "homebrew_casks" + "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 diff --git a/completions/bash/brew b/completions/bash/brew index abd7782871..badc67053b 100644 --- a/completions/bash/brew +++ b/completions/bash/brew @@ -427,9 +427,12 @@ _brew_bump() { case "$cur" in -*) __brewcomp " + --cask --debug + --formula --help --limit + --no-pull-requests --quiet --verbose " @@ -437,6 +440,7 @@ _brew_bump() { ;; esac __brew_complete_formulae + __brew_complete_casks } _brew_bump_cask_pr() { diff --git a/completions/fish/brew.fish b/completions/fish/brew.fish index 88c2de9ab4..bdeea8667a 100644 --- a/completions/fish/brew.fish +++ b/completions/fish/brew.fish @@ -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' diff --git a/completions/zsh/_brew b/completions/zsh/_brew index 821684dc31..a0b7f98a26 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -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 diff --git a/docs/Manpage.md b/docs/Manpage.md index 8460fab863..2448641b65 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -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. diff --git a/manpages/brew.1 b/manpages/brew.1 index 756f71c1c2..159b167730 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -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\. .