Module: Utils::Path Private

Included in:
Cask::DSL, Cask::DSL::Base, Formula, Homebrew::Service
Defined in:
utils/path.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.

Helpers for Homebrew path handling and package path validation.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.child_of?(parent, child) ⇒ 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)


10
11
12
13
14
15
# File 'utils/path.rb', line 10

def self.child_of?(parent, child)
  parent_pathname = Pathname(parent).expand_path
  child_pathname = Pathname(child).expand_path
  child_pathname.ascend { |p| return true if p == parent_pathname }
  false
end

.ensure_child_of!(parent, child, message:) ⇒ 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:



18
19
20
21
22
# File 'utils/path.rb', line 18

def self.ensure_child_of!(parent, child, message:)
  return if child_of?(parent, child)

  raise message
end

.formula_any_version_installed?(formula_names) ⇒ Boolean

Whether any installed keg for one or more formula names has an install receipt.

Parameters:

Returns:

  • (Boolean)


120
121
122
# File 'utils/path.rb', line 120

def self.formula_any_version_installed?(formula_names)
  formula_installed_prefixes(formula_names).any? { |keg| (keg/"INSTALL_RECEIPT.json").file? }
end

.formula_installed_prefixes(formula_names) ⇒ Array<Pathname>

The installed prefix directories for one or more formula names.

Parameters:

Returns:



108
109
110
111
112
113
114
# File 'utils/path.rb', line 108

def self.formula_installed_prefixes(formula_names)
  Array(formula_names).map { |formula_name| HOMEBREW_CELLAR/Utils.name_from_full_name(formula_name) }
                      .select(&:directory?)
                      .uniq(&:realpath)
                      .flat_map(&:subdirs)
                      .sort_by(&:basename)
end

.formula_opt_bin(formula_name) ⇒ Pathname

The bin directory under the stable install path for a given formula name.

Parameters:

Returns:



44
45
46
# File 'utils/path.rb', line 44

def self.formula_opt_bin(formula_name)
  formula_opt_prefix(formula_name)/"bin"
end

.formula_opt_bin_env(formula_name, *paths) ⇒ Hash{String => String}

An environment hash with PATH prepended by a formula's stable bin directory.

Parameters:

Returns:



144
145
146
# File 'utils/path.rb', line 144

def self.formula_opt_bin_env(formula_name, *paths)
  { "PATH" => formula_opt_bin_path(formula_name, *paths).to_s }
end

.formula_opt_bin_path(formula_name, *paths) ⇒ PATH

The current PATH with a formula's stable bin directory prepended.

Parameters:

Returns:



136
137
138
# File 'utils/path.rb', line 136

def self.formula_opt_bin_path(formula_name, *paths)
  PATH.new(formula_opt_bin(formula_name), *paths, ENV.fetch("PATH"))
end

.formula_opt_include(formula_name) ⇒ Pathname

The include directory under the stable install path for a given formula name.

Parameters:

Returns:



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

def self.formula_opt_include(formula_name)
  formula_opt_prefix(formula_name)/"include"
end

.formula_opt_lib(formula_name) ⇒ Pathname

The lib directory under the stable install path for a given formula name.

Parameters:

Returns:



60
61
62
# File 'utils/path.rb', line 60

def self.formula_opt_lib(formula_name)
  formula_opt_prefix(formula_name)/"lib"
end

.formula_opt_libexec(formula_name) ⇒ Pathname

The libexec directory under the stable install path for a given formula name.

Parameters:

Returns:



76
77
78
# File 'utils/path.rb', line 76

def self.formula_opt_libexec(formula_name)
  formula_opt_prefix(formula_name)/"libexec"
end

.formula_opt_prefix(formula_name) ⇒ Pathname

The stable install path for a given formula name.

Parameters:

Returns:



28
29
30
# File 'utils/path.rb', line 28

