| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | require "formula" | 
					
						
							|  |  |  | require "keg" | 
					
						
							|  |  |  | require "bottles" | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-18 22:41:47 -05:00
										 |  |  | module Homebrew | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |   def cleanup | 
					
						
							| 
									
										
										
										
											2014-05-17 16:59:14 -07:00
										 |  |  |     # individual cleanup_ methods should also check for the existence of the | 
					
						
							|  |  |  |     # appropriate directories before assuming they exist | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:39 -05:00
										 |  |  |     return unless HOMEBREW_CELLAR.directory? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |     if ARGV.named.empty? | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:39 -05:00
										 |  |  |       cleanup_cellar | 
					
						
							|  |  |  |       cleanup_cache | 
					
						
							| 
									
										
										
										
											2014-05-14 12:12:30 -05:00
										 |  |  |       cleanup_logs | 
					
						
							| 
									
										
										
										
											2013-06-21 15:42:14 -05:00
										 |  |  |       unless ARGV.dry_run? | 
					
						
							|  |  |  |         cleanup_lockfiles | 
					
						
							|  |  |  |         rm_DS_Store | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2015-05-17 20:09:49 +08:00
										 |  |  |       ARGV.resolved_formulae.each { |f| cleanup_formula(f) } | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:35 -05:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-14 12:12:30 -05:00
										 |  |  |   def cleanup_logs | 
					
						
							| 
									
										
										
										
											2014-05-17 16:59:14 -07:00
										 |  |  |     return unless HOMEBREW_LOGS.directory? | 
					
						
							| 
									
										
										
										
											2014-05-14 12:12:30 -05:00
										 |  |  |     time = Time.now - 2 * 7 * 24 * 60 * 60 # two weeks | 
					
						
							|  |  |  |     HOMEBREW_LOGS.subdirs.each do |dir| | 
					
						
							| 
									
										
										
										
											2015-04-07 21:14:32 -04:00
										 |  |  |       cleanup_path(dir) { dir.rmtree } if dir.mtime < time | 
					
						
							| 
									
										
										
										
											2014-05-14 12:12:30 -05:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:39 -05:00
										 |  |  |   def cleanup_cellar | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:36 -05:00
										 |  |  |     HOMEBREW_CELLAR.subdirs.each do |rack| | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:36 -05:00
										 |  |  |       begin | 
					
						
							| 
									
										
										
										
											2015-05-17 20:09:49 +08:00
										 |  |  |         cleanup_formula Formulary.from_rack(rack) | 
					
						
							|  |  |  |       rescue FormulaUnavailableError, TapFormulaAmbiguityError | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:36 -05:00
										 |  |  |         # Don't complain about directories from DIY installs | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def cleanup_formula(f) | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:36 -05:00
										 |  |  |     if f.installed? | 
					
						
							| 
									
										
										
										
											2014-03-05 20:12:51 -06:00
										 |  |  |       eligible_kegs = f.rack.subdirs.map { |d| Keg.new(d) }.select { |k| f.pkg_version > k.version } | 
					
						
							| 
									
										
										
										
											2015-04-17 22:58:02 -04:00
										 |  |  |       if eligible_kegs.any? && eligible_for_cleanup?(f) | 
					
						
							| 
									
										
										
										
											2015-04-17 22:58:02 -04:00
										 |  |  |         eligible_kegs.each { |keg| cleanup_keg(keg) } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         eligible_kegs.each { |keg| opoo "Skipping (old) keg-only: #{keg}" } | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:36 -05:00
										 |  |  |     elsif f.rack.subdirs.length > 1
 | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |       # If the cellar only has one version installed, don't complain | 
					
						
							|  |  |  |       # that we can't tell which one to keep. | 
					
						
							| 
									
										
										
										
											2015-05-27 20:48:32 +08:00
										 |  |  |       opoo "Skipping #{f.full_name}: most recent version #{f.pkg_version} not installed" | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def cleanup_keg(keg) | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:38 -05:00
										 |  |  |     if keg.linked? | 
					
						
							|  |  |  |       opoo "Skipping (old) #{keg} due to it being linked" | 
					
						
							|  |  |  |     else | 
					
						
							| 
									
										
										
										
											2015-04-07 21:14:32 -04:00
										 |  |  |       cleanup_path(keg) { keg.uninstall } | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:38 -05:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:36 -05:00
										 |  |  |   def cleanup_cache | 
					
						
							| 
									
										
										
										
											2014-10-19 12:18:44 +01:00
										 |  |  |     return unless HOMEBREW_CACHE.directory? | 
					
						
							| 
									
										
										
										
											2015-04-11 16:37:47 +01:00
										 |  |  |     prune = ARGV.value "prune" | 
					
						
							|  |  |  |     time = Time.now - 60 * 60 * 24 * prune.to_i | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:38 -05:00
										 |  |  |     HOMEBREW_CACHE.children.select(&:file?).each do |file| | 
					
						
							| 
									
										
										
										
											2015-04-11 16:37:47 +01:00
										 |  |  |       next cleanup_path(file) { file.unlink } if prune && file.mtime < time | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 21:41:07 +08:00
										 |  |  |       if Pathname::BOTTLE_EXTNAME_RX === file.to_s | 
					
						
							|  |  |  |         version = bottle_resolve_version(file) rescue file.version | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         version = file.version | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       next unless version | 
					
						
							| 
									
										
										
										
											2013-06-06 12:34:47 -05:00
										 |  |  |       next unless (name = file.basename.to_s[/(.*)-(?:#{Regexp.escape(version)})/, 1]) | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:39 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       begin | 
					
						
							| 
									
										
										
										
											2015-05-17 20:09:49 +08:00
										 |  |  |         f = Formulary.from_rack(HOMEBREW_CELLAR/name) | 
					
						
							|  |  |  |       rescue FormulaUnavailableError, TapFormulaAmbiguityError | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:39 -05:00
										 |  |  |         next | 
					
						
							| 
									
										
										
										
											2012-03-06 20:12:42 +00:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:39 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-22 22:26:52 +08:00
										 |  |  |       file_is_stale = if PkgVersion === version | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |         f.pkg_version > version | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         f.version > version | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2015-07-22 22:26:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |       if file_is_stale || ARGV.switch?("s") && !f.installed? || bottle_file_outdated?(f, file) | 
					
						
							| 
									
										
										
										
											2015-04-07 21:14:32 -04:00
										 |  |  |         cleanup_path(file) { file.unlink } | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:39 -05:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 21:14:32 -04:00
										 |  |  |   def cleanup_path(path) | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:39 -05:00
										 |  |  |     if ARGV.dry_run? | 
					
						
							| 
									
										
										
										
											2015-04-07 21:14:32 -04:00
										 |  |  |       puts "Would remove: #{path} (#{path.abv})" | 
					
						
							| 
									
										
										
										
											2013-05-15 12:45:39 -05:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2015-04-07 21:14:32 -04:00
										 |  |  |       puts "Removing: #{path}... (#{path.abv})" | 
					
						
							|  |  |  |       yield | 
					
						
							| 
									
										
										
										
											2012-03-06 20:12:42 +00:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-21 15:42:14 -05:00
										 |  |  |   def cleanup_lockfiles | 
					
						
							| 
									
										
										
										
											2013-06-21 18:37:52 -05:00
										 |  |  |     return unless HOMEBREW_CACHE_FORMULA.directory? | 
					
						
							| 
									
										
										
										
											2013-06-21 15:42:14 -05:00
										 |  |  |     candidates = HOMEBREW_CACHE_FORMULA.children | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     lockfiles  = candidates.select { |f| f.file? && f.extname == ".brewing" } | 
					
						
							| 
									
										
										
										
											2013-06-21 15:42:14 -05:00
										 |  |  |     lockfiles.select(&:readable?).each do |file| | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |       file.open.flock(File::LOCK_EX | File::LOCK_NB) && file.unlink | 
					
						
							| 
									
										
										
										
											2013-06-21 15:42:14 -05:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-10 16:06:24 -04:00
										 |  |  |   def rm_DS_Store | 
					
						
							| 
									
										
										
										
											2015-03-06 10:39:46 +08:00
										 |  |  |     paths = %w[Cellar Frameworks Library bin etc include lib opt sbin share var]. | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |             map { |p| HOMEBREW_PREFIX/p }.select(&:exist?) | 
					
						
							| 
									
										
										
										
											2015-03-06 10:39:46 +08:00
										 |  |  |     args = paths.map(&:to_s) + %w[-name .DS_Store -delete] | 
					
						
							|  |  |  |     quiet_system "find", *args | 
					
						
							| 
									
										
										
										
											2012-08-10 16:06:24 -04:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-17 22:58:02 -04:00
										 |  |  |   def eligible_for_cleanup?(formula) | 
					
						
							| 
									
										
										
										
											2012-08-10 16:33:47 -04:00
										 |  |  |     # It used to be the case that keg-only kegs could not be cleaned up, because | 
					
						
							|  |  |  |     # older brews were built against the full path to the keg-only keg. Then we | 
					
						
							|  |  |  |     # introduced the opt symlink, and built against that instead. So provided | 
					
						
							|  |  |  |     # no brew exists that was built against an old-style keg-only keg, we can | 
					
						
							|  |  |  |     # remove it. | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     if !formula.keg_only? || ARGV.force? | 
					
						
							| 
									
										
										
										
											2012-08-10 16:33:47 -04:00
										 |  |  |       true | 
					
						
							| 
									
										
										
										
											2015-04-17 22:58:02 -04:00
										 |  |  |     elsif formula.opt_prefix.directory? | 
					
						
							| 
									
										
										
										
											2012-08-10 16:33:47 -04:00
										 |  |  |       # SHA records were added to INSTALL_RECEIPTS the same day as opt symlinks | 
					
						
							| 
									
										
										
										
											2015-06-14 14:44:41 +08:00
										 |  |  |       Formula.installed.select do |f| | 
					
						
							|  |  |  |         f.deps.any? do |d| | 
					
						
							|  |  |  |           d.to_formula.full_name == formula.full_name rescue d.name == formula.name | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end.all? { |f| f.rack.subdirs.all? { |keg| Tab.for_keg(keg).HEAD } } | 
					
						
							| 
									
										
										
										
											2012-08-10 16:33:47 -04:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |