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.

Constant Summary

Constants included from Kernel

Kernel::IGNORE_INTERRUPTS_MUTEX

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?, #mach_o_executable?, #ppc64?, #ppc7400?, #resolve_rpath, #resolve_variable_name, #universal?, #x86_64?

Methods included from Kernel

#disk_usage_readable, #ensure_executable!, #ensure_formula_installed!, #exec_browser, #exec_editor, #ignore_interrupts, #interactive_shell, #number_readable, #odebug, #odeprecated, #odie, #odisabled, #ofail, #oh1, #oh1_title, #ohai, #ohai_title, #onoe, #opoo, #paths, #pretty_duration, #pretty_installed, #pretty_outdated, #pretty_uninstalled, #quiet_system, #redact_secrets, #redirect_stdout, #require?, #safe_system, #tap_and_name_comparison, #truncate_text_to_approximate_size, #which, #which_all, #which_editor, #with_custom_locale, #with_env, #with_homebrew_path

Methods included from ELFShim

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

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)


172
173
174
175
176
# File 'extend/pathname.rb', line 172

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

#atomic_write(content) ⇒ void

Note:

This always overwrites.

This method returns an undefined value.

Write to a file atomically.

Parameters:



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

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)


458
459
460
# File 'extend/pathname.rb', line 458

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))


311
312
313
# File 'extend/pathname.rb', line 311

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

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



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'extend/pathname.rb', line 215

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

  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)


453
454
455
# File 'extend/pathname.rb', line 453

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)


468
469
470
# File 'extend/pathname.rb', line 468

def dylib?
  false
end

#ensure_writableObject

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.



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

def ensure_writable
  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) ⇒ 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.

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



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

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

    dst.install(file)
    new_file = dst.join(file.basename)
    file.write_env_script(new_file, env)
  end
end

#extnameString

Extended to support common double extensions.

Returns:



235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'extend/pathname.rb', line 235

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:



489
490
491
492
# File 'extend/pathname.rb', line 489

def file_type
  @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.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'extend/pathname.rb', line 89

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_infoObject

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.



363
364
365
# File 'extend/pathname.rb', line 363

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

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



433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
# File 'extend/pathname.rb', line 433

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:



146
147
148
149
150
151
152
153
154
155
156
157
# File 'extend/pathname.rb', line 146

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)


463
464
465
# File 'extend/pathname.rb', line 463

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:



478
479
480
481
482
483
484
485
486
# File 'extend/pathname.rb', line 478

def magic_number
  @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.



338
339
340
341
# File 'extend/pathname.rb', line 338

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:



324
325
326
# File 'extend/pathname.rb', line 324

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)


329
330
331
332
333
334
335
336
# File 'extend/pathname.rb', line 329

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)


262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'extend/pathname.rb', line 262

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

#rmtree(noop: nil, verbose: nil, secure: nil) ⇒ Object

Like regular rmtree, except it never ignores errors.

This was the default behaviour in Ruby 3.1 and earlier.



507
508
509
510
511
512
513
514
515
# File 'extend/pathname.rb', line 507

def rmtree(noop: nil, verbose: nil, secure: nil)
  # Ideally we'd odeprecate this but probably can't given gems so let's
  # create a RuboCop autocorrect instead soon.
  # This is why monkeypatching is non-ideal (but right solution to get
  # Ruby 3.3 over the line).
  # odeprecated "rmtree", "FileUtils#rm_r"
  FileUtils.rm_r(@path, noop:, verbose:, secure:)
  nil
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:



473
474
475
# File 'extend/pathname.rb', line 473

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:



288
289
290
291
# File 'extend/pathname.rb', line 288

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

#stemString

For filetypes we support, returns basename without extension.

Returns:



254
255
256
# File 'extend/pathname.rb', line 254

def stem
  File.basename(self, extname)
end

#subdirsArray<Pathname>

Get all sub-directories of this directory.

Returns:



319
320
321
# File 'extend/pathname.rb', line 319

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)


283
284
285
# File 'extend/pathname.rb', line 283

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

#uninstall_infoObject

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.



367
368
369
# File 'extend/pathname.rb', line 367

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:



294
295
296
297
298
299
# File 'extend/pathname.rb', line 294

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:



277
278
279
280
# File 'extend/pathname.rb', line 277

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

#which_install_infoObject

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.



354
355
356
357
358
359
360
361
# File 'extend/pathname.rb', line 354

def which_install_info
  @which_install_info ||=
    if File.executable?("/usr/bin/install-info")
      "/usr/bin/install-info"
    elsif Formula["texinfo"].any_version_installed?
      Formula["texinfo"].opt_bin/"install-info"
    end
end

#write_env_script(target, args, env = 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.

Writes an exec script that sets environment variables.



389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'extend/pathname.rb', line 389

def write_env_script(target, args, env = nil)
  unless env
    env = args
    args = nil
  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) ⇒ 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.

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



372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'extend/pathname.rb', line 372

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)


424
425
426
427
428
429
430
431
# File 'extend/pathname.rb', line 424

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:



495
496
497
498
499
500
# File 'extend/pathname.rb', line 495

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