Utils::Cp: Add force_system keyword argument

This fixes the test for `UnpackStrategy::Directory`, which needs the
`cp` command.
This commit is contained in:
Daiki Mizukami 2024-06-09 05:54:36 +09:00
parent 9156891c99
commit 67f280eb53
No known key found for this signature in database
GPG Key ID: 10478E598B944AA2
4 changed files with 56 additions and 34 deletions

View File

@ -109,7 +109,7 @@ module Cask
if target.writable?
source.children.each { |child| FileUtils.move(child, target/child.basename) }
else
::Utils::Cp.recursive_with_attributes(source.children, target, sudo: true, command:)
::Utils::Cp.recursive_with_attributes(source.children, target, force_command: true, sudo: true, command:)
end
Quarantine.copy_xattrs(source, target, command:)
source.rmtree
@ -118,7 +118,7 @@ module Cask
else
# default sudo user isn't necessarily able to write to Homebrew's locations
# e.g. with runas_default set in the sudoers (5) file.
::Utils::Cp.recursive_with_attributes(source, target, sudo: true, command:)
::Utils::Cp.recursive_with_attributes(source, target, force_command: true, sudo: true, command:)
source.rmtree
end
@ -161,8 +161,9 @@ module Cask
ohai "Backing #{self.class.english_name} '#{target.basename}' up to '#{source}'"
source.dirname.mkpath
# `Utils::Cp` preserves extended attributes between copies.
::Utils::Cp.recursive_with_attributes(target, source, sudo: !source.parent.writable?, command:)
::Utils::Cp.recursive_with_attributes(target, source, sudo: !source.parent.writable?, command:,
# This is required to preserve extended attributes between copies.
force_command: true)
delete(target, force:, command:, **options)
end

View File

@ -7,30 +7,41 @@ module Utils
module MacOSOverride
sig {
params(
source: T.any(String, Pathname, T::Array[T.any(String, Pathname)]),
target: T.any(String, Pathname),
sudo: T::Boolean,
verbose: T::Boolean,
command: T.class_of(SystemCommand),
).returns(SystemCommand::Result)
source: T.any(String, Pathname, T::Array[T.any(String, Pathname)]),
target: T.any(String, Pathname),
force_command: T::Boolean,
sudo: T::Boolean,
verbose: T::Boolean,
command: T.class_of(SystemCommand),
).void
}
def with_attributes(source, target, sudo: false, verbose: false, command: SystemCommand)
# `cp -p` on macOS guarantees to preserve extended attributes (including quarantine
# information) in addition to file mode, which is requered when copying cask artifacts.
command.run! "cp", args: ["-p", *extra_flags, *source, target], sudo:, verbose:
def with_attributes(source, target, force_command: false, sudo: false, verbose: false, command: SystemCommand)
if (flags = extra_flags)
command.run! "cp", args: ["-p", *flags, *source, target], sudo:, verbose:
nil
else
super
end
end
sig {
params(
source: T.any(String, Pathname, T::Array[T.any(String, Pathname)]),
target: T.any(String, Pathname),
sudo: T::Boolean,
verbose: T::Boolean,
command: T.class_of(SystemCommand),
).returns(SystemCommand::Result)
source: T.any(String, Pathname, T::Array[T.any(String, Pathname)]),
target: T.any(String, Pathname),
force_command: T::Boolean,
sudo: T::Boolean,
verbose: T::Boolean,
command: T.class_of(SystemCommand),
).void
}
def recursive_with_attributes(source, target, sudo: false, verbose: false, command: SystemCommand)
command.run! "cp", args: ["-pR", *extra_flags, *source, target], sudo:, verbose:
def recursive_with_attributes(source, target, force_command: false, sudo: false, verbose: false,
command: SystemCommand)
if (flags = extra_flags)
command.run! "cp", args: ["-pR", *flags, *source, target], sudo:, verbose:
nil
else
super
end
end
private
@ -38,17 +49,15 @@ module Utils
# Use the lightweight `clonefile(2)` syscall if applicable.
SONOMA_FLAGS = ["-c"].freeze
sig { returns(T::Array[String]) }
sig { returns(T.nilable(T::Array[String])) }
def extra_flags
# The `cp` command on older macOS versions also had the `-c` option, but before Sonoma,
# the command would fail if the `clonefile` syscall isn't applicable (the underlying
# filesystem doesn't support the feature or the source and the target are on different
# filesystems).
if MacOS.version >= :sonoma
SONOMA_FLAGS
else
[].freeze
end
return if MacOS.version < :sonoma
SONOMA_FLAGS
end
end

View File

@ -24,6 +24,7 @@ module UnpackStrategy
path.children.each do |child|
Utils::Cp.recursive_with_attributes (child.directory? && !child.symlink?) ? "#{child}/." : child,
unpack_dir/child.basename,
force_command: true,
verbose:
end
end

View File

@ -9,14 +9,25 @@ module Utils
# Helper functions for copying files.
module Cp
class << self
def with_attributes(source, target, sudo: false, verbose: false, command: SystemCommand)
odisabled "`Utils::Cp.with_attributes` with `sudo: true` on Linux" if sudo
FileUtils.cp source, target, preserve: true, verbose:
def with_attributes(source, target, force_command: false, sudo: false, verbose: false, command: SystemCommand)
if force_command || sudo
command.run! "cp", args: ["-p", *source, target], sudo:, verbose:
else
FileUtils.cp source, target, preserve: true, verbose:
end
nil
end
def recursive_with_attributes(source, target, sudo: false, verbose: false, command: SystemCommand)
odisabled "`Utils::Cp.recursive_with_attributes` with `sudo: true` on Linux" if sudo
FileUtils.cp_r source, target, preserve: true, verbose:
def recursive_with_attributes(source, target, force_command: false, sudo: false, verbose: false,
command: SystemCommand)
if force_command || sudo
command.run! "cp", args: ["-pR", *source, target], sudo:, verbose:
else
FileUtils.cp_r source, target, preserve: true, verbose:
end
nil
end
end
end