diff --git a/Library/Homebrew/dev-cmd/unbottled.rb b/Library/Homebrew/dev-cmd/unbottled.rb index 0d3e6201f94a5..b4dc78796d827 100644 --- a/Library/Homebrew/dev-cmd/unbottled.rb +++ b/Library/Homebrew/dev-cmd/unbottled.rb @@ -21,11 +21,13 @@ def unbottled_args description: "Skip getting analytics data and sort by number of dependents instead." switch "--total", description: "Print the number of unbottled and total formulae." + switch "--lost", + description: "Print the `homebrew/core` commits where bottles were lost in the last week." switch "--eval-all", description: "Evaluate all available formulae and casks, whether installed or not, to check them. " \ "Implied if `HOMEBREW_EVAL_ALL` is set." - conflicts "--dependents", "--total" + conflicts "--dependents", "--total", "--lost" named_args :formula end @@ -43,6 +45,17 @@ def unbottled Utils::Bottles.tag end + if args.lost? + if args.named.present? + raise UsageError, "`brew unbottled --lost` cannot be used with formula arguments!" + elsif !CoreTap.instance.installed? + raise UsageError, "`brew unbottled --lost` requires `homebrew/core` to be tapped locally!" + else + output_lost_bottles + return + end + end + os = @bottle_tag.system arch = if Hardware::CPU::INTEL_ARCHS.include?(@bottle_tag.arch) :intel @@ -243,4 +256,53 @@ def output_unbottled(formulae, deps_hash, noun, hash, any_named_args) puts "No unbottled dependencies found!" end + + def output_lost_bottles + # $ git log --patch -G\^\ \+sha256.\*\ sonoma: --since=@\{\'1\ week\ ago\'\} + git_log = %w[git log --patch] + git_log << "-G^ +sha256.* #{@bottle_tag}:" + git_log << "--since=@{'1 week ago'}" + + bottle_tag_sha_regex = /^[+-] +sha256.* #{@bottle_tag}: / + + processed_formulae = Set.new + commit = T.let(nil, T.nilable(String)) + formula = T.let(nil, T.nilable(String)) + lost_bottles = 0 + + CoreTap.instance.path.cd do + Utils.safe_popen_read(*git_log) do |io| + io.each_line do |line| + case line + when /^commit [0-9a-f]{40}$/ + # Example match: `commit 7289b409b96a752540befef1a56b8a818baf1db7` + if commit && lost_bottles.positive? && processed_formulae.exclude?(formula) + puts "#{commit}: bottle lost for #{formula}" + end + processed_formulae << formula + commit = line.split.last + lost_bottles = 0 + when %r{^diff --git a/Formula/} + # Example match: `diff --git a/Formula/a/aws-cdk.rb b/Formula/a/aws-cdk.rb` + formula = line.split("/").last.chomp(".rb\n") + when bottle_tag_sha_regex + # Example match: `- sha256 cellar: :any_skip_relocation, sonoma: "f0a4..."` + next if processed_formulae.include?(formula) + + case line.chr + when "+" then lost_bottles -= 1 + when "-" then lost_bottles += 1 + end + when /^[+] +sha256.* all: / + # Example match: `+ sha256 cellar: :any_skip_relocation, all: "9e35..."` + lost_bottles -= 1 + end + end + end + end + + return if !commit || !lost_bottles.positive? || processed_formulae.include?(formula) + + puts "#{commit}: bottle lost for #{formula}" + end end diff --git a/completions/bash/brew b/completions/bash/brew index bddbb67163eb7..5bd972d729782 100644 --- a/completions/bash/brew +++ b/completions/bash/brew @@ -2258,6 +2258,7 @@ _brew_unbottled() { --dependents --eval-all --help + --lost --quiet --tag --total diff --git a/completions/fish/brew.fish b/completions/fish/brew.fish index 67a255d7d0448..c7bb873e439c1 100644 --- a/completions/fish/brew.fish +++ b/completions/fish/brew.fish @@ -1500,6 +1500,7 @@ __fish_brew_complete_arg 'unbottled' -l debug -d 'Display any debugging informat __fish_brew_complete_arg 'unbottled' -l dependents -d 'Skip getting analytics data and sort by number of dependents instead' __fish_brew_complete_arg 'unbottled' -l eval-all -d 'Evaluate all available formulae and casks, whether installed or not, to check them. Implied if `HOMEBREW_EVAL_ALL` is set' __fish_brew_complete_arg 'unbottled' -l help -d 'Show this message' +__fish_brew_complete_arg 'unbottled' -l lost -d 'Print the `homebrew/core` commits where bottles were lost in the last week' __fish_brew_complete_arg 'unbottled' -l quiet -d 'Make some output more quiet' __fish_brew_complete_arg 'unbottled' -l tag -d 'Use the specified bottle tag (e.g. `big_sur`) instead of the current OS' __fish_brew_complete_arg 'unbottled' -l total -d 'Print the number of unbottled and total formulae' diff --git a/completions/zsh/_brew b/completions/zsh/_brew index b6aee53e4bd5e..d853a5fffa9b6 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -1846,12 +1846,13 @@ _brew_typecheck() { _brew_unbottled() { _arguments \ '--debug[Display any debugging information]' \ - '(--total)--dependents[Skip getting analytics data and sort by number of dependents instead]' \ + '(--total --lost)--dependents[Skip getting analytics data and sort by number of dependents instead]' \ '--eval-all[Evaluate all available formulae and casks, whether installed or not, to check them. Implied if `HOMEBREW_EVAL_ALL` is set]' \ '--help[Show this message]' \ + '(--dependents --total)--lost[Print the `homebrew/core` commits where bottles were lost in the last week]' \ '--quiet[Make some output more quiet]' \ '--tag[Use the specified bottle tag (e.g. `big_sur`) instead of the current OS]' \ - '(--dependents)--total[Print the number of unbottled and total formulae]' \ + '(--dependents --lost)--total[Print the number of unbottled and total formulae]' \ '--verbose[Make some output more verbose]' \ - formula \ '*::formula:__brew_formulae' diff --git a/docs/Manpage.md b/docs/Manpage.md index 3d9e4779651dd..b43aeff9db903 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -1626,6 +1626,8 @@ Show the unbottled dependents of formulae. Skip getting analytics data and sort by number of dependents instead. * `--total`: Print the number of unbottled and total formulae. +* `--lost`: + Print the `homebrew/core` commits where bottles were lost in the last week. * `--eval-all`: Evaluate all available formulae and casks, whether installed or not, to check them. Implied if `HOMEBREW_EVAL_ALL` is set. diff --git a/manpages/brew.1 b/manpages/brew.1 index 1c433fc6a754a..5286d72d9464c 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -2339,6 +2339,10 @@ Skip getting analytics data and sort by number of dependents instead\. Print the number of unbottled and total formulae\. . .TP +\fB\-\-lost\fR +Print the \fBhomebrew/core\fR commits where bottles were lost in the last week\. +. +.TP \fB\-\-eval\-all\fR Evaluate all available formulae and casks, whether installed or not, to check them\. Implied if \fBHOMEBREW_EVAL_ALL\fR is set\. .