Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9423 from reitermarkus/bump-unversioned-casks
Add `bump-unversioned-casks` command.
- Loading branch information
Showing
14 changed files
with
457 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,8 @@ | |
|
||
module Cask | ||
class Cask | ||
def artifacts; end | ||
|
||
def homepage; end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
# typed: false | ||
# frozen_string_literal: true | ||
|
||
require "cask/download" | ||
require "cask/installer" | ||
require "cask/cask_loader" | ||
require "cli/parser" | ||
require "tap" | ||
require "unversioned_cask_checker" | ||
|
||
module Homebrew | ||
extend T::Sig | ||
|
||
extend SystemCommand::Mixin | ||
|
||
sig { returns(CLI::Parser) } | ||
def self.bump_unversioned_casks_args | ||
Homebrew::CLI::Parser.new do | ||
usage_banner <<~EOS | ||
`bump-unversioned-casks` [<options>] [<tap>] | ||
Check all casks with unversioned URLs in a given <tap> for updates. | ||
EOS | ||
switch "-n", "--dry-run", | ||
description: "Do everything except caching state and opening pull requests." | ||
flag "--limit=", | ||
description: "Maximum runtime in minutes." | ||
flag "--state-file=", | ||
description: "File for caching state." | ||
|
||
named 1 | ||
end | ||
end | ||
|
||
sig { void } | ||
def self.bump_unversioned_casks | ||
args = bump_unversioned_casks_args.parse | ||
|
||
state_file = if args.state_file.present? | ||
Pathname(args.state_file).expand_path | ||
else | ||
HOMEBREW_CACHE/"bump_unversioned_casks.json" | ||
end | ||
state_file.dirname.mkpath | ||
|
||
tap = Tap.fetch(args.named.first) | ||
|
||
state = state_file.exist? ? JSON.parse(state_file.read) : {} | ||
|
||
cask_files = tap.cask_files | ||
unversioned_cask_files = cask_files.select do |cask_file| | ||
url = cask_file.each_line do |line| | ||
url = line[/\s*url\s+"([^"]+)"\s*/, 1] | ||
break url if url | ||
end | ||
|
||
url.present? && url.exclude?('#{') | ||
end.sort | ||
|
||
unversioned_casks = unversioned_cask_files.map { |path| Cask::CaskLoader.load(path) } | ||
|
||
ohai "Unversioned Casks: #{unversioned_casks.count}" | ||
|
||
checked, unchecked = unversioned_casks.partition { |c| state.key?(c.full_name) } | ||
|
||
queue = Queue.new | ||
|
||
# Start with random casks which have not been checked. | ||
unchecked.shuffle.each do |c| | ||
queue.enq c | ||
end | ||
|
||
# Continue with previously checked casks, ordered by when they were last checked. | ||
checked.sort_by { |c| state.dig(c.full_name, "check_time") }.each do |c| | ||
queue.enq c | ||
end | ||
|
||
limit = args.limit.presence&.to_i | ||
end_time = Time.now + limit.minutes if limit | ||
|
||
until queue.empty? || (end_time && end_time < Time.now) | ||
cask = queue.deq | ||
|
||
key = cask.full_name | ||
|
||
new_state = bump_unversioned_cask(cask, state: state.fetch(key, {}), dry_run: args.dry_run?) | ||
|
||
next unless new_state | ||
|
||
state[key] = new_state | ||
|
||
state_file.atomic_write JSON.generate(state) unless args.dry_run? | ||
end | ||
end | ||
|
||
sig do | ||
params(cask: Cask::Cask, state: T::Hash[String, T.untyped], dry_run: T.nilable(T::Boolean)) | ||
.returns(T.nilable(T::Hash[String, T.untyped])) | ||
end | ||
def self.bump_unversioned_cask(cask, state:, dry_run:) | ||
ohai "Checking #{cask.full_name}" | ||
|
||
unversioned_cask_checker = UnversionedCaskChecker.new(cask) | ||
|
||
unless unversioned_cask_checker.single_app_cask? || unversioned_cask_checker.single_pkg_cask? | ||
opoo "Skipping, not a single-app or PKG cask." | ||
return | ||
end | ||
|
||
last_check_time = state["check_time"]&.yield_self { |t| Time.parse(t) } | ||
|
||
check_time = Time.now | ||
if last_check_time && check_time < (last_check_time + 1.day) | ||
opoo "Skipping, already checked within the last 24 hours." | ||
return | ||
end | ||
|
||
last_sha256 = state["sha256"] | ||
last_time = state["time"]&.yield_self { |t| Time.parse(t) } | ||
last_file_size = state["file_size"] | ||
|
||
download = Cask::Download.new(cask) | ||
time, file_size = begin | ||
download.time_file_size | ||
rescue | ||
[nil, nil] | ||
end | ||
|
||
if last_time != time || last_file_size != file_size | ||
begin | ||
cached_download = unversioned_cask_checker.installer.download | ||
rescue => e | ||
onoe e | ||
return | ||
end | ||
|
||
sha256 = cached_download.sha256 | ||
|
||
if last_sha256 != sha256 && (version = unversioned_cask_checker.guess_cask_version) | ||
if cask.version == version | ||
oh1 "Cask #{cask} is up-to-date at #{version}" | ||
else | ||
bump_cask_pr_args = [ | ||
"bump-cask-pr", | ||
"--version", version.to_s, | ||
"--sha256", ":no_check", | ||
"--message", "Automatic update via `brew bump-unversioned-casks`.", | ||
cask.sourcefile_path | ||
] | ||
|
||
if dry_run | ||
bump_cask_pr_args << "--dry-run" | ||
oh1 "Would bump #{cask} from #{cask.version} to #{version}" | ||
else | ||
oh1 "Bumping #{cask} from #{cask.version} to #{version}" | ||
end | ||
|
||
begin | ||
system_command! HOMEBREW_BREW_FILE, args: bump_cask_pr_args | ||
rescue ErrorDuringExecution => e | ||
onoe e | ||
return | ||
end | ||
end | ||
end | ||
end | ||
|
||
{ | ||
"sha256" => sha256, | ||
"check_time" => check_time.iso8601, | ||
"time" => time&.iso8601, | ||
"file_size" => file_size, | ||
} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.