Class: Pathname Private

Inherits:
Object show all
Includes:
DiskUsageExtension, ELFShim, MachOShim, SystemCommand::Mixin
Defined in:
extend/pathname.rb,
extend/os/mac/extend/pathname.rb,
extend/os/linux/extend/pathname.rb,
extend/os/mac/extend/pathname.rbi,
extend/os/linux/extend/pathname.rbi

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.

Instance Method Summary collapse

Methods included from DiskUsageExtension

#abv, #disk_usage, #file_count

Methods included from SystemCommand::Mixin

#system_command, #system_command!

Methods included from MachOShim

#arch, #archs, #change_dylib_id, #change_install_name, #change_rpath, #delete_rpath, #dylib_id, #dynamically_linked_libraries, #i386?, #initialize, #mach_o_executable?, #ppc64?, #ppc7400?, #resolve_rpath, #resolve_variable_name, #universal?, #x86_64?

Methods included from ELFShim

#arch, #dylib_id, #dynamic_elf?, #dynamically_linked_libraries, #elf?, #elf_type, #initialize, #interpreter, #patch!, #patchelf_patcher, #read_uint16, #read_uint8, #rpath, #save_using_patchelf_rb, #section_names

Instance Method Details

#append_lines(content, **open_args) ⇒ void

This method returns an undefined value.

Only appends to a file that is already created.

Parameters:

  • content (String)
  • open_args (T.untyped)


73
74
75
76
77
# File 'extend/pathname.rb', line 73

def append_lines(content, **open_args)
  raise "Cannot append file that doesn't exist: #{self}" unless exist?

  T.unsafe(self).open("a", **open_args) { |f| f.puts(content) }
end

#arch_compatible?(_wanted_arch) ⇒ 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)


393
394
395
# File 'extend/pathname.rb', line 393

def arch_compatible?(_wanted_arch)
  true
end

#atomic_write(content) ⇒ void

Note:

This always overwrites.

This method returns an undefined value.

Write to a file atomically.

Parameters:



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
# File 'extend/pathname.rb', line 85

def atomic_write(content)
  require "extend/file/atomic"

  old_stat = stat if exist?
  File.atomic_write(self) do |file|
    file.write(content)
  end

  return unless old_stat

  # Try to restore original file's permissions separately
  # atomic_write does it itself, but it actually erases
  # them if chown fails
  begin
    # Set correct permissions on new file
    chown(old_stat.uid, nil)
    chown(nil, old_stat.gid)
  rescue Errno::EPERM, Errno::EACCES
    # Changing file ownership failed, moving on.
    nil
  end

  begin
    # This operation will affect filesystem ACL's
    chmod(old_stat.mode)
  rescue Errno::EPERM, Errno::EACCES
    # Changing file permissions failed, moving on.
    nil
  end
end

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


378
379
380
# File 'extend/pathname.rb', line 378

def binary_executable?
  false
end

#cd(&_block) ⇒ T.type_parameter(:U)

Change to this directory, optionally executing the given block.

Parameters:

  • _block (T.proc.params(path: Pathname).returns(T.type_parameter(:U)))

Returns:

  • (T.type_parameter(:U))


218
219
220
# File 'extend/pathname.rb', line 218

def cd(&_block)
  Dir.chdir(self) { yield self }
end

#cp_path_sub(pattern, replacement, &_block) ⇒ 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:



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'extend/pathname.rb', line 120

def cp_path_sub(pattern, replacement, &_block)
  raise "#{self} does not exist" unless exist?

  pattern = pattern.to_s if pattern.is_a?(Pathname)
  replacement = replacement.to_s if replacement.is_a?(Pathname)
  dst = sub(pattern, replacement)

  raise "#{self} is the same file as #{dst}" if self == dst

  if directory?
    dst.mkpath
  else
    dst.dirname.mkpath
    dst = yield(self, dst) if block_given?
    FileUtils.cp(self, dst)
  end
end

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


373
374
375
# File 'extend/pathname.rb', line 373

def ds_store?
  basename.to_s == ".DS_Store"
end

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


388
389
390
# File 'extend/pathname.rb', line 388

def dylib?
  false
end

#ensure_writable(&_block) ⇒ 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:

  • _block (T.proc.void)


252
253
254
255
256
257
258
259
260
261
# File 'extend/pathname.rb', line 252

def ensure_writable(&_block)
  saved_perms = nil
  unless writable?
    saved_perms = stat.mode
    FileUtils.chmod "u+rw", to_path
  end
  yield
ensure
  chmod saved_perms if saved_perms
end

#env_script_all_files(dst, env) ⇒ 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.

