Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cask install receipts #17554

Merged
merged 11 commits into from
Jul 13, 2024
1 change: 1 addition & 0 deletions Library/Homebrew/cask.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
require "cask/pkg"
require "cask/quarantine"
require "cask/staged"
require "cask/tab"
require "cask/url"
require "cask/utils"
6 changes: 6 additions & 0 deletions Library/Homebrew/cask/artifact/abstract_flight_block.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@
directives.keys.map(&:to_s).join(", ")
end

def uninstall?
directives.keys.any? do |key|
key.to_s.start_with?("uninstall_")

Check warning on line 39 in Library/Homebrew/cask/artifact/abstract_flight_block.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/artifact/abstract_flight_block.rb#L38-L39

Added lines #L38 - L39 were not covered by tests
end
end

private

def class_for_dsl_key(dsl_key)
Expand Down
43 changes: 30 additions & 13 deletions Library/Homebrew/cask/cask.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require "cask/config"
require "cask/dsl"
require "cask/metadata"
require "cask/tab"
require "utils/bottles"
require "extend/api_hashable"

Expand Down Expand Up @@ -158,6 +159,12 @@
languages.any? || artifacts.any?(Artifact::AbstractFlightBlock)
end

def uninstall_flight_blocks?
artifacts.any? do |artifact|
artifact.is_a?(Artifact::AbstractFlightBlock) && artifact.uninstall?

Check warning on line 164 in Library/Homebrew/cask/cask.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/cask.rb#L163-L164

Added lines #L163 - L164 were not covered by tests
end
end
Rylan12 marked this conversation as resolved.
Show resolved Hide resolved

sig { returns(T.nilable(Time)) }
def install_time
# <caskroom_path>/.metadata/<version>/<timestamp>/Casks/<token>.{rb,json} -> <timestamp>
Expand Down Expand Up @@ -209,6 +216,10 @@
bundle_version&.version
end

def tab
Tab.for_cask(self)

Check warning on line 220 in Library/Homebrew/cask/cask.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/cask.rb#L220

Added line #L220 was not covered by tests
end

def config_path
metadata_main_container_path/"config.json"
end
Expand Down Expand Up @@ -465,6 +476,25 @@
hash
end

def artifacts_list(compact: false, uninstall_only: false)
artifacts.filter_map do |artifact|
case artifact

Check warning on line 481 in Library/Homebrew/cask/cask.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/cask.rb#L480-L481

Added lines #L480 - L481 were not covered by tests
when Artifact::AbstractFlightBlock
next if uninstall_only && !artifact.uninstall?

# Only indicate whether this block is used as we don't load it from the API
# We can skip this entirely once we move to internal JSON v3.
{ artifact.summarize => nil } unless compact
Rylan12 marked this conversation as resolved.
Show resolved Hide resolved
else
zap_artifact = artifact.is_a?(Artifact::Zap)
uninstall_artifact = artifact.respond_to?(:uninstall_phase) || artifact.respond_to?(:post_uninstall_phase)

Check warning on line 490 in Library/Homebrew/cask/cask.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/cask.rb#L490

Added line #L490 was not covered by tests
next if uninstall_only && !zap_artifact && !uninstall_artifact

{ artifact.class.dsl_key => artifact.to_args }

Check warning on line 493 in Library/Homebrew/cask/cask.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/cask.rb#L493

Added line #L493 was not covered by tests
end
end
end

private

sig { returns(T.nilable(Homebrew::BundleVersion)) }
Expand All @@ -482,19 +512,6 @@
hash
end

def artifacts_list(compact: false)
artifacts.filter_map do |artifact|
case artifact
when Artifact::AbstractFlightBlock
# Only indicate whether this block is used as we don't load it from the API
# We can skip this entirely once we move to internal JSON v3.
{ artifact.summarize => nil } unless compact
else
{ artifact.class.dsl_key => artifact.to_args }
end
end
end

def url_specs
url&.specs.dup.tap do |url_specs|
case url_specs&.dig(:user_agent)
Expand Down
11 changes: 8 additions & 3 deletions Library/Homebrew/cask/info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
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)
output << "#{installation_info(cask)}\n"

Check warning on line 15 in Library/Homebrew/cask/info.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/info.rb#L15

Added line #L15 was not covered by tests
repo = repo_info(cask)
output << "#{repo}\n" if repo
output << name_info(cask)
Expand All @@ -37,7 +37,7 @@
end

def self.installation_info(cask)
return "Not installed\n" unless cask.installed?
return "Not installed" unless cask.installed?

