Enable typing in Homebrew::Cleanup

This commit is contained in:
Douglas Eichelberger 2023-03-25 13:16:11 -07:00
parent c271a9ae75
commit eaeceda31e
2 changed files with 52 additions and 52 deletions

View File

@ -1,4 +1,4 @@
# typed: false
# typed: true
# frozen_string_literal: true
require "utils/bottles"
@ -15,15 +15,18 @@ module Homebrew
CLEANUP_DEFAULT_DAYS = Homebrew::EnvConfig.cleanup_periodic_full_days.to_i.freeze
private_constant :CLEANUP_DEFAULT_DAYS
# {Pathname} refinement with helper functions for cleaning up files.
module CleanupRefinement
refine Pathname do
def incomplete?
extname.end_with?(".incomplete")
module PathnameUtils
class << self
extend T::Sig
sig { params(pathname: Pathname).returns(T::Boolean) }
def incomplete?(pathname)
pathname.extname.end_with?(".incomplete")
end
def nested_cache?
directory? && %w[
sig { params(pathname: Pathname).returns(T::Boolean) }
def nested_cache?(pathname)
pathname.directory? && %w[
cargo_cache
go_cache
go_mod_cache
@ -31,56 +34,62 @@ module Homebrew
java_cache
npm_cache
gclient_cache
].include?(basename.to_s)
].include?(pathname.basename.to_s)
end
def go_cache_directory?
sig { params(pathname: Pathname).returns(T::Boolean) }
def go_cache_directory?(pathname)
# 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 go_mod_cache].include?(basename.to_s)
pathname.directory? && %w[go_cache go_mod_cache].include?(pathname.basename.to_s)
end
def prune?(days)
sig { params(pathname: Pathname, days: T.nilable(Integer)).returns(T::Boolean) }
def prune?(pathname, days)
return false unless days
return true if days.zero?
return true if symlink? && !exist?
return true if pathname.symlink? && !pathname.exist?
days_ago = (DateTime.now - days).to_time
mtime < days_ago && ctime < days_ago
pathname.mtime < days_ago && pathname.ctime < days_ago
end
def stale?(scrub: false)
return false unless resolved_path.file?
sig { params(pathname: Pathname, scrub: T::Boolean).returns(T::Boolean) }
def stale?(pathname, scrub: false)
return false unless pathname.resolved_path.file?
if dirname.basename.to_s == "Cask"
stale_cask?(scrub)
if pathname.dirname.basename.to_s == "Cask"
stale_cask?(pathname, scrub)
else
stale_formula?(scrub)
stale_formula?(pathname, scrub)
end
end
private
def stale_formula?(scrub)
sig { params(pathname: Pathname, scrub: T::Boolean).returns(T::Boolean) }
def stale_formula?(pathname, scrub)
return false unless HOMEBREW_CELLAR.directory?
version = if HOMEBREW_BOTTLES_EXTNAME_REGEX.match?(to_s)
begin
Utils::Bottles.resolve_version(self)
Utils::Bottles.resolve_version(pathname)
rescue
nil
end
end
basename_str = pathname.basename.to_s
version ||= basename.to_s[/\A.*(?:--.*?)*--(.*?)#{Regexp.escape(extname)}\Z/, 1]
version ||= basename.to_s[/\A.*--?(.*?)#{Regexp.escape(extname)}\Z/, 1]
version ||= basename_str[/\A.*(?:--.*?)*--(.*?)#{Regexp.escape(pathname.extname)}\Z/, 1]
version ||= basename_str[/\A.*--?(.*?)#{Regexp.escape(pathname.extname)}\Z/, 1]
return false unless version
version = Version.new(version)
return false unless (formula_name = basename.to_s[/\A(.*?)(?:--.*?)*--?(?:#{Regexp.escape(version)})/, 1])
unless (formula_name = basename_str[/\A(.*?)(?:--.*?)*--?(?:#{Regexp.escape(version.to_s)})/, 1])
return false
end
formula = begin
Formulary.from_rack(HOMEBREW_CELLAR/formula_name)
@ -90,27 +99,26 @@ module Homebrew
return false if formula.blank?
resource_name = basename.to_s[/\A.*?--(.*?)--?(?:#{Regexp.escape(version)})/, 1]
resource_name = basename_str[/\A.*?--(.*?)--?(?:#{Regexp.escape(version.to_s)})/, 1]
if resource_name == "patch"
patch_hashes = formula.stable&.patches&.select(&:external?)&.map(&:resource)&.map(&:version)
return true unless patch_hashes&.include?(Checksum.new(version.to_s))
elsif resource_name && (resource_version = formula.stable&.resources&.dig(resource_name)&.version)
return true if resource_version != version
elsif version.is_a?(PkgVersion)
return true if formula.pkg_version > version
elsif formula.version > version
return true
end
return true if scrub && !formula.latest_version_installed?
return true if Utils::Bottles.file_outdated?(formula, self)
return true if Utils::Bottles.file_outdated?(formula, pathname)
false
end
def stale_cask?(scrub)
sig { params(pathname: Pathname, scrub: T::Boolean).returns(T::Boolean) }
def stale_cask?(pathname, scrub)
basename = pathname.basename
return false unless (name = basename.to_s[/\A(.*?)--/, 1])
cask = begin
@ -120,14 +128,12 @@ module Homebrew
end
return false if cask.blank?
return true unless basename.to_s.match?(/\A#{Regexp.escape(name)}--#{Regexp.escape(cask.version)}\b/)
return true if scrub && cask.versions.exclude?(cask.version)
if cask.version.latest?
cleanup_threshold = (DateTime.now - CLEANUP_DEFAULT_DAYS).to_time
return mtime < cleanup_threshold && ctime < cleanup_threshold
return pathname.mtime < cleanup_threshold && pathname.ctime < cleanup_threshold
end
false
@ -135,8 +141,6 @@ module Homebrew
end
end
using CleanupRefinement
extend Predicable
PERIODIC_CLEAN_FILE = (HOMEBREW_CACHE/".cleaned").freeze
@ -190,7 +194,7 @@ module Homebrew
def self.skip_clean_formula?(formula)
return false if Homebrew::EnvConfig.no_cleanup_formulae.blank?
@skip_clean_formulae ||= Homebrew::EnvConfig.no_cleanup_formulae.split(",")
@skip_clean_formulae ||= T.must(Homebrew::EnvConfig.no_cleanup_formulae).split(",")
@skip_clean_formulae.include?(formula.name) || (@skip_clean_formulae & formula.aliases).present?
end
@ -311,7 +315,7 @@ module Homebrew
logs_days = [days, CLEANUP_DEFAULT_DAYS].min
HOMEBREW_LOGS.subdirs.each do |dir|
cleanup_path(dir) { dir.rmtree } if dir.prune?(logs_days)
cleanup_path(dir) { dir.rmtree } if PathnameUtils.prune?(dir, logs_days)
end
end
@ -327,7 +331,7 @@ module Homebrew
.map(&:resolved_path)
(downloads - referenced_downloads).each do |download|
if download.incomplete?
if PathnameUtils.incomplete?(download)
begin
LockFile.new(download.basename).with_lock do
download.unlink
@ -350,11 +354,11 @@ module Homebrew
entries.each do |path|
next if path == PERIODIC_CLEAN_FILE
FileUtils.chmod_R 0755, path if path.go_cache_directory? && !dry_run?
next cleanup_path(path) { path.unlink } if path.incomplete?
next cleanup_path(path) { FileUtils.rm_rf path } if path.nested_cache?
FileUtils.chmod_R 0755, path if PathnameUtils.go_cache_directory?(path) && !dry_run?
next cleanup_path(path) { path.unlink } if PathnameUtils.incomplete?(path)
next cleanup_path(path) { FileUtils.rm_rf path } if PathnameUtils.nested_cache?(path)
if path.prune?(days)
if PathnameUtils.prune?(path, days)
if path.file? || path.symlink?
cleanup_path(path) { path.unlink }
elsif path.directory? && path.to_s.include?("--")
@ -364,7 +368,7 @@ module Homebrew
end
# If we've specified --prune don't do the (expensive) .stale? check.
cleanup_path(path) { path.unlink } if !prune? && path.stale?(scrub: scrub?)
cleanup_path(path) { path.unlink } if !prune? && PathnameUtils.stale?(path, scrub: scrub?)
end
cleanup_unreferenced_downloads
@ -485,7 +489,7 @@ module Homebrew
if child.basename.to_s == "__pycache__"
child.find do |path|
next unless path.extname == ".pyc"
next unless path.prune?(days)
next unless PathnameUtils.prune?(path, days)
unused_pyc_files << path
end

View File

@ -6,8 +6,6 @@ require "cleanup"
require "cask/cache"
require "fileutils"
using Homebrew::Cleanup::CleanupRefinement
describe Homebrew::Cleanup do
subject(:cleanup) { described_class.new }
@ -27,9 +25,7 @@ describe Homebrew::Cleanup do
FileUtils.rm_rf HOMEBREW_LIBRARY/"Homebrew"
end
describe "::CleanupRefinement::prune?" do
alias_matcher :be_pruned, :be_prune
describe "::PathnameUtils.prune?" do
subject(:path) { HOMEBREW_CACHE/"foo" }
before do
@ -39,11 +35,11 @@ describe Homebrew::Cleanup do
it "returns true when ctime and mtime < days_default" do
allow_any_instance_of(Pathname).to receive(:ctime).and_return((DateTime.now - 2).to_time)
allow_any_instance_of(Pathname).to receive(:mtime).and_return((DateTime.now - 2).to_time)
expect(path.prune?(1)).to be true
expect(described_class::PathnameUtils.prune?(path, 1)).to be true
end
it "returns false when ctime and mtime >= days_default" do
expect(path.prune?(2)).to be false
expect(described_class::PathnameUtils.prune?(path, 2)).to be false
end
end