aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
authorXiyue Deng2013-08-28 04:51:24 -0700
committerSamuel John2013-09-05 14:02:29 +0200
commit4b320eec6b76e195ddaad6dbcb20b549af07747c (patch)
tree30f97583fc40d281d5c6245a46c409db23343567 /Library
parent5ba030c162a8ad000623e04867fdd696923dabf7 (diff)
downloadhomebrew-4b320eec6b76e195ddaad6dbcb20b549af07747c.tar.bz2
Make reinstall transaction safe.
* Aborting during reinstall will now restore the originally installed keg. - Change install code to pass on CannotInstallFormulaError exception to caller so it can be reused in reinstall. * Add "--force-new-install" flag to force installing a new formula. Closes #22190. Signed-off-by: Samuel John <github@SamuelJohn.de>
Diffstat (limited to 'Library')
-rw-r--r--Library/Homebrew/cmd/install.rb11
-rw-r--r--Library/Homebrew/cmd/reinstall.rb70
2 files changed, 67 insertions, 14 deletions
diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb
index 46bc59b91..2fe22cfa4 100644
--- a/Library/Homebrew/cmd/install.rb
+++ b/Library/Homebrew/cmd/install.rb
@@ -19,7 +19,13 @@ module Homebrew extend self
end unless ARGV.force?
perform_preinstall_checks
- ARGV.formulae.each { |f| install_formula(f) }
+ ARGV.formulae.each do |f|
+ begin
+ install_formula(f)
+ rescue CannotInstallFormulaError => e
+ ofail e.message
+ end
+ end
end
def check_ppc
@@ -80,7 +86,6 @@ module Homebrew extend self
# another formula. In that case, don't generate an error, just move on.
rescue FormulaAlreadyInstalledError => e
opoo e.message
- rescue CannotInstallFormulaError => e
- ofail e.message
+ # Ignore CannotInstallFormulaError and let caller handle it.
end
end
diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb
index 485cf4c30..5e9390074 100644
--- a/Library/Homebrew/cmd/reinstall.rb
+++ b/Library/Homebrew/cmd/reinstall.rb
@@ -1,4 +1,3 @@
-require 'cmd/uninstall'
require 'cmd/install'
module Homebrew extend self
@@ -6,9 +5,6 @@ module Homebrew extend self
# At first save the named formulae and remove them from ARGV
named = ARGV.named
ARGV.delete_if { |arg| named.include? arg }
- # We add --force because then uninstall always succeeds and so reinstall
- # works for formulae not yet installed.
- ARGV << "--force"
clean_ARGV = ARGV.clone
# Add the used_options for each named formula separately so
@@ -21,13 +17,65 @@ module Homebrew extend self
if tab.built_as_bottle and not tab.poured_from_bottle
ARGV << '--build-bottle'
end
- # Todo: Be as smart as upgrade to restore the old state if reinstall fails.
- self.uninstall
- # Don't display --force in options; user didn't request it so a bit scary.
- options_only = ARGV.options_only
- options_only.delete "--force"
- oh1 "Reinstalling #{name} #{options_only*' '}"
- self.install
+
+ canonical_name = Formula.canonical_name(name)
+ formula = Formula.factory(canonical_name)
+
+ if not formula.installed?
+ if force_new_install?
+ oh1 "Force installing new formula: #{name}"
+ self.install_formula formula
+ next
+ else
+ raise <<-EOS.undent
+ #{formula} is not installed. Please install it first or use
+ "--force-new-install" flag.
+ EOS
+ end
+ end
+
+ linked_keg_ref = HOMEBREW_REPOSITORY/'opt'/canonical_name
+ keg = Keg.new(linked_keg_ref.realpath)
+
+ begin
+ oh1 "Reinstalling #{name} #{ARGV.options_only*' '}"
+ quarantine keg
+ self.install_formula formula
+ rescue Exception => e
+ ofail e.message unless e.message.empty?
+ restore_quarantine keg, formula
+ raise 'Reinstallation abort.'
+ else
+ remove_quarantine keg
+ end
+ end
+ end
+
+ def force_new_install?
+ ARGV.include? '--force-new-install'
+ end
+
+ def quarantine keg
+ keg.unlink
+
+ path = Pathname.new(keg.to_s)
+ path.rename quarantine_path(path)
+ end
+
+ def restore_quarantine keg, formula
+ path = Pathname.new(quarantine_path(keg))
+ if path.directory?
+ path.rename keg.to_s
+ keg.link unless formula.keg_only?
end
end
+
+ def remove_quarantine keg
+ path = Pathname.new(quarantine_path(keg))
+ path.rmtree
+ end
+
+ def quarantine_path path
+ path.to_s + '.reinstall'
+ end
end