Module: Utils::Bottles

Defined in:
utils/bottles.rb

Overview

This module is part of an internal API. This module may only be used internally in repositories owned by Homebrew, except in casks or formulae. Third parties should avoid using this module if possible, as it may be removed or changed without warning.

Helper functions for bottles.

Defined Under Namespace

Classes: Collector, Tag, TagSpecification

Class Method Summary collapse

Class Method Details

.built_as?(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)


31
32
33
34
35
36
# File 'utils/bottles.rb', line 31

def built_as?(formula)
  return false unless formula.latest_version_installed?

  tab = Keg.new(formula.latest_installed_prefix).tab
  tab.built_as_bottle
end

.extname_tag_rebuild(filename) ⇒ 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.

Parameters:

Returns:



53
54
55
# File 'utils/bottles.rb', line 53

def extname_tag_rebuild(filename)
  HOMEBREW_BOTTLES_EXTNAME_REGEX.match(filename).to_a
end

.file_from_bottle(bottle_file, file_path) ⇒ 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:



65
66
67
# File 'utils/bottles.rb', line 65

def file_from_bottle(bottle_file, file_path)
  Utils.popen_read("tar", "--extract", "--to-stdout", "--file", bottle_file, file_path)
end

.file_outdated?(formula, file) ⇒ 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)


39
40
41
42
43
44
45
46
47
48
49
50
# File 'utils/bottles.rb', line 39

def file_outdated?(formula, file)
  file = file.resolved_path

  filename = file.basename.to_s
  bottle = formula.bottle
  return false unless bottle

  _, bottle_tag, bottle_rebuild = extname_tag_rebuild(filename)
  return false if bottle_tag.blank?

  bottle_tag != bottle.tag.to_s || bottle_rebuild.to_i != bottle.rebuild
end

.formula_contents(bottle_file, 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.

Parameters:

Returns:

Raises:



97
98
99
100
101
102
103
104
# File 'utils/bottles.rb', line 97

def formula_contents(bottle_file, name: resolve_formula_names(bottle_file)[0])
  bottle_version = resolve_version bottle_file
  formula_path = "#{name}/#{bottle_version}/.brew/#{name}.rb"
  contents = file_from_bottle(bottle_file, formula_path)
  raise BottleFormulaUnavailableError.new(bottle_file, formula_path) unless $CHILD_STATUS.success?

  contents
end

.load_tab(formula) ⇒ Tab

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:



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'utils/bottles.rb', line 120

def load_tab(formula)
  keg = Keg.new(formula.prefix)
  tabfile = keg/AbstractTab::FILENAME
  bottle_json_path = formula.local_bottle_path&.sub(/\.(\d+\.)?tar\.gz$/, ".json")

  if (tab_attributes = formula.bottle_tab_attributes.presence)
    Tab.from_file_content(tab_attributes.to_json, tabfile)
  elsif !tabfile.exist? && bottle_json_path&.exist?
    _, tag, = Utils::Bottles.extname_tag_rebuild(formula.local_bottle_path.to_s)
    bottle_hash = JSON.parse(File.read(bottle_json_path))
    tab_json = bottle_hash[formula.full_name]["bottle"]["tags"][tag]["tab"].to_json
    Tab.from_file_content(tab_json, tabfile)
  else
    tab = keg.tab

    tab.runtime_dependencies = begin
      f_runtime_deps = formula.runtime_dependencies(read_from_tab: false)
      Tab.runtime_deps_hash(formula, f_runtime_deps)
    end

    tab
  end
end

.path_resolved_basename(root_url, name, checksum, filename) ⇒ Array<(String, [String, nil])>, 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:



110
111
112
113
114
115
116
117
# File 'utils/bottles.rb', line 110

def path_resolved_basename(root_url, name, checksum, filename)
  if root_url.match?(GitHubPackages::URL_REGEX)
    image_name = GitHubPackages.image_formula_name(name)
    ["#{image_name}/blobs/sha256:#{checksum}", filename&.github_packages]
  else
    filename&.url_encode
  end
end

.receipt_path(bottle_file) ⇒ 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:



58
59
60
61
62
# File 'utils/bottles.rb', line 58

def receipt_path(bottle_file)
  bottle_file_list(bottle_file).find do |line|
    %r{.+/.+/INSTALL_RECEIPT.json}.match?(line)
  end
end

.resolve_formula_names(bottle_file) ⇒ 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:

Returns:



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'utils/bottles.rb', line 70

def resolve_formula_names(bottle_file)
  name = bottle_file_list(bottle_file).first.to_s.split("/").fetch(0)
  full_name = if (receipt_file_path = receipt_path(bottle_file))
    receipt_file = file_from_bottle(bottle_file, receipt_file_path)
    tap = Tab.from_file_content(receipt_file, "#{bottle_file}/#{receipt_file_path}").tap
    "#{tap}/#{name}" if tap.present? && !tap.core_tap?
  else
    bottle_json_path = Pathname(bottle_file.sub(/\.(\d+\.)?tar\.gz$/, ".json"))
    if bottle_json_path.exist? &&
       (bottle_json_path_contents = bottle_json_path.read.presence) &&
       (bottle_json = JSON.parse(bottle_json_path_contents).presence) &&
       bottle_json.is_a?(Hash)
      bottle_json.keys.first.presence
    end
  end
  full_name ||= name

  [name, full_name]
end

.resolve_version(bottle_file) ⇒ PkgVersion

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:



91
92
93
94
# File 'utils/bottles.rb', line 91

def resolve_version(bottle_file)
  version = bottle_file_list(bottle_file).first.to_s.split("/").fetch(1)
  PkgVersion.parse(version)
end

.tag(tag = nil) ⇒ Tag

This method is part of an internal API. This method may only be used internally in repositories owned by Homebrew, except in casks or formulae. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Gets the tag for the running OS.

Parameters:

Returns:



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'utils/bottles.rb', line 16

def tag(tag = nil)
  case tag
  when Symbol
    Tag.from_symbol(tag)
  when Tag
    tag
  else
    @tag ||= T.let(Tag.new(
                     system: HOMEBREW_SYSTEM.downcase.to_sym,
                     arch:   HOMEBREW_PROCESSOR.downcase.to_sym,
                   ), T.nilable(Tag))
  end
end