Skip to content
Open
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
5 changes: 5 additions & 0 deletions Library/Homebrew/cask/artifact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# frozen_string_literal: true

require "cask/artifact/app"
require "cask/artifact/appimage"
require "cask/artifact/artifact" # generic 'artifact' stanza
require "cask/artifact/audio_unit_plugin"
require "cask/artifact/binary"
Expand Down Expand Up @@ -53,5 +54,9 @@ module Artifact
::Cask::Artifact::VstPlugin,
::Cask::Artifact::Vst3Plugin,
].freeze

LINUX_ONLY_ARTIFACTS = [
::Cask::Artifact::AppImage,
].freeze
end
end
15 changes: 15 additions & 0 deletions Library/Homebrew/cask/artifact/appimage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# typed: strict
# frozen_string_literal: true

require "cask/artifact/symlinked"

module Cask
module Artifact
class AppImage < Symlinked
sig { params(target: T.any(String, Pathname)).returns(Pathname) }
def resolve_target(target)
config.appimagedir/target
end
end
end
end
58 changes: 54 additions & 4 deletions Library/Homebrew/cask/cask.rb
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,67 @@ def font?
end

sig { returns(T::Boolean) }
def supports_macos? = true
def supports_macos?
return true if font?

if @dsl.on_system_blocks_exist?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given this block is nearly identical in the macOS and Linux cases: it'd be nicer to have a shared helper method in this class that both cases call.

any_loaded = false
begin
OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag|
next unless bottle_tag.macos?

Homebrew::SimulateSystem.with_tag(bottle_tag) do
refresh

any_loaded = true
return false if artifacts.any? do |artifact|
::Cask::Artifact::LINUX_ONLY_ARTIFACTS.include?(artifact.class)
end
end
end
rescue CaskInvalidError => e
# Invalid cask for macOS
odebug e.message
ensure
refresh
end

return false unless any_loaded
end

true
end

sig { returns(T::Boolean) }
def supports_linux?
return true if font?

return false if artifacts.any? do |artifact|
::Cask::Artifact::MACOS_ONLY_ARTIFACTS.include?(artifact.class)
if @dsl.on_system_blocks_exist?
any_loaded = false
begin
OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag|
next unless bottle_tag.linux?

Homebrew::SimulateSystem.with_tag(bottle_tag) do
refresh

any_loaded = true
return false if artifacts.any? do |artifact|
::Cask::Artifact::MACOS_ONLY_ARTIFACTS.include?(artifact.class)
end
end
end
rescue CaskInvalidError
# Invalid cask for Linux
ensure
refresh
end

return false unless any_loaded
end

@dsl.os.present?
# Only assume Linux support if there is an explicit `on_system` stanza
@dsl.on_system_blocks_exist?
end

