diff --git a/Library/Homebrew/dev-cmd/bump.rb b/Library/Homebrew/dev-cmd/bump.rb index 5cb9138a70..43c1cca140 100644 --- a/Library/Homebrew/dev-cmd/bump.rb +++ b/Library/Homebrew/dev-cmd/bump.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "cli/parser" +require "utils/popen" module Homebrew module_function @@ -9,6 +10,7 @@ module Homebrew Homebrew::CLI::Parser.new do usage_banner <<~EOS `bump` + Display out-of-date brew formulae, the latest version available, and whether a pull request has been opened. EOS end @@ -18,6 +20,21 @@ module Homebrew bump_args.parse outdated_repology_packages = RepologyParser.parse_api_response - ohai RepologyParser.validate__packages(outdated_repology_packages) + outdated_packages = RepologyParser.validate_and_format_packages(outdated_repology_packages) + + display(outdated_packages) + end + + def display(outdated_packages) + ohai "Outdated Formulae" + + outdated_packages.each do |formula, package_details| + puts "" + puts "Formula: #{formula}" + puts "Current formula version: #{package_details["current_formula_version"]}" + puts "Latest repology version: #{package_details["repology_latest_version"]}" + puts "Latest livecheck version: #{package_details["livecheck_latest_version"]}" + puts "Open pull requests: #{package_details["open_pull_requests"]}" + end end end diff --git a/Library/Homebrew/utils/livecheck.rb b/Library/Homebrew/utils/livecheck.rb deleted file mode 100644 index 07c7acdaa6..0000000000 --- a/Library/Homebrew/utils/livecheck.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Livecheck - def livecheck_formula_response(name) - ohai "Checking livecheck formula : #{name}" - - response = Utils.popen_read("brew", "livecheck", name, "--quiet").chomp - parse_livecheck_response(response) - end - - def parse_livecheck_response(response) - output = response.delete(" ").split(/:|==>/) - - # eg: ["burp", "2.2.18", "2.2.18"] - package_name, brew_version, latest_version = output - - { - name: package_name, - formula_version: brew_version, - livecheck_version: latest_version, - } - end -end diff --git a/Library/Homebrew/utils/repology.rb b/Library/Homebrew/utils/repology.rb index b5770013e7..c51e595c71 100644 --- a/Library/Homebrew/utils/repology.rb +++ b/Library/Homebrew/utils/repology.rb @@ -1,15 +1,15 @@ # frozen_string_literal: true require "utils/curl" +require "utils/versions" + require "formula_info" module RepologyParser module_function - MAX_PAGE_LIMIT = 15 - def query_api(last_package_in_response = "") - 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=homebrew&outdated=1" ohai "Calling API #{url}" if Homebrew.args.verbose? output, _errors, _status = curl_output(url.to_s) @@ -19,22 +19,23 @@ module RepologyParser def parse_api_response ohai "Querying outdated packages from Repology" page_no = 1 - ohai "Paginating Repology api page: #{page_no}" if Homebrew.args.verbose? + ohai "Paginating repology api page: #{page_no}" if Homebrew.args.verbose? outdated_packages = query_api - last_package_index = outdated_packages.size - 1 + last_pacakge_index = outdated_packages.size - 1 response_size = outdated_packages.size + page_limit = 15 - while response_size > 1 && page_no <= MAX_PAGE_LIMIT + while response_size > 1 && page_no <= page_limit page_no += 1 - ohai "Paginating Repology api page: #{page_no}" if Homebrew.args.verbose? + ohai "Paginating repology api page: #{page_no}" if Homebrew.args.verbose? - last_package_in_response = outdated_packages.keys[last_package_index] - response = query_api(last_package_in_response) + last_package_in_response = outdated_packages.keys[last_pacakge_index] + response = query_api("#{last_package_in_response}/") response_size = response.size outdated_packages.merge!(response) - last_package_index = outdated_packages.size - 1 + last_pacakge_index = outdated_packages.size - 1 end ohai "#{outdated_packages.size} outdated packages identified" @@ -42,8 +43,8 @@ module RepologyParser outdated_packages end - def validate__packages(outdated_repology_packages) - ohai "Verifying outdated Repology packages as Homebrew Formulae" + def validate_and_format_packages(outdated_repology_packages) + ohai "Verifying outdated repology packages as Homebrew Formulae" packages = {} outdated_repology_packages.each do |_name, repositories| @@ -61,18 +62,24 @@ module RepologyParser latest_version = repo["version"] if repo["status"] == "newest" end - info = FormulaInfo.lookup(repology_homebrew_repo["srcname"]) - next unless info - - current_version = info.pkg_version - - packages[repology_homebrew_repo["srcname"]] = { - "repology_latest_version" => latest_version, - "current_formula_version" => current_version.to_s, - } - puts packages + packages[repology_homebrew_repo["srcname"]] = format_package(repology_homebrew_repo["srcname"], latest_version) end # hash of hashes {"aacgain"=>{"repology_latest_version"=>"1.9", "current_formula_version"=>"1.8"}, ...} packages end + + def format_package(package_name, latest_version) + current_version = Versions.current_formula_version(package_name) + livecheck_response = Versions.livecheck_formula(package_name) + pull_requests = Versions.check_for_duplicate_pull_requests(package_name, latest_version) + + formatted_package = { + "repology_latest_version" => latest_version, + "current_formula_version" => current_version.to_s, + "livecheck_latest_version" => livecheck_response["livecheck_latest_version"], + "open_pull_requests" => pull_requests, + } + + formatted_package + end end diff --git a/Library/Homebrew/utils/versions.rb b/Library/Homebrew/utils/versions.rb index f688a5b8c7..0b44a607b9 100644 --- a/Library/Homebrew/utils/versions.rb +++ b/Library/Homebrew/utils/versions.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require "formula" - module Versions + module_function + def current_formula_version(formula_name) Formula[formula_name].version.to_s.to_f end @@ -12,10 +12,57 @@ module Versions formula_name, "--url=#{url}").chomp end - def check_for_open_pr(formula_name, download_url) - ohai "- Checking for open PRs for formula : #{formula_name}" + def check_for_open_pr(formula_name) + # ohai "- Checking for open PRs for formula : #{formula_name}" - response = bump_formula_pr(formula_name, download_url) - !response.include? "Error: These open pull requests may be duplicates" + # response = bump_formula_pr(formula_name, download_url) + # !response.include? "Error: These open pull requests may be duplicates" + + # check_for_duplicate_pull_requests(formula, tap_full_name, new_formula_version.to_s) + end + + def livecheck_formula(formula) + ohai "Checking livecheck formula : #{formula}" if Homebrew.args.verbose? + + response = Utils.popen_read(HOMEBREW_BREW_FILE, "livecheck", formula, "--quiet").chomp + + parse_livecheck_response(response) + end + + def parse_livecheck_response(response) + output = response.delete(" ").split(/:|==>/) + + # eg: ["openclonk", "7.0", "8.1"] + package_name, brew_version, latest_version = output + + { + "formula" => package_name, + "current_brew_version" => brew_version, + "livecheck_latest_version" => latest_version, + } + end + + def fetch_pull_requests(query, tap_full_name, state: nil) + GitHub.issues_for_formula(query, tap_full_name: tap_full_name, state: state).select do |pr| + pr["html_url"].include?("/pull/") && + /(^|\s)#{Regexp.quote(query)}(:|\s|$)/i =~ pr["title"] + end + rescue GitHub::RateLimitExceededError => e + opoo e.message + [] + end + + def check_for_duplicate_pull_requests(formula, version) + formula = Formula[formula] + tap_full_name = formula.tap&.full_name + + # check for open requests + pull_requests = fetch_pull_requests(formula.name, tap_full_name, state: "open") + + # if we haven't already found open requests, try for an exact match across all requests + pull_requests = fetch_pull_requests("#{formula.name} #{version}", tap_full_name) if pull_requests.blank? + return if pull_requests.blank? + + pull_requests.map { |pr| { "title" => pr["title"], "url" => pr["html_url"] } } end end