Class: Cask::Cask Private

Inherits:
Object show all
Extended by:
APIHashable, Forwardable, Predicable
Includes:
Metadata
Defined in:
cask/cask.rb

Overview

This class is part of a private API. This class may only be used in the Homebrew/brew repository. Third parties should avoid using this class if possible, as it may be removed or changed without warning.

An instance of a cask.

Constant Summary

Constants included from Metadata

Metadata::METADATA_SUBDIR, Metadata::TIMESTAMP_FORMAT

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Predicable

attr_predicate

Methods included from APIHashable

generated_hash!, generating_hash!, generating_hash?

Methods included from Metadata

#metadata_main_container_path, #metadata_subdir, #metadata_timestamped_path, #metadata_versioned_path

Constructor Details

#initialize(token, sourcefile_path: nil, source: nil, tap: nil, loaded_from_api: false, config: nil, allow_reassignment: false, loader: nil, &block) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

  • token (String)
  • sourcefile_path (Pathname, nil) (defaults to: nil)
  • source (String, nil) (defaults to: nil)
  • tap (Tap, nil) (defaults to: nil)
  • loaded_from_api (Boolean) (defaults to: false)
  • config (Config, nil) (defaults to: nil)
  • allow_reassignment (Boolean) (defaults to: false)
  • loader (CaskLoader::ILoader, nil) (defaults to: nil)
  • block (T.proc.bind(DSL).void, nil)


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'cask/cask.rb', line 60

def initialize(token, sourcefile_path: nil, source: nil, tap: nil, loaded_from_api: false,
               config: nil, allow_reassignment: false, loader: nil, &block)
  @token = token
  @sourcefile_path = sourcefile_path
  @source = source
  @tap = tap
  @allow_reassignment = allow_reassignment
  @loaded_from_api = loaded_from_api
  @loader = loader
  # Sorbet has trouble with bound procs assigned to ivars: https://github.com/sorbet/sorbet/issues/6843
  instance_variable_set(:@block, block)

  @default_config = config || Config.new

  self.config = if config_path.exist?
    Config.from_json(File.read(config_path), ignore_invalid_keys: true)
  else
    @default_config
  end
end

Instance Attribute Details

#allow_reassignmentObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



22
23
24
# File 'cask/cask.rb', line 22

def allow_reassignment
  @allow_reassignment
end

#configObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



21
22
23
# File 'cask/cask.rb', line 21

def config
  @config
end

#default_configObject (readonly)

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



21
22
23
# File 'cask/cask.rb', line 21

def default_config
  @default_config
end

#downloadObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



22
23
24
# File 'cask/cask.rb', line 22

def download
  @download
end

#loaderObject (readonly)

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



21
22
23
# File 'cask/cask.rb', line 21

def loader
  @loader
end

#sourceObject (readonly)

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



21
22
23
# File 'cask/cask.rb', line 21

def source
  @source
end

#sourcefile_pathObject (readonly)

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



21
22
23
# File 'cask/cask.rb', line 21

def sourcefile_path
  @sourcefile_path
end

#tokenObject (readonly)

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



21
22
23
# File 'cask/cask.rb', line 21

def token
  @token
end

Class Method Details

.allObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'cask/cask.rb', line 26

def self.all
  # TODO: ideally avoid using ARGV by moving to e.g. CLI::Parser
  if ARGV.exclude?("--eval-all") && !Homebrew::EnvConfig.eval_all?
    odisabled "Cask::Cask#all without --eval-all or HOMEBREW_EVAL_ALL"
  end

  Tap.flat_map(&:cask_files).map do |f|
    CaskLoader::FromTapPathLoader.new(f).load(config: nil)
  rescue CaskUnreadableError => e
    opoo e.message

    nil
  end.compact
end

Instance Method Details

#caskfile_only?Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

The caskfile is needed during installation when there are *flight blocks or the cask has multiple languages

Returns:

  • (Boolean)


136
137
138
# File 'cask/cask.rb', line 136

def caskfile_only?
  languages.any? || artifacts.any?(Artifact::AbstractFlightBlock)
end

#caskroom_pathPathname

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



208
209
210
# File 'cask/cask.rb', line 208

def caskroom_path
  @caskroom_path ||= Caskroom.path.join(token)
end

#checksumable?Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


183
184
185
# File 'cask/cask.rb', line 183

def checksumable?
  DownloadStrategyDetector.detect(url.to_s, url.using) <= AbstractFileDownloadStrategy
end

#config_pathObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



179
180
181
# File 'cask/cask.rb', line 179

def config_path
  /"config.json"
end

#download_sha_pathObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



187
188
189
# File 'cask/cask.rb', line 187

def download_sha_path
  /"LATEST_DOWNLOAD_SHA256"
end

#eql?(other) ⇒ Boolean Also known as: ==

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


297
298
299
# File 'cask/cask.rb', line 297

def eql?(other)
  instance_of?(other.class) && token == other.token
