diff --git a/cmd/find-appcast.rb b/cmd/find-appcast.rb new file mode 100755 index 000000000000..c92a4865d3e0 --- /dev/null +++ b/cmd/find-appcast.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require "cli/parser" +require "formula" +require "open3" +require "pathname" +require "yaml" +require "net/http" +require "uri" + +module Homebrew + module_function + + sig { returns(CLI::Parser) } + def find_appcast_args + Homebrew::CLI::Parser.new do + usage_banner <<~EOS + `find-appcast` + + Finds the appcast for a given app when a path is provided to the .app bundle. + EOS + + named_args :app_path, min: 1 + + hide_from_man_page! + end + end + + def find_appcast + args = find_appcast_args.parse + + app = Pathname.new(args.named.first) + find_sparkle(app) || find_electron_builder(app) + end + + def verify_appcast(appcast_type, *urls) + print "Looking for #{appcast_type} appcast… " + urls.each do |url| + next unless url_exist?(url) + + puts "Found!" + puts " #{url}" + return true + end + puts "Not found." + false + end + + def url_exist?(url) + return false unless url + + system("curl", "--silent", "--location", "--fail", url, out: File::NULL) + end + + def find_sparkle(app) + plist = app.join("Contents/Info.plist") + url = Open3.capture3("defaults", "read", plist.to_path, "SUFeedURL").first.strip + verify_appcast("Sparkle", url) + end + + def find_electron_builder(app) + appcast_file = app.join("Contents/Resources/app-update.yml") + unless appcast_file.exist? + verify_appcast("electron-builder", false) + return false + end + YAML.load_file(appcast_file) + end +end diff --git a/developer/bin/find-appcast b/developer/bin/find-appcast deleted file mode 100755 index d27f026e2f11..000000000000 --- a/developer/bin/find-appcast +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -# rubocop:disable Style/TopLevelMethodDefinition - -require "open3" -require "pathname" -require "yaml" - -require "net/http" -require "uri" - -def verify_appcast(appcast_type, *urls) - print "Looking for #{appcast_type} appcast… " - - urls.each do |url| - next unless url_exist?(url) - - puts "Found!" - puts " #{url}" - return true - end - - puts "Not found." - false -end - -def url_exist?(url) - return false unless url - - system("curl", "--silent", "--location", "--fail", url, out: File::NULL) -end - -def find_sparkle(app) - plist = app.join("Contents/Info.plist") - url = Open3.capture3("defaults", "read", plist.to_path, "SUFeedURL").first.strip - - verify_appcast("Sparkle", url) -end - -def find_electron_builder(app) - appcast_file = app.join("Contents/Resources/app-update.yml") - - unless appcast_file.exist? - verify_appcast("electron-builder", false) - return false - end - - data = YAML.load_file(appcast_file) - bucket = data["bucket"] - channel = data["channel"] - endpoint = data["endpoint"] - name = data["name"] - owner = data["owner"] - path = data["path"] - region = data["region"] - repo = data["repo"] - url = data["url"] - - possible_appcasts = [ - "#{url}/latest-mac.yml", - "#{url}/updates/latest/mac/latest-mac.yml", - "https://github.com/#{owner}/#{repo}/releases.atom", - "https://#{bucket}.s3.amazon-aws.yml/#{channel}/latest-mac.yml", - "https://#{bucket}.s3.amazonaws.com/latest-mac.yml", - "https://#{bucket}.s3.amazonaws.com/#{path}/latest-mac.yml", - "https://s3-#{region}.amazonaws.com/#{bucket}/#{path}/latest-mac.yml", - "https://s3.amazonaws.com/#{bucket}/#{path}/latest-mac.yml", - "https://#{name}.#{region}.digitaloceanspaces.com/latest-mac.yml", - "https://#{name}.#{region}.digitaloceanspaces.com/#{path}/latest-mac.yml", - "#{endpoint}/#{bucket}/#{path}/latest-mac.yml", - ].map do |appcast| - # Collapse groups of two or more forward slashes into one, except when preceded by a colon - appcast.gsub(%r{(?