Use option parser for brew cleanup.

This commit is contained in:
Markus Reiter 2018-08-08 11:20:53 +02:00
parent 6ae224611c
commit 03b93da296
5 changed files with 90 additions and 76 deletions

View File

@ -1,5 +1,6 @@
require "utils/bottles" require "utils/bottles"
require "formula" require "formula"
require "hbc/cask_loader"
module CleanupRefinement module CleanupRefinement
refine Pathname do refine Pathname do
@ -67,22 +68,50 @@ end
using CleanupRefinement using CleanupRefinement
module Homebrew module Homebrew
module Cleanup class Cleanup
@disk_cleanup_size = 0 extend Predicable
class << self attr_predicate :dry_run?, :scrub?
attr_reader :disk_cleanup_size 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
end end
module_function def clean!
if args.empty?
Formula.installed.each do |formula|
cleanup_formula(formula)
end
cleanup_cache
cleanup_logs
return if dry_run?
cleanup_lockfiles
rm_ds_store
else
args.each do |arg|
formula = begin
Formula[arg]
rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
nil
end
def cleanup cask = begin
cleanup_cellar Hbc::CaskLoader.load(arg)
cleanup_cache rescue Hbc::CaskUnavailableError
cleanup_logs nil
return if ARGV.dry_run? end
cleanup_lockfiles
rm_ds_store cleanup_formula(formula) if formula
cleanup_cask(cask) if cask
end
end
end end
def update_disk_cleanup_size(path_size) def update_disk_cleanup_size(path_size)
@ -93,14 +122,12 @@ module Homebrew
@unremovable_kegs ||= [] @unremovable_kegs ||= []
end end
def cleanup_cellar(formulae = Formula.installed)
formulae.each(&method(:cleanup_formula))
end
def cleanup_formula(formula) def cleanup_formula(formula)
formula.eligible_kegs_for_cleanup.each(&method(:cleanup_keg)) formula.eligible_kegs_for_cleanup.each(&method(:cleanup_keg))
end end
def cleanup_cask(cask); end
def cleanup_keg(keg) def cleanup_keg(keg)
cleanup_path(keg) { keg.uninstall } cleanup_path(keg) { keg.uninstall }
rescue Errno::EACCES => e rescue Errno::EACCES => e
@ -113,17 +140,17 @@ module Homebrew
def cleanup_logs def cleanup_logs
return unless HOMEBREW_LOGS.directory? return unless HOMEBREW_LOGS.directory?
HOMEBREW_LOGS.subdirs.each do |dir| HOMEBREW_LOGS.subdirs.each do |dir|
cleanup_path(dir) { dir.rmtree } if dir.prune?(ARGV.value("prune")&.to_i || DEFAULT_LOG_DAYS) cleanup_path(dir) { dir.rmtree } if dir.prune?(days || DEFAULT_LOG_DAYS)
end end
end end
def cleanup_cache(cache = HOMEBREW_CACHE) def cleanup_cache
return unless cache.directory? return unless cache.directory?
cache.children.each do |path| cache.children.each do |path|
next cleanup_path(path) { path.unlink } if path.incomplete? next cleanup_path(path) { path.unlink } if path.incomplete?
next cleanup_path(path) { FileUtils.rm_rf path } if path.nested_cache? next cleanup_path(path) { FileUtils.rm_rf path } if path.nested_cache?
if path.prune?(ARGV.value("prune")&.to_i) if path.prune?(days)
if path.file? if path.file?
cleanup_path(path) { path.unlink } cleanup_path(path) { path.unlink }
elsif path.directory? && path.to_s.include?("--") elsif path.directory? && path.to_s.include?("--")
@ -139,7 +166,7 @@ module Homebrew
def cleanup_path(path) def cleanup_path(path)
disk_usage = path.disk_usage disk_usage = path.disk_usage
if ARGV.dry_run? if dry_run?
puts "Would remove: #{path} (#{path.abv})" puts "Would remove: #{path} (#{path.abv})"
else else
puts "Removing: #{path}... (#{path.abv})" puts "Removing: #{path}... (#{path.abv})"

View File

@ -12,34 +12,36 @@
#: deleted. If you want to delete those too: `rm -rf $(brew --cache)` #: deleted. If you want to delete those too: `rm -rf $(brew --cache)`
require "cleanup" require "cleanup"
require "cli_parser"
module Homebrew module Homebrew
module_function module_function
def cleanup def cleanup
if ARGV.named.empty? CLI::Parser.parse do
Cleanup.cleanup switch "-n", "--dry-run"
else switch "-s"
Cleanup.cleanup_cellar(ARGV.resolved_formulae) flag "--prune="
end end
report_disk_usage unless Cleanup.disk_cleanup_size.zero? cleanup = Cleanup.new(*args.remaining, dry_run: args.dry_run?, scrub: args.s?, days: args.prune&.to_i)
report_unremovable_kegs unless Cleanup.unremovable_kegs.empty?
end
def report_disk_usage cleanup.clean!
disk_space = disk_usage_readable(Cleanup.disk_cleanup_size)
if ARGV.dry_run? unless cleanup.disk_cleanup_size.zero?
ohai "This operation would free approximately #{disk_space} of disk space." disk_space = disk_usage_readable(cleanup.disk_cleanup_size)
else if args.dry_run?
ohai "This operation has freed approximately #{disk_space} of disk space." ohai "This operation would free approximately #{disk_space} of disk space."
else
ohai "This operation has freed approximately #{disk_space} of disk space."
end
end end
end
def report_unremovable_kegs return if cleanup.unremovable_kegs.empty?
ofail <<~EOS ofail <<~EOS
Could not cleanup old kegs! Fix your permissions on: Could not cleanup old kegs! Fix your permissions on:
#{Cleanup.unremovable_kegs.join "\n "} #{cleanup.unremovable_kegs.join "\n "}
EOS EOS
end end
end end

View File

@ -147,10 +147,6 @@ module Homebrew
return unless legacy_cache.writable_real? return unless legacy_cache.writable_real?
FileUtils.touch migration_attempted_file FileUtils.touch migration_attempted_file
# Cleanup to avoid copying files unnecessarily
ohai "Cleaning up #{legacy_cache}..."
Cleanup.cleanup_cache legacy_cache
# This directory could have been compromised if it's world-writable/ # This directory could have been compromised if it's world-writable/
# a symlink/owned by another user so don't copy files in those cases. # a symlink/owned by another user so don't copy files in those cases.
world_writable = legacy_cache.stat.mode & 0777 == 0777 world_writable = legacy_cache.stat.mode & 0777 == 0777

View File

@ -98,7 +98,7 @@ module Homebrew
upgrade_formula(f) upgrade_formula(f)
next if !ARGV.include?("--cleanup") && !ENV["HOMEBREW_UPGRADE_CLEANUP"] next if !ARGV.include?("--cleanup") && !ENV["HOMEBREW_UPGRADE_CLEANUP"]
next unless f.installed? next unless f.installed?
Homebrew::Cleanup.cleanup_formula f Cleanup.new.cleanup_formula(f)
rescue UnsatisfiedRequirements => e rescue UnsatisfiedRequirements => e
Homebrew.failed = true Homebrew.failed = true
onoe "#{f}: #{e}" onoe "#{f}: #{e}"

View File