Check warning on line 40 in Library/Homebrew/cask/info.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/info.rb#L40

Added line #L40 was not covered by tests

versioned_staged_path = cask.caskroom_path.join(cask.installed_version)
path_details = if versioned_staged_path.exist?
Expand All @@ -46,7 +46,12 @@
Formatter.error("does not exist")
end

"Installed\n#{versioned_staged_path} (#{path_details})\n"
tab = Tab.for_cask(cask)

Check warning on line 49 in Library/Homebrew/cask/info.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/info.rb#L49

Added line #L49 was not covered by tests
Rylan12 marked this conversation as resolved.
Show resolved Hide resolved

info = ["Installed"]
info << "#{versioned_staged_path} (#{path_details})"
info << " #{tab}" if tab.tabfile&.exist?
info.join("\n")

Check warning on line 54 in Library/Homebrew/cask/info.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/info.rb#L51-L54

Added lines #L51 - L54 were not covered by tests
end

def self.name_info(cask)
Expand Down
21 changes: 18 additions & 3 deletions Library/Homebrew/cask/installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
require "cask/download"
require "cask/migrator"
require "cask/quarantine"
require "cask/tab"

require "cgi"

Expand All @@ -21,8 +22,8 @@
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, quarantine: true,
verify_download_integrity: true, quiet: false)
installed_as_dependency: false, installed_on_request: true,
quarantine: true, verify_download_integrity: true, quiet: false)
@cask = cask
@command = command
@force = force
Expand All @@ -35,13 +36,14 @@
@reinstall = reinstall
@upgrade = upgrade
@installed_as_dependency = installed_as_dependency
@installed_on_request = installed_on_request

Check warning on line 39 in Library/Homebrew/cask/installer.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/installer.rb#L39

Added line #L39 was not covered by tests
@quarantine = quarantine
@verify_download_integrity = verify_download_integrity
@quiet = quiet
end

attr_predicate :binaries?, :force?, :adopt?, :skip_cask_deps?, :require_sha?,
:reinstall?, :upgrade?, :verbose?, :zap?, :installed_as_dependency?,
:reinstall?, :upgrade?, :verbose?, :zap?, :installed_as_dependency?, :installed_on_request?,
:quarantine?, :quiet?

def self.caveats(cask)
Expand Down Expand Up @@ -112,6 +114,11 @@

install_artifacts(predecessor:)

tab = Tab.create(@cask)
tab.installed_as_dependency = installed_as_dependency?
tab.installed_on_request = installed_on_request?
tab.write

Check warning on line 120 in Library/Homebrew/cask/installer.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/installer.rb#L117-L120

Added lines #L117 - L120 were not covered by tests

if (tap = @cask.tap) && tap.should_report_analytics?
::Utils::Analytics.report_package_event(:cask_install, package_name: @cask.token, tap_name: tap.name,
on_request: true)
Expand Down Expand Up @@ -356,6 +363,7 @@
binaries: binaries?,
verbose: verbose?,
installed_as_dependency: true,
installed_on_request: false,
force: false,
).install
else
Expand Down Expand Up @@ -408,13 +416,20 @@
oh1 "Uninstalling Cask #{Formatter.identifier(@cask)}"
uninstall_artifacts(clear: true, successor:)
if !reinstall? && !upgrade?
remove_tabfile
remove_download_sha
remove_config_file
end
purge_versioned_files
purge_caskroom_path if force?
end

def remove_tabfile
tabfile = @cask.tab.tabfile

Check warning on line 428 in Library/Homebrew/cask/installer.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/installer.rb#L428

Added line #L428 was not covered by tests
FileUtils.rm_f tabfile if tabfile.present? && tabfile.exist?
Rylan12 marked this conversation as resolved.
Show resolved Hide resolved
@cask.config_path.parent.rmdir_if_possible

Check warning on line 430 in Library/Homebrew/cask/installer.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/installer.rb#L430

Added line #L430 was not covered by tests
end

def remove_config_file
FileUtils.rm_f @cask.config_path
@cask.config_path.parent.rmdir_if_possible
Expand Down
120 changes: 120 additions & 0 deletions Library/Homebrew/cask/tab.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# typed: true
# frozen_string_literal: true

require "tab"

module Cask
class Tab < ::AbstractTab
attr_accessor :uninstall_flight_blocks, :uninstall_artifacts

