Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Library/Homebrew/cask/cask.rb
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ def to_h
"disable_reason" => disable_reason,
"disable_replacement_formula" => disable_replacement_formula,
"disable_replacement_cask" => disable_replacement_cask,
"uninstall_on_upgrade" => uninstall_on_upgrade?,
"tap_git_head" => tap_git_head,
"languages" => languages,
"ruby_source_path" => ruby_source_path,
Expand Down
2 changes: 2 additions & 0 deletions Library/Homebrew/cask/cask_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,8 @@ def load(config:)
container(**container_hash)
end

uninstall_on_upgrade! if json_cask[:uninstall_on_upgrade]

json_cask[:artifacts]&.each do |artifact|
# convert generic string replacements into actual ones
artifact = cask.loader.from_h_gsubs(artifact, appdir)
Expand Down
16 changes: 16 additions & 0 deletions Library/Homebrew/cask/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ class DSL
:rename,
:sha256,
:staged_path,
:uninstall_on_upgrade!,
:uninstall_on_upgrade?,
:url,
:version,
:appdir,
Expand Down Expand Up @@ -143,6 +145,7 @@ def initialize(cask)
@container_set_in_block = T.let(false, T::Boolean)
@depends_on = T.let(DSL::DependsOn.new, DSL::DependsOn)
@depends_on_set_in_block = T.let(false, T::Boolean)
@uninstall_on_upgrade = T.let(false, T::Boolean)
@deprecated = T.let(false, T::Boolean)
@deprecation_date = T.let(nil, T.nilable(Date))
@deprecation_reason = T.let(nil, T.nilable(T.any(String, Symbol)))
Expand Down Expand Up @@ -559,6 +562,19 @@ def auto_updates(auto_updates = nil)
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
end

# Forces the uninstall to run during upgrades and reinstalls even when
# `HOMEBREW_NO_UNINSTALL_ON_CASK_UPGRADE` is set.
#
# @api public
def uninstall_on_upgrade!
@uninstall_on_upgrade = true
end

# Is uninstall_on_upgrade! method defined?
def uninstall_on_upgrade?
@uninstall_on_upgrade == true
end

# Automatically fetch the latest version of a cask from changelogs.
#
# @api public
Expand Down
15 changes: 13 additions & 2 deletions Library/Homebrew/cask/installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ def require_sha? = @require_sha
sig { returns(T::Boolean) }
def skip_cask_deps? = @skip_cask_deps

sig { returns(T::Boolean) }
def skip_uninstall?
return false unless Homebrew::EnvConfig.no_uninstall_on_cask_upgrade?
return false if @cask.uninstall_on_upgrade?
return false if !reinstall? && !upgrade?

true
end

sig { returns(T::Boolean) }
def upgrade? = @upgrade

Expand Down Expand Up @@ -160,6 +169,7 @@ def install
opoo_outside_github_actions "--no-quarantine bypasses macOS’s Gatekeeper, reducing system security. " \
"Do not use this flag unless you understand the risks."
end
purge_versioned_files if skip_uninstall? && @cask.staged_path.exist?
stage

@cask.config = @cask.default_config.merge(old_config)
Expand Down Expand Up @@ -222,6 +232,7 @@ def check_conflicts

sig { void }
def uninstall_existing_cask
return if skip_uninstall?
return unless @cask.installed?

# Always force uninstallation, ignore method parameter
Expand Down Expand Up @@ -342,7 +353,7 @@ def install_artifacts(predecessor: nil)

artifact.install_phase(
command: @command, verbose: verbose?, adopt: adopt?, auto_updates: @cask.auto_updates,
force: force?, predecessor:
force: force? || skip_uninstall?, predecessor: skip_uninstall? ? nil : predecessor
)
already_installed_artifacts.unshift(artifact)
end
Expand Down Expand Up @@ -552,7 +563,7 @@ def remove_download_sha

sig { params(successor: T.nilable(Cask)).void }
def start_upgrade(successor:)
uninstall_artifacts(successor:)
uninstall_artifacts(successor:) unless skip_uninstall?
backup
end

Expand Down
5 changes: 5 additions & 0 deletions Library/Homebrew/env_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,11 @@ module EnvConfig
"outdated.",
boolean: true,
},
HOMEBREW_NO_UNINSTALL_ON_CASK_UPGRADE: {
description: "If set, `brew upgrade` will not run the uninstall script during cask upgrades and will " \
"install over the top instead.",
boolean: true,
},
HOMEBREW_NO_UPDATE_REPORT_NEW: {
description: "If set, `brew update` will not show the list of newly added formulae/casks.",
boolean: true,
Expand Down
6 changes: 6 additions & 0 deletions Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Library/Homebrew/sorbet/rbi/dsl/homebrew/env_config.rbi

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Library/Homebrew/test/api/cask_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def mock_curl_download(stdout:)
it "specifies the correct URL and sha256" do
expect(Homebrew::API::SourceDownload).to receive(:new).with(
"https://raw.githubusercontent.com/Homebrew/homebrew-cask/abcdef1234567890abcdef1234567890abcdef12/Casks/everything.rb",
Checksum.new("d3c19b564ee5a17f22191599ad795a6cc9c4758d0e1269f2d13207155b378dea"),
Checksum.new("d4799fe58288f669de4688e57eb9f568b7c48d04abddfaaf8aa0a21beba0f2d3"),
any_args,
).and_call_original
described_class.source_download(cask)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
rename "Foobar.app", "Foo.app"
rename "Foo.app", "Bar.app"

uninstall_on_upgrade!

app "Everything.app"
installer script: {
executable: "~/just/another/path/install.sh",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,15 @@
"disable_reason": null,
"disable_replacement_formula": null,
"disable_replacement_cask": null,
"uninstall_on_upgrade": true,
"tap_git_head": "abcdef1234567890abcdef1234567890abcdef12",
"languages": [
"en",
"eo"
],
"ruby_source_path": "Casks/everything-with-variations.rb",
"ruby_source_checksum": {
"sha256": "d3c19b564ee5a17f22191599ad795a6cc9c4758d0e1269f2d13207155b378dea"
"sha256": "d4799fe58288f669de4688e57eb9f568b7c48d04abddfaaf8aa0a21beba0f2d3"
},
"variations": {
"arm64_monterey": {
Expand Down
3 changes: 2 additions & 1 deletion Library/Homebrew/test/support/fixtures/cask/everything.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,14 @@
"disable_reason": null,
"disable_replacement_formula": null,
"disable_replacement_cask": null,
"uninstall_on_upgrade": true,
"tap_git_head": "abcdef1234567890abcdef1234567890abcdef12",
"languages": [
"en",
"eo"
],
"ruby_source_path": "Casks/everything.rb",
"ruby_source_checksum": {
"sha256": "d3c19b564ee5a17f22191599ad795a6cc9c4758d0e1269f2d13207155b378dea"
"sha256": "d4799fe58288f669de4688e57eb9f568b7c48d04abddfaaf8aa0a21beba0f2d3"
}
}
Loading