2016-04-25 17:57:51 +01:00
|
|
|
require "utils/bottles"
|
2015-12-29 12:57:48 +01:00
|
|
|
require "formula"
|
|
|
|
|
2018-08-08 09:43:38 +02:00
|
|
|
module CleanupRefinement
|
|
|
|
refine Pathname do
|
|
|
|
def incomplete?
|
|
|
|
extname.end_with?(".incomplete")
|
|
|
|
end
|
|
|
|
|
|
|
|
def nested_cache?
|
|
|
|
directory? && ["glide_home", "java_cache", "npm_cache"].include?(basename.to_s)
|
|
|
|
end
|
|
|
|
|
|
|
|
def prune?(days)
|
|
|
|
return false unless days
|
|
|
|
return true if days.zero?
|
|
|
|
|
|
|
|
# TODO: Replace with ActiveSupport's `.days.ago`.
|
|
|
|
mtime < ((@time ||= Time.now) - days * 60 * 60 * 24)
|
|
|
|
end
|
|
|
|
|
|
|
|
def stale?(scrub = false)
|
|
|
|
return false unless file?
|
|
|
|
|
|
|
|
stale_formula?(scrub)
|
|
|
|
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
|
|
|
|
self.version
|
|
|
|
end
|
|
|
|
else
|
|
|
|
self.version
|
|
|
|
end
|
|
|
|
|
|
|
|
return false unless version
|
|
|
|
return false unless (name = basename.to_s[/\A(.*?)\-\-?(?:#{Regexp.escape(version)})/, 1])
|
|
|
|
|
|
|
|
formula = begin
|
|
|
|
Formulary.from_rack(HOMEBREW_CELLAR/name)
|
|
|
|
rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
if version.is_a?(PkgVersion)
|
|
|
|
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
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using CleanupRefinement
|
|
|
|
|
2015-12-29 12:57:48 +01:00
|
|
|
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
|
|
|
|
|
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?
|
|
|
|
HOMEBREW_LOGS.subdirs.each do |dir|
|
2018-08-08 09:43:38 +02:00
|
|
|
cleanup_path(dir) { dir.rmtree } if dir.prune?(ARGV.value("prune")&.to_i || DEFAULT_LOG_DAYS)
|
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|
|
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?
|
|
|
|
|
|
|
|
if path.prune?(ARGV.value("prune")&.to_i)
|
2015-12-29 12:57:48 +01:00
|
|
|
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
|
|
|
|
|
2018-08-08 09:43:38 +02:00
|
|
|
next cleanup_path(path) { path.unlink } if path.stale?(ARGV.switch?("s"))
|
2015-12-29 12:57:48 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-03-21 04:13:13 -05:00
|
|
|
def cleanup_path(path)
|
2018-08-08 09:43:38 +02:00
|
|
|
disk_usage = path.disk_usage
|
|
|
|
|
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
|
|
|
|
|
2018-08-08 09:43:38 +02:00
|
|
|
update_disk_cleanup_size(disk_usage)
|
2015-12-29 12:57:48 +01:00
|
|
|
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
|
|
|
|
end
|
|
|
|
end
|