2010-09-11 20:22:54 +01:00
|
|
|
require 'formula'
|
2012-08-10 16:33:47 -04:00
|
|
|
require 'keg'
|
2012-04-30 15:10:51 -05:00
|
|
|
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
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2013-05-15 12:45:38 -05:00
|
|
|
def cleanup_keg keg
|
|
|
|
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
|
|
|
|
2014-12-27 16:16:16 -05:00
|
|
|
if f.version > version || 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
|
|
|
|
lockfiles = candidates.select { |f| f.file? && f.extname == '.brewing' }
|
|
|
|
lockfiles.select(&:readable?).each do |file|
|
|
|
|
file.open.flock(File::LOCK_EX | File::LOCK_NB) and file.unlink
|
|
|
|
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].
|
|
|
|
map { |p| HOMEBREW_PREFIX/p }.select(&:exist?)
|
|
|
|
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-04-17 22:58:02 -04:00
|
|
|
if not formula.keg_only? or 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-04-17 22:58:02 -04:00
|
|
|
Formula.installed.
|
2015-05-27 20:48:32 +08:00
|
|
|
select { |f| f.deps.any? { |d| d.to_formula.full_name == formula.full_name } }.
|
2015-04-17 22:58:02 -04:00
|
|
|
all? { |f| f.rack.subdirs.all? { |keg| Tab.for_keg(keg).HEAD } }
|
2012-08-10 16:33:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|