Skip to content
Draft
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 .ruby-version
1 change: 1 addition & 0 deletions Library/Homebrew/ast_constants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
[{ name: :include, type: :method_call }],
[{ name: :desc, type: :method_call }],
[{ name: :homepage, type: :method_call }],
[{ name: :login_items, type: :method_call }],
[{ name: :url, type: :method_call }],
[{ name: :mirror, type: :method_call }],
[{ name: :version, type: :method_call }],
Expand Down
2 changes: 2 additions & 0 deletions Library/Homebrew/cask/artifact/abstract_uninstall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class AbstractUninstall < AbstractArtifact
:launchctl,
:quit,
:signal,
# odeprecated: deprecate when all casks have been migrated to top-level login_items
:login_item,
:kext,
:script,
Expand Down Expand Up @@ -297,6 +298,7 @@ def uninstall_signal(*signals, command: nil, **_)
end
end

# TODO: Need to refer to attribute from the cask instead of this uninstall stanza
def uninstall_login_item(*login_items, command: nil, successor: nil, **_)
return if successor

Expand Down
6 changes: 6 additions & 0 deletions Library/Homebrew/cask/cask.rb
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,10 @@ def languages
@languages ||= @dsl.languages
end

def login_items
@login_items ||= @dsl.login_items
end

def tap_git_head
@tap_git_head ||= tap&.git_head
rescue TapUnavailableError
Expand All @@ -357,6 +361,7 @@ def populate_from_api!(json_cask)
raise ArgumentError, "Expected cask to be loaded from the API" unless loaded_from_api?

@languages = json_cask.fetch(:languages, [])
@login_items = json_cask.fetch(:login_items, [])
@tap_git_head = json_cask.fetch(:tap_git_head, "HEAD")

@ruby_source_path = json_cask[:ruby_source_path]
Expand Down Expand Up @@ -427,6 +432,7 @@ def to_h
"languages" => languages,
"ruby_source_path" => ruby_source_path,
"ruby_source_checksum" => ruby_source_checksum,
"login_items" => login_items,
}
end

Expand Down
3 changes: 2 additions & 1 deletion Library/Homebrew/cask/cask_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ def load(config:)
end
desc json_cask[:desc]
homepage json_cask[:homepage]
login_items json_cask[:login_items] if json_cask[:login_items].present?

if (date = json_cask[:deprecation_date].presence)
because = DeprecateDisable.to_reason_string_or_symbol json_cask[:deprecation_reason], type: :cask
Expand All @@ -389,7 +390,7 @@ def load(config:)
disable! date:, because:
end

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

if json_cask[:rename].present?
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 @@ -108,6 +108,7 @@ class DSL
:no_autobump!,
:autobump?,
:no_autobump_message,
:login_items,
:on_system_blocks_exist?,
:on_system_block_min_os,
:depends_on_set_in_block?,
Expand Down Expand Up @@ -243,6 +244,21 @@ def set_unique_stanza(stanza, should_return)
raise CaskInvalidError.new(cask, "'#{stanza}' stanza failed with: #{e}")
end

# Sets the cask's login items
#
# ### Example
#
# ```ruby
# login_items "Raycast"
# ```
#
# @api public
def login_items(login_items = nil)
return [] if login_items.nil?

set_unique_stanza(:login_items, login_items.nil?) { Array(login_items) }
end

# Sets the cask's homepage.
#
# ### Example
Expand Down
12 changes: 12 additions & 0 deletions Library/Homebrew/cask/info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ def self.get_info(cask)
language = language_info(cask)
output << language if language
output << "#{artifact_info(cask)}\n"
login_items = login_items_info(cask)
output << login_items if login_items
caveats = Installer.caveats(cask)
output << caveats if caveats
output
Expand Down Expand Up @@ -137,5 +139,15 @@ def self.artifact_info(cask)
end
artifact_output.freeze
end

sig { params(cask: Cask).returns(T.nilable(String)) }
def self.login_items_info(cask)
return if cask.login_items.empty?

