Module: Homebrew::Install Private

Included in:
Cmd::GistLogs
Defined in:
install.rb,
extend/os/linux/install.rb

Overview

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

Helper module for performing (pre-)install checks.

Class Method Summary collapse

Class Method Details

.check_cc_argv(cc) ⇒ 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.



23
24
25
26
27
28
29
30
31
# File 'install.rb', line 23

def check_cc_argv(cc)
  return unless cc

  @checks ||= Diagnostic::Checks.new
  opoo <<~EOS
    You passed `--cc=#{cc}`.
    #{@checks.please_create_pull_requests}
  EOS
end

.check_prefixObject

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'install.rb', line 41

def check_prefix
  if (Hardware::CPU.intel? || Hardware::CPU.in_rosetta2?) &&
     HOMEBREW_PREFIX.to_s == HOMEBREW_MACOS_ARM_DEFAULT_PREFIX
    if Hardware::CPU.in_rosetta2?
      odie <<~EOS
        Cannot install under Rosetta 2 in ARM default prefix (#{HOMEBREW_PREFIX})!
        To rerun under ARM use:
            arch -arm64 brew install ...
        To install under x86_64, install Homebrew into #{HOMEBREW_DEFAULT_PREFIX}.
      EOS
    else
      odie "Cannot install on Intel processor in ARM default prefix (#{HOMEBREW_PREFIX})!"
    end
  elsif Hardware::CPU.arm? && HOMEBREW_PREFIX.to_s == HOMEBREW_DEFAULT_PREFIX
    odie <<~EOS
      Cannot install in Homebrew on ARM processor in Intel default prefix (#{HOMEBREW_PREFIX})!
      Please create a new installation in #{HOMEBREW_MACOS_ARM_DEFAULT_PREFIX} using one of the
      "Alternative Installs" from:
        #{Formatter.url("https://docs.brew.sh/Installation")}
      You can migrate your previously installed formula list with:
        brew bundle dump
    EOS
  end
end

.global_post_installObject Also known as: generic_global_post_install

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.



40
41
42
43
44
# File 'extend/os/linux/install.rb', line 40

def self.global_post_install
  generic_global_post_install
  symlink_ld_so
  setup_preferred_gcc_libs
end

.install_formula?(formula, head: false, fetch_head: false, only_dependencies: false, force: false, quiet: false, overwrite: 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)


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'install.rb', line 66

def install_formula?(
  formula,
  head: false,
  fetch_head: false,
  only_dependencies: false,
  force: false,
  quiet: false,
  overwrite: false
)
  # head-only without --HEAD is an error
  if !head && formula.stable.nil?
    odie <<~EOS
      #{formula.full_name} is a head-only formula.
      To install it, run:
        brew install --HEAD #{formula.full_name}
    EOS
  end

  # --HEAD, fail with no head defined
  odie "No head is defined for #{formula.full_name}" if head && formula.head.nil?

  installed_head_version = formula.latest_head_version
  if installed_head_version &&
     !formula.head_version_outdated?(installed_head_version, fetch_head:)
    new_head_installed = true
  end
  prefix_installed = formula.prefix.exist? && !formula.prefix.children.empty?

  if formula.keg_only? && formula.any_version_installed? && formula.optlinked? && !force
    # keg-only install is only possible when no other version is
    # linked to opt, because installing without any warnings can break
    # dependencies. Therefore before performing other checks we need to be
    # sure the --force switch is passed.
    if formula.outdated?
      if !Homebrew::EnvConfig.no_install_upgrade? && !formula.pinned?
        name = formula.name
        version = formula.linked_version
        puts "#{name} #{version} is already installed but outdated (so it will be upgraded)."
        return true
      end

      unpin_cmd_if_needed = ("brew unpin #{formula.full_name} && " if formula.pinned?)
      optlinked_version = Keg.for(formula.opt_prefix).version
      onoe <<~EOS
        #{formula.full_name} #{optlinked_version} is already installed.
        To upgrade to #{formula.version}, run:
          #{unpin_cmd_if_needed}brew upgrade #{formula.full_name}
      EOS
    elsif only_dependencies
      return true
    elsif !quiet
      opoo <<~EOS
        #{formula.full_name} #{formula.pkg_version} is already installed and up-to-date.
        To reinstall #{formula.pkg_version}, run:
          brew reinstall #{formula.name}
      EOS
    end
  elsif (head && new_head_installed) || prefix_installed
    # After we're sure the --force switch was passed for linking to opt
    # keg-only we need to be sure that the version we're attempting to
    # install is not already installed.

    installed_version = if head
      formula.latest_head_version
    else
      formula.pkg_version
    end

    msg = "#{formula.full_name} #{installed_version} is already installed"
    linked_not_equals_installed = formula.linked_version != installed_version
    if formula.linked? && linked_not_equals_installed
      msg = if quiet
        nil
      else
        <<~EOS
          #{msg}.
          The currently linked version is: #{formula.linked_version}
        EOS
      end
    elsif only_dependencies || (!formula.linked? && overwrite)
      msg = nil
      return true
    elsif !formula.linked? || formula.keg_only?
      msg = <<~EOS
        #{msg}, it's just not linked.
        To link this version, run:
          brew link #{formula}
      EOS
    else
      msg = if quiet
        nil
      else
        <<~EOS
          #{msg} and up-to-date.
          To reinstall #{formula.pkg_version}, run:
            brew reinstall #{formula.name}
        EOS
      end
    end
    opoo msg if msg
  elsif !formula.any_version_installed? && (old_formula = formula.old_installed_formulae.first)
    msg = "#{old_formula.full_name} #{old_formula.any_installed_version} already installed"
    msg = if !old_formula.linked? && !old_formula.keg_only?
      <<~EOS
        #{msg}, it's just not linked.
        To link this version, run:
          brew link #{old_formula.full_name}
      EOS
    elsif quiet
      nil
    else
      "#{msg}."
    end
    opoo msg if msg
  elsif formula.migration_needed? && !force
    # Check if the formula we try to install is the same as installed
    # but not migrated one. If --force is passed then install anyway.
    opoo <<~EOS
      #{formula.oldnames_to_migrate.first} is already installed, it's just not migrated.
      To migrate this formula, run:
        brew migrate #{formula}
      Or to force-install it, run:
        brew install #{formula} --force
    EOS
  elsif formula.linked?
    message = "#{formula.name} #{formula.linked_version} is already installed"
    if formula.outdated? && !head
      if !Homebrew::EnvConfig.no_install_upgrade? && !formula.pinned?
        puts "#{message} but outdated (so it will be upgraded)."
        return true
      end

      unpin_cmd_if_needed = ("brew unpin #{formula.full_name} && " if formula.pinned?)
      onoe <<~EOS
        #{message}
        To upgrade to #{formula.pkg_version}, run:
          #{unpin_cmd_if_needed}brew upgrade #{formula.full_name}
      EOS
    elsif only_dependencies
      return true
    else
      onoe <<~EOS
        #{message}
        To install #{formula.pkg_version}, first run:
          brew unlink #{formula.name}
      EOS
    end
  else
    # If none of the above is true and the formula is linked, then
    # FormulaInstaller will handle this case.
    return true
  end

  # Even if we don't install this formula mark it as no longer just
  # installed as a dependency.
  return false unless formula.opt_prefix.directory?

  keg = Keg.new(formula.opt_prefix.resolved_path)
  tab = keg.tab
  unless tab.installed_on_request
    tab.installed_on_request = true
    tab.write
  end

  false
end

.install_formulae(formulae_to_install, build_bottle: false, force_bottle: false, bottle_arch: nil, ignore_deps: false, only_deps: false, include_test_formulae: [], build_from_source_formulae: [], cc: nil, git: false, interactive: false, keep_tmp: false, debug_symbols: false, force: false, overwrite: false, debug: false, quiet: false, verbose: false, dry_run: false, skip_post_install: 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.



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'install.rb', line 233

def install_formulae(
  formulae_to_install,
  build_bottle: false,
  force_bottle: false,
  bottle_arch: nil,
  ignore_deps: false,
  only_deps: false,
  include_test_formulae: [],
  build_from_source_formulae: [],
  cc: nil,
  git: false,
  interactive: false,
  keep_tmp: false,
  debug_symbols: false,
  force: false,
  overwrite: false,
  debug: false,
  quiet: false,
  verbose: false,
  dry_run: false,
  skip_post_install: false
)
  formula_installers = formulae_to_install.filter_map do |formula|
    Migrator.migrate_if_needed(formula, force:, dry_run:)
    build_options = formula.build

    formula_installer = FormulaInstaller.new(
      formula,
      options:                    build_options.used_options,
      installed_on_request:       true,
      installed_as_dependency:    false,
      build_bottle:,
      force_bottle:,
      bottle_arch:,
      ignore_deps:,
      only_deps:,
      include_test_formulae:,
      build_from_source_formulae:,
      cc:,
      git:,
      interactive:,
      keep_tmp:,
      debug_symbols:,
      force:,
      overwrite:,
      debug:,
      quiet:,
      verbose:,
      skip_post_install:,
    )

    begin
      unless dry_run
        formula_installer.prelude
        formula_installer.fetch
      end
      formula_installer
    rescue CannotInstallFormulaError => e
      ofail e.message
      nil
    rescue UnsatisfiedRequirements, DownloadError, ChecksumMismatchError => e
      ofail "#{formula}: #{e}"
      nil
    end
  end

  if dry_run
    if (formulae_name_to_install = formulae_to_install.map(&:name))
      ohai "Would install #{Utils.pluralize("formula", formulae_name_to_install.count,
                                            plural: "e", include_count: true)}:"
      puts formulae_name_to_install.join(" ")

      formula_installers.each do |fi|
        print_dry_run_dependencies(fi.formula, fi.compute_dependencies, &:name)
      end
    end
    return
  end

  formula_installers.each do |fi|
    install_formula(fi)
    Cleanup.install_formula_clean!(fi.formula)
  end
end

.perform_build_from_source_checks(all_fatal: 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.



33
34
35
36
# File 'install.rb', line 33

def perform_build_from_source_checks(all_fatal: false)
  Diagnostic.checks(:fatal_build_from_source_checks)
  Diagnostic.checks(:build_from_source_checks, fatal: all_fatal)
end

.perform_preinstall_checks_once(all_fatal: false) ⇒ 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:

  • all_fatal (Boolean) (defaults to: false)


15
16
17
18
19
20
21
# File 'install.rb', line 15

def perform_preinstall_checks_once(all_fatal: false)
  @perform_preinstall_checks_once ||= {}
  @perform_preinstall_checks_once[all_fatal] ||= begin
    perform_preinstall_checks(all_fatal:)
    true
  end
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.



318
319
320
321
322
323
324
325
# File 'install.rb', line 318

def print_dry_run_dependencies(formula, dependencies)
  return if dependencies.empty?

  ohai "Would install #{Utils.pluralize("dependenc", dependencies.count, plural: "ies", singular: "y",
                                      include_count: true)} for #{formula.name}:"
  formula_names = dependencies.map { |(dep, _options)| yield dep.to_formula }
  puts formula_names.join(" ")
end