# The caskfile is needed during installation when there are
Expand Down
2 changes: 2 additions & 0 deletions Library/Homebrew/cask/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Config
DEFAULT_DIRS = T.let(
{
appdir: "/Applications",
appimagedir: "~/Applications",
keyboard_layoutdir: "/Library/Keyboard Layouts",
colorpickerdir: "~/Library/ColorPickers",
prefpanedir: "~/Library/PreferencePanes",
Expand Down Expand Up @@ -49,6 +50,7 @@ def self.from_args(args)
args = T.unsafe(args)
new(explicit: {
appdir: args.appdir,
appimagedir: args.appimagedir,
keyboard_layoutdir: args.keyboard_layoutdir,
colorpickerdir: args.colorpickerdir,
prefpanedir: args.prefpanedir,
Expand Down
1 change: 1 addition & 0 deletions Library/Homebrew/cask/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class DSL
ORDINARY_ARTIFACT_CLASSES = [
Artifact::Installer,
Artifact::App,
Artifact::AppImage,
Artifact::Artifact,
Artifact::AudioUnitPlugin,
Artifact::Binary,
Expand Down
4 changes: 4 additions & 0 deletions Library/Homebrew/cli/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ def self.global_cask_options
description: "Target location for Applications " \
"(default: `#{Cask::Config::DEFAULT_DIRS[:appdir]}`).",
}],
[:flag, "--appimagedir=", {
description: "Target location for AppImages " \
"(default: `#{Cask::Config::DEFAULT_DIRS[:appimagedir]}`).",
}],
[:flag, "--keyboard-layoutdir=", {
description: "Target location for Keyboard Layouts " \
"(default: `#{Cask::Config::DEFAULT_DIRS[:keyboard_layoutdir]}`).",
Expand Down
56 changes: 42 additions & 14 deletions Library/Homebrew/dev-cmd/generate-cask-ci-matrix.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,33 +127,61 @@ def run

sig { params(cask: Cask::Cask).returns(T::Hash[T::Hash[Symbol, T.any(Symbol, String)], Float]) }
def filter_runners(cask)
filtered_macos_runners = RUNNERS.select do |runner, _|
runner[:symbol] != :linux &&
filtered_runners = if cask.supports_macos?
filtered_macos_runners = MACOS_RUNNERS.select do |runner, _|
cask.depends_on.macos.present? &&
cask.depends_on.macos.allows?(MacOSVersion.from_symbol(T.must(runner[:symbol]).to_sym))
end
cask.depends_on.macos.allows?(MacOSVersion.from_symbol(T.must(runner[:symbol]).to_sym))
end

return MACOS_RUNNERS.dup if filtered_macos_runners.none?

filtered_runners = if filtered_macos_runners.any?
filtered_macos_runners
else
RUNNERS.dup
end

filtered_runners = filtered_runners.merge(LINUX_RUNNERS) if cask.supports_linux?

archs = architectures(cask:)
odebug "Architectures macOS: #{archs}" if archs.any?
filtered_runners.select! do |runner, _|
archs.include?(runner.fetch(:arch))
end

odebug "Filtered runners: #{filtered_runners.keys.map { |r| r[:name] }}" if filtered_runners.any?
if cask.supports_linux?
filtered_linux_runners = LINUX_RUNNERS.dup

archs = architectures(cask:, os: :linux, arch: :intel)
filtered_linux_runners.select! do |runner, _|
archs.include?(runner.fetch(:arch))
end

filtered_runners.merge!(filtered_linux_runners)
end

odebug "Architectures linux: #{archs}" if archs.any?
odebug "Filtered runners: #{filtered_runners.keys.map { |r| r[:name] }}" if filtered_runners.any?

filtered_runners
end

sig { params(cask: Cask::Cask).returns(T::Array[Symbol]) }
def architectures(cask:)
return RUNNERS.keys.map { |r| r.fetch(:arch).to_sym }.uniq.sort if cask.depends_on.arch.blank?
sig { params(cask: Cask::Cask, os: Symbol, arch: Symbol).returns(T::Array[Symbol]) }
def architectures(cask:, os: :macos, arch: :arm)
architectures = []
begin
tag = Utils::Bottles::Tag.new(system: os, arch: arch)
Homebrew::SimulateSystem.with_tag(tag) do
cask.refresh

if cask.depends_on.arch.blank?
architectures = RUNNERS.keys.map { |r| r.fetch(:arch).to_sym }.uniq.sort
next
end

architectures = cask.depends_on.arch.map { |arch| arch[:type] }
end
rescue ::Cask::CaskInvalidError
# Can't read cask for this system-arch combination.
end

cask.depends_on.arch.map { |arch| arch[:type] }.uniq.sort
architectures
end

sig {
Expand Down Expand Up @@ -255,7 +283,7 @@ def generate_matrix(tap, labels: [], cask_names: [], skip_install: false, new_ca
native_runner_arch = arch == runner.fetch(:arch)
# we don't need to run simulated archs on Linux
next if runner.fetch(:symbol) == :linux && !native_runner_arch
# we don't need to run simulated archs on macOS
# we don't need to run simulated archs on macOS Sequoia
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because an intel runner exists for it, in contrary to all the other macOS versions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# we don't need to run simulated archs on macOS Sequoia
# we don't need to run simulated archs on macOS Sequoia
# because it has a GitHub hosted x86_64 runner

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I add the same to the Linux block above?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if that's the reason: yup!

next if runner.fetch(:symbol) == :sequoia && !native_runner_arch

# If it's just a single OS test then we can just use the two real arch runners.
Expand Down
1 change: 1 addition & 0 deletions Library/Homebrew/extend/os/cask/installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
# frozen_string_literal: true

require "extend/os/linux/cask/installer" if OS.linux?
require "extend/os/mac/cask/installer" if OS.mac?
4 changes: 1 addition & 3 deletions Library/Homebrew/extend/os/linux/cask/installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ module Installer

sig { void }
def check_stanza_os_requirements
return unless artifacts.any? do |artifact|
::Cask::Artifact::MACOS_ONLY_ARTIFACTS.include?(artifact.class)
end
return unless @cask.supports_linux?

raise ::Cask::CaskError, "macOS is required for this software."
end
Expand Down
23 changes: 23 additions & 0 deletions Library/Homebrew/extend/os/mac/cask/installer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# typed: strict
# frozen_string_literal: true

module OS
module Mac
module Cask
module Installer
extend T::Helpers

requires_ancestor { ::Cask::Installer }

sig { void }
def check_stanza_os_requirements
return unless @cask.supports_macos?

raise ::Cask::CaskError, "Linux is required for this software."
end
end
end
end
end

Cask::Installer.prepend(OS::Mac::Cask::Installer)
Loading