def self.formula_opt_prefix(formula_name)
  HOMEBREW_PREFIX/"opt/#{Utils.name_from_full_name(formula_name)}"
end

.loadable_package_path?(path, package_type) ⇒ 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)


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
# File 'utils/path.rb', line 149

def self.loadable_package_path?(path, package_type)
  return true unless Homebrew::EnvConfig.forbid_packages_from_paths?

  path_realpath = path.realpath.to_s
  path_string = path.to_s

  allowed_paths = [trusted_package_root("#{HOMEBREW_LIBRARY}/Taps/")]
  allowed_paths << if package_type == :formula
    trusted_package_root(HOMEBREW_CELLAR)
  else
    trusted_package_root(Cask::Caskroom.path)
  end

  # Casks can also be loaded from local JSON files, not just Ruby.
  package_extnames = (package_type == :cask) ? %w[.rb .json] : %w[.rb]
  return true if package_extnames.none? { |ext| path_realpath.end_with?(ext) || path_string.end_with?(ext) }

  # Compare path ancestry, not string prefixes, so `..` can't escape a trusted root.
  return true if allowed_paths.any? { |root| child_of?(root, path_realpath) }
  return true if allowed_paths.any? { |root| child_of?(root, path) }

  # Looks like a local path, Ruby file and not a tap.
  if path_string.include?("./") || path_string.end_with?(".rb") || path_string.count("/") != 2
    package_type_plural = Utils.pluralize(package_type.to_s, 2)
    path_realpath_if_different = " (#{path_realpath})" if path_realpath != path_string
    create_flag = " --cask" if package_type == :cask

    raise <<~WARNING
      Homebrew requires #{package_type_plural} to be in a tap, rejecting:
        #{path_string}#{path_realpath_if_different}

      To create a tap, run e.g.
        brew tap-new <user|org>/<repository>
      To create a #{package_type} in a tap run e.g.
        brew create#{create_flag} <url> --tap=<user|org>/<repository>
    WARNING
  else
    # Looks like a tap, let's quietly reject but not error.
    path_string.count("/") != 2
  end
end

Instance Method Details

#formula_any_version_installed?(formula_names) ⇒ Boolean

Whether any installed keg for one or more formula names has an install receipt.

Parameters:

Returns:

  • (Boolean)


128
129
130
# File 'utils/path.rb', line 128

def formula_any_version_installed?(formula_names)
  Utils::Path.formula_any_version_installed?(formula_names)
end

#formula_opt_bin(formula_name) ⇒ Pathname

The bin directory under the stable install path for a given formula name.

Parameters:

Returns:



52
53
54
# File 'utils/path.rb', line 52

def formula_opt_bin(formula_name)
  Utils::Path.formula_opt_bin(formula_name)
end

#formula_opt_include(formula_name) ⇒ Pathname

The include directory under the stable install path for a given formula name.

Parameters:

Returns:



100
101
102
# File 'utils/path.rb', line 100

def formula_opt_include(formula_name)
  Utils::Path.formula_opt_include(formula_name)
end

#formula_opt_lib(formula_name) ⇒ Pathname

The lib directory under the stable install path for a given formula name.

Parameters:

Returns:



68
69
70
# File 'utils/path.rb', line 68

def formula_opt_lib(formula_name)
  Utils::Path.formula_opt_lib(formula_name)
end

#formula_opt_libexec(formula_name) ⇒ Pathname

The libexec directory under the stable install path for a given formula name.

Parameters:

Returns:



84
85
86
# File 'utils/path.rb', line 84

def formula_opt_libexec(formula_name)
  Utils::Path.formula_opt_libexec(formula_name)
end

#formula_opt_prefix(formula_name) ⇒ Pathname

The stable install path for a given formula name.

Parameters:

Returns:



36
37
38
# File 'utils/path.rb', line 36

def formula_opt_prefix(formula_name)
  Utils::Path.formula_opt_prefix(formula_name)
end