Change permission failure from fatal to warning.

This commit is contained in:
JBYoshi 2023-05-26 11:13:23 -05:00
parent 40352cb2da
commit 97b9b61061
No known key found for this signature in database
GPG Key ID: AE4430116622D05D
3 changed files with 24 additions and 16 deletions

View File

@ -84,8 +84,7 @@ module Cask
Utils.gain_permissions_mkpath(target.dirname, command: command) unless target.dirname.exist? Utils.gain_permissions_mkpath(target.dirname, command: command) unless target.dirname.exist?
if target.directory? if target.directory? && Quarantine.app_management_permissions_granted?(app: target, command: command)
Quarantine.ensure_app_management_permissions_granted(app: target, command: command)
if target.writable? if target.writable?
source.children.each { |child| FileUtils.move(child, target/child.basename) } source.children.each { |child| FileUtils.move(child, target/child.basename) }
else else
@ -154,10 +153,11 @@ module Cask
return unless Utils.path_occupied?(target) return unless Utils.path_occupied?(target)
if target.directory? && matching_artifact?(successor) if target.directory? && matching_artifact?(successor) && Quarantine.app_management_permissions_granted?(
app: target, command: command,
)
# If an app folder is deleted, macOS considers the app uninstalled and removes some data. # If an app folder is deleted, macOS considers the app uninstalled and removes some data.
# Remove only the contents to handle this case. # Remove only the contents to handle this case.
Quarantine.ensure_app_management_permissions_granted(app: target, command: command)
target.children.each do |child| target.children.each do |child|
if target.writable? && !force if target.writable? && !force
child.rmtree child.rmtree

View File

@ -192,9 +192,9 @@ module Cask
# Ensures that Homebrew has permission to update apps on macOS Ventura. # Ensures that Homebrew has permission to update apps on macOS Ventura.
# This may be granted either through the App Management toggle or the Full Disk Access toggle. # This may be granted either through the App Management toggle or the Full Disk Access toggle.
# The system will only show a prompt for App Management, so we ask the user to grant that. # The system will only show a prompt for App Management, so we ask the user to grant that.
sig { params(app: Pathname, command: T.class_of(SystemCommand)).void } sig { params(app: Pathname, command: T.class_of(SystemCommand)).returns(T::Boolean) }
def self.ensure_app_management_permissions_granted(app:, command:) def self.app_management_permissions_granted?(app:, command:)
return unless app.directory? return true unless app.directory?
# To get macOS to prompt the user for permissions, we need to actually attempt to # To get macOS to prompt the user for permissions, we need to actually attempt to
# modify a file in the app. # modify a file in the app.
@ -215,7 +215,7 @@ module Cask
begin begin
File.write(test_file, "") File.write(test_file, "")
test_file.delete test_file.delete
return return true
rescue Errno::EACCES rescue Errno::EACCES
# Using error handler below # Using error handler below
end end
@ -237,17 +237,19 @@ module Cask
print_stderr: false, print_stderr: false,
sudo: true, sudo: true,
) )
return return true
rescue ErrorDuringExecution => e rescue ErrorDuringExecution => e
# We only want to handle "touch" errors here; propagate "sudo" errors up # We only want to handle "touch" errors here; propagate "sudo" errors up
raise e unless e.stderr.include?("touch: #{test_file}: Operation not permitted") raise e unless e.stderr.include?("touch: #{test_file}: Operation not permitted")
end end
end end
odie <<~EOF opoo <<~EOF
Your terminal needs permission to update apps. Your terminal does not have App Management permissions, so Homebrew will delete and reinstall the app.
Go to Settings > Security and Privacy > App Management, or look for a notification saying your terminal was prevented from modifying apps. This may result in some configurations (like notification settings or location in the Dock/Launchpad) being lost.
To fix this, go to Settings > Security and Privacy > App Management and turn on the switch for your terminal.
EOF EOF
false
end end
end end
end end

View File

@ -329,13 +329,16 @@ describe Cask::Artifact::App, :cask do
end end
describe "when the system blocks modifying apps" do describe "when the system blocks modifying apps" do
it "does not delete files" do it "uninstalls and reinstalls the app" do
target_contents_path = target_path.join("Contents") target_contents_path = target_path.join("Contents")
expect(File).to receive(:write).with(target_path / ".homebrew-write-test", expect(File).to receive(:write).with(target_path / ".homebrew-write-test",
instance_of(String)).and_raise(Errno::EACCES) instance_of(String)).and_raise(Errno::EACCES)
expect { app.uninstall_phase(command: command, force: force, successor: cask) }.to raise_error(SystemExit) app.uninstall_phase(command: command, force: force, successor: cask)
expect(target_path).not_to exist
app.install_phase(command: command, adopt: adopt, force: force, predecessor: cask)
expect(target_contents_path).to exist expect(target_contents_path).to exist
end end
end end
@ -368,7 +371,7 @@ describe Cask::Artifact::App, :cask do
end end
describe "when the system blocks modifying apps" do describe "when the system blocks modifying apps" do
it "does not delete files" do it "uninstalls and reinstalls the app" do
target_contents_path = target_path.join("Contents") target_contents_path = target_path.join("Contents")
allow(command).to receive(:run!).with(any_args).and_call_original allow(command).to receive(:run!).with(any_args).and_call_original
@ -380,7 +383,10 @@ describe Cask::Artifact::App, :cask do
.and_raise(ErrorDuringExecution.new([], status: 1, .and_raise(ErrorDuringExecution.new([], status: 1,
output: [[:stderr, "touch: #{target_path}/.homebrew-write-test: Operation not permitted\n"]], secrets: [])) output: [[:stderr, "touch: #{target_path}/.homebrew-write-test: Operation not permitted\n"]], secrets: []))
expect { app.uninstall_phase(command: command, force: force, successor: cask) }.to raise_error(SystemExit) app.uninstall_phase(command: command, force: force, successor: cask)
expect(target_path).not_to exist
app.install_phase(command: command, adopt: adopt, force: force, predecessor: cask)
expect(target_contents_path).to exist expect(target_contents_path).to exist
end end
end end