Class: Homebrew::Bundle::Cargo Private

Inherits:
Extension show all
Defined in:
bundle/extensions/cargo.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.

Constant Summary collapse

SourceOptions =

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.

T.type_alias { T::Hash[Symbol, String] }
Crate =

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.

T.type_alias { { name: String, source: T.nilable(String) } }
Checkable =

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.

T.type_alias { { name: String, options: SourceOptions } }
CrateEntry =

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.

T.type_alias { T.any(Crate, Checkable) }
GIT_SOURCE_REGEX =

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.

cargo install --list reports the origin of anything not installed from a registry, as either a git URL or a local path. Only a git URL that resolves from another machine is supported here, so neither a path nor the file:// scheme is accepted. --git rejects an scp-style remote, so a scheme is required too.

%r{\A(?:ssh|git|https?)://}
GIT_REFERENCE_KEYS =

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.

%w[branch tag rev].freeze
PACKAGE_LIST_REGEX =

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.

/\A(?<name>[^\s:]+)\s+v(?<version>[0-9A-Za-z.+-]+)(?:\s+\((?<origin>[^)]+)\))?/

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Extension

add_supported?, check, cleanup!, cleanup_disable_description, cleanup_disable_env, cleanup_item_name, cleanup_items, cleanup_supported?, disable_predicate_method, dump, dump_disable_description, dump_disable_env, dump_disable_predicate_method, dump_disable_supported?, dump_output, dump_supported?, dump_with, ensure_package_manager_installed!, #failure_reason, flag, inherited, install_supported?, install_verb, legacy_check_step, package_description, package_manager_executable!, package_manager_installed?, predicate_method, quote, remove_supported?, switch_description, with_package_manager_env

Methods included from Utils::Output::Mixin

#issue_reporting_message, #odebug, #odeprecated, #odie, #odisabled, #ofail, #oh1, #oh1_title, #ohai, #ohai_title, #onoe, #opoo, #opoo_once, #opoo_outside_github_actions, #opoo_without_github_actions_annotation, #pretty_cannot_install, #pretty_deprecated, #pretty_disabled, #pretty_duration, #pretty_install_status, #pretty_installed, #pretty_removed, #pretty_uninstalled, #pretty_unmarked, #pretty_upgradable, #pretty_warning

Methods inherited from PackageType

check, #checkable_entries, dump, dump_output, dump_supported?, #exit_early_check, #failure_reason, #find_actionable, #full_check, inherited, install_supported?, install_verb

Class Method Details

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:



31
# File 'bundle/extensions/cargo.rb', line 31

def banner_name = "Cargo packages"

