Utils::Cp: Use FileUtils.cp on Linux

`FileUtils.cp` is implemented with the lightweight `copy_file_range(2)`
syscall on Linux, so it's more performant than the plain `cp` command on
that platform.

cf. https://github.com/Homebrew/brew/pull/17373#pullrequestreview-2105629022
This commit is contained in:
Daiki Mizukami 2024-06-08 19:39:56 +09:00
parent a4271fdad1
commit 9156891c99
No known key found for this signature in database
GPG Key ID: 10478E598B944AA2
2 changed files with 35 additions and 32 deletions

View File

@ -5,6 +5,34 @@ module Utils
module Cp
class << self
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)
}
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:
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)
}
def recursive_with_attributes(source, target, sudo: false, verbose: false, command: SystemCommand)
command.run! "cp", args: ["-pR", *extra_flags, *source, target], sudo:, verbose:
end
private
# Use the lightweight `clonefile(2)` syscall if applicable.
@ -19,7 +47,7 @@ module Utils
if MacOS.version >= :sonoma
SONOMA_FLAGS
else
super
[].freeze
end
end
end

View File

@ -2,46 +2,21 @@
# frozen_string_literal: true
require "extend/os/cp"
require "fileutils"
require "system_command"
module Utils
# Helper functions for interacting with the `cp` command.
# Helper functions for copying files.
module Cp
class << self
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)
}
def with_attributes(source, target, sudo: false, verbose: false, command: SystemCommand)
# On macOS, `cp -p` guarantees to preserve extended attributes (including quarantine
# information) in addition to file mode. Other implementations like coreutils does not
# necessarily guarantee the same behavior, but that is fine because we don't really need to
# preserve extended attributes except when copying Cask artifacts.
command.run! "cp", args: ["-p", *extra_flags, *source, target], sudo:, verbose:
odisabled "`Utils::Cp.with_attributes` with `sudo: true` on Linux" if sudo
FileUtils.cp source, target, preserve: true, verbose:
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)
}
def recursive_with_attributes(source, target, sudo: false, verbose: false, command: SystemCommand)
command.run! "cp", args: ["-pR", *extra_flags, *source, target], sudo:, verbose:
end
private
def extra_flags
[].freeze
odisabled "`Utils::Cp.recursive_with_attributes` with `sudo: true` on Linux" if sudo
FileUtils.cp_r source, target, preserve: true, verbose:
end
end
end