Skip to content

Commit

Permalink
Merge pull request #16292 from Rylan12/cask-deprecate-disable
Browse files Browse the repository at this point in the history
Add `deprecate!` and `disable!` to casks
  • Loading branch information
Rylan12 committed Dec 17, 2023
2 parents 3431996 + c21b8bd commit 4793677
Show file tree
Hide file tree
Showing 23 changed files with 367 additions and 76 deletions.
12 changes: 6 additions & 6 deletions Library/Homebrew/cask/audit.rb
Expand Up @@ -289,7 +289,7 @@ def audit_latest_with_auto_updates

sig { params(livecheck_result: T.any(NilClass, T::Boolean, Symbol)).void }
def audit_hosting_with_livecheck(livecheck_result: audit_livecheck_version)
return if cask.discontinued?
return if cask.deprecated? || cask.disabled?
return if cask.version&.latest?
return unless cask.url
return if block_url_offline?
Expand Down Expand Up @@ -544,7 +544,7 @@ def audit_livecheck_version
)
end

# Respect cask skip conditions (e.g. discontinued, latest, unversioned)
# Respect cask skip conditions (e.g. deprecated, disabled, latest, unversioned)
skip_info ||= Homebrew::Livecheck::SkipConditions.skip_information(cask)
return :skip if skip_info.present?

Expand Down Expand Up @@ -682,8 +682,8 @@ def audit_gitlab_prerelease_version

sig { void }
def audit_github_repository_archived
# Discontinued casks may have an archived repo.
return if cask.discontinued?
# Deprecated/disabled casks may have an archived repo.
return if cask.deprecated? || cask.disabled?

user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if online?
return if user.nil?
Expand All @@ -696,8 +696,8 @@ def audit_github_repository_archived

sig { void }
def audit_gitlab_repository_archived
# Discontinued casks may have an archived repo.
return if cask.discontinued?
# Deprecated/disabled casks may have an archived repo.
return if cask.deprecated? || cask.disabled?

user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) if online?
return if user.nil?
Expand Down
6 changes: 6 additions & 0 deletions Library/Homebrew/cask/cask.rb
Expand Up @@ -331,6 +331,12 @@ def to_h
"conflicts_with" => conflicts_with,
"container" => container&.pairs,
"auto_updates" => auto_updates,
"deprecated" => deprecated?,
"deprecation_date" => deprecation_date,
"deprecation_reason" => deprecation_reason,
"disabled" => disabled?,
"disable_date" => disable_date,
"disable_reason" => disable_reason,
"tap_git_head" => tap_git_head,
"languages" => languages,
"ruby_source_path" => ruby_source_path,
Expand Down
12 changes: 11 additions & 1 deletion Library/Homebrew/cask/cask.rbi
Expand Up @@ -20,7 +20,17 @@ module Cask

def desc; end

def discontinued?; end
def deprecated?; end

def deprecation_date; end

def deprecation_reason; end

def disabled?; end

def disable_date; end

def disable_reason; end

def homepage; end

Expand Down
10 changes: 10 additions & 0 deletions Library/Homebrew/cask/cask_loader.rb
Expand Up @@ -286,6 +286,16 @@ def load(config:)
desc json_cask[:desc]
homepage json_cask[:homepage]

if (deprecation_date = json_cask[:deprecation_date].presence)
reason = DeprecateDisable.to_reason_string_or_symbol json_cask[:deprecation_reason], type: :cask
deprecate! date: deprecation_date, because: reason
end

if (disable_date = json_cask[:disable_date].presence)
reason = DeprecateDisable.to_reason_string_or_symbol json_cask[:disable_reason], type: :cask
disable! date: disable_date, because: reason
end

auto_updates json_cask[:auto_updates] unless json_cask[:auto_updates].nil?
conflicts_with(**json_cask[:conflicts_with]) if json_cask[:conflicts_with].present?

Expand Down
41 changes: 37 additions & 4 deletions Library/Homebrew/cask/dsl.rb
Expand Up @@ -84,6 +84,14 @@ class DSL
:url,
:version,
:appdir,
:deprecate!,
:deprecated?,
:deprecation_date,
:deprecation_reason,
:disable!,
:disabled?,
:disable_date,
:disable_reason,
:discontinued?,
:livecheck,
:livecheckable?,
Expand All @@ -96,9 +104,9 @@ class DSL
extend Predicable
include OnSystem::MacOSOnly

attr_reader :cask, :token
attr_reader :cask, :token, :deprecation_date, :deprecation_reason, :disable_date, :disable_reason

attr_predicate :on_system_blocks_exist?
attr_predicate :on_system_blocks_exist?, :disabled?, :livecheckable?

def initialize(cask)
@cask = cask
Expand Down Expand Up @@ -316,9 +324,15 @@ def caveats(*strings, &block)
end

def discontinued?
# odeprecated "`discontinued?`", "`deprecated?` or `disabled?`"
@caveats&.discontinued? == true
end