end

#full_nameObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



122
123
124
125
126
127
# File 'cask/cask.rb', line 122

def full_name
  return token if tap.nil?
  return token if tap.user == "Homebrew"

  "#{tap.name}/#{token}"
end

#hashObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



293
294
295
# File 'cask/cask.rb', line 293

def hash
  token.hash
end

#inspectObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



289
290
291
# File 'cask/cask.rb', line 289

def inspect
  "#<Cask #{token}#{sourcefile_path&.to_s&.prepend(" ")}>"
end

#install_timeTime?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



141
142
143
144
145
# File 'cask/cask.rb', line 141

def install_time
  # <caskroom_path>/.metadata/<version>/<timestamp>/Casks/<token>.{rb,json} -> <timestamp>
  time = installed_caskfile&.dirname&.dirname&.basename&.to_s
  Time.strptime(time, Metadata::TIMESTAMP_FORMAT) if time
end

#installed?Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


130
131
132
# File 'cask/cask.rb', line 130

def installed?
  installed_caskfile&.exist? || false
end

#installed_caskfilePathname?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'cask/cask.rb', line 148

def installed_caskfile
  installed_caskroom_path = caskroom_path
  installed_token = token

  # Check if the cask is installed with an old name.
  old_tokens.each do |old_token|
    old_caskroom_path = Caskroom.path/old_token
    next if !old_caskroom_path.directory? || old_caskroom_path.symlink?

    installed_caskroom_path = old_caskroom_path
    installed_token = old_token
    break
  end

  installed_version = timestamped_versions(caskroom_path: installed_caskroom_path).last
  return unless installed_version

  caskfile_dir = (caskroom_path: installed_caskroom_path)
                 .join(*installed_version, "Casks")

  ["json", "rb"]
    .map { |ext| caskfile_dir.join("#{installed_token}.#{ext}") }
    .find(&:exist?)
end

#installed_versionString?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



174
175
176
177
# File 'cask/cask.rb', line 174

def installed_version
  # <caskroom_path>/.metadata/<version>/<timestamp>/Casks/<token>.{rb,json} -> <version>
  installed_caskfile&.dirname&.dirname&.dirname&.basename&.to_s
end

#languagesObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



267
268
269
# File 'cask/cask.rb', line 267

def languages
  @languages ||= @dsl.languages
end

#new_download_shaObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



191
192
193
194
195
196
197
198
# File 'cask/cask.rb', line 191

def new_download_sha
  require "cask/installer"

  # Call checksumable? before hashing
  @new_download_sha ||= Installer.new(self, verify_download_integrity: false)
                                 .download(quiet: true)
                                 .instance_eval { |x| Digest::SHA256.file(x).hexdigest }
end

#old_tokensArray<String>

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

An old name for the cask.

Returns:



83
84
85
86
87
88
89
90
# File 'cask/cask.rb', line 83

def old_tokens
  @old_tokens ||= if tap
    tap.cask_renames
       .flat_map { |old_token, new_token| (new_token == token) ? old_token : [] }
  else
    []
  end
end

#outdated?(greedy: false, greedy_latest: false, greedy_auto_updates: false) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


212
213
214
215
# File 'cask/cask.rb', line 212

def outdated?(greedy: false, greedy_latest: false, greedy_auto_updates: false)
  !outdated_version(greedy: greedy, greedy_latest: greedy_latest,
                    greedy_auto_updates: greedy_auto_updates).nil?
end

#outdated_download_sha?Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


200
201
202
203
204
205
# File 'cask/cask.rb', line 200

def outdated_download_sha?
  return true unless checksumable?

  current_download_sha = download_sha_path.read if download_sha_path.exist?
  current_download_sha.blank? || current_download_sha != new_download_sha
end

#outdated_info(greedy, verbose, json, greedy_latest, greedy_auto_updates) ⇒ Object

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'cask/cask.rb', line 235

def outdated_info(greedy, verbose, json, greedy_latest, greedy_auto_updates)
  return token if !verbose && !json

  installed_version = outdated_version(greedy: greedy, greedy_latest: greedy_latest,
                                       greedy_auto_updates: greedy_auto_updates).to_s

  if json
    {
      name:               token,
      installed_versions: [installed_version],
      current_version:    version,
    }
  else
    "#{token} (#{installed_version}) != #{version}"
  end
end

#outdated_version(greedy: false, greedy_latest: false, greedy_auto_updates: false) ⇒ Object

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'cask/cask.rb', line 217

def outdated_version(greedy: false, greedy_latest: false, greedy_auto_updates: false)
  # special case: tap version is not available
  return if version.nil?

  if version.latest?
    return installed_version if (greedy || greedy_latest) && outdated_download_sha?

    return
  elsif auto_updates && !greedy && !greedy_auto_updates
    return
  end

  # not outdated unless there is a different version on tap
  return if installed_version == version

  installed_version
end