.batch_installable?(_name, _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:

Returns:

  • (Boolean)


81
82
83
# File 'bundle/extensions/cargo.rb', line 81

def batch_installable?(_name, _options = {})
  true
end

.cargo_env(cargo) ⇒ Hash{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:

Returns:



355
356
357
358
359
360
361
362
# File 'bundle/extensions/cargo.rb', line 355

def cargo_env(cargo)
  {
    "CARGO_HOME"         => ENV.fetch("HOMEBREW_CARGO_HOME", nil),
    "CARGO_INSTALL_ROOT" => ENV.fetch("HOMEBREW_CARGO_INSTALL_ROOT", nil),
    "PATH"               => "#{cargo.dirname}:#{ENV.fetch("PATH")}",
    "RUSTUP_HOME"        => ENV.fetch("HOMEBREW_RUSTUP_HOME", nil),
  }.compact
end

.check_label ⇒ 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:



28
# File 'bundle/extensions/cargo.rb', line 28

def check_label = "Cargo Package"

.cleanup_heading ⇒ 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:



66
67
68
# File 'bundle/extensions/cargo.rb', line 66

def cleanup_heading
  banner_name
end

.crate_record(name, source: nil) ⇒ Crate

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:



241
242
243
# File 'bundle/extensions/cargo.rb', line 241

def crate_record(name, source: nil)
  { name: name.strip, source: normalize_source(source) }
end

.dump_entry(package) ⇒ 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:

Returns:



129
130
131
132
133
134
135
# File 'bundle/extensions/cargo.rb', line 129

def dump_entry(package)
  line = super
  source = dump_source(package)
  line = "#{line}, source: #{quote(source)}" if source.present?

  line
end

.dump_name(package) ⇒ 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:

Returns:



116
117
118
# File 'bundle/extensions/cargo.rb', line 116

def dump_name(package)
  T.cast(package, CrateEntry)[:name]
end

.dump_source(package) ⇒ 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:

Returns:



121
122
123
124
125
126
# File 'bundle/extensions/cargo.rb', line 121

def dump_source(package)
  package = T.cast(package, CrateEntry)
  return package[:source] if package.key?(:source)

  package[:options].fetch(:source, nil)
end

.entry(name, options = {}) ⇒ Dsl::Entry

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:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'bundle/extensions/cargo.rb', line 34

def entry(name, options = {})
  unknown_options = options.keys - [:source]
  raise "unknown options(#{unknown_options.inspect}) for cargo" if unknown_options.present?

  source = options.fetch(:source, nil)
  if !source.nil? && !source.is_a?(String)
    raise "options[:source](#{source.inspect}) should be a String object"
  end

  normalized_options = {}
  if source.present?
    normalized_source = normalize_source(source)
    raise "options[:source](#{source.inspect}) should be a git URL" if normalized_source.nil?

    selector = normalized_source.partition("?").last
    if selector.present? && GIT_REFERENCE_KEYS.exclude?(selector.partition("=").first)
      raise "options[:source](#{source.inspect}) should select a branch, tag or rev"
    end

    normalized_options[:source] = normalized_source
  end

  Dsl::Entry.new(:cargo, name, normalized_options)
end

.install!(name, with: nil, source: nil, 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)
  • with (Array<String>, nil) (defaults to: nil)
  • source (String, nil) (defaults to: nil)
  • preinstall (Boolean) (defaults to: true)
  • no_upgrade (Boolean) (defaults to: false)
  • verbose (Boolean) (defaults to: false)
  • force (Boolean) (defaults to: false)
  • _options (Homebrew::Bundle::EntryOption)

Returns:

  • (Boolean)


292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'bundle/extensions/cargo.rb', line 292

def install!(name, with: nil, source: nil, preinstall: true, no_upgrade: false, verbose: false, force: false,
             **_options)
  _ = no_upgrade
  _ = force

  return true unless preinstall

  puts "Installing #{name} #{package_description}." if verbose
  return false unless install_package!(name, with:, source:, verbose:)

  package = crate_record(name, source:)
  installed_packages << package unless installed_packages.include?(package)
  packages << package unless packages.include?(package)
  true
end

.install_batch!(entries, 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:

Returns:

  • (Boolean)


86
87
88
89
90
91
92
93
94
95
96
97
# File 'bundle/extensions/cargo.rb', line 86

def install_batch!(entries, verbose: false)
  cargo = package_manager_executable!
  success = T.let(true, T::Boolean)
  entries.group_by { |entry| entry.options[:source] }.each do |source, source_entries|
    installed = with_env(cargo_env(cargo)) do
      Bundle.system(cargo.to_s, "install", "--locked", *source_args(T.cast(source, T.nilable(String))),
                    *source_entries.map(&:name), verbose:)
    end
    success &&= installed
  end
  success
end

.install_package!(name, with: nil, source: nil, 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:

  • name (String)
  • with (Array<String>, nil) (defaults to: nil)
  • source (String, nil) (defaults to: nil)
  • verbose (Boolean) (defaults to: false)

Returns:

  • (Boolean)


145
146
147
148
149
150
151
152
153
# File 'bundle/extensions/cargo.rb', line 145

def install_package!(name, with: nil, source: nil, verbose: false)
  _ = with

  cargo = package_manager_executable!

  with_env(cargo_env(cargo)) do
    Bundle.system(cargo.to_s, "install", "--locked", *source_args(source), name, verbose:)
  end
end

.installed_packages ⇒ Array<Crate>

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:



156
157
158
# File 'bundle/extensions/cargo.rb', line 156

def installed_packages
  @installed_packages ||= packages.dup
end

.normalize_source(source) ⇒ 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.

The resolved revision that cargo install --list appends to a git origin is deliberately dropped: a dumped Brewfile has to compare equal to a hand-written one, which a pinned revision would prevent. Anything that is not a git URL has no source: to dump, whether it is a registry crate or a local path.

Parameters:

Returns:



345
346
347
348
349
350
351
# File 'bundle/extensions/cargo.rb', line 345

def normalize_source(source)
  source = source.presence&.strip&.sub(/#[^#]*\z/, "")
  return if source.blank?
  return source if source.match?(GIT_SOURCE_REGEX)

  nil
end

.package_installed?(name, with: nil, source: nil) ⇒ 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)


253
254
255
# File 'bundle/extensions/cargo.rb', line 253

def package_installed?(name, with: nil, source: nil)
  installed_packages.include?(package_record(name, with:, source:))
end

.package_list ⇒ 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:



212
213
214
# File 'bundle/extensions/cargo.rb', line 212

def package_list
  command_output(package_manager_executable!, args: ["install", "--list"], print_stderr: true)
end

.package_manager_env(executable) ⇒ Hash{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:

Returns:



223
224
225
# File 'bundle/extensions/cargo.rb', line 223

def package_manager_env(executable)
  cargo_env(executable)
end

.package_manager_executable ⇒ Pathname?

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:



76
77
78
# File 'bundle/extensions/cargo.rb', line 76

def package_manager_executable
  which("cargo", ORIGINAL_PATHS)
end

.package_manager_name ⇒ 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:



71
72
73
# File 'bundle/extensions/cargo.rb', line 71

def package_manager_name
  "rust"
end

.package_outdated?(name, with: nil, source: nil) ⇒ 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)


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
# File 'bundle/extensions/cargo.rb', line 163

def package_outdated?(name, with: nil, source: nil)
  source = normalize_source(source)
  url, _, query = source.to_s.partition("?")
  key, _, ref = query.partition("=")
  return false if key == "rev" && ref.match?(/\A[0-9a-f]{7,40}\z/i)

  cargo = package_manager_executable!
  with_env(cargo_env(cargo)) do
    installed = package_list.each_line.filter_map { |line| line.match(PACKAGE_LIST_REGEX) }
                            .find do |match|
      match[:name] == name && normalize_source(match[:origin]) == source
    end
    raise "Missing Cargo version for #{name}" unless installed
    return false if source.nil? && installed[:origin].present?

    if source
      revisions = SystemCommand.run!("git", args: ["ls-remote", "--exit-code", url, *case key
      when "branch" then ["refs/heads/#{ref}"]
      when "tag" then ["refs/tags/#{ref}", "refs/tags/#{ref}^{}"]
      when "rev" then [ref, "refs/heads/#{ref}", "refs/tags/#{ref}", "refs/tags/#{ref}^{}"]
      else ["HEAD"]
      end], env: { "GIT_TERMINAL_PROMPT" => "0" }, print_stderr: false).stdout.lines
      revision = (revisions.find do |line|
        line.split.last&.end_with?("^{}")
      end || revisions.first).to_s.split.first
      installed_revision = installed[:origin].to_s.partition("#").last
      if revision.blank? || installed_revision.blank?
        raise "Missing Cargo Git revision for #{name}"
      end

      !revision.start_with?(installed_revision)
    else
      version_line = SystemCommand.run!(cargo, args: ["info", "--color=never", name],
                                               chdir: HOMEBREW_TEMP, print_stderr: false)
                                  .stdout.lines.find { |line| line.start_with?("version: ") }.to_s
      latest = version_line[/\(latest ([^)]+)\)/, 1] || version_line[/\Aversion: (\S+)/, 1]
      unless latest&.match?(/\A\d+\.\d+\.\d+/)
        raise "Invalid Cargo version for #{name}: #{version_line.inspect}"
      end

      Version.new(latest) > Version.new(installed[:version].to_s)
    end
  end
rescue ErrorDuringExecution => e
  opoo "Unable to check #{name} for upgrades. Using the installed version.\n#{e}"
  false
end

.package_record(name, with: nil, source: nil) ⇒ 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.

Parameters:

Returns:



234
235
236
237
238
# File 'bundle/extensions/cargo.rb', line 234

def package_record(name, with: nil, source: nil)
  _ = with

  crate_record(name, source:)
end

.packages ⇒ Array<Crate>

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:



100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'bundle/extensions/cargo.rb', line 100

def packages
  packages = @packages
  return packages if packages

  @packages = if (cargo = package_manager_executable) &&
                 (!cargo.to_s.start_with?("/") || cargo.exist?)
    with_env(cargo_env(cargo)) do
      parse_package_list(package_list)
    end
  end
  return [] if @packages.nil?

  @packages
end

.parse_package_list(output) ⇒ Array<Crate>

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:



326
327
328
329
330
331
332
333
334
335
336
# File 'bundle/extensions/cargo.rb', line 326

def parse_package_list(output)
  output.each_line.filter_map do |line|
    match = line.match(PACKAGE_LIST_REGEX)
    next if match.nil?

    name = match[:name]
    next if name.nil?

    { name:, source: normalize_source(match[:origin]) }
  end.uniq
end

.preinstall!(name, with: nil, source: nil, 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:

Returns:

  • (Boolean)


267
268
269
270
271
272
273
274
275
276
277
278
# File 'bundle/extensions/cargo.rb', line 267

def preinstall!(name, with: nil, source: nil, no_upgrade: false, verbose: false, **_options)
  ensure_package_manager_installed!(name, verbose:)

  if package_installed?(name, with:, source:)
    return true if !no_upgrade && package_outdated?(name, with:, source:)

    puts "Skipping install of #{name} #{package_description}. It is already installed." if verbose
    return false
  end

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



60
61
62
63
# File 'bundle/extensions/cargo.rb', line 60

def reset!
  @packages = T.let(nil, T.nilable(T::Array[Crate]))
  @installed_packages = T.let(nil, T.nilable(T::Array[Crate]))
end

.source_args(source) ⇒ Array<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.

A branch, tag or revision selected at install time is reported by cargo install --list as a URL query, and never more than one of them, but --git rejects a query: it has to be passed as the matching flag.

Parameters:

Returns:



312
313
314
315
316
317
318
319
320
321
322
# File 'bundle/extensions/cargo.rb', line 312

def source_args(source)
  source = normalize_source(source)
  return [] if source.nil?

  url, _, query = source.partition("?")
  key, _, value = query.partition("=")
  args = ["--git", url]
  args.push("--#{key}", value) if GIT_REFERENCE_KEYS.include?(key)

  args
end

.type ⇒ Symbol

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:



25
# File 'bundle/extensions/cargo.rb', line 25

def type = :cargo

.uninstall_package!(name, executable: Pathname.new("")) ⇒ 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)


218
219
220
# File 'bundle/extensions/cargo.rb', line 218

def uninstall_package!(name, executable: Pathname.new(""))
  Bundle.system(executable.to_s, "uninstall", name, verbose: false)
end

Instance Method Details

#format_checkable(entries) ⇒ Array<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.

Parameters:

Returns:



367
368
369
370
371
# File 'bundle/extensions/cargo.rb', line 367

def format_checkable(entries)
  checkable_entries(entries).map do |entry|
    { name: entry.name, options: entry.options }
  end
end

#installed_and_up_to_date?(package, 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:

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

Returns:

  • (Boolean)


374
375
376
377
378
379
380
381
382
# File 'bundle/extensions/cargo.rb', line 374

def installed_and_up_to_date?(package, no_upgrade: false)
  self.class.package_installed?(
    self.class.dump_name(package),
    source: self.class.dump_source(package),
  ) && (no_upgrade || !self.class.package_outdated?(
    self.class.dump_name(package),
    source: self.class.dump_source(package),
  ))
end