# Instantiates a {Tab} for a new installation of a cask.
def self.create(cask)
attributes = generic_attributes(cask).merge({

Check warning on line 12 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L12

Added line #L12 was not covered by tests
"tabfile" => cask.metadata_main_container_path/FILENAME,
"uninstall_flight_blocks" => cask.uninstall_flight_blocks?,
"runtime_dependencies" => Tab.runtime_deps_hash(cask, cask.depends_on),
"source" => {
"path" => cask.sourcefile_path.to_s,
"tap" => cask.tap&.name,
"tap_git_head" => nil, # Filled in later if possible
"version" => cask.version.to_s,
},
"uninstall_artifacts" => cask.artifacts_list(uninstall_only: true),
})

# We can only get `tap_git_head` if the tap is installed locally
attributes["source"]["tap_git_head"] = cask.tap.git_head if cask.tap&.installed?
Rylan12 marked this conversation as resolved.
Show resolved Hide resolved

new(attributes)

Check warning on line 28 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L28

Added line #L28 was not covered by tests
end

# Returns a {Tab} for an already installed cask,
# or a fake one if the cask is not installed.
def self.for_cask(cask)
path = cask.metadata_main_container_path/FILENAME

Check warning on line 34 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L34

Added line #L34 was not covered by tests

return from_file(path) if path.exist?

tab = empty
tab.source = {

Check warning on line 39 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L38-L39

Added lines #L38 - L39 were not covered by tests
"path" => cask.sourcefile_path.to_s,
"tap" => cask.tap&.name,
"tap_git_head" => nil,
"version" => cask.version.to_s,
}
tab.uninstall_artifacts = cask.artifacts_list(uninstall_only: true)

Check warning on line 45 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L45

Added line #L45 was not covered by tests
tab.source["tap_git_head"] = cask.tap.git_head if cask.tap&.installed?

tab

Check warning on line 48 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L48

Added line #L48 was not covered by tests
end

def self.empty
tab = super
tab.uninstall_flight_blocks = false
tab.uninstall_artifacts = []
tab.source["version"] = nil

Check warning on line 55 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L52-L55

Added lines #L52 - L55 were not covered by tests

tab

Check warning on line 57 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L57

Added line #L57 was not covered by tests
end

def self.runtime_deps_hash(cask, depends_on)
mappable_types = [:cask, :formula]
depends_on.to_h do |type, deps|

Check warning on line 62 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L61-L62

Added lines #L61 - L62 were not covered by tests
next [type, deps] unless mappable_types.include? type

deps = deps.map do |dep|
if type == :cask

Check warning on line 66 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L65-L66

Added lines #L65 - L66 were not covered by tests
c = CaskLoader.load(dep)
{
"full_name" => c.full_name,

Check warning on line 69 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L69

Added line #L69 was not covered by tests
"version" => c.version.to_s,
"declared_directly" => cask.depends_on.cask.include?(dep),
}
elsif type == :formula
f = Formulary.factory(dep, warn: false)
{
"full_name" => f.full_name,

Check warning on line 76 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L76

Added line #L76 was not covered by tests
"version" => f.version.to_s,
"revision" => f.revision,
"pkg_version" => f.pkg_version.to_s,
"declared_directly" => cask.depends_on.formula.include?(dep),
}
else
dep
end
apainintheneck marked this conversation as resolved.
Show resolved Hide resolved
end

[type, deps]

Check warning on line 87 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L87

Added line #L87 was not covered by tests
end
end

def version
source["version"]

Check warning on line 92 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L92

Added line #L92 was not covered by tests
end

def to_json(*_args)
attributes = {
"homebrew_version" => homebrew_version,

Check warning on line 97 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L97

Added line #L97 was not covered by tests
"loaded_from_api" => loaded_from_api,
"uninstall_flight_blocks" => uninstall_flight_blocks,
"installed_as_dependency" => installed_as_dependency,
"installed_on_request" => installed_on_request,
"time" => time,
"runtime_dependencies" => runtime_dependencies,
"source" => source,
"arch" => arch,
"uninstall_artifacts" => uninstall_artifacts,
"built_on" => built_on,
}

JSON.pretty_generate(attributes)

Check warning on line 110 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L110

Added line #L110 was not covered by tests
end

def to_s
s = ["Installed"]

Check warning on line 114 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L114

Added line #L114 was not covered by tests
Rylan12 marked this conversation as resolved.
Show resolved Hide resolved
s << "using the formulae.brew.sh API" if loaded_from_api
s << Time.at(time).strftime("on %Y-%m-%d at %H:%M:%S") if time
s.join(" ")

Check warning on line 117 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L117

Added line #L117 was not covered by tests
end
end
end
Loading
Loading