'brew cask upgrade' will continue upgrading casks after a failure
'cask upgrade' command collects all exceptions thrown from individual casks during the upgrade process. If there were more than one cask that raised exceptions during the upgrade process, a MultipleCaskErrors exception will be thrown. Issue #5203
This commit is contained in:
parent
cf4511f72a
commit
41b5b788d5
@ -31,72 +31,74 @@ module Cask
|
||||
|
||||
ohai "Casks with `auto_updates` or `version :latest` will not be upgraded" if args.empty? && !greedy?
|
||||
oh1 "Upgrading #{outdated_casks.count} #{"outdated package".pluralize(outdated_casks.count)}:"
|
||||
cask_upgrades = outdated_casks.map do |cask|
|
||||
if cask.installed_caskfile.nil?
|
||||
"#{cask.full_name} #{cask.version}"
|
||||
else
|
||||
"#{cask.full_name} #{CaskLoader.load(cask.installed_caskfile).version} -> #{cask.version}"
|
||||
caught_exceptions = []
|
||||
outdated_casks.each do |cask|
|
||||
begin
|
||||
old_cask = CaskLoader.load(cask.installed_caskfile)
|
||||
puts "#{cask.full_name} #{old_cask.version} -> #{cask.version}"
|
||||
upgrade_cask(old_cask)
|
||||
rescue CaskError => e
|
||||
caught_exceptions << e
|
||||
next
|
||||
end
|
||||
end
|
||||
puts cask_upgrades.join(", ")
|
||||
return if caught_exceptions.empty?
|
||||
raise MultipleCaskErrors, caught_exceptions if caught_exceptions.count > 1
|
||||
raise caught_exceptions.first if caught_exceptions.count == 1
|
||||
end
|
||||
|
||||
outdated_casks.each do |old_cask|
|
||||
odebug "Started upgrade process for Cask #{old_cask}"
|
||||
raise CaskUnavailableError.new(old_cask, "The Caskfile is missing!") if old_cask.installed_caskfile.nil?
|
||||
def upgrade_cask(old_cask)
|
||||
odebug "Started upgrade process for Cask #{old_cask}"
|
||||
old_config = old_cask.config
|
||||
|
||||
old_cask = CaskLoader.load(old_cask.installed_caskfile)
|
||||
old_cask_installer =
|
||||
Installer.new(old_cask, binaries: binaries?,
|
||||
verbose: verbose?,
|
||||
force: force?,
|
||||
upgrade: true)
|
||||
|
||||
old_config = old_cask.config
|
||||
new_cask = CaskLoader.load(old_cask.token)
|
||||
|
||||
old_cask_installer =
|
||||
Installer.new(old_cask, binaries: binaries?,
|
||||
verbose: verbose?,
|
||||
force: force?,
|
||||
upgrade: true)
|
||||
new_cask.config = Config.global.merge(old_config)
|
||||
|
||||
new_cask = CaskLoader.load(old_cask.token)
|
||||
new_cask_installer =
|
||||
Installer.new(new_cask, binaries: binaries?,
|
||||
verbose: verbose?,
|
||||
force: force?,
|
||||
skip_cask_deps: skip_cask_deps?,
|
||||
require_sha: require_sha?,
|
||||
upgrade: true,
|
||||
quarantine: quarantine?)
|
||||
|
||||
new_cask.config = Config.global.merge(old_config)
|
||||
started_upgrade = false
|
||||
new_artifacts_installed = false
|
||||
|
||||
new_cask_installer =
|
||||
Installer.new(new_cask, binaries: binaries?,
|
||||
verbose: verbose?,
|
||||
force: force?,
|
||||
skip_cask_deps: skip_cask_deps?,
|
||||
require_sha: require_sha?,
|
||||
upgrade: true,
|
||||
quarantine: quarantine?)
|
||||
begin
|
||||
# Start new Cask's installation steps
|
||||
new_cask_installer.check_conflicts
|
||||
|
||||
started_upgrade = false
|
||||
new_artifacts_installed = false
|
||||
puts new_cask_installer.caveats
|
||||
|
||||
begin
|
||||
# Start new Cask's installation steps
|
||||
new_cask_installer.check_conflicts
|
||||
new_cask_installer.fetch
|
||||
|
||||
puts new_cask_installer.caveats
|
||||
# Move the old Cask's artifacts back to staging
|
||||
old_cask_installer.start_upgrade
|
||||
# And flag it so in case of error
|
||||
started_upgrade = true
|
||||
|
||||
new_cask_installer.fetch
|
||||
# Install the new Cask
|
||||
new_cask_installer.stage
|
||||
|
||||
# Move the old Cask's artifacts back to staging
|
||||
old_cask_installer.start_upgrade
|
||||
# And flag it so in case of error
|
||||
started_upgrade = true
|
||||
new_cask_installer.install_artifacts
|
||||
new_artifacts_installed = true
|
||||
|
||||
# Install the new Cask
|
||||
new_cask_installer.stage
|
||||
|
||||
new_cask_installer.install_artifacts
|
||||
new_artifacts_installed = true
|
||||
|
||||
# If successful, wipe the old Cask from staging
|
||||
old_cask_installer.finalize_upgrade
|
||||
rescue CaskError => e
|
||||
new_cask_installer.uninstall_artifacts if new_artifacts_installed
|
||||
new_cask_installer.purge_versioned_files
|
||||
old_cask_installer.revert_upgrade if started_upgrade
|
||||
raise e
|
||||
end
|
||||
# If successful, wipe the old Cask from staging
|
||||
old_cask_installer.finalize_upgrade
|
||||
rescue CaskError => e
|
||||
new_cask_installer.uninstall_artifacts if new_artifacts_installed
|
||||
new_cask_installer.purge_versioned_files
|
||||
old_cask_installer.revert_upgrade if started_upgrade
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,19 @@
|
||||
module Cask
|
||||
class CaskError < RuntimeError; end
|
||||
|
||||
class MultipleCaskErrors < CaskError
|
||||
def initialize(errors)
|
||||
@errors = errors
|
||||
end
|
||||
|
||||
def to_s
|
||||
<<~EOS
|
||||
Problems with multiple casks:
|
||||
#{@errors.map(&:to_s).join("\n")}
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
||||
class AbstractCaskErrorWithToken < CaskError
|
||||
attr_reader :token
|
||||
attr_reader :reason
|
||||
|
@ -222,4 +222,61 @@ describe Cask::Cmd::Upgrade, :cask do
|
||||
expect(bad_checksum.staged_path).not_to exist
|
||||
end
|
||||
end
|
||||
|
||||
context "multiple failures" do
|
||||
let(:installed) {
|
||||
[
|
||||
"outdated/bad-checksum",
|
||||
"outdated/local-transmission",
|
||||
"outdated/bad-checksum2",
|
||||
]
|
||||
}
|
||||
|
||||
before do
|
||||
installed.each { |cask| Cask::Cmd::Install.run(cask) }
|
||||
|
||||
allow_any_instance_of(described_class).to receive(:verbose?).and_return(true)
|
||||
end
|
||||
|
||||
it "will not end the upgrade process" do
|
||||
bad_checksum = Cask::CaskLoader.load("bad-checksum")
|
||||
bad_checksum_path = bad_checksum.config.appdir.join("Caffeine.app")
|
||||
|
||||
local_transmission = Cask::CaskLoader.load("local-transmission")
|
||||
local_transmission_path = Cask::Config.global.appdir.join("Transmission.app")
|
||||
|
||||
bad_checksum_2 = Cask::CaskLoader.load("bad-checksum2")
|
||||
bad_checksum_2_path = bad_checksum_2.config.appdir.join("container")
|
||||
|
||||
expect(bad_checksum).to be_installed
|
||||
expect(bad_checksum_path).to be_a_directory
|
||||
expect(bad_checksum.versions).to include("1.2.2")
|
||||
|
||||
expect(local_transmission).to be_installed
|
||||
expect(local_transmission_path).to be_a_directory
|
||||
expect(local_transmission.versions).to include("2.60")
|
||||
|
||||
expect(bad_checksum_2).to be_installed
|
||||
expect(bad_checksum_2_path).to be_a_file
|
||||
expect(bad_checksum_2.versions).to include("1.2.2")
|
||||
|
||||
expect {
|
||||
described_class.run
|
||||
}.to raise_error(Cask::MultipleCaskErrors)
|
||||
|
||||
expect(bad_checksum).to be_installed
|
||||
expect(bad_checksum_path).to be_a_directory
|
||||
expect(bad_checksum.versions).to include("1.2.2")
|
||||
expect(bad_checksum.staged_path).not_to exist
|
||||
|
||||
expect(local_transmission).to be_installed
|
||||
expect(local_transmission_path).to be_a_directory
|
||||
expect(local_transmission.versions).to include("2.61")
|
||||
|
||||
expect(bad_checksum_2).to be_installed
|
||||
expect(bad_checksum_2_path).to be_a_file
|
||||
expect(bad_checksum_2.versions).to include("1.2.2")
|
||||
expect(bad_checksum_2.staged_path).not_to exist
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,9 @@
|
||||
cask 'bad-checksum2' do
|
||||
version '1.2.3'
|
||||
sha256 'badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadb'
|
||||
|
||||
url "file://#{TEST_FIXTURE_DIR}/cask/container.tar.gz"
|
||||
homepage 'https://brew.sh/container-tar-gz'
|
||||
|
||||
app 'container'
|
||||
end
|
@ -0,0 +1,9 @@
|
||||
cask 'bad-checksum2' do
|
||||
version '1.2.2'
|
||||
sha256 'fab685fabf73d5a9382581ce8698fce9408f5feaa49fa10d9bc6c510493300f5'
|
||||
|
||||
url "file://#{TEST_FIXTURE_DIR}/cask/container.tar.gz"
|
||||
homepage 'https://brew.sh/container-tar-gz'
|
||||
|
||||
app 'container'
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user