# TODO: replace with with attr_predicate once discontinued? is disabled
def deprecated?
@deprecated == true || @caveats&.discontinued? == true
end

# @api public
def auto_updates(auto_updates = nil)
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
Expand All @@ -337,8 +351,27 @@ def livecheck(&block)
@livecheck.instance_eval(&block)
end

def livecheckable?
@livecheckable == true
# @api public
def deprecate!(date:, because:)
@deprecation_date = Date.parse(date)
return if @deprecation_date > Date.today

@deprecation_reason = because
@deprecated = true
end

# @api public
def disable!(date:, because:)
@disable_date = Date.parse(date)

if @disable_date > Date.today
@deprecation_reason = because
@deprecated = true
return
end

@disable_reason = because
@disabled = true
end

ORDINARY_ARTIFACT_CLASSES.each do |klass|
Expand Down
1 change: 1 addition & 0 deletions Library/Homebrew/cask/dsl/caveats.rb
Expand Up @@ -163,6 +163,7 @@ def eval_caveats(&block)
end

caveat :discontinued do
# odeprecated "`caveats :discontinued`", "`deprecate!`"
@discontinued = true
<<~EOS
#{@cask} has been officially discontinued upstream.
Expand Down
17 changes: 17 additions & 0 deletions Library/Homebrew/cask/exceptions.rb
Expand Up @@ -54,6 +54,23 @@ def to_s
end
end

# Error when a cask cannot be installed.
#
# @api private
class CaskCannotBeInstalledError < AbstractCaskErrorWithToken
attr_reader :message

def initialize(token, message)
super(token)
@message = message
end

sig { returns(String) }
def to_s
"Cask '#{token}' has been #{message}"
end
end

# Error when a cask conflicts with another cask.
#
# @api private
Expand Down
2 changes: 2 additions & 0 deletions Library/Homebrew/cask/info.rb
Expand Up @@ -12,6 +12,8 @@ def self.get_info(cask)

output = +"#{title_info(cask)}\n"
output << "#{Formatter.url(cask.homepage)}\n" if cask.homepage
deprecate_disable = DeprecateDisable.message(cask)
output << "#{deprecate_disable.capitalize}\n" if deprecate_disable
output << installation_info(cask)
repo = repo_info(cask)
output << "#{repo}\n" if repo
Expand Down
13 changes: 13 additions & 0 deletions Library/Homebrew/cask/installer.rb
Expand Up @@ -93,6 +93,7 @@ def install
old_config = @cask.config
predecessor = @cask if reinstall? && @cask.installed?

check_deprecate_disable
check_conflicts

print caveats
Expand Down Expand Up @@ -124,6 +125,18 @@ def install
raise
end

def check_deprecate_disable
deprecate_disable_type = DeprecateDisable.type(@cask)
return if deprecate_disable_type.nil?

case deprecate_disable_type
when :deprecated
opoo "#{@cask.token} has been #{DeprecateDisable.message(@cask)}"
when :disabled
raise CaskCannotBeInstalledError.new(@cask, DeprecateDisable.message(@cask))
end
end

def check_conflicts
return unless @cask.conflicts_with

Expand Down
10 changes: 2 additions & 8 deletions Library/Homebrew/cmd/info.rb
Expand Up @@ -278,14 +278,8 @@ def info_formula(formula, args:)
puts formula.desc if formula.desc
puts Formatter.url(formula.homepage) if formula.homepage

deprecate_disable_type, deprecate_disable_reason = DeprecateDisable.deprecate_disable_info formula
if deprecate_disable_type.present?
if deprecate_disable_reason.present?
puts "#{deprecate_disable_type.capitalize} because it #{deprecate_disable_reason}!"
else
puts "#{deprecate_disable_type.capitalize}!"
end
end
deprecate_disable_info_string = DeprecateDisable.message(formula)
puts deprecate_disable_info_string.capitalize if deprecate_disable_info_string.present?

conflicts = formula.conflicts.map do |conflict|
reason = " (because #{conflict.reason})" if conflict.reason
Expand Down
47 changes: 36 additions & 11 deletions Library/Homebrew/deprecate_disable.rb
Expand Up @@ -7,7 +7,7 @@
module DeprecateDisable
module_function