@ -43,16 +43,14 @@ describe Homebrew::Cleanup do
describe "::cleanup" do describe "::cleanup" do
it "removes .DS_Store and lock files" do it "removes .DS_Store and lock files" do
described_class.cleanup subject.clean!
expect(ds_store).not_to exist expect(ds_store).not_to exist
expect(lock_file).not_to exist expect(lock_file).not_to exist
end end
it "doesn't remove anything if `--dry-run` is specified" do it "doesn't remove anything if `dry_run` is true" do
ARGV << "--dry-run" described_class.new(dry_run: true).clean!
described_class.cleanup
expect(ds_store).to exist expect(ds_store).to exist
expect(lock_file).to exist expect(lock_file).to exist
@ -61,7 +59,7 @@ describe Homebrew::Cleanup do
it "doesn't remove the lock file if it is locked" do it "doesn't remove the lock file if it is locked" do
lock_file.open(File::RDWR | File::CREAT).flock(File::LOCK_EX | File::LOCK_NB) lock_file.open(File::RDWR | File::CREAT).flock(File::LOCK_EX | File::LOCK_NB)
described_class.cleanup subject.clean!
expect(lock_file).to exist expect(lock_file).to exist
end end
@ -69,10 +67,8 @@ describe Homebrew::Cleanup do
context "when it can't remove a keg" do context "when it can't remove a keg" do
let(:f1) { Class.new(Testball) { version "0.1" }.new } let(:f1) { Class.new(Testball) { version "0.1" }.new }
let(:f2) { Class.new(Testball) { version "0.2" }.new } let(:f2) { Class.new(Testball) { version "0.2" }.new }
let(:unremovable_kegs) { [] }
before do before do
described_class.instance_variable_set(:@unremovable_kegs, [])
[f1, f2].each do |f| [f1, f2].each do |f|
f.brew do f.brew do
f.install f.install
@ -87,13 +83,13 @@ describe Homebrew::Cleanup do
end end
it "doesn't remove any kegs" do it "doesn't remove any kegs" do
described_class.cleanup_formula f2 subject.cleanup_formula f2
expect(f1.installed_kegs.size).to eq(2) expect(f1.installed_kegs.size).to eq(2)
end end
it "lists the unremovable kegs" do it "lists the unremovable kegs" do
described_class.cleanup_formula f2 subject.cleanup_formula f2
expect(described_class.unremovable_kegs).to contain_exactly(f1.installed_kegs[0]) expect(subject.unremovable_kegs).to contain_exactly(f1.installed_kegs[0])
end end
end end
end end
@ -131,7 +127,7 @@ describe Homebrew::Cleanup do
expect(f3).to be_installed expect(f3).to be_installed
expect(f4).to be_installed expect(f4).to be_installed
described_class.cleanup_formula f3 subject.cleanup_formula f3
expect(f1).not_to be_installed expect(f1).not_to be_installed
expect(f2).not_to be_installed expect(f2).not_to be_installed
@ -146,21 +142,20 @@ describe Homebrew::Cleanup do
path.mkpath path.mkpath
end end
it "cleans all logs if prune all" do it "cleans all logs if prune is 0" do
ARGV << "--prune=all" described_class.new(days: 0).cleanup_logs
described_class.cleanup_logs
expect(path).not_to exist expect(path).not_to exist
end end
it "cleans up logs if older than 14 days" do it "cleans up logs if older than 14 days" do
allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - 15 * 60 * 60 * 24) allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - 15 * 60 * 60 * 24)
described_class.cleanup_logs subject.cleanup_logs
expect(path).not_to exist expect(path).not_to exist
end end
it "does not clean up logs less than 14 days old" do it "does not clean up logs less than 14 days old" do
allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - 2 * 60 * 60 * 24) allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - 2 * 60 * 60 * 24)
described_class.cleanup_logs subject.cleanup_logs
expect(path).to exist expect(path).to exist
end end
end end
@ -170,7 +165,7 @@ describe Homebrew::Cleanup do
incomplete = (HOMEBREW_CACHE/"something.incomplete") incomplete = (HOMEBREW_CACHE/"something.incomplete")
incomplete.mkpath incomplete.mkpath
described_class.cleanup_cache subject.cleanup_cache
expect(incomplete).not_to exist expect(incomplete).not_to exist
end end
@ -179,7 +174,7 @@ describe Homebrew::Cleanup do
glide_home = (HOMEBREW_CACHE/"glide_home") glide_home = (HOMEBREW_CACHE/"glide_home")
glide_home.mkpath glide_home.mkpath
described_class.cleanup_cache subject.cleanup_cache
expect(glide_home).not_to exist expect(glide_home).not_to exist
end end
@ -188,7 +183,7 @@ describe Homebrew::Cleanup do
java_cache = (HOMEBREW_CACHE/"java_cache") java_cache = (HOMEBREW_CACHE/"java_cache")
java_cache.mkpath java_cache.mkpath
described_class.cleanup_cache subject.cleanup_cache
expect(java_cache).not_to exist expect(java_cache).not_to exist
end end
@ -197,7 +192,7 @@ describe Homebrew::Cleanup do
npm_cache = (HOMEBREW_CACHE/"npm_cache") npm_cache = (HOMEBREW_CACHE/"npm_cache")
npm_cache.mkpath npm_cache.mkpath
described_class.cleanup_cache subject.cleanup_cache
expect(npm_cache).not_to exist expect(npm_cache).not_to exist
end end
@ -211,9 +206,7 @@ describe Homebrew::Cleanup do
gist.mkpath gist.mkpath
FileUtils.touch svn FileUtils.touch svn
allow(ARGV).to receive(:value).with("prune").and_return("all") described_class.new(days: 0).cleanup_cache
described_class.cleanup_cache
expect(git).not_to exist expect(git).not_to exist
expect(gist).to exist expect(gist).to exist
@ -223,9 +216,8 @@ describe Homebrew::Cleanup do
it "does not clean up directories that are not VCS checkouts" do it "does not clean up directories that are not VCS checkouts" do
git = (HOMEBREW_CACHE/"git") git = (HOMEBREW_CACHE/"git")
git.mkpath git.mkpath
allow(ARGV).to receive(:value).with("prune").and_return("all")
described_class.cleanup_cache described_class.new(days: 0).cleanup_cache
expect(git).to exist expect(git).to exist
end end
@ -233,17 +225,15 @@ describe Homebrew::Cleanup do
it "cleans up VCS checkout directories with modified time < prune time" do it "cleans up VCS checkout directories with modified time < prune time" do
foo = (HOMEBREW_CACHE/"--foo") foo = (HOMEBREW_CACHE/"--foo")
foo.mkpath foo.mkpath
allow(ARGV).to receive(:value).with("prune").and_return("1")
allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - 2 * 60 * 60 * 24) allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - 2 * 60 * 60 * 24)
described_class.cleanup_cache described_class.new(days: 1).cleanup_cache
expect(foo).not_to exist expect(foo).not_to exist
end end
it "does not clean up VCS checkout directories with modified time >= prune time" do it "does not clean up VCS checkout directories with modified time >= prune time" do
foo = (HOMEBREW_CACHE/"--foo") foo = (HOMEBREW_CACHE/"--foo")
foo.mkpath foo.mkpath
allow(ARGV).to receive(:value).with("prune").and_return("1") described_class.new(days: 1).cleanup_cache
described_class.cleanup_cache
expect(foo).to exist expect(foo).to exist
end end
@ -260,20 +250,19 @@ describe Homebrew::Cleanup do
it "cleans up file if outdated" do it "cleans up file if outdated" do
allow(Utils::Bottles).to receive(:file_outdated?).with(any_args).and_return(true) allow(Utils::Bottles).to receive(:file_outdated?).with(any_args).and_return(true)
described_class.cleanup_cache subject.cleanup_cache
expect(bottle).not_to exist expect(bottle).not_to exist
expect(testball).not_to exist expect(testball).not_to exist
end end
it "cleans up file if ARGV has -s and formula not installed" do it "cleans up file if `scrub` is true and formula not installed" do
ARGV << "-s" described_class.new(scrub: true).cleanup_cache
described_class.cleanup_cache
expect(bottle).not_to exist expect(bottle).not_to exist
expect(testball).not_to exist expect(testball).not_to exist
end end
it "cleans up file if stale" do it "cleans up file if stale" do
described_class.cleanup_cache subject.cleanup_cache
expect(bottle).not_to exist expect(bottle).not_to exist
expect(testball).not_to exist expect(testball).not_to exist
end end