#populate_from_api!(json_cask) ⇒ Object

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Raises:

  • (ArgumentError)


275
276
277
278
279
280
281
282
283
# File 'cask/cask.rb', line 275

def populate_from_api!(json_cask)
  raise ArgumentError, "Expected cask to be loaded from the API" unless loaded_from_api?

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

  @ruby_source_path = json_cask[:ruby_source_path]
  @ruby_source_checksum = json_cask[:ruby_source_checksum].freeze
end

#refreshObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



98
99
100
101
102
103
104
# File 'cask/cask.rb', line 98

def refresh
  @dsl = DSL.new(self)
  return unless @block

  @dsl.instance_eval(&@block)
  @dsl.language_eval
end

#ruby_source_checksumObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



261
262
263
264
265
# File 'cask/cask.rb', line 261

def ruby_source_checksum
  @ruby_source_checksum ||= {
    "sha256" => Digest::SHA256.file(sourcefile_path).hexdigest,
  }.freeze
end

#ruby_source_pathObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



252
253
254
255
256
257
258
259
# File 'cask/cask.rb', line 252

def ruby_source_path
  return @ruby_source_path if defined?(@ruby_source_path)

  return unless sourcefile_path
  return unless tap

  @ruby_source_path = sourcefile_path.relative_path_from(tap.path)
end

#tapObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



41
42
43
44
45
# File 'cask/cask.rb', line 41

def tap
  return super if block_given? # Object#tap

  @tap
end

#tap_git_headObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



271
272
273
# File 'cask/cask.rb', line 271

def tap_git_head
  @tap_git_head ||= tap&.git_head
end

#timestamped_versions(caskroom_path: self.caskroom_path) ⇒ Array<Array(String, String)>

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

  • caskroom_path (Pathname) (defaults to: self.caskroom_path)

Returns:



111
112
113
114
115
116
117
118
119
120
# File 'cask/cask.rb', line 111

def timestamped_versions(caskroom_path: self.caskroom_path)
  relative_paths = Pathname.glob((
                                   version: "*", timestamp: "*",
                                   caskroom_path: caskroom_path
                                 ))
                           .map { |p| p.relative_path_from(p.parent.parent) }
  # Sorbet is unaware that Pathname is sortable: https://github.com/sorbet/sorbet/issues/6844
  T.unsafe(relative_paths).sort_by(&:basename) # sort by timestamp
   .map { |p| p.split.map(&:to_s) }
end

#to_hObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'cask/cask.rb', line 302

def to_h
  url_specs = url&.specs.dup
  case url_specs&.dig(:user_agent)
  when :default
    url_specs.delete(:user_agent)
  when Symbol
    url_specs[:user_agent] = ":#{url_specs[:user_agent]}"
  end

  {
    "token"                => token,
    "full_token"           => full_name,
    "old_tokens"           => old_tokens,
    "tap"                  => tap&.name,
    "name"                 => name,
    "desc"                 => desc,
    "homepage"             => homepage,
    "url"                  => url,
    "url_specs"            => url_specs,
    "appcast"              => appcast,
    "version"              => version,
    "installed"            => installed_version,
    "installed_time"       => install_time&.to_i,
    "outdated"             => outdated?,
    "sha256"               => sha256,
    "artifacts"            => artifacts_list,
    "caveats"              => (caveats unless caveats.empty?),
    "depends_on"           => depends_on,
    "conflicts_with"       => conflicts_with,
    "container"            => container&.pairs,
    "auto_updates"         => auto_updates,
    "tap_git_head"         => tap_git_head,
    "languages"            => languages,
    "ruby_source_path"     => ruby_source_path,
    "ruby_source_checksum" => ruby_source_checksum,
  }
end

#to_hash_with_variationsObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'cask/cask.rb', line 340

def to_hash_with_variations
  if loaded_from_api? && !Homebrew::EnvConfig.no_install_from_api?
    return api_to_local_hash(Homebrew::API::Cask.all_casks[token])
  end

  hash = to_h
  variations = {}

  hash_keys_to_skip = %w[outdated installed versions]

  if @dsl.on_system_blocks_exist?
    begin
      MacOSVersion::SYMBOLS.keys.product(OnSystem::ARCH_OPTIONS).each do |os, arch|
        bottle_tag = ::Utils::Bottles::Tag.new(system: os, arch: arch)
        next unless bottle_tag.valid_combination?

        Homebrew::SimulateSystem.with os: os, arch: arch do
          refresh

          to_h.each do |key, value|
            next if hash_keys_to_skip.include? key
            next if value.to_s == hash[key].to_s

            variations[bottle_tag.to_sym] ||= {}
            variations[bottle_tag.to_sym][key] = value
          end
        end
      end
    ensure
      refresh
    end
  end

  hash["variations"] = variations
  hash
end

#to_sObject

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



285
286
287
# File 'cask/cask.rb', line 285

def to_s
  @token
end