DEPRECATE_DISABLE_REASONS = {
FORMULA_DEPRECATE_DISABLE_REASONS = {
does_not_build: "does not build",
no_license: "has no license",
repo_archived: "has an archived upstream repository",
Expand All @@ -22,19 +22,44 @@ module DeprecateDisable
"We can re-package this once upstream has confirmed that they retagged their release",
}.freeze

def deprecate_disable_info(formula)
if formula.deprecated?
type = :deprecated
reason = formula.deprecation_reason
elsif formula.disabled?
type = :disabled
reason = formula.disable_reason
CASK_DEPRECATE_DISABLE_REASONS = {
discontinued: "is discontinued upstream",
}.freeze

def type(formula_or_cask)
return :deprecated if formula_or_cask.deprecated?

:disabled if formula_or_cask.disabled?
end

def message(formula_or_cask)
return if type(formula_or_cask).blank?

reason = if formula_or_cask.deprecated?
formula_or_cask.deprecation_reason
elsif formula_or_cask.disabled?
formula_or_cask.disable_reason
end

reason = if formula_or_cask.is_a?(Formula) && FORMULA_DEPRECATE_DISABLE_REASONS.key?(reason)
FORMULA_DEPRECATE_DISABLE_REASONS[reason]
elsif formula_or_cask.is_a?(Cask::Cask) && CASK_DEPRECATE_DISABLE_REASONS.key?(reason)
CASK_DEPRECATE_DISABLE_REASONS[reason]
else
return
reason
end

reason = DEPRECATE_DISABLE_REASONS[reason] if DEPRECATE_DISABLE_REASONS.key? reason
return "#{type(formula_or_cask)} because it #{reason}!" if reason.present?

"#{type(formula_or_cask)}!"
end

def to_reason_string_or_symbol(string, type:)
if (type == :formula && FORMULA_DEPRECATE_DISABLE_REASONS.key?(string&.to_sym)) ||
(type == :cask && CASK_DEPRECATE_DISABLE_REASONS.key?(string&.to_sym))
return string.to_sym
end

[type, reason]
string
end
end
12 changes: 12 additions & 0 deletions Library/Homebrew/diagnostic.rb
Expand Up @@ -642,6 +642,18 @@ def check_deprecated_disabled
EOS
end

def check_cask_deprecated_disabled
deprecated_or_disabled = Cask::Caskroom.casks.select(&:deprecated?)
deprecated_or_disabled += Cask::Caskroom.casks.select(&:disabled?)
return if deprecated_or_disabled.empty?

<<~EOS
Some installed casks are deprecated or disabled.
You should find replacements for the following casks:
#{deprecated_or_disabled.sort_by(&:token).uniq * "\n "}
EOS
end

sig { returns(T.nilable(String)) }
def check_git_status
return unless Utils::Git.available?
Expand Down
4 changes: 2 additions & 2 deletions Library/Homebrew/formula.rb
Expand Up @@ -3550,7 +3550,7 @@ def pour_bottle?(only_if: nil, &block)
# <pre>deprecate! date: "2020-08-27", because: :unmaintained</pre>
# <pre>deprecate! date: "2020-08-27", because: "has been replaced by foo"</pre>
# @see https://docs.brew.sh/Deprecating-Disabling-and-Removing-Formulae
# @see DeprecateDisable::DEPRECATE_DISABLE_REASONS
# @see DeprecateDisable::FORMULA_DEPRECATE_DISABLE_REASONS
def deprecate!(date:, because:)
@deprecation_date = Date.parse(date)
return if @deprecation_date > Date.today
Expand Down Expand Up @@ -3585,7 +3585,7 @@ def deprecated?
# <pre>disable! date: "2020-08-27", because: :does_not_build</pre>
# <pre>disable! date: "2020-08-27", because: "has been replaced by foo"</pre>
# @see https://docs.brew.sh/Deprecating-Disabling-and-Removing-Formulae
# @see DeprecateDisable::DEPRECATE_DISABLE_REASONS
# @see DeprecateDisable::FORMULA_DEPRECATE_DISABLE_REASONS
def disable!(date:, because:)
@disable_date = Date.parse(date)

Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/formula_auditor.rb
Expand Up @@ -412,7 +412,7 @@ def audit_deps
return if formula.disabled?

return if formula.deprecated? &&
formula.deprecation_reason != DeprecateDisable::DEPRECATE_DISABLE_REASONS[:versioned_formula]
formula.deprecation_reason != DeprecateDisable::FORMULA_DEPRECATE_DISABLE_REASONS[:versioned_formula]

problem <<~EOS
#{formula.full_name} contains conflicting version recursive dependencies:
Expand Down
20 changes: 7 additions & 13 deletions Library/Homebrew/formula_installer.rb
Expand Up @@ -200,21 +200,15 @@ def install_bottle_for?(dep, build)

sig { void }
def prelude
type, reason = DeprecateDisable.deprecate_disable_info formula
if type.present?
case type
deprecate_disable_type = DeprecateDisable.type(formula)
if deprecate_disable_type.present?
message = "#{formula.full_name} has been #{DeprecateDisable.message(formula)}"

case deprecate_disable_type
when :deprecated
if reason.present?
opoo "#{formula.full_name} has been deprecated because it #{reason}!"
else
opoo "#{formula.full_name} has been deprecated!"
end
opoo message
when :disabled
if reason.present?
raise CannotInstallFormulaError, "#{formula.full_name} has been disabled because it #{reason}!"
end

raise CannotInstallFormulaError, "#{formula.full_name} has been disabled!"
raise CannotInstallFormulaError, message
end
end

Expand Down

0 comments on commit 4793677

Please sign in to comment.