Skip to content

Commit

Permalink
Add cask install receipts
Browse files Browse the repository at this point in the history
  • Loading branch information
Rylan12 committed Jun 22, 2024
1 parent 2974be8 commit a6e1592
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 4 deletions.
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"
5 changes: 5 additions & 0 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 @@ -209,6 +210,10 @@ def bundle_long_version
bundle_version&.version
end

def tab
Tab.for_cask(self)

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/cask.rb#L214

Added line #L214 was not covered by tests
end

def config_path
metadata_main_container_path/"config.json"
end
Expand Down
5 changes: 4 additions & 1 deletion Library/Homebrew/cask/info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ def self.installation_info(cask)
Formatter.error("does not exist")
end

"Installed\n#{versioned_staged_path} (#{path_details})\n"
tab = Tab.for_cask(cask)
tab_details = "\n #{tab}" if tab.tabfile&.exist?

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/info.rb#L49-L50

Added lines #L49 - L50 were not covered by tests

"Installed\n#{versioned_staged_path} (#{path_details})#{tab_details}\n"

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/info.rb#L52

Added line #L52 was 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 @@ class Installer
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 @@ def initialize(cask, command: SystemCommand, force: false, adopt: false,
@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 @@ def install

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 @@ def satisfy_cask_and_formula_dependencies
binaries: binaries?,
verbose: verbose?,
installed_as_dependency: true,
installed_on_request: false,
force: false,
).install
else
Expand Down Expand Up @@ -408,13 +416,20 @@ def uninstall(successor: nil)
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?
@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
184 changes: 184 additions & 0 deletions Library/Homebrew/cask/tab.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# typed: true
# frozen_string_literal: true

module Cask
class Tab
extend Cachable

FILENAME = "INSTALL_RECEIPT.json"

attr_accessor :homebrew_version, :tabfile, :loaded_from_api, :installed_as_dependency, :installed_on_request,
:time, :dependencies, :arch, :source, :installed_on, :artifacts

# Instantiates a {Tab} for a new installation of a cask.
sig { params(cask: Cask).returns(Tab) }
def self.create(cask)
attributes = {
"homebrew_version" => HOMEBREW_VERSION,

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L17

Added line #L17 was not covered by tests
"tabfile" => cask.metadata_main_container_path/FILENAME,
"loaded_from_api" => cask.loaded_from_api?,
"installed_as_dependency" => false,
"installed_on_request" => false,
"time" => Time.now.to_i,
"dependencies" => Tab.runtime_deps_hash(cask, cask.depends_on),
"arch" => Hardware::CPU.arch,
"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,
},
"installed_on" => DevelopmentTools.build_system_info,
"artifacts" => cask.to_h["artifacts"],
}

# 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?

new(attributes)

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L38

Added line #L38 was not covered by tests
end

# Returns the {Tab} for an install receipt at `path`.
#
# NOTE: Results are cached.
sig { params(path: Pathname).returns(Tab) }
def self.from_file(path)
cache.fetch(path) do |p|
content = File.read(p)

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L46-L47

Added lines #L46 - L47 were not covered by tests
return empty if content.blank?

cache[p] = from_file_content(content, p)

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L50

Added line #L50 was not covered by tests
end
end

# Like {from_file}, but bypass the cache.
sig { params(content: String, path: Pathname).returns(Tab) }
def self.from_file_content(content, path)
attributes = begin
JSON.parse(content)

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L58

Added line #L58 was not covered by tests
rescue JSON::ParserError => e
raise e, "Cannot parse #{path}: #{e}", e.backtrace

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L60

Added line #L60 was not covered by tests
end
attributes["tabfile"] = path

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#L62

Added line #L62 was not covered by tests

new(attributes)

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L64

Added line #L64 was not covered by tests
end

sig { params(cask: Cask).returns(Tab) }
def self.for_cask(cask)
path = cask.metadata_main_container_path/FILENAME

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

return from_file(path) if path.exist?

tab = empty
tab.source = {

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L73-L74

Added lines #L73 - L74 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.artifacts = cask.to_h["artifacts"]

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L80

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

tab

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L83

Added line #L83 was not covered by tests
end

sig { returns(Tab) }
def self.empty
attributes = {
"homebrew_version" => HOMEBREW_VERSION,

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L89

Added line #L89 was not covered by tests
"loaded_from_api" => false,
"installed_as_dependency" => false,
"installed_on_request" => false,
"time" => nil,
"dependencies" => nil,
"arch" => nil,
"source" => {
"path" => nil,
"tap" => nil,
"tap_git_head" => nil,
"version" => nil,
},
"installed_on" => DevelopmentTools.generic_build_system_info,
"artifacts" => [],
}

new(attributes)

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L106

Added line #L106 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 111 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L110-L111

Added lines #L110 - L111 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 115 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L114-L115

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

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L118

Added line #L118 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 125 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L125

Added line #L125 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
end

[type, deps]

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L136

Added line #L136 was not covered by tests
end
end

def initialize(attributes = {})
attributes.each { |key, value| instance_variable_set(:"@#{key}", value) }

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L141

Added line #L141 was not covered by tests
end

sig { returns(T.nilable(Tap)) }
def tap
tap_name = source["tap"]

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L146

Added line #L146 was not covered by tests
Tap.fetch(tap_name) if tap_name
end

sig { params(_args: T::Array[T.untyped]).returns(String) }
def to_json(*_args)
attributes = {
"homebrew_version" => homebrew_version,

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L153

Added line #L153 was not covered by tests
"loaded_from_api" => loaded_from_api,
"installed_as_dependency" => installed_as_dependency,
"installed_on_request" => installed_on_request,
"time" => time,
"dependencies" => dependencies,
"arch" => arch,
"source" => source,
"installed_on" => installed_on,
"artifacts" => artifacts,
}

JSON.pretty_generate(attributes)

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L165

Added line #L165 was not covered by tests
end

sig { void }
def write
self.class.cache[tabfile] = self
tabfile.atomic_write(to_json)

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L170-L171

Added lines #L170 - L171 were not covered by tests
end

sig { returns(String) }
def to_s
s = ["Installed"]

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

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L176

Added line #L176 was not covered by tests

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 181 in Library/Homebrew/cask/tab.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/tab.rb#L181

Added line #L181 was not covered by tests
end
end
end
3 changes: 3 additions & 0 deletions Library/Homebrew/sorbet/rbi/parlour.rbi
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ module Cask
sig { returns(T::Boolean) }
def installed_as_dependency?; end

sig { returns(T::Boolean) }
def installed_on_request?; end

sig { returns(T::Boolean) }
def quarantine?; end

Expand Down

0 comments on commit a6e1592

Please sign in to comment.