From 7308c105a48e25d613cdfbe6f68130dca23e6baf Mon Sep 17 00:00:00 2001 From: Bo Anderson Date: Fri, 22 Nov 2024 22:16:44 +0000 Subject: [PATCH] cask: try fix a couple of permission edge cases under multi-user --- .../cask/artifact/abstract_uninstall.rb | 5 ++++- Library/Homebrew/cask/artifact/moved.rb | 11 +++++++++- .../artifact/shared_examples/uninstall_zap.rb | 21 +++++++++++-------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Library/Homebrew/cask/artifact/abstract_uninstall.rb b/Library/Homebrew/cask/artifact/abstract_uninstall.rb index 36b7aea555..0cfdcad7ba 100644 --- a/Library/Homebrew/cask/artifact/abstract_uninstall.rb +++ b/Library/Homebrew/cask/artifact/abstract_uninstall.rb @@ -116,12 +116,15 @@ module Cask print_stderr: false, ).stdout if plist_status.start_with?("{") - command.run!( + result = command.run( "/bin/launchctl", args: ["remove", service], + must_succeed: sudo, sudo:, sudo_as_root: sudo, ) + next if !sudo && !result.success? + sleep 1 end paths = [ diff --git a/Library/Homebrew/cask/artifact/moved.rb b/Library/Homebrew/cask/artifact/moved.rb index ee4a040051..d3c5331639 100644 --- a/Library/Homebrew/cask/artifact/moved.rb +++ b/Library/Homebrew/cask/artifact/moved.rb @@ -164,7 +164,16 @@ module Cask source.dirname.mkpath # We need to preserve extended attributes between copies. - command.run!("/bin/cp", args: ["-pR", target, source], sudo: !source.parent.writable?) + # This may fail and need sudo if the source has files with restricted permissions. + [!source.parent.writable?, true].uniq.each do |sudo| + result = command.run( + "/bin/cp", + args: ["-pR", target, source], + must_succeed: sudo, + sudo:, + ) + break if result.success? + end delete(target, force:, command:, **options) end diff --git a/Library/Homebrew/test/cask/artifact/shared_examples/uninstall_zap.rb b/Library/Homebrew/test/cask/artifact/shared_examples/uninstall_zap.rb index b5813809b7..3ffd343e26 100644 --- a/Library/Homebrew/test/cask/artifact/shared_examples/uninstall_zap.rb +++ b/Library/Homebrew/test/cask/artifact/shared_examples/uninstall_zap.rb @@ -49,9 +49,10 @@ RSpec.shared_examples "#uninstall_phase or #zap_phase" do ) .and_return(instance_double(SystemCommand::Result, stdout: unknown_response)) - expect(fake_system_command).to receive(:run!) - .with("/bin/launchctl", args: ["remove", "my.fancy.package.service"], sudo: false, sudo_as_root: false) - .and_return(instance_double(SystemCommand::Result)) + expect(fake_system_command).to receive(:run) + .with("/bin/launchctl", args: ["remove", "my.fancy.package.service"], + must_succeed: false, sudo: false, sudo_as_root: false) + .and_return(instance_double(SystemCommand::Result, success?: true)) subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command) end @@ -76,9 +77,10 @@ RSpec.shared_examples "#uninstall_phase or #zap_phase" do ) .and_return(instance_double(SystemCommand::Result, stdout: service_info)) - expect(fake_system_command).to receive(:run!) - .with("/bin/launchctl", args: ["remove", "my.fancy.package.service"], sudo: true, sudo_as_root: true) - .and_return(instance_double(SystemCommand::Result)) + expect(fake_system_command).to receive(:run) + .with("/bin/launchctl", args: ["remove", "my.fancy.package.service"], + must_succeed: true, sudo: true, sudo_as_root: true) + .and_return(instance_double(SystemCommand::Result, success?: true)) subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command) end @@ -136,9 +138,10 @@ RSpec.shared_examples "#uninstall_phase or #zap_phase" do ) .and_return(instance_double(SystemCommand::Result, stdout: service_info)) - expect(fake_system_command).to receive(:run!) - .with("/bin/launchctl", args: ["remove", "my.fancy.package.service.12345"], sudo: true, sudo_as_root: true) - .and_return(instance_double(SystemCommand::Result)) + expect(fake_system_command).to receive(:run) + .with("/bin/launchctl", args: ["remove", "my.fancy.package.service.12345"], + must_succeed: true, sudo: true, sudo_as_root: true) + .and_return(instance_double(SystemCommand::Result, success?: true)) subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command) end