<<~EOS
#{ohai_title("Login Items")}
#{cask.login_items.join(", ")}
EOS
end
end
end
29 changes: 27 additions & 2 deletions Library/Homebrew/cask/installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ class Installer
skip_cask_deps: T::Boolean, binaries: T::Boolean, verbose: T::Boolean, zap: T::Boolean,
require_sha: T::Boolean, upgrade: T::Boolean, reinstall: T::Boolean, installed_as_dependency: T::Boolean,
installed_on_request: T::Boolean, quarantine: T::Boolean, verify_download_integrity: T::Boolean,
quiet: T::Boolean, download_queue: T.nilable(Homebrew::DownloadQueue)
quiet: T::Boolean, download_queue: T.nilable(Homebrew::DownloadQueue), login_items: T::Boolean
).void
}
def initialize(cask, command: SystemCommand, force: false, adopt: false,
skip_cask_deps: false, binaries: true, verbose: false,
zap: false, require_sha: false, upgrade: false, reinstall: false,
installed_as_dependency: false, installed_on_request: true,
quarantine: true, verify_download_integrity: true, quiet: false, download_queue: nil)
quarantine: true, verify_download_integrity: true, quiet: false, download_queue: nil,
login_items: false)
@cask = cask
@command = command
@force = force
Expand All @@ -51,6 +52,7 @@ def initialize(cask, command: SystemCommand, force: false, adopt: false,
@quiet = quiet
@download_queue = download_queue
@ran_prelude = T.let(false, T::Boolean)
@login_items = login_items
end

sig { returns(T::Boolean) }
Expand All @@ -68,6 +70,9 @@ def installed_as_dependency? = @installed_as_dependency
sig { returns(T::Boolean) }
def installed_on_request? = @installed_on_request

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

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

Expand Down Expand Up @@ -348,6 +353,17 @@ def install_artifacts(predecessor: nil)
already_installed_artifacts.unshift(artifact)
end

unless @cask.login_items.empty?
if login_items?
@cask.login_items.each do |lgi|
# TODO: register the login_items here using osascript
ohai "***** Will REGISTER login_item: #{lgi}"
end
else
ohai "Skipping processing of login_items"
end
end

save_config_file
save_download_sha if @cask.version.latest?
rescue => e
Expand Down Expand Up @@ -592,6 +608,15 @@ def uninstall_artifacts(clear: false, successor: nil)
odebug "Uninstalling artifacts"
odebug "#{::Utils.pluralize("artifact", artifacts.length, include_count: true)} defined", artifacts

if login_items?
@cask.login_items.each do |lgi|
# TODO: unregister the login_items here using osascript
ohai "***** Will UNREGISTER login_item: #{lgi}"
end
else
ohai "Skipping processing of login_items"
end

artifacts.each do |artifact|
if artifact.respond_to?(:uninstall_phase)
artifact = T.cast(
Expand Down
7 changes: 4 additions & 3 deletions Library/Homebrew/cask/reinstall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Reinstall
sig {
params(
casks: ::Cask::Cask, verbose: T::Boolean, force: T::Boolean, skip_cask_deps: T::Boolean, binaries: T::Boolean,
require_sha: T::Boolean, quarantine: T::Boolean, zap: T::Boolean
require_sha: T::Boolean, quarantine: T::Boolean, zap: T::Boolean, login_items: T::Boolean
).void
}
def self.reinstall_casks(
Expand All @@ -21,7 +21,8 @@ def self.reinstall_casks(
binaries: false,
require_sha: false,
quarantine: false,
zap: false
zap: false,
login_items: true
)
require "cask/installer"

Expand All @@ -30,7 +31,7 @@ def self.reinstall_casks(
download_queue = Homebrew::DownloadQueue.new_if_concurrency_enabled(pour: true)
cask_installers = casks.map do |cask|
Installer.new(cask, binaries:, verbose:, force:, skip_cask_deps:, require_sha:, reinstall: true,
quarantine:, zap:, download_queue:)
quarantine:, zap:, download_queue:, login_items:)
end

if download_queue
Expand Down
10 changes: 7 additions & 3 deletions Library/Homebrew/cask/upgrade.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def self.outdated_casks(casks, args:, force:, quiet:,
binaries: T.nilable(T::Boolean),
quarantine: T.nilable(T::Boolean),
require_sha: T.nilable(T::Boolean),
login_items: T.nilable(T::Boolean),
).returns(T::Boolean)
}
def self.upgrade_casks!(
Expand All @@ -86,7 +87,8 @@ def self.upgrade_casks!(
quiet: false,
binaries: nil,
quarantine: nil,
require_sha: nil
require_sha: nil,
login_items: nil
)
quarantine = true if quarantine.nil?

Expand Down Expand Up @@ -171,7 +173,7 @@ def self.upgrade_casks!(
upgrade_cask(
old_cask, new_cask,
binaries:, force:, skip_cask_deps:, verbose:,
quarantine:, require_sha:, download_queue:
quarantine:, require_sha:, download_queue:, login_items:
)
rescue => e
new_exception = e.exception("#{new_cask.full_name}: #{e}")
Expand All @@ -195,14 +197,15 @@ def self.upgrade_casks!(
force: T.nilable(T::Boolean),
quarantine: T.nilable(T::Boolean),
require_sha: T.nilable(T::Boolean),
login_items: T.nilable(T::Boolean),
skip_cask_deps: T.nilable(T::Boolean),
verbose: T.nilable(T::Boolean),
download_queue: T.nilable(Homebrew::DownloadQueue),
).void
}
def self.upgrade_cask(
old_cask, new_cask,
binaries:, force:, quarantine:, require_sha:, skip_cask_deps:, verbose:, download_queue:
binaries:, force:, quarantine:, require_sha:, login_items:, skip_cask_deps:, verbose:, download_queue:
)
require "cask/installer"

Expand Down Expand Up @@ -231,6 +234,7 @@ def self.upgrade_cask(
upgrade: true,
quarantine:,
download_queue:,
login_items:,
}.compact

new_cask_installer =
Expand Down
6 changes: 6 additions & 0 deletions Library/Homebrew/cmd/install.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ class InstallCmd < AbstractCommand
env: :cask_opts_quarantine,
odeprecated: true,
}],
[:switch, "--[no-]login-items", {
description: "Disable/enable registering of login item(s) (default: disabled).",
env: :cask_opts_login_items,
}],
[:switch, "--adopt", {
description: "Adopt existing artifacts in the destination that are identical to those being installed. " \
"Cannot be combined with `--force`.",
Expand Down Expand Up @@ -282,6 +286,7 @@ def run
binaries: args.binaries?,
force: args.force?,
quarantine: args.quarantine?,
login_items: args.login_items?,
quiet: args.quiet?,
require_sha: args.require_sha?,
skip_cask_deps: args.skip_cask_deps?,
Expand All @@ -296,6 +301,7 @@ def run
dry_run: args.dry_run?,
binaries: args.binaries?,
quarantine: args.quarantine?,
login_items: args.login_items?,
require_sha: args.require_sha?,
skip_cask_deps: args.skip_cask_deps?,
verbose: args.verbose?,
Expand Down
5 changes: 5 additions & 0 deletions Library/Homebrew/cmd/reinstall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ class Reinstall < AbstractCommand
env: :cask_opts_quarantine,
odeprecated: true,
}],
[:switch, "--[no-]login-items", {
description: "Disable/enable registering of login item(s) (default: disabled).",
env: :cask_opts_login_items,
}],
[:switch, "--adopt", {
description: "Adopt existing artifacts in the destination that are identical to those being installed. " \
"Cannot be combined with `--force`.",
Expand Down Expand Up @@ -210,6 +214,7 @@ def run
require_sha: args.require_sha?,
skip_cask_deps: args.skip_cask_deps?,
quarantine: args.quarantine?,
login_items: args.login_items?,
zap: args.zap?,
)
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/cmd/uninstall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def run

raise Cask::CaskNotInstalledError, cask if !cask.installed? && !args.force?

Cask::Installer.new(cask, verbose: args.verbose?, force: args.force?).zap
Cask::Installer.new(cask, verbose: args.verbose?, force: args.force?, login_items: true).zap
end
else
Cask::Uninstall.uninstall_casks(
Expand Down
5 changes: 5 additions & 0 deletions Library/Homebrew/cmd/upgrade.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ class UpgradeCmd < AbstractCommand
env: :cask_opts_quarantine,
odeprecated: true,
}],
[:switch, "--[no-]login-items", {
description: "Disable/enable registering of login item(s) (default: disabled).",
env: :cask_opts_login_items,
}],
].each do |args|
options = args.pop
send(*args, **options)
Expand Down Expand Up @@ -301,6 +305,7 @@ def upgrade_outdated_casks!(casks)
dry_run: args.dry_run?,
binaries: args.binaries?,
quarantine: args.quarantine?,
login_items: args.login_items?,
require_sha: args.require_sha?,
skip_cask_deps: args.skip_cask_deps?,
verbose: args.verbose?,
Expand Down
12 changes: 11 additions & 1 deletion Library/Homebrew/env_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ module EnvConfig
},
HOMEBREW_CASK_OPTS: {
description: "Append these options to all `cask` commands. All `--*dir` options, " \
"`--language`, `--require-sha` and `--no-binaries` are supported. " \
"`--language`, `--require-sha`, `--no-login-items` and `--no-binaries` are supported. " \
"For example, you might add something like the following to your " \
"`~/.profile`, `~/.bash_profile`, or `~/.zshenv`:" \
"\n\n `export HOMEBREW_CASK_OPTS=\"--appdir=${HOME}/Applications --fontdir=/Library/Fonts\"`",
Expand Down Expand Up @@ -640,6 +640,16 @@ def cask_opts_quarantine?
true
end

sig { returns(T::Boolean) }
def cask_opts_login_items?
cask_opts.reverse_each do |opt|
return true if opt == "--login-items"
return false if opt == "--no-login-items"
end

false
end

sig { returns(T::Boolean) }
def cask_opts_require_sha?
cask_opts.include?("--require-sha")
Expand Down
2 changes: 2 additions & 0 deletions Library/Homebrew/rubocops/cask/constants/stanza.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ module Constants
:app,
:pkg,
:installer,
:login_items,
:binary,
:manpage,
:bash_completion,
Expand Down Expand Up @@ -89,6 +90,7 @@ module Constants
:launchctl,
:quit,
:signal,
# odeprecated: deprecate when all casks have been migrated to top-level login_items
:login_item,
:kext,
:script,
Expand Down
Loading
Loading