| 
									
										
										
										
											2016-04-25 17:57:51 +01:00
										 |  |  | require "utils/bottles" | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  | require "formula" | 
					
						
							| 
									
										
										
										
											2018-09-03 19:39:07 +01:00
										 |  |  | require "cask/cask_loader" | 
					
						
							| 
									
										
										
										
											2018-08-10 00:54:03 +02:00
										 |  |  | require "set" | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  | module CleanupRefinement | 
					
						
							| 
									
										
										
										
											2018-09-17 04:11:09 +02:00
										 |  |  |   LATEST_CASK_OUTDATED = 7.days.ago | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-09 01:55:43 +02:00
										 |  |  |   refine Enumerator do | 
					
						
							|  |  |  |     def parallel | 
					
						
							|  |  |  |       queue = Queue.new | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       each do |element| | 
					
						
							|  |  |  |         queue.enq(element) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       workers = (0...Hardware::CPU.cores).map do | 
					
						
							|  |  |  |         Thread.new do | 
					
						
							|  |  |  |           Kernel.loop do | 
					
						
							|  |  |  |             begin | 
					
						
							|  |  |  |               yield queue.deq(true) | 
					
						
							|  |  |  |             rescue ThreadError | 
					
						
							|  |  |  |               break # if queue is empty | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       workers.each(&:join) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |   refine Pathname do | 
					
						
							|  |  |  |     def incomplete? | 
					
						
							|  |  |  |       extname.end_with?(".incomplete") | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def nested_cache? | 
					
						
							| 
									
										
										
										
											2018-09-03 18:59:53 +10:00
										 |  |  |       directory? && %w[cargo_cache go_cache glide_home java_cache npm_cache gclient_cache].include?(basename.to_s) | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-30 05:19:20 +01:00
										 |  |  |     def go_cache_directory? | 
					
						
							|  |  |  |       # Go makes its cache contents read-only to ensure cache integrity, | 
					
						
							|  |  |  |       # which makes sense but is something we need to undo for cleanup. | 
					
						
							|  |  |  |       directory? && %w[go_cache].include?(basename.to_s) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |     def prune?(days) | 
					
						
							|  |  |  |       return false unless days | 
					
						
							|  |  |  |       return true if days.zero? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-01 06:42:47 +02:00
										 |  |  |       return true if symlink? && !exist? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 04:11:09 +02:00
										 |  |  |       mtime < days.days.ago | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def stale?(scrub = false) | 
					
						
							| 
									
										
										
										
											2018-08-29 01:34:40 +02:00
										 |  |  |       return false unless resolved_path.file? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  |       stale_formula?(scrub) || stale_cask?(scrub) | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def stale_formula?(scrub) | 
					
						
							|  |  |  |       return false unless HOMEBREW_CELLAR.directory? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       version = if to_s.match?(Pathname::BOTTLE_EXTNAME_RX) | 
					
						
							|  |  |  |         begin | 
					
						
							|  |  |  |           Utils::Bottles.resolve_version(self) | 
					
						
							|  |  |  |         rescue | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  |           nil | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 05:08:50 +02:00
										 |  |  |       version ||= basename.to_s[/\A.*(?:\-\-.*?)*\-\-(.*?)#{Regexp.escape(extname)}\Z/, 1] | 
					
						
							| 
									
										
										
										
											2018-08-10 00:54:03 +02:00
										 |  |  |       version ||= basename.to_s[/\A.*\-\-?(.*?)#{Regexp.escape(extname)}\Z/, 1] | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |       return false unless version | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 00:54:03 +02:00
										 |  |  |       version = Version.new(version) | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 05:08:50 +02:00
										 |  |  |       return false unless formula_name = basename.to_s[/\A(.*?)(?:\-\-.*?)*\-\-?(?:#{Regexp.escape(version)})/, 1] | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       formula = begin | 
					
						
							| 
									
										
										
										
											2018-08-10 00:54:03 +02:00
										 |  |  |         Formulary.from_rack(HOMEBREW_CELLAR/formula_name) | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |       rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError | 
					
						
							|  |  |  |         return false | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 00:54:03 +02:00
										 |  |  |       resource_name = basename.to_s[/\A.*?\-\-(.*?)\-\-?(?:#{Regexp.escape(version)})/, 1] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 05:08:50 +02:00
										 |  |  |       if resource_name == "patch" | 
					
						
							| 
									
										
										
										
											2018-08-12 19:54:08 +02:00
										 |  |  |         patch_hashes = formula.stable&.patches&.select(&:external?)&.map(&:resource)&.map(&:version) | 
					
						
							| 
									
										
										
										
											2018-08-10 05:08:50 +02:00
										 |  |  |         return true unless patch_hashes&.include?(Checksum.new(:sha256, version.to_s)) | 
					
						
							|  |  |  |       elsif resource_name && resource_version = formula.stable&.resources&.dig(resource_name)&.version | 
					
						
							|  |  |  |         return true if resource_version != version | 
					
						
							| 
									
										
										
										
											2018-08-10 00:54:03 +02:00
										 |  |  |       elsif version.is_a?(PkgVersion) | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |         return true if formula.pkg_version > version | 
					
						
							|  |  |  |       elsif formula.version > version | 
					
						
							|  |  |  |         return true | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return true if scrub && !formula.installed? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return true if Utils::Bottles.file_outdated?(formula, self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       false | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def stale_cask?(scrub) | 
					
						
							|  |  |  |       return false unless name = basename.to_s[/\A(.*?)\-\-/, 1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       cask = begin | 
					
						
							| 
									
										
										
										
											2018-09-06 08:29:14 +02:00
										 |  |  |         Cask::CaskLoader.load(name) | 
					
						
							|  |  |  |       rescue Cask::CaskUnavailableError | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  |         return false | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       unless basename.to_s.match?(/\A#{Regexp.escape(name)}\-\-#{Regexp.escape(cask.version)}\b/) | 
					
						
							|  |  |  |         return true | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return true if scrub && !cask.versions.include?(cask.version) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 04:11:09 +02:00
										 |  |  |       return mtime < LATEST_CASK_OUTDATED if cask.version.latest? | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       false | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using CleanupRefinement | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  | module Homebrew | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |   class Cleanup | 
					
						
							|  |  |  |     extend Predicable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     attr_predicate :dry_run?, :scrub? | 
					
						
							|  |  |  |     attr_reader :args, :days, :cache | 
					
						
							|  |  |  |     attr_reader :disk_cleanup_size | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def initialize(*args, dry_run: false, scrub: false, days: nil, cache: HOMEBREW_CACHE) | 
					
						
							|  |  |  |       @disk_cleanup_size = 0
 | 
					
						
							|  |  |  |       @args = args | 
					
						
							|  |  |  |       @dry_run = dry_run | 
					
						
							|  |  |  |       @scrub = scrub | 
					
						
							|  |  |  |       @days = days | 
					
						
							|  |  |  |       @cache = cache | 
					
						
							| 
									
										
										
										
											2018-08-10 00:54:03 +02:00
										 |  |  |       @cleaned_up_paths = Set.new | 
					
						
							| 
									
										
										
										
											2017-08-13 04:21:07 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |     def clean! | 
					
						
							|  |  |  |       if args.empty? | 
					
						
							| 
									
										
										
										
											2018-08-11 17:23:46 +02:00
										 |  |  |         Formula.installed.sort_by(&:name).each do |formula| | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |           cleanup_formula(formula) | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         cleanup_cache | 
					
						
							|  |  |  |         cleanup_logs | 
					
						
							| 
									
										
										
										
											2018-10-03 19:26:49 +01:00
										 |  |  |         cleanup_portable_ruby | 
					
						
							| 
									
										
										
										
											2018-10-14 00:13:04 +02:00
										 |  |  |         cleanup_lockfiles | 
					
						
							| 
									
										
										
										
											2018-08-11 17:23:35 +02:00
										 |  |  |         return if dry_run? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 08:22:51 -07:00
										 |  |  |         cleanup_old_cache_db | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |         rm_ds_store | 
					
						
							| 
									
										
										
										
											2019-01-02 13:21:34 +00:00
										 |  |  |         prune_prefix_symlinks_and_directories | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |       else | 
					
						
							|  |  |  |         args.each do |arg| | 
					
						
							|  |  |  |           formula = begin | 
					
						
							| 
									
										
										
										
											2018-09-11 17:44:18 +02:00
										 |  |  |             Formulary.resolve(arg) | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |           rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError | 
					
						
							|  |  |  |             nil | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           cask = begin | 
					
						
							| 
									
										
										
										
											2018-09-06 08:29:14 +02:00
										 |  |  |             Cask::CaskLoader.load(arg) | 
					
						
							|  |  |  |           rescue Cask::CaskUnavailableError | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |             nil | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |           cleanup_formula(formula) if formula | 
					
						
							|  |  |  |           cleanup_cask(cask) if cask | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											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_formula(formula) | 
					
						
							|  |  |  |       formula.eligible_kegs_for_cleanup.each(&method(:cleanup_keg)) | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  |       cleanup_cache(Pathname.glob(cache/"#{formula.name}--*")) | 
					
						
							| 
									
										
										
										
											2018-08-09 01:55:43 +02:00
										 |  |  |       rm_ds_store([formula.rack]) | 
					
						
							| 
									
										
										
										
											2018-08-09 16:46:39 +02:00
										 |  |  |       cleanup_lockfiles(FormulaLock.new(formula.name).path) | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  |     def cleanup_cask(cask) | 
					
						
							|  |  |  |       cleanup_cache(Pathname.glob(cache/"Cask/#{cask.token}--*")) | 
					
						
							| 
									
										
										
										
											2018-08-09 01:55:43 +02:00
										 |  |  |       rm_ds_store([cask.caskroom_path]) | 
					
						
							| 
									
										
										
										
											2018-08-09 16:46:39 +02:00
										 |  |  |       cleanup_lockfiles(CaskLock.new(cask.token).path) | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |     DEFAULT_LOG_DAYS = 14
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     def cleanup_logs | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       return unless HOMEBREW_LOGS.directory? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       HOMEBREW_LOGS.subdirs.each do |dir| | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |         cleanup_path(dir) { dir.rmtree } if dir.prune?(days || DEFAULT_LOG_DAYS) | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 04:11:54 +02:00
										 |  |  |     def cleanup_unreferenced_downloads | 
					
						
							|  |  |  |       return if dry_run? | 
					
						
							|  |  |  |       return unless (cache/"downloads").directory? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-14 00:13:04 +02:00
										 |  |  |       downloads = (cache/"downloads").children | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 04:11:54 +02:00
										 |  |  |       referenced_downloads = [cache, cache/"Cask"].select(&:directory?) | 
					
						
							|  |  |  |                                                   .flat_map(&:children) | 
					
						
							|  |  |  |                                                   .select(&:symlink?) | 
					
						
							|  |  |  |                                                   .map(&:resolved_path) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-14 00:13:04 +02:00
										 |  |  |       (downloads - referenced_downloads).each do |download| | 
					
						
							|  |  |  |         if download.incomplete? | 
					
						
							|  |  |  |           begin | 
					
						
							|  |  |  |             LockFile.new(download.basename).with_lock do | 
					
						
							|  |  |  |               download.unlink | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           rescue OperationInProgressError | 
					
						
							|  |  |  |             # Skip incomplete downloads which are still in progress. | 
					
						
							|  |  |  |             next | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           download.unlink | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2018-08-10 04:11:54 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  |     def cleanup_cache(entries = nil) | 
					
						
							|  |  |  |       entries ||= [cache, cache/"Cask"].select(&:directory?).flat_map(&:children) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       entries.each do |path| | 
					
						
							| 
									
										
										
										
											2018-08-30 05:19:20 +01:00
										 |  |  |         FileUtils.chmod_R 0755, path if path.go_cache_directory? && !dry_run? | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |         next cleanup_path(path) { path.unlink } if path.incomplete? | 
					
						
							|  |  |  |         next cleanup_path(path) { FileUtils.rm_rf path } if path.nested_cache? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |         if path.prune?(days) | 
					
						
							| 
									
										
										
										
											2018-08-25 22:06:24 +02:00
										 |  |  |           if path.file? || path.symlink? | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |             cleanup_path(path) { path.unlink } | 
					
						
							|  |  |  |           elsif path.directory? && path.to_s.include?("--") | 
					
						
							|  |  |  |             cleanup_path(path) { FileUtils.rm_rf path } | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |           next | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  |         next cleanup_path(path) { path.unlink } if path.stale?(scrub?) | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2018-08-10 04:11:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       cleanup_unreferenced_downloads | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 04:13:13 -05:00
										 |  |  |     def cleanup_path(path) | 
					
						
							| 
									
										
										
										
											2018-08-10 00:54:03 +02:00
										 |  |  |       return unless @cleaned_up_paths.add?(path) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 09:43:38 +02:00
										 |  |  |       disk_usage = path.disk_usage | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 11:20:53 +02:00
										 |  |  |       if dry_run? | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |         puts "Would remove: #{path} (#{path.abv})" | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         puts "Removing: #{path}... (#{path.abv})" | 
					
						
							|  |  |  |         yield | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 22:23:55 +02:00
										 |  |  |       @disk_cleanup_size += disk_usage | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-09 16:46:39 +02:00
										 |  |  |     def cleanup_lockfiles(*lockfiles) | 
					
						
							| 
									
										
										
										
											2018-08-16 05:55:17 +02:00
										 |  |  |       return if dry_run? | 
					
						
							| 
									
										
										
										
											2018-08-09 16:46:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |       if lockfiles.empty? && HOMEBREW_LOCKS.directory? | 
					
						
							|  |  |  |         lockfiles = HOMEBREW_LOCKS.children.select(&:file?) | 
					
						
							| 
									
										
										
										
											2018-08-09 16:46:39 +02:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       lockfiles.each do |file| | 
					
						
							|  |  |  |         next unless file.readable? | 
					
						
							| 
									
										
										
										
											2018-08-09 16:46:39 +02:00
										 |  |  |         next unless file.open(File::RDWR).flock(File::LOCK_EX | File::LOCK_NB) | 
					
						
							| 
									
										
										
										
											2018-08-11 17:23:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         begin | 
					
						
							| 
									
										
										
										
											2018-08-16 05:55:17 +02:00
										 |  |  |           file.unlink | 
					
						
							| 
									
										
										
										
											2018-08-11 17:23:35 +02:00
										 |  |  |         ensure | 
					
						
							|  |  |  |           file.open(File::RDWR).flock(File::LOCK_UN) if file.exist? | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 19:26:49 +01:00
										 |  |  |     def cleanup_portable_ruby | 
					
						
							|  |  |  |       system_ruby_version = | 
					
						
							|  |  |  |         Utils.popen_read("/usr/bin/ruby", "-e", "puts RUBY_VERSION") | 
					
						
							|  |  |  |              .chomp | 
					
						
							|  |  |  |       use_system_ruby = ( | 
					
						
							|  |  |  |         Gem::Version.new(system_ruby_version) >= Gem::Version.new(RUBY_VERSION) | 
					
						
							|  |  |  |       ) && ENV["HOMEBREW_FORCE_VENDOR_RUBY"].nil? | 
					
						
							|  |  |  |       vendor_path = HOMEBREW_LIBRARY/"Homebrew/vendor" | 
					
						
							|  |  |  |       portable_ruby_version_file = vendor_path/"portable-ruby-version" | 
					
						
							|  |  |  |       portable_ruby_version = if portable_ruby_version_file.exist? | 
					
						
							|  |  |  |         portable_ruby_version_file.read | 
					
						
							|  |  |  |                                   .chomp | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       portable_ruby_path = vendor_path/"portable-ruby" | 
					
						
							|  |  |  |       portable_ruby_glob = "#{portable_ruby_path}/*.*" | 
					
						
							|  |  |  |       Pathname.glob(portable_ruby_glob).each do |path| | 
					
						
							|  |  |  |         next if !use_system_ruby && portable_ruby_version == path.basename.to_s | 
					
						
							|  |  |  |         if dry_run? | 
					
						
							|  |  |  |           puts "Would remove: #{path} (#{path.abv})" | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           FileUtils.rm_rf path | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return unless Dir.glob(portable_ruby_glob).empty? | 
					
						
							|  |  |  |       return unless portable_ruby_path.exist? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-04 15:08:38 +01:00
										 |  |  |       bundler_path = vendor_path/"bundle/ruby" | 
					
						
							| 
									
										
										
										
											2018-10-03 19:26:49 +01:00
										 |  |  |       if dry_run? | 
					
						
							| 
									
										
										
										
											2018-10-04 15:08:38 +01:00
										 |  |  |         puts "Would remove: #{bundler_path} (#{bundler_path.abv})" | 
					
						
							| 
									
										
										
										
											2018-10-03 19:26:49 +01:00
										 |  |  |         puts "Would remove: #{portable_ruby_path} (#{portable_ruby_path.abv})" | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2018-10-04 15:08:38 +01:00
										 |  |  |         FileUtils.rm_rf [bundler_path, portable_ruby_path] | 
					
						
							| 
									
										
										
										
											2018-10-03 19:26:49 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 08:22:51 -07:00
										 |  |  |     def cleanup_old_cache_db | 
					
						
							|  |  |  |       FileUtils.rm_rf [ | 
					
						
							|  |  |  |         cache/"desc_cache.json", | 
					
						
							|  |  |  |         cache/"linkage.db", | 
					
						
							|  |  |  |         cache/"linkage.db.db", | 
					
						
							|  |  |  |       ] | 
					
						
							| 
									
										
										
										
											2018-10-03 19:26:49 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-09 01:55:43 +02:00
										 |  |  |     def rm_ds_store(dirs = nil) | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |       dirs ||= begin | 
					
						
							|  |  |  |         Keg::MUST_EXIST_DIRECTORIES + [ | 
					
						
							|  |  |  |           HOMEBREW_PREFIX/"Caskroom", | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2018-08-09 01:55:43 +02:00
										 |  |  |       dirs.select(&:directory?).each.parallel do |dir| | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |         system_command "find", | 
					
						
							| 
									
										
										
										
											2018-11-02 17:18:07 +00:00
										 |  |  |           args:         [dir, "-name", ".DS_Store", "-delete"], | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |           print_stderr: false | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2019-01-02 13:21:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def prune_prefix_symlinks_and_directories | 
					
						
							|  |  |  |       ObserverPathnameExtension.reset_counts! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dirs = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Keg::MUST_EXIST_SUBDIRECTORIES.each do |dir| | 
					
						
							|  |  |  |         next unless dir.directory? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dir.find do |path| | 
					
						
							|  |  |  |           path.extend(ObserverPathnameExtension) | 
					
						
							|  |  |  |           if path.symlink? | 
					
						
							|  |  |  |             unless path.resolved_path_exists? | 
					
						
							|  |  |  |               if path.to_s =~ Keg::INFOFILE_RX | 
					
						
							|  |  |  |                 path.uninstall_info unless dry_run? | 
					
						
							|  |  |  |               end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               if dry_run? | 
					
						
							|  |  |  |                 puts "Would remove (broken link): #{path}" | 
					
						
							|  |  |  |               else | 
					
						
							|  |  |  |                 path.unlink | 
					
						
							|  |  |  |               end | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           elsif path.directory? && !Keg::MUST_EXIST_SUBDIRECTORIES.include?(path) | 
					
						
							|  |  |  |             dirs << path | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dirs.reverse_each do |d| | 
					
						
							|  |  |  |         if dry_run? && d.children.empty? | 
					
						
							|  |  |  |           puts "Would remove (empty directory): #{d}" | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           d.rmdir_if_possible | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return if dry_run? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return if ObserverPathnameExtension.total.zero? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       n, d = ObserverPathnameExtension.counts | 
					
						
							|  |  |  |       print "Pruned #{n} symbolic links " | 
					
						
							|  |  |  |       print "and #{d} directories " if d.positive? | 
					
						
							|  |  |  |       puts "from #{HOMEBREW_PREFIX}" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-12-29 12:57:48 +01:00
										 |  |  |   end | 
					
						
							|  |  |  | end |