Class: Homebrew::Bundle::Brew Private

Inherits:
PackageType show all
Extended by:
Utils::Output::Mixin
Defined in:
bundle/brew.rb,
bundle/brew_services.rb

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.

Direct Known Subclasses

Services

Defined Under Namespace

Classes: Services, Topo

Constant Summary collapse

PACKAGE_TYPE =

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

:brew
PACKAGE_TYPE_NAME =

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

"Formula"

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils::Output::Mixin

odebug, odeprecated, odie, odisabled, ofail, oh1, oh1_title, ohai, ohai_title, onoe, opoo, opoo_outside_github_actions, pretty_deprecated, pretty_disabled, pretty_duration, pretty_installed, pretty_outdated, pretty_uninstalled

Methods inherited from PackageType

check, #checkable_entries, dump_supported?, #exit_early_check, #failure_reason, #find_actionable, #format_checkable, #full_check, install_supported?, type

Constructor Details

#initialize(name = "", options = {}) ⇒ 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:

  • name (String) (defaults to: "")
  • options (Hash{Symbol => T.untyped}) (defaults to: {})


378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'bundle/brew.rb', line 378

def initialize(name = "", options = {})
  super()
  @full_name = name
  @name = T.let(Utils.name_from_full_name(name), String)
  @args = T.let(options.fetch(:args, []).map { |arg| "--#{arg}" }, T::Array[String])
  @conflicts_with_arg = T.let(options.fetch(:conflicts_with, []), T::Array[String])
  @restart_service = T.let(options[:restart_service], T.nilable(T.any(Symbol, T::Boolean)))
  @start_service = T.let(options.fetch(:start_service, @restart_service), T.nilable(T.any(Symbol, T::Boolean)))
  @link = T.let(options.fetch(:link, nil), T.nilable(T.any(Symbol, T::Boolean)))
  @postinstall = T.let(options.fetch(:postinstall, nil), T.nilable(String))
  @version_file = T.let(options.fetch(:version_file, nil), T.nilable(String))
  @changed = T.let(nil, T.nilable(T::Boolean))
end

Class Method Details

.dump(describe: false, no_restart: false) ⇒ 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:

  • describe (Boolean) (defaults to: false)
  • no_restart (Boolean) (defaults to: false)

Returns:



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'bundle/brew.rb', line 174

def dump(describe: false, no_restart: false)
  require "bundle/brew_services"

  requested_formula = formulae.select do |f|
    f[:installed_on_request?] || !f[:installed_as_dependency?]
  end
  requested_formula.map do |f|
    brewline = if describe && f[:desc].present?
      f[:desc].split("\n").map { |s| "# #{s}\n" }.join
    else
      ""
    end
    brewline += "brew \"#{f[:full_name]}\""

    args = f[:args].map { |arg| "\"#{arg}\"" }.sort.join(", ")
    brewline += ", args: [#{args}]" unless f[:args].empty?
    brewline += ", restart_service: :changed" if !no_restart && Services.started?(f[:full_name])
    brewline += ", link: #{f[:link?]}" unless f[:link?].nil?
    brewline
  end.join("\n")
end

.dump_output(describe: false, no_restart: false) ⇒ 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:

  • describe (Boolean) (defaults to: false)
  • no_restart (Boolean) (defaults to: false)

Returns:



197
198
199
# File 'bundle/brew.rb', line 197

def dump_output(describe: false, no_restart: false)
  dump(describe:, no_restart:)
end

.fetchable_name(name, options = {}, no_upgrade: false) ⇒ 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:

  • name (String)
  • options (Hash{Symbol => T.untyped}) (defaults to: {})
  • no_upgrade (Boolean) (defaults to: false)

Returns:



202
203
204
205
206
207
208
209
210
# File 'bundle/brew.rb', line 202

def fetchable_name(name, options = {}, no_upgrade: false)
  _ = options

  return if (tap_name = Utils.tap_from_full_name(name)) &&
            Homebrew::Bundle::Tap.installed_taps.exclude?(tap_name)
  return if formula_installed_and_up_to_date?(name, no_upgrade:)

  name
end

.formula_aliasesHash{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.

Returns:



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'bundle/brew.rb', line 213

def formula_aliases
  return @formula_aliases if @formula_aliases

  @formula_aliases = {}
  formulae.each do |f|
    aliases = f[:aliases]
    next if aliases.blank?

    aliases.each do |a|
      @formula_aliases[a] = f[:full_name]
      if (tap_name = Utils.tap_from_full_name(f[:full_name]))
        @formula_aliases["#{tap_name}/#{a}"] = f[:full_name]
      end
    end
  end
  @formula_aliases
end

.formula_in_array?(formula, array) ⇒ 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.

Parameters:

Returns:

  • (Boolean)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'bundle/brew.rb', line 82

def formula_in_array?(formula, array)
  return true if array.include?(formula)
  return true if array.include?(Utils.name_from_full_name(formula))

  old_name = formula_oldnames[formula]
  old_name ||= formula_oldnames[Utils.name_from_full_name(formula)]
  return true if old_name && array.include?(old_name)

  resolved_full_name = formula_aliases[formula]
  return false unless resolved_full_name
  return true if array.include?(resolved_full_name)
  return true if array.include?(Utils.name_from_full_name(resolved_full_name))

  false
end

.formula_installed?(formula) ⇒ 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.

Parameters:

Returns:

  • (Boolean)


99
100
101
# File 'bundle/brew.rb', line 99

def formula_installed?(formula)
  formula_in_array?(formula, installed_formulae)
end

.formula_installed_and_up_to_date?(formula, no_upgrade: 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.

Parameters:

  • formula (String)
  • no_upgrade (Boolean) (defaults to: false)

Returns:

  • (Boolean)


69
70
71
72
73
74
# File 'bundle/brew.rb', line 69

def formula_installed_and_up_to_date?(formula, no_upgrade: false)
  return false unless formula_installed?(formula)
  return true if no_upgrade_with_args?(no_upgrade, formula)

  !formula_upgradable?(formula)
end

.formula_oldnamesHash{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.

Returns:



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'bundle/brew.rb', line 232

def formula_oldnames
  return @formula_oldnames if @formula_oldnames

  @formula_oldnames = {}
  formulae.each do |f|
    oldnames = f[:oldnames]
    next if oldnames.blank?

    oldnames.each do |oldname|
      @formula_oldnames[oldname] = f[:full_name]
      if (tap_name = Utils.tap_from_full_name(f[:full_name]))
        @formula_oldnames["#{tap_name}/#{oldname}"] = f[:full_name]
      end
    end
  end
  @formula_oldnames
end

.formula_upgradable?(formula) ⇒ 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.

Parameters:

Returns:

  • (Boolean)


104
105
106
107
# File 'bundle/brew.rb', line 104

def formula_upgradable?(formula)
  # Check local cache first and then authoritative Homebrew source.
  (formula_in_array?(formula, upgradable_formulae) && Formula[formula].outdated?) || false
end

.formulaeArray<Hash{Symbol => T.untyped}>

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:



130
131
132
133
134
135
136
# File 'bundle/brew.rb', line 130

def formulae
  return @formulae if @formulae

  formulae_by_full_name
  # formulae_by_full_name sets @formulae as a side effect of calling sort!
  T.cast(@formulae, T::Array[T::Hash[Symbol, T.untyped]])
end

.formulae_by_full_name(name = nil) ⇒ Hash{Symbol => T.untyped}, ...

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 the full @formulae_by_full_name map when called without a name, or a single formula's attribute hash when called with a name.

Parameters:

  • name (String, nil) (defaults to: nil)

Returns:



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'bundle/brew.rb', line 145

def formulae_by_full_name(name = nil)
  return @formulae_by_full_name[name] if name.present? && @formulae_by_full_name&.key?(name)

  require "formula"
  require "formulary"
  Formulary.enable_factory_cache!

  @formulae_by_name ||= {}
  @formulae_by_full_name ||= {}

  if name.nil?
    formulae = Formula.installed.map { add_formula(it) }
    sort!(formulae)
    return @formulae_by_full_name
  end

  formula = Formula[name]
  add_formula(formula)
rescue FormulaUnavailableError => e
  opoo "'#{name}' formula is unreadable: #{e}"
  {}
end

.formulae_by_name(name) ⇒ Hash{Symbol => T.untyped}?

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:

Returns:



169
170
171
# File 'bundle/brew.rb', line 169

def formulae_by_name(name)
  T.cast(formulae_by_full_name(name), T.nilable(T::Hash[Symbol, T.untyped])) || @formulae_by_name&.[](name)
end

.inherited(subclass) ⇒ 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.

This method returns an undefined value.

Parameters:



20
21
22
23
24
# File 'bundle/brew.rb', line 20

def inherited(subclass)
  return if subclass.name == "Homebrew::Bundle::Brew::Services"

  super
end

.install!(name, preinstall: true, no_upgrade: false, verbose: false, force: false, **options) ⇒ 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.

Parameters:

  • name (String)
  • preinstall (Boolean) (defaults to: true)
  • no_upgrade (Boolean) (defaults to: false)
  • verbose (Boolean) (defaults to: false)
  • force (Boolean) (defaults to: false)
  • options (T.untyped)

Returns:

  • (Boolean)


50
51
52
# File 'bundle/brew.rb', line 50

def install!(name, preinstall: true, no_upgrade: false, verbose: false, force: false, **options)
  new(name, options).install!(preinstall:, no_upgrade:, verbose:, force:)
end

.install_verb(name, options = {}) ⇒ 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.



60
61
62
63
64
65
66
# File 'bundle/brew.rb', line 60

def install_verb(name, options = {})
  _ = options

  return "Installing" unless formula_upgradable?(name)

  "Upgrading"
end

.installed_formulaeArray<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.

Returns:



110
111
112
# File 'bundle/brew.rb', line 110

def installed_formulae
  @installed_formulae ||= formulae.map { |f| f[:name] }
end

.no_upgrade_with_args?(no_upgrade, formula_name) ⇒ 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.

Parameters:

  • no_upgrade (Boolean)
  • formula_name (String)

Returns:

  • (Boolean)


77
78
79
# File 'bundle/brew.rb', line 77

def no_upgrade_with_args?(no_upgrade, formula_name)
  no_upgrade && Bundle.upgrade_formulae.exclude?(formula_name)
end

.outdated_formulaeArray<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.

Returns:



120
121
122
# File 'bundle/brew.rb', line 120

def outdated_formulae
  @outdated_formulae ||= formulae.filter_map { |f| f[:name] if f[:outdated?] }
end

.pinned_formulaeArray<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.

Returns:



125
126
127
# File 'bundle/brew.rb', line 125

def pinned_formulae
  @pinned_formulae ||= formulae.filter_map { |f| f[:name] if f[:pinned?] }
end

.preinstall!(name, no_upgrade: false, verbose: false, **options) ⇒ 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.

Parameters:

  • name (String)
  • no_upgrade (Boolean) (defaults to: false)
  • verbose (Boolean) (defaults to: false)
  • options (T.untyped)

Returns:

  • (Boolean)


42
43
44
# File 'bundle/brew.rb', line 42

def preinstall!(name, no_upgrade: false, verbose: false, **options)
  new(name, options).preinstall!(no_upgrade:, verbose:)
end

.reset!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.

This method returns an undefined value.



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

def reset!
  require "bundle/brew_services"

  Homebrew::Bundle::Brew::Services.reset!
  @installed_formulae = T.let(nil, T.nilable(T::Array[String]))
  @outdated_formulae = T.let(nil, T.nilable(T::Array[String]))
  @pinned_formulae = T.let(nil, T.nilable(T::Array[String]))
  @formulae = T.let(nil, T.nilable(T::Array[T::Hash[Symbol, T.untyped]]))
  @formulae_by_full_name = T.let(nil, T.nilable(T::Hash[String, T::Hash[Symbol, T.untyped]]))
  @formulae_by_name = T.let(nil, T.nilable(T::Hash[String, T::Hash[Symbol, T.untyped]]))
  @formula_aliases = T.let(nil, T.nilable(T::Hash[String, String]))
  @formula_oldnames = T.let(nil, T.nilable(T::Hash[String, String]))
end

.upgradable_formulaeArray<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.

Returns:



115
116
117
# File 'bundle/brew.rb', line 115

def upgradable_formulae
  outdated_formulae - pinned_formulae
end

Instance Method Details

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


488
489
490
# File 'bundle/brew.rb', line 488

def changed?
  @changed.present?
end

#install!(preinstall: true, no_upgrade: false, verbose: false, force: 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.

Parameters:

  • preinstall (Boolean) (defaults to: true)
  • no_upgrade (Boolean) (defaults to: false)
  • verbose (Boolean) (defaults to: false)
  • force (Boolean) (defaults to: false)

Returns:

  • (Boolean)


411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# File 'bundle/brew.rb', line 411

def install!(preinstall: true, no_upgrade: false, verbose: false, force: false)
  install_result = if preinstall
    install_change_state!(no_upgrade:, verbose:, force:)
  else
    true
  end
  result = install_result

  if installed?
    service_result = service_change_state!(verbose:)
    result &&= service_result

    link_result = link_change_state!(verbose:)
    result &&= link_result

    postinstall_result = postinstall_change_state!(verbose:)
    result &&= postinstall_result

    if result && @version_file.present?
      # Use the version from the environment if it hasn't changed.
      # Strip the revision number because it's not part of the non-Homebrew version.
      version = if !changed? && (env_version = Bundle.formula_versions_from_env(@name))
        PkgVersion.parse(env_version).version
      else
        Formula[@full_name].version
      end.to_s
      File.write(@version_file, "#{version}\n")

      puts "Wrote #{@name} version #{version} to #{@version_file}" if verbose
    end
  end

  result
end

#install_change_state!(no_upgrade:, verbose:, force:) ⇒ 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.

Parameters:

  • no_upgrade (Boolean)
  • verbose (Boolean)
  • force (Boolean)

Returns:

  • (Boolean)


447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
# File 'bundle/brew.rb', line 447

def install_change_state!(no_upgrade:, verbose:, force:)
  require "tap"
  if (tap_with_name = ::Tap.with_formula_name(@full_name))
    tap, = tap_with_name
    tap.ensure_installed!
  end

  return false unless resolve_conflicts!(verbose:)

  if installed?
    upgrade_formula!(verbose:, force:)
  else
    install_formula!(verbose:, force:)
  end
end

#installed_and_up_to_date?(formula, no_upgrade: 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.

Parameters:

  • formula (Object)
  • no_upgrade (Boolean) (defaults to: false)

Returns:

  • (Boolean)


393
394
395
396
397
# File 'bundle/brew.rb', line 393

def installed_and_up_to_date?(formula, no_upgrade: false)
  raise "formula must be a String, got #{formula.class}: #{formula}" unless formula.is_a?(String)

  self.class.formula_installed_and_up_to_date?(formula, no_upgrade:)
end

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:

  • verbose (Boolean) (defaults to: false)

Returns:

  • (Boolean)


510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
# File 'bundle/brew.rb', line 510

def link_change_state!(verbose: false)
  link_args = []
  link_args << "--force" if unlinked_and_keg_only?

  cmd = case @link
  when :overwrite
    link_args << "--overwrite"
    "link" unless linked?
  when true
    "link" unless linked?
  when false
    "unlink" if linked?
  when nil
    if keg_only?
      "unlink" if linked?
    else
      "link" unless linked?
    end
  end

  if cmd.present?
    verb = "#{cmd}ing".capitalize
    with_args = " with #{link_args.join(" ")}" if link_args.present?
    puts "#{verb} #{@name} formula#{with_args}." if verbose
    return Bundle.brew(cmd, *link_args, @name, verbose:)
  end

  true
end

#postinstall_change_state!(verbose:) ⇒ 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.

Parameters:

  • verbose (Boolean)

Returns:

  • (Boolean)


541
542
543
544
545
546
547
# File 'bundle/brew.rb', line 541

def postinstall_change_state!(verbose:)
  return true if @postinstall.blank?
  return true unless changed?

  puts "Running postinstall for #{@name}: #{@postinstall}" if verbose
  Kernel.system(@postinstall) || false
end

#preinstall!(no_upgrade: false, verbose: 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.

Parameters:

  • no_upgrade (Boolean) (defaults to: false)
  • verbose (Boolean) (defaults to: false)

Returns:

  • (Boolean)


400
401
402
403
404
405
406
407
408
# File 'bundle/brew.rb', line 400

def preinstall!(no_upgrade: false, verbose: false)
  if installed? && (self.class.no_upgrade_with_args?(no_upgrade, @name) || !upgradable?)
    puts "Skipping install of #{@name} formula. It is already installed." if verbose
    @changed = nil
    return false
  end

  true
end

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


475
476
477
# File 'bundle/brew.rb', line 475

def restart_service?
  @restart_service.present?
end

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


480
481
482
483
484
485
# File 'bundle/brew.rb', line 480

def restart_service_needed?
  return false unless restart_service?

  # Restart if `restart_service: :always`, or if the formula was installed or upgraded
  @restart_service.to_s == "always" || changed?
end

#service_change_state!(verbose:) ⇒ 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.

Parameters:

  • verbose (Boolean)

Returns:

  • (Boolean)


493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
# File 'bundle/brew.rb', line 493

def service_change_state!(verbose:)
  require "bundle/brew_services"

  file = Services.versioned_service_file(@name)&.to_s

  if restart_service_needed?
    puts "Restarting #{@name} service." if verbose
    Services.restart(@full_name, file:, verbose:)
  elsif start_service_needed?
    puts "Starting #{@name} service." if verbose
    Services.start(@full_name, file:, verbose:)
  else
    true
  end
end

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


464
465
466
# File 'bundle/brew.rb', line 464

def start_service?
  @start_service.present?
end

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


469
470
471
472
# File 'bundle/brew.rb', line 469

def start_service_needed?
  require "bundle/brew_services"
  start_service? && !Services.started?(@full_name)
end