| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  | require "utils/bottles" | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  | require "formula" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module Homebrew | 
					
						
							|  |  |  |   module Cleanup | 
					
						
							| 
									
										
										
										
											2016-09-25 01:52:07 +02:00
										 |  |  |     @disk_cleanup_size = 0
 | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-13 04:21:07 +05:30
										 |  |  |     class << self | 
					
						
							|  |  |  |       attr_reader :disk_cleanup_size | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     module_function | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def cleanup | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       cleanup_cellar | 
					
						
							|  |  |  |       cleanup_cache | 
					
						
							|  |  |  |       cleanup_logs | 
					
						
							| 
									
										
										
										
											2016-10-24 17:07:57 +02:00
										 |  |  |       return if ARGV.dry_run? | 
					
						
							|  |  |  |       cleanup_lockfiles | 
					
						
							|  |  |  |       rm_ds_store | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     def update_disk_cleanup_size(path_size) | 
					
						
							| 
									
										
										
										
											2016-09-25 01:52:07 +02:00
										 |  |  |       @disk_cleanup_size += path_size | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     def unremovable_kegs | 
					
						
							|  |  |  |       @unremovable_kegs ||= [] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def cleanup_cellar(formulae = Formula.installed) | 
					
						
							|  |  |  |       formulae.each(&method(:cleanup_formula)) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def cleanup_formula(formula) | 
					
						
							|  |  |  |       formula.eligible_kegs_for_cleanup.each(&method(:cleanup_keg)) | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     def cleanup_keg(keg) | 
					
						
							|  |  |  |       cleanup_path(keg) { keg.uninstall } | 
					
						
							|  |  |  |     rescue Errno::EACCES => e | 
					
						
							|  |  |  |       opoo e.message | 
					
						
							|  |  |  |       unremovable_kegs << keg | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def cleanup_logs | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       return unless HOMEBREW_LOGS.directory? | 
					
						
							|  |  |  |       HOMEBREW_LOGS.subdirs.each do |dir| | 
					
						
							| 
									
										
										
										
											2016-09-17 15:32:44 +01:00
										 |  |  |         cleanup_path(dir) { dir.rmtree } if prune?(dir, days_default: 14) | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     def cleanup_cache(cache = HOMEBREW_CACHE) | 
					
						
							| 
									
										
										
										
											2016-06-01 08:46:33 +01:00
										 |  |  |       return unless cache.directory? | 
					
						
							|  |  |  |       cache.children.each do |path| | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |         if path.to_s.end_with? ".incomplete" | 
					
						
							|  |  |  |           cleanup_path(path) { path.unlink } | 
					
						
							|  |  |  |           next | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-10-08 10:05:04 -07:00
										 |  |  |         if %w[glide_home java_cache npm_cache].include?(path.basename.to_s) && path.directory? | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |           cleanup_path(path) { FileUtils.rm_rf path } | 
					
						
							|  |  |  |           next | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         if prune?(path) | 
					
						
							|  |  |  |           if path.file? | 
					
						
							|  |  |  |             cleanup_path(path) { path.unlink } | 
					
						
							|  |  |  |           elsif path.directory? && path.to_s.include?("--") | 
					
						
							|  |  |  |             cleanup_path(path) { FileUtils.rm_rf path } | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |           next | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         next unless path.file? | 
					
						
							|  |  |  |         file = path | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 22:03:08 +02:00
										 |  |  |         if file.to_s =~ Pathname::BOTTLE_EXTNAME_RX | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |           version = begin | 
					
						
							|  |  |  |                       Utils::Bottles.resolve_version(file) | 
					
						
							|  |  |  |                     rescue | 
					
						
							|  |  |  |                       file.version | 
					
						
							|  |  |  |                     end | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |         else | 
					
						
							|  |  |  |           version = file.version | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         next unless version | 
					
						
							|  |  |  |         next unless (name = file.basename.to_s[/(.*)-(?:#{Regexp.escape(version)})/, 1]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         next unless HOMEBREW_CELLAR.directory? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         begin | 
					
						
							|  |  |  |           f = Formulary.from_rack(HOMEBREW_CELLAR/name) | 
					
						
							|  |  |  |         rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError | 
					
						
							|  |  |  |           next | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 22:03:08 +02:00
										 |  |  |         file_is_stale = if version.is_a?(PkgVersion) | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |           f.pkg_version > version | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           f.version > version | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |         if file_is_stale || ARGV.switch?("s") && !f.installed? || Utils::Bottles.file_outdated?(f, file) | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |           cleanup_path(file) { file.unlink } | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     def cleanup_path(path) | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       if ARGV.dry_run? | 
					
						
							|  |  |  |         puts "Would remove: #{path} (#{path.abv})" | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         puts "Removing: #{path}... (#{path.abv})" | 
					
						
							|  |  |  |         yield | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       update_disk_cleanup_size(path.disk_usage) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     def cleanup_lockfiles | 
					
						
							| 
									
										
										
										
											2016-06-08 17:29:03 +08:00
										 |  |  |       return unless HOMEBREW_LOCK_DIR.directory? | 
					
						
							|  |  |  |       candidates = HOMEBREW_LOCK_DIR.children | 
					
						
							|  |  |  |       lockfiles  = candidates.select(&:file?) | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       lockfiles.each do |file| | 
					
						
							|  |  |  |         next unless file.readable? | 
					
						
							| 
									
										
										
										
											2018-03-14 21:50:53 +08:00
										 |  |  |         file.open(File::RDWR).flock(File::LOCK_EX | File::LOCK_NB) && file.unlink | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     def rm_ds_store | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       paths = Queue.new | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |       %w[Cellar Frameworks Library bin etc include lib opt sbin share var] | 
					
						
							|  |  |  |         .map { |p| HOMEBREW_PREFIX/p }.each { |p| paths << p if p.exist? } | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       workers = (0...Hardware::CPU.cores).map do | 
					
						
							|  |  |  |         Thread.new do | 
					
						
							| 
									
										
										
										
											2016-08-22 08:52:42 +02:00
										 |  |  |           Kernel.loop do | 
					
						
							|  |  |  |             begin | 
					
						
							|  |  |  |               quiet_system "find", paths.deq(true), "-name", ".DS_Store", "-delete" | 
					
						
							|  |  |  |             rescue ThreadError | 
					
						
							|  |  |  |               break # if queue is empty | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       workers.map(&:join) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     def prune?(path, options = {}) | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       @time ||= Time.now | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       path_modified_time = path.mtime | 
					
						
							|  |  |  |       days_default = options[:days_default] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       prune = ARGV.value "prune" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return true if prune == "all" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       prune_time = if prune | 
					
						
							|  |  |  |         @time - 60 * 60 * 24 * prune.to_i | 
					
						
							|  |  |  |       elsif days_default | 
					
						
							|  |  |  |         @time - 60 * 60 * 24 * days_default.to_i | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return false unless prune_time | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       path_modified_time < prune_time | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |