2024-08-12 10:30:59 +01:00
|
|
|
# typed: true # rubocop:todo Sorbet/StrictSigil
|
2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2024-07-14 08:49:39 -04:00
|
|
|
require "system_command"
|
2025-06-09 19:06:16 +01:00
|
|
|
require "extend/pathname/disk_usage_extension"
|
|
|
|
require "extend/pathname/observer_pathname_extension"
|
2024-07-14 08:49:39 -04:00
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# Homebrew extends Ruby's `Pathname` to make our code more readable.
|
2020-11-03 12:39:26 -05:00
|
|
|
# @see https://ruby-doc.org/stdlib-2.6.3/libdoc/pathname/rdoc/Pathname.html Ruby's Pathname API
|
2009-07-31 02:51:17 +01:00
|
|
|
class Pathname
|
2024-01-26 17:33:55 -08:00
|
|
|
include SystemCommand::Mixin
|
2015-11-17 16:49:55 +05:30
|
|
|
include DiskUsageExtension
|
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# Moves a file from the original location to the {Pathname}'s.
|
2024-03-06 01:00:39 +01:00
|
|
|
#
|
|
|
|
# @api public
|
2021-01-17 22:45:55 -08:00
|
|
|
sig {
|
2020-11-24 11:27:12 +01:00
|
|
|
params(sources: T.any(
|
|
|
|
Resource, Resource::Partial, String, Pathname,
|
|
|
|
T::Array[T.any(String, Pathname)], T::Hash[T.any(String, Pathname), String]
|
|
|
|
)).void
|
2021-01-17 22:45:55 -08:00
|
|
|
}
|
2015-08-03 13:09:07 +01:00
|
|
|
def install(*sources)
|
2012-02-09 18:43:47 -08:00
|
|
|
sources.each do |src|
|
|
|
|
case src
|
2013-08-06 19:52:58 -07:00
|
|
|
when Resource
|
|
|
|
src.stage(self)
|
2013-09-17 21:25:43 -05:00
|
|
|
when Resource::Partial
|
|
|
|
src.resource.stage { install(*src.files) }
|
2012-02-09 18:43:47 -08:00
|
|
|
when Array
|
2012-03-30 22:34:42 -07:00
|
|
|
if src.empty?
|
2020-07-29 17:31:11 -04:00
|
|
|
opoo "Tried to install empty array to #{self}"
|
2016-09-21 09:58:26 +02:00
|
|
|
break
|
2012-03-30 22:34:42 -07:00
|
|
|
end
|
2015-03-23 21:03:55 -04:00
|
|
|
src.each { |s| install_p(s, File.basename(s)) }
|
2012-02-09 18:43:47 -08:00
|
|
|
when Hash
|
2012-03-30 22:34:42 -07:00
|
|
|
if src.empty?
|
2020-07-29 17:31:11 -04:00
|
|
|
opoo "Tried to install empty hash to #{self}"
|
2016-09-21 09:58:26 +02:00
|
|
|
break
|
2012-03-30 22:34:42 -07:00
|
|
|
end
|
2015-03-23 21:03:55 -04:00
|
|
|
src.each { |s, new_basename| install_p(s, new_basename) }
|
2012-02-09 18:43:47 -08:00
|
|
|
else
|
2015-03-23 21:03:55 -04:00
|
|
|
install_p(src, File.basename(src))
|
2012-02-09 18:43:47 -08:00
|
|
|
end
|
2009-07-31 02:51:17 +01:00
|
|
|
end
|
|
|
|
end
|
2010-02-19 13:13:42 +00:00
|
|
|
|
2020-11-24 11:27:12 +01:00
|
|
|
sig { params(src: T.any(String, Pathname), new_basename: String).void }
|
2015-03-23 21:03:55 -04:00
|
|
|
def install_p(src, new_basename)
|
2015-03-26 22:22:45 -04:00
|
|
|
src = Pathname(src)
|
2021-01-07 13:49:05 -08:00
|
|
|
raise Errno::ENOENT, src.to_s if !src.symlink? && !src.exist?
|
|
|
|
|
2015-03-26 22:22:45 -04:00
|
|
|
dst = join(new_basename)
|
2013-10-06 22:04:46 +01:00
|
|
|
dst = yield(src, dst) if block_given?
|
2016-03-07 15:11:00 +00:00
|
|
|
return unless dst
|
2013-10-06 22:04:46 +01:00
|
|
|
|
2010-02-19 13:13:42 +00:00
|
|
|
mkpath
|
2014-07-10 15:39:55 -05:00
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Use `FileUtils.mv` over `File.rename` to handle filesystem boundaries. If `src`
|
|
|
|
# is a symlink and its target is moved first, `FileUtils.mv` will fail
|
|
|
|
# (https://bugs.ruby-lang.org/issues/7707).
|
|
|
|
#
|
|
|
|
# In that case, use the system `mv` command.
|
2015-03-26 22:22:45 -04:00
|
|
|
if src.symlink?
|
2023-11-05 08:55:58 -08:00
|
|
|
raise unless Kernel.system "mv", src.to_s, dst
|
2010-02-19 13:13:42 +00:00
|
|
|
else
|
|
|
|
FileUtils.mv src, dst
|
|
|
|
end
|
|
|
|
end
|
2015-03-24 21:08:12 -04:00
|
|
|
private :install_p
|
2010-02-19 13:13:42 +00:00
|
|
|
|
2012-02-12 10:36:16 -08:00
|
|
|
# Creates symlinks to sources in this folder.
|
2024-03-06 01:00:39 +01:00
|
|
|
#
|
|
|
|
# @api public
|
2021-01-17 22:45:55 -08:00
|
|
|
sig {
|
2020-11-24 11:27:12 +01:00
|
|
|
params(
|
|
|
|
sources: T.any(String, Pathname, T::Array[T.any(String, Pathname)], T::Hash[T.any(String, Pathname), String]),
|
|
|
|
).void
|
2021-01-17 22:45:55 -08:00
|
|
|
}
|
2015-08-03 13:09:07 +01:00
|
|
|
def install_symlink(*sources)
|
2012-02-12 10:36:16 -08:00
|
|
|
sources.each do |src|
|
|
|
|
case src
|
|
|
|
when Array
|
2015-03-24 21:05:34 -04:00
|
|
|
src.each { |s| install_symlink_p(s, File.basename(s)) }
|
2012-02-12 10:36:16 -08:00
|
|
|
when Hash
|
2015-03-24 21:05:34 -04:00
|
|
|
src.each { |s, new_basename| install_symlink_p(s, new_basename) }
|
2012-02-12 10:36:16 -08:00
|
|
|
else
|
2015-03-24 21:05:34 -04:00
|
|
|
install_symlink_p(src, File.basename(src))
|
2012-02-12 10:36:16 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-03-24 21:05:34 -04:00
|
|
|
def install_symlink_p(src, new_basename)
|
2012-02-12 10:36:16 -08:00
|
|
|
mkpath
|
2019-02-22 13:18:47 -08:00
|
|
|
dstdir = realpath
|
|
|
|
src = Pathname(src).expand_path(dstdir)
|
|
|
|
src = src.dirname.realpath/src.basename if src.dirname.exist?
|
|
|
|
FileUtils.ln_sf(src.relative_path_from(dstdir), dstdir/new_basename)
|
2012-02-12 10:36:16 -08:00
|
|
|
end
|
2015-03-24 21:08:12 -04:00
|
|
|
private :install_symlink_p
|
2012-02-12 10:36:16 -08:00
|
|
|
|
2016-02-16 16:34:51 +00:00
|
|
|
# Only appends to a file that is already created.
|
2024-03-06 01:00:39 +01:00
|
|
|
#
|
|
|
|
# @api public
|
2020-11-24 11:27:12 +01:00
|
|
|
sig { params(content: String, open_args: T.untyped).void }
|
|
|
|
def append_lines(content, **open_args)
|
2016-02-16 16:34:51 +00:00
|
|
|
raise "Cannot append file that doesn't exist: #{self}" unless exist?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2020-11-24 11:27:12 +01:00
|
|
|
T.unsafe(self).open("a", **open_args) { |f| f.puts(content) }
|
2016-02-16 16:34:51 +00:00
|
|
|
end
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Write to a file atomically.
|
|
|
|
#
|
|
|
|
# NOTE: This always overwrites.
|
2024-03-06 01:00:39 +01:00
|
|
|
#
|
|
|
|
# @api public
|
2020-11-24 11:27:12 +01:00
|
|
|
sig { params(content: String).void }
|
2015-08-03 13:09:07 +01:00
|
|
|
def atomic_write(content)
|
2024-07-14 08:49:39 -04:00
|
|
|
require "extend/file/atomic"
|
|
|
|
|
2019-04-13 17:18:14 +00:00
|
|
|
old_stat = stat if exist?
|
2018-11-22 23:37:57 +01:00
|
|
|
File.atomic_write(self) do |file|
|
|
|
|
file.write(content)
|
2014-11-09 18:17:10 -06:00
|
|
|
end
|
2019-04-12 18:46:57 +00:00
|
|
|
|
|
|
|
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)
|
2019-04-13 17:18:14 +00:00
|
|
|
rescue Errno::EPERM, Errno::EACCES
|
2019-04-12 18:46:57 +00:00
|
|
|
# Changing file ownership failed, moving on.
|
2019-04-13 17:18:14 +00:00
|
|
|
nil
|
2019-04-12 18:46:57 +00:00
|
|
|
end
|
2024-04-26 20:55:51 +02:00
|
|
|
|
2019-04-12 18:46:57 +00:00
|
|
|
begin
|
|
|
|
# This operation will affect filesystem ACL's
|
|
|
|
chmod(old_stat.mode)
|
2019-04-13 17:18:14 +00:00
|
|
|
rescue Errno::EPERM, Errno::EACCES
|
2019-04-12 18:46:57 +00:00
|
|
|
# Changing file permissions failed, moving on.
|
2019-04-13 17:18:14 +00:00
|
|
|
nil
|
2019-04-12 18:46:57 +00:00
|
|
|
end
|
2014-03-22 10:20:39 -05:00
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def cp_path_sub(pattern, replacement)
|
2016-09-11 17:53:00 +01:00
|
|
|
raise "#{self} does not exist" unless exist?
|
2013-10-05 20:29:02 +01:00
|
|
|
|
2015-03-26 22:22:45 -04:00
|
|
|
dst = sub(pattern, replacement)
|
2013-10-05 20:29:02 +01:00
|
|
|
|
2015-03-26 22:22:45 -04:00
|
|
|
raise "#{self} is the same file as #{dst}" if self == dst
|
2013-10-05 20:29:02 +01:00
|
|
|
|
2015-03-26 22:22:45 -04:00
|
|
|
if directory?
|
|
|
|
dst.mkpath
|
|
|
|
else
|
|
|
|
dst.dirname.mkpath
|
|
|
|
dst = yield(self, dst) if block_given?
|
2024-06-17 21:17:10 -07:00
|
|
|
FileUtils.cp(self, dst)
|
2013-10-05 20:29:02 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-11-05 17:17:03 -05:00
|
|
|
# Extended to support common double extensions.
|
2024-03-06 01:00:39 +01:00
|
|
|
#
|
|
|
|
# @api public
|
2020-11-24 11:27:12 +01:00
|
|
|
sig { returns(String) }
|
|
|
|
def extname
|
|
|
|
basename = File.basename(self)
|
2018-08-10 00:54:03 +02:00
|
|
|
|
2021-03-30 17:35:13 +01:00
|
|
|
bottle_ext, = HOMEBREW_BOTTLES_EXTNAME_REGEX.match(basename).to_a
|
2016-08-23 02:36:21 +02:00
|
|
|
return bottle_ext if bottle_ext
|
2018-08-10 00:54:03 +02:00
|
|
|
|
2021-09-16 15:56:31 +01:00
|
|
|
archive_ext = basename[/(\.(tar|cpio|pax)\.(gz|bz2|lz|xz|zst|Z))\Z/, 1]
|
2016-08-23 02:36:21 +02:00
|
|
|
return archive_ext if archive_ext
|
2018-08-10 00:54:03 +02:00
|
|
|
|
|
|
|
# Don't treat version numbers as extname.
|
2020-06-02 09:49:23 +01:00
|
|
|
return "" if basename.match?(/\b\d+\.\d+[^.]*\Z/) && !basename.end_with?(".7z")
|
2018-08-10 00:54:03 +02:00
|
|
|
|
|
|
|
File.extname(basename)
|
2009-07-31 02:51:17 +01:00
|
|
|
end
|
|
|
|
|
2020-11-05 17:17:03 -05:00
|
|
|
# For filetypes we support, returns basename without extension.
|
2024-03-06 01:00:39 +01:00
|
|
|
#
|
|
|
|
# @api public
|
2020-11-24 11:27:12 +01:00
|
|
|
sig { returns(String) }
|
2009-07-31 02:51:17 +01:00
|
|
|
def stem
|
2020-11-24 11:27:12 +01:00
|
|
|
File.basename(self, extname)
|
2009-07-31 02:51:17 +01:00
|
|
|
end
|
|
|
|
|
2009-08-10 16:48:30 +01:00
|
|
|
# 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
|
2020-11-24 11:27:12 +01:00
|
|
|
sig { returns(T::Boolean) }
|
2009-08-10 16:48:30 +01:00
|
|
|
def rmdir_if_possible
|
|
|
|
rmdir
|
2009-09-02 14:31:28 +01:00
|
|
|
true
|
2013-04-27 15:21:05 -05:00
|
|
|
rescue Errno::ENOTEMPTY
|
2017-06-01 16:06:51 +02:00
|
|
|
if (ds_store = join(".DS_Store")).exist? && children.length == 1
|
2013-04-27 15:21:05 -05:00
|
|
|
ds_store.unlink
|
2012-11-11 11:39:09 -08:00
|
|
|
retry
|
2013-04-27 15:21:05 -05:00
|
|
|
else
|
|
|
|
false
|
2012-11-11 11:39:09 -08:00
|
|
|
end
|
2021-07-28 15:40:23 +01:00
|
|
|
rescue Errno::EACCES, Errno::ENOENT, Errno::EBUSY, Errno::EPERM
|
2009-09-02 14:31:28 +01:00
|
|
|
false
|
2009-08-10 16:48:30 +01:00
|
|
|
end
|
2012-01-22 22:12:39 +01:00
|
|
|
|
2020-11-24 11:27:12 +01:00
|
|
|
sig { returns(Version) }
|
2009-07-31 02:51:17 +01:00
|
|
|
def version
|
2015-08-03 13:09:07 +01:00
|
|
|
require "version"
|
2016-03-31 17:08:00 +08:00
|
|
|
Version.parse(basename)
|
2009-07-31 02:51:17 +01:00
|
|
|
end
|
2012-01-22 22:12:39 +01:00
|
|
|
|
2020-11-24 11:27:12 +01:00
|
|
|
sig { returns(T::Boolean) }
|
2012-05-25 23:44:11 -05:00
|
|
|
def text_executable?
|
2023-06-25 17:33:49 +01:00
|
|
|
/\A#!\s*\S+/.match?(open("r") { |f| f.read(1024) })
|
2012-05-25 23:44:11 -05:00
|
|
|
end
|
|
|
|
|
2020-11-24 11:27:12 +01:00
|
|
|
sig { returns(String) }
|
2013-10-14 22:05:30 -05:00
|
|
|
def sha256
|
2015-08-03 13:09:07 +01:00
|
|
|
require "digest/sha2"
|
2018-07-06 22:54:54 +02:00
|
|
|
Digest::SHA256.file(self).hexdigest
|
2009-12-30 18:56:46 +00:00
|
|
|
end
|
2012-06-18 19:58:35 -05:00
|
|
|
|
2020-11-24 11:27:12 +01:00
|
|
|
sig { params(expected: T.nilable(Checksum)).void }
|
2015-08-03 13:09:07 +01:00
|
|
|
def verify_checksum(expected)
|
2020-12-01 17:04:59 +00:00
|
|
|
raise ChecksumMissingError if expected.blank?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2021-01-07 08:33:57 +01:00
|
|
|
actual = Checksum.new(sha256.downcase)
|
2023-04-18 15:06:50 -07:00
|
|
|
raise ChecksumMismatchError.new(self, expected, actual) if expected != actual
|
2012-06-18 19:58:35 -05:00
|
|
|
end
|
2009-12-30 18:56:46 +00:00
|
|
|
|
2018-07-09 15:29:40 +01:00
|
|
|
alias to_str to_s
|
2010-02-27 12:29:45 +00:00
|
|
|
|
2024-03-06 01:00:39 +01:00
|
|
|
# Change to this directory, optionally executing the given block.
|
|
|
|
#
|
|
|
|
# @api public
|
2021-01-17 22:45:55 -08:00
|
|
|
sig {
|
2020-11-24 11:27:12 +01:00
|
|
|
type_parameters(:U).params(
|
|
|
|
_block: T.proc.params(path: Pathname).returns(T.type_parameter(:U)),
|
|
|
|
).returns(T.type_parameter(:U))
|
2021-01-17 22:45:55 -08:00
|
|
|
}
|
2020-11-24 11:27:12 +01:00
|
|
|
def cd(&_block)
|
2017-02-22 07:19:16 +01:00
|
|
|
Dir.chdir(self) { yield self }
|
2010-02-27 12:29:45 +00:00
|
|
|
end
|
|
|
|
|
2024-03-06 01:00:39 +01:00
|
|
|
# Get all sub-directories of this directory.
|
|
|
|
#
|
|
|
|
# @api public
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(T::Array[Pathname]) }
|
2010-02-27 12:29:45 +00:00
|
|
|
def subdirs
|
2015-08-03 13:09:07 +01:00
|
|
|
children.select(&:directory?)
|
2010-02-27 12:29:45 +00:00
|
|
|
end
|
2010-06-14 11:56:27 -07:00
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(Pathname) }
|
2010-07-25 12:07:35 -07:00
|
|
|
def resolved_path
|
2017-06-01 16:06:51 +02:00
|
|
|
symlink? ? dirname.join(readlink) : self
|
2010-07-25 12:07:35 -07:00
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(T::Boolean) }
|
2010-06-14 11:56:27 -07:00
|
|
|
def resolved_path_exists?
|
2013-07-13 16:38:30 -05:00
|
|
|
link = readlink
|
|
|
|
rescue ArgumentError
|
|
|
|
# The link target contains NUL bytes
|
|
|
|
false
|
|
|
|
else
|
2017-06-01 16:06:51 +02:00
|
|
|
dirname.join(link).exist?
|
2010-06-14 11:56:27 -07:00
|
|
|
end
|
2010-08-08 09:13:27 -07:00
|
|
|
|
2014-04-21 09:40:23 -05:00
|
|
|
def make_relative_symlink(src)
|
2014-03-27 18:39:54 -05:00
|
|
|
dirname.mkpath
|
2014-04-21 09:40:23 -05:00
|
|
|
File.symlink(src.relative_path_from(dirname), self)
|
2010-08-15 17:17:26 -07:00
|
|
|
end
|
2010-09-12 21:52:30 +01:00
|
|
|
|
2010-05-10 01:10:49 +01:00
|
|
|
def ensure_writable
|
2011-06-16 17:38:52 +01:00
|
|
|
saved_perms = nil
|
2024-03-27 06:26:32 +00:00
|
|
|
unless writable?
|
2011-06-16 17:38:52 +01:00
|
|
|
saved_perms = stat.mode
|
2017-11-07 14:18:25 -06:00
|
|
|
FileUtils.chmod "u+rw", to_path
|
2010-05-10 01:10:49 +01:00
|
|
|
end
|
|
|
|
yield
|
|
|
|
ensure
|
|
|
|
chmod saved_perms if saved_perms
|
|
|
|
end
|
2012-01-21 00:51:20 +01:00
|
|
|
|
2023-03-14 13:41:46 -04:00
|
|
|
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
|
|
|
|
|
2012-01-21 00:51:20 +01:00
|
|
|
def install_info
|
2023-03-14 13:41:46 -04:00
|
|
|
quiet_system(which_install_info, "--quiet", to_s, "#{dirname}/dir")
|
2012-01-21 00:51:20 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def uninstall_info
|
2023-03-14 13:41:46 -04:00
|
|
|
quiet_system(which_install_info, "--delete", "--quiet", to_s, "#{dirname}/dir")
|
2012-01-21 00:51:20 +01:00
|
|
|
end
|
2012-03-02 20:28:54 +00:00
|
|
|
|
2020-11-05 17:17:03 -05:00
|
|
|
# Writes an exec script in this folder for each target pathname.
|
2015-08-03 13:09:07 +01:00
|
|
|
def write_exec_script(*targets)
|
2013-06-20 16:18:01 -05:00
|
|
|
targets.flatten!
|
2012-08-07 11:16:45 -07:00
|
|
|
if targets.empty?
|
2020-07-29 17:31:11 -04:00
|
|
|
opoo "Tried to write exec scripts to #{self} for an empty list of targets"
|
2013-12-12 08:21:22 -08:00
|
|
|
return
|
2012-08-07 11:16:45 -07:00
|
|
|
end
|
2014-06-17 21:41:22 -05:00
|
|
|
mkpath
|
2012-08-07 11:16:45 -07:00
|
|
|
targets.each do |target|
|
|
|
|
target = Pathname.new(target) # allow pathnames or strings
|
2018-07-18 09:45:05 +00:00
|
|
|
join(target.basename).write <<~SH
|
2013-12-12 08:21:22 -08:00
|
|
|
#!/bin/bash
|
2021-06-17 20:29:43 -07:00
|
|
|
exec "#{target}" "$@"
|
2018-07-11 15:17:40 +02:00
|
|
|
SH
|
2012-08-07 11:16:45 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-11-05 17:17:03 -05:00
|
|
|
# Writes an exec script that sets environment variables.
|
2020-06-19 11:54:04 +01:00
|
|
|
def write_env_script(target, args, env = nil)
|
|
|
|
unless env
|
|
|
|
env = args
|
|
|
|
args = nil
|
|
|
|
end
|
2019-04-18 17:33:02 +09:00
|
|
|
env_export = +""
|
|
|
|
env.each { |key, value| env_export << "#{key}=\"#{value}\" " }
|
2014-06-17 21:44:13 -05:00
|
|
|
dirname.mkpath
|
2018-07-11 15:17:40 +02:00
|
|
|
write <<~SH
|
2017-10-15 02:28:32 +02:00
|
|
|
#!/bin/bash
|
2021-06-17 20:29:43 -07:00
|
|
|
#{env_export}exec "#{target}" #{args} "$@"
|
2018-07-11 15:17:40 +02:00
|
|
|
SH
|
2014-01-04 12:49:38 +00:00
|
|
|
end
|
|
|
|
|
2020-11-05 17:17:03 -05:00
|
|
|
# Writes a wrapper env script and moves all files to the dst.
|
2015-08-03 13:09:07 +01:00
|
|
|
def env_script_all_files(dst, env)
|
2014-01-04 12:49:38 +00:00
|
|
|
dst.mkpath
|
2014-05-31 23:53:46 -05:00
|
|
|
Pathname.glob("#{self}/*") do |file|
|
2015-02-25 18:10:03 +08:00
|
|
|
next if file.directory?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2015-03-23 21:01:50 -04:00
|
|
|
dst.install(file)
|
2017-06-01 16:06:51 +02:00
|
|
|
new_file = dst.join(file.basename)
|
2014-01-04 12:49:38 +00:00
|
|
|
file.write_env_script(new_file, env)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-11-05 17:17:03 -05:00
|
|
|
# Writes an exec script that invokes a Java jar.
|
2021-01-17 22:45:55 -08:00
|
|
|
sig {
|
2020-11-24 11:27:12 +01:00
|
|
|
params(
|
|
|
|
target_jar: T.any(String, Pathname),
|
|
|
|
script_name: T.any(String, Pathname),
|
|
|
|
java_opts: String,
|
|
|
|
java_version: T.nilable(String),
|
|
|
|
).returns(Integer)
|
2021-01-17 22:45:55 -08:00
|
|
|
}
|
2025-05-26 17:19:48 +01:00
|
|
|
def write_jar_script(target_jar, script_name, java_opts = "", java_version: nil)
|
2021-05-03 13:24:32 +01:00
|
|
|
mkpath
|
2025-05-26 17:19:48 +01:00
|
|
|
(self/script_name).write <<~EOS
|
2020-07-31 20:25:13 -04:00
|
|
|
#!/bin/bash
|
2025-05-26 17:19:48 +01:00
|
|
|
export JAVA_HOME="#{Language::Java.overridable_java_home_env(java_version)[:JAVA_HOME]}"
|
|
|
|
exec "${JAVA_HOME}/bin/java" #{java_opts} -jar "#{target_jar}" "$@"
|
|
|
|
EOS
|
2012-08-07 11:16:45 -07:00
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def install_metafiles(from = Pathname.pwd)
|
2024-07-14 08:49:39 -04:00
|
|
|
require "metafiles"
|
|
|
|
|
2014-06-07 17:52:11 -05:00
|
|
|
Pathname(from).children.each do |p|
|
2012-11-11 10:45:58 -08:00
|
|
|
next if p.directory?
|
2023-03-07 08:54:02 +00:00
|
|
|
next if File.empty?(p)
|
2014-06-07 23:40:26 -05:00
|
|
|
next unless Metafiles.copy?(p.basename.to_s)
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2012-11-11 10:45:58 -08:00
|
|
|
# Some software symlinks these files (see help2man.rb)
|
|
|
|
filename = p.resolved_path
|
2012-11-12 20:56:05 -08:00
|
|
|
# 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?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2012-11-11 10:45:58 -08:00
|
|
|
filename.chmod 0644
|
2014-06-07 17:52:11 -05:00
|
|
|
install(filename)
|
2012-11-11 10:45:58 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(T::Boolean) }
|
2017-02-24 17:44:18 +09:00
|
|
|
def ds_store?
|
|
|
|
basename.to_s == ".DS_Store"
|
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(T::Boolean) }
|
2018-04-25 12:08:33 +01:00
|
|
|
def binary_executable?
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(T::Boolean) }
|
2017-12-01 16:43:00 -08:00
|
|
|
def mach_o_bundle?
|
|
|
|
false
|
|
|
|
end
|
2018-04-25 12:08:33 +01:00
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(T::Boolean) }
|
2018-04-25 12:08:33 +01:00
|
|
|
def dylib?
|
|
|
|
false
|
|
|
|
end
|
2021-12-17 08:14:44 -08:00
|
|
|
|
2024-09-29 05:15:36 +08:00
|
|
|
sig { params(_wanted_arch: Symbol).returns(T::Boolean) }
|
|
|
|
def arch_compatible?(_wanted_arch)
|
2024-09-30 22:29:03 +08:00
|
|
|
true
|
2024-09-29 05:15:36 +08:00
|
|
|
end
|
|
|
|
|
2021-12-17 08:14:44 -08:00
|
|
|
sig { returns(T::Array[String]) }
|
|
|
|
def rpaths
|
|
|
|
[]
|
|
|
|
end
|
2023-03-20 13:15:43 -07:00
|
|
|
|
2023-03-20 13:35:29 -07:00
|
|
|
sig { returns(String) }
|
2023-03-20 13:15:43 -07:00
|
|
|
def magic_number
|
|
|
|
@magic_number ||= if directory?
|
|
|
|
""
|
|
|
|
else
|
|
|
|
# Length of the longest regex (currently Tar).
|
2023-03-22 10:04:53 -07:00
|
|
|
max_magic_number_length = 262
|
2024-01-26 12:00:13 -08:00
|
|
|
binread(max_magic_number_length) || ""
|
2023-03-20 13:15:43 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-03-20 13:35:29 -07:00
|
|
|
sig { returns(String) }
|
2023-03-20 13:15:43 -07:00
|
|
|
def file_type
|
|
|
|
@file_type ||= system_command("file", args: ["-b", self], print_stderr: false)
|
|
|
|
.stdout.chomp
|
|
|
|
end
|
|
|
|
|
2023-03-20 13:35:29 -07:00
|
|
|
sig { returns(T::Array[String]) }
|
2023-03-20 13:15:43 -07:00
|
|
|
def zipinfo
|
|
|
|
@zipinfo ||= system_command("zipinfo", args: ["-1", self], print_stderr: false)
|
|
|
|
.stdout
|
|
|
|
.encode(Encoding::UTF_8, invalid: :replace)
|
|
|
|
.split("\n")
|
|
|
|
end
|
2024-05-18 08:16:34 +01:00
|
|
|
|
|
|
|
# Like regular `rmtree`, except it never ignores errors.
|
|
|
|
#
|
|
|
|
# This was the default behaviour in Ruby 3.1 and earlier.
|
|
|
|
#
|
|
|
|
# @api public
|
|
|
|
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).
|
2025-04-22 17:15:23 +01:00
|
|
|
odisabled "rmtree", "FileUtils#rm_r"
|
2024-05-18 08:16:34 +01:00
|
|
|
FileUtils.rm_r(@path, noop:, verbose:, secure:)
|
|
|
|
nil
|
|
|
|
end
|
2009-07-31 02:51:17 +01:00
|
|
|
end
|
2017-11-07 14:18:25 -06:00
|
|
|
require "extend/os/pathname"
|