Writes a wrapper env script and moves all files to the dst.

Parameters:



321
322
323
324
325
326
327
328
329
330
331
332
# File 'extend/pathname.rb', line 321

def env_script_all_files(dst, env)
  dst.mkpath
  Pathname.glob("#{self}/*") do |file|
    next if file.directory?

    new_file = dst.join(file.basename)
    raise Errno::EEXIST, new_file.to_s if new_file.exist?

    dst.install(file)
    file.write_env_script(new_file, env)
  end
end

#extnameString

Extended to support common double extensions.

Returns:



142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'extend/pathname.rb', line 142

def extname
  basename = File.basename(self)

  bottle_ext, = HOMEBREW_BOTTLES_EXTNAME_REGEX.match(basename).to_a
  return bottle_ext if bottle_ext

  archive_ext = basename[/(\.(tar|cpio|pax)\.(gz|bz2|lz|xz|zst|Z))\Z/, 1]
  return archive_ext if archive_ext

  # Don't treat version numbers as extname.
  return "" if basename.match?(/\b\d+\.\d+[^.]*\Z/) && !basename.end_with?(".7z")

  File.extname(basename)
end

#file_typeString

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:



415
416
417
418
419
# File 'extend/pathname.rb', line 415

def file_type
  @file_type ||= T.let(nil, T.nilable(String))
  @file_type ||= system_command("file", args: ["-b", self], print_stderr: false)
                 .stdout.chomp
end

#install(*sources) ⇒ void

This method returns an undefined value.

Moves a file from the original location to the Pathname's.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'extend/pathname.rb', line 23

def install(*sources)
  sources.each do |src|
    case src
    when Resource
      src.stage(self)
    when Resource::Partial
      src.resource.stage { install(*src.files) }
    when Array
      if src.empty?
        opoo "Tried to install empty array to #{self}"
        break
      end
      src.each { |s| install_p(s, File.basename(s)) }
    when Hash
      if src.empty?
        opoo "Tried to install empty hash to #{self}"
        break
      end
      src.each { |s, new_basename| install_p(s, new_basename) }
    else
      install_p(src, File.basename(src))
    end
  end
end

#install_infovoid

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.



264
265
266
# File 'extend/pathname.rb', line 264

def install_info
  quiet_system(which_install_info, "--quiet", to_s, "#{dirname}/dir")
end

#install_metafiles(from = Pathname.pwd) ⇒ 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:

  • from (Pathname) (defaults to: Pathname.pwd)


353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
# File 'extend/pathname.rb', line 353

def install_metafiles(from = Pathname.pwd)
  require "metafiles"

  Pathname(from).children.each do |p|
    next if p.directory?
    next if File.empty?(p)
    next unless Metafiles.copy?(p.basename.to_s)

    # Some software symlinks these files (see help2man.rb)
    filename = p.resolved_path
    # Some software links metafiles together, so by the time we iterate to one of them
    # we may have already moved it. libxml2's COPYING and Copyright are affected by this.
    next unless filename.exist?

    filename.chmod 0644
    install(filename)
  end
end

This method returns an undefined value.

Creates symlinks to sources in this folder.

Parameters:



56
57
58
59
60
61
62
63
64
65
66
67
# File 'extend/pathname.rb', line 56

def install_symlink(*sources)
  sources.each do |src|
    case src
    when Array
      src.each { |s| install_symlink_p(s, File.basename(s)) }
    when Hash
      src.each { |s, new_basename| install_symlink_p(s, new_basename) }
    else
      install_symlink_p(src, File.basename(src))
    end
  end
end

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


383
384
385
# File 'extend/pathname.rb', line 383

def mach_o_bundle?
  false
end

#magic_numberString

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:



403
404
405
406
407
408
409
410
411
412
# File 'extend/pathname.rb', line 403

def magic_number
  @magic_number ||= T.let(nil, T.nilable(String))
  @magic_number ||= if directory?
    ""
  else
    # Length of the longest regex (currently Tar).
    max_magic_number_length = 262
    binread(max_magic_number_length) || ""
  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.

This method returns an undefined value.

Parameters:



246
247
248
249
# File 'extend/pathname.rb', line 246

def make_relative_symlink(src)
  dirname.mkpath
  File.symlink(src.relative_path_from(dirname), self)
end

#resolved_pathPathname

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:



231
232
233
# File 'extend/pathname.rb', line 231

def resolved_path
  symlink? ? dirname.join(readlink) : self
end

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


236
237
238
239
240
241
242
243
# File 'extend/pathname.rb', line 236

def resolved_path_exists?
  link = readlink
rescue ArgumentError
  # The link target contains NUL bytes
  false
else
  dirname.join(link).exist?
end

#rmdir_if_possibleBoolean

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.

I don't trust the children.length == 0 check particularly, not to mention it is slow to enumerate the whole directory just to see if it is empty, instead rely on good ol' libc and the filesystem

Returns:

  • (Boolean)


169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'extend/pathname.rb', line 169

def rmdir_if_possible
  rmdir
  true
rescue Errno::ENOTEMPTY
  if (ds_store = join(".DS_Store")).exist? && children.length == 1
    ds_store.unlink
    retry
  else
    false
  end
rescue Errno::EACCES, Errno::ENOENT, Errno::EBUSY, Errno::EPERM
  false
end

#rpathsArray<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:



398
399
400
# File 'extend/pathname.rb', line 398

def rpaths
  []
end

#sha256String

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:



195
196
197
198
# File 'extend/pathname.rb', line 195

def sha256
  require "digest/sha2"
  Digest::SHA256.file(self).hexdigest
end

#stemString

For filetypes we support, returns basename without extension.

Returns:



161
162
163
# File 'extend/pathname.rb', line 161

def stem
  File.basename(self, extname)
end

#subdirsArray<Pathname>

Get all sub-directories of this directory.

Returns:



226
227
228
# File 'extend/pathname.rb', line 226

def subdirs
  children.select(&:directory?)
end

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


190
191
192
# File 'extend/pathname.rb', line 190

def text_executable?
  /\A#!\s*\S+/.match?(open("r") { |f| f.read(1024) })
end

#uninstall_infovoid

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.



269
270
271
# File 'extend/pathname.rb', line 269

def uninstall_info
  quiet_system(which_install_info, "--delete", "--quiet", to_s, "#{dirname}/dir")
end

#verify_checksum(expected) ⇒ 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:

Raises:



201
202
203
204
205
206
# File 'extend/pathname.rb', line 201

def verify_checksum(expected)
  raise ChecksumMissingError if expected.blank?

  actual = Checksum.new(sha256.downcase)
  raise ChecksumMismatchError.new(self, expected, actual) if expected != actual
end

#versionVersion

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:



184
185
186
187
# File 'extend/pathname.rb', line 184

def version
  require "version"
  Version.parse(basename)
end

#write_env_script(target, args_or_env, env = T.unsafe(nil)) ⇒ 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.

Writes an exec script that sets environment variables.

Parameters:



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'extend/pathname.rb', line 297

def write_env_script(target, args_or_env, env = T.unsafe(nil))
  args = if env.nil?
    env = args_or_env if args_or_env.is_a?(Hash)

    nil
  elsif args_or_env.is_a?(Array)
    args_or_env.join(" ")
  else
    T.cast(args_or_env, T.nilable(String))
  end

  env_export = +""
  env.each { |key, value| env_export << "#{key}=\"#{value}\" " }

  dirname.mkpath

  write <<~SH
    #!/bin/bash
    #{env_export}exec "#{target}" #{args} "$@"
  SH
end

#write_exec_script(*targets) ⇒ 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.

Writes an exec script in this folder for each target pathname.

Parameters:



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'extend/pathname.rb', line 275

def write_exec_script(*targets)
  targets.flatten!
  if targets.empty?
    opoo "Tried to write exec scripts to #{self} for an empty list of targets"
    return
  end
  mkpath
  targets.each do |target|
    target = Pathname.new(target) # allow pathnames or strings
    join(target.basename).write <<~SH
      #!/bin/bash
      exec "#{target}" "$@"
    SH
  end
end

#write_jar_script(target_jar, script_name, java_opts = "", java_version: nil) ⇒ Integer

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.

Writes an exec script that invokes a Java jar.

Parameters:

Returns:

  • (Integer)


343
344
345
346
347
348
349
350
# File 'extend/pathname.rb', line 343

def write_jar_script(target_jar, script_name, java_opts = "", java_version: nil)
  mkpath
  (self/script_name).write <<~EOS
    #!/bin/bash
    export JAVA_HOME="#{Language::Java.overridable_java_home_env(java_version)[:JAVA_HOME]}"
    exec "${JAVA_HOME}/bin/java" #{java_opts} -jar "#{target_jar}" "$@"
  EOS
end

#zipinfoArray<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:



422
423
424
425
426
427
428
# File 'extend/pathname.rb', line 422

def zipinfo
  @zipinfo ||= T.let(nil, T.nilable(String))
  @zipinfo ||= system_command("zipinfo", args: ["-1", self], print_stderr: false)
               .stdout
               .encode(Encoding::UTF_8, invalid: :replace)
               .split("\n")
end