diff --git a/Library/Homebrew/test/formula_installer_bottle_spec.rb b/Library/Homebrew/test/formula_installer_bottle_spec.rb index 10a6adb49d..0f4e4eee6a 100644 --- a/Library/Homebrew/test/formula_installer_bottle_spec.rb +++ b/Library/Homebrew/test/formula_installer_bottle_spec.rb @@ -21,8 +21,6 @@ RSpec.describe FormulaInstaller do expect(formula).to be_bottled expect(formula).to pour_bottle - stub_formula_loader formula("coreutils") { url "coreutils-1.0" } - stub_formula_loader formula("uutils-coreutils") { url "uutils-coreutils-1.0" } stub_formula_loader formula("gcc") { url "gcc-1.0" } stub_formula_loader formula("glibc") { url "glibc-1.0" } stub_formula_loader formula diff --git a/Library/Homebrew/utils/cp.rb b/Library/Homebrew/utils/cp.rb index 61b805a608..d64804b71c 100644 --- a/Library/Homebrew/utils/cp.rb +++ b/Library/Homebrew/utils/cp.rb @@ -17,7 +17,11 @@ module Utils ).returns(SystemCommand::Result) } def copy(source, target, sudo: false, verbose: false, command: SystemCommand) - command.run! executable, args: ["-p", *extra_flags, *source, target], sudo:, verbose: + # 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: end sig { @@ -30,78 +34,26 @@ module Utils ).returns(SystemCommand::Result) } def copy_recursive(source, target, sudo: false, verbose: false, command: SystemCommand) - command.run! executable, args: ["-pR", *extra_flags, *source, target], sudo:, verbose: + command.run! "cp", args: ["-pR", *extra_flags, *source, target], sudo:, verbose: end private - GCP = (HOMEBREW_PREFIX/"opt/coreutils/libexec/gnubin/cp").freeze - UCP = (HOMEBREW_PREFIX/"opt/uutils-coreutils/libexec/uubin/cp").freeze - - sig { returns(T.any(String, Pathname)) } - def executable - case type - when :macos - Pathname("/bin/cp") - when :coreutils - GCP - when :uutils - UCP - else - "cp" - end - end - - MACOS_FLAGS = [ - # Perform a lightweight copy-on-write clone if applicable. - "-c", - ].freeze - GNU_FLAGS = [ - # Unlike BSD cp, `gcp -p` doesn't guarantee to preserve extended attributes, including - # quarantine information on macOS. - "--preserve=all", - "--no-preserve=links", - # Equivalent to `-c` on macOS. - "--reflink=auto", - ].freeze + # Use the lightweight `clonefile(2)` syscall if applicable. + MACOS_FLAGS = ["-c"].freeze GENERIC_FLAGS = [].freeze sig { returns(T::Array[String]) } def extra_flags - case type - when :macos + # 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 MACOS_FLAGS - when :coreutils, :uutils - GNU_FLAGS else GENERIC_FLAGS end end - - sig { returns(T.nilable(Symbol)) } - def type - return @type if defined?(@type) - - # The `cp` command on some 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). - return @type = :macos if MacOS.version >= :sonoma - - { - coreutils: "coreutils", - uutils: "uutils-coreutils", - }.each do |type, formula| - begin - formula = Formula[formula] - rescue FormulaUnavailableError - next - end - return @type = type if formula.optlinked? - end - - @type = nil - end end end end