Enable typing in Homebrew::Cleanup
This commit is contained in:
parent
c271a9ae75
commit
eaeceda31e
@ -1,4 +1,4 @@
|
|||||||
# typed: false
|
# typed: true
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "utils/bottles"
|
require "utils/bottles"
|
||||||
@ -15,15 +15,18 @@ module Homebrew
|
|||||||
CLEANUP_DEFAULT_DAYS = Homebrew::EnvConfig.cleanup_periodic_full_days.to_i.freeze
|
CLEANUP_DEFAULT_DAYS = Homebrew::EnvConfig.cleanup_periodic_full_days.to_i.freeze
|
||||||
private_constant :CLEANUP_DEFAULT_DAYS
|
private_constant :CLEANUP_DEFAULT_DAYS
|
||||||
|
|
||||||
# {Pathname} refinement with helper functions for cleaning up files.
|
module PathnameUtils
|
||||||
module CleanupRefinement
|
class << self
|
||||||
refine Pathname do
|
extend T::Sig
|
||||||
def incomplete?
|
|
||||||
extname.end_with?(".incomplete")
|
sig { params(pathname: Pathname).returns(T::Boolean) }
|
||||||
|
def incomplete?(pathname)
|
||||||
|
pathname.extname.end_with?(".incomplete")
|
||||||
end
|
end
|
||||||
|
|
||||||
def nested_cache?
|
sig { params(pathname: Pathname).returns(T::Boolean) }
|
||||||
directory? && %w[
|
def nested_cache?(pathname)
|
||||||
|
pathname.directory? && %w[
|
||||||
cargo_cache
|
cargo_cache
|
||||||
go_cache
|
go_cache
|
||||||
go_mod_cache
|
go_mod_cache
|
||||||
@ -31,56 +34,62 @@ module Homebrew
|
|||||||
java_cache
|
java_cache
|
||||||
npm_cache
|
npm_cache
|
||||||
gclient_cache
|
gclient_cache
|
||||||
].include?(basename.to_s)
|
].include?(pathname.basename.to_s)
|
||||||
end
|
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,
|
# Go makes its cache contents read-only to ensure cache integrity,
|
||||||
# which makes sense but is something we need to undo for cleanup.
|
# 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
|
end
|
||||||
|
|
||||||
def prune?(days)
|
sig { params(pathname: Pathname, days: T.nilable(Integer)).returns(T::Boolean) }
|
||||||
|
def prune?(pathname, days)
|
||||||
return false unless days
|
return false unless days
|
||||||
return true if days.zero?
|
return true if days.zero?
|
||||||
|
return true if pathname.symlink? && !pathname.exist?
|
||||||
return true if symlink? && !exist?
|
|
||||||
|
|
||||||
days_ago = (DateTime.now - days).to_time
|
days_ago = (DateTime.now - days).to_time
|
||||||
mtime < days_ago && ctime < days_ago
|
pathname.mtime < days_ago && pathname.ctime < days_ago
|
||||||
end
|
end
|
||||||
|
|
||||||
def stale?(scrub: false)
|
sig { params(pathname: Pathname, scrub: T::Boolean).returns(T::Boolean) }
|
||||||
return false unless resolved_path.file?
|
def stale?(pathname, scrub: false)
|
||||||
|
return false unless pathname.resolved_path.file?
|
||||||
|
|
||||||
if dirname.basename.to_s == "Cask"
|
if pathname.dirname.basename.to_s == "Cask"
|
||||||
stale_cask?(scrub)
|
stale_cask?(pathname, scrub)
|
||||||
else
|
else
|
||||||
stale_formula?(scrub)
|
stale_formula?(pathname, scrub)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
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?
|
return false unless HOMEBREW_CELLAR.directory?
|
||||||
|
|
||||||
version = if HOMEBREW_BOTTLES_EXTNAME_REGEX.match?(to_s)
|
version = if HOMEBREW_BOTTLES_EXTNAME_REGEX.match?(to_s)
|
||||||
begin
|
begin
|
||||||
Utils::Bottles.resolve_version(self)
|
Utils::Bottles.resolve_version(pathname)
|
||||||
rescue
|
rescue
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
basename_str = pathname.basename.to_s
|
||||||
|
|
||||||
version ||= basename.to_s[/\A.*(?:--.*?)*--(.*?)#{Regexp.escape(extname)}\Z/, 1]
|
version ||= basename_str[/\A.*(?:--.*?)*--(.*?)#{Regexp.escape(pathname.extname)}\Z/, 1]
|
||||||
version ||= basename.to_s[/\A.*--?(.*?)#{Regexp.escape(extname)}\Z/, 1]
|
version ||= basename_str[/\A.*--?(.*?)#{Regexp.escape(pathname.extname)}\Z/, 1]
|
||||||
|
|
||||||
return false unless version
|
return false unless version
|
||||||
|
|
||||||
version = Version.new(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
|
formula = begin
|
||||||
Formulary.from_rack(HOMEBREW_CELLAR/formula_name)
|
Formulary.from_rack(HOMEBREW_CELLAR/formula_name)
|
||||||
@ -90,27 +99,26 @@ module Homebrew
|
|||||||
|
|
||||||
return false if formula.blank?
|
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"
|
if resource_name == "patch"
|
||||||
patch_hashes = formula.stable&.patches&.select(&:external?)&.map(&:resource)&.map(&:version)
|
patch_hashes = formula.stable&.patches&.select(&:external?)&.map(&:resource)&.map(&:version)
|
||||||
return true unless patch_hashes&.include?(Checksum.new(version.to_s))
|
return true unless patch_hashes&.include?(Checksum.new(version.to_s))
|
||||||
elsif resource_name && (resource_version = formula.stable&.resources&.dig(resource_name)&.version)
|
elsif resource_name && (resource_version = formula.stable&.resources&.dig(resource_name)&.version)
|
||||||
return true if resource_version != version
|
return true if resource_version != version
|
||||||
elsif version.is_a?(PkgVersion)
|
|
||||||
return true if formula.pkg_version > version
|
|
||||||
elsif formula.version > version
|
elsif formula.version > version
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return true if scrub && !formula.latest_version_installed?
|
return true if scrub && !formula.latest_version_installed?
|
||||||
|
return true if Utils::Bottles.file_outdated?(formula, pathname)
|
||||||
return true if Utils::Bottles.file_outdated?(formula, self)
|
|
||||||
|
|
||||||
false
|
false
|
||||||
end
|
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])
|
return false unless (name = basename.to_s[/\A(.*?)--/, 1])
|
||||||
|
|
||||||
cask = begin
|
cask = begin
|
||||||
@ -120,14 +128,12 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
return false if cask.blank?
|
return false if cask.blank?
|
||||||
|
|
||||||
return true unless basename.to_s.match?(/\A#{Regexp.escape(name)}--#{Regexp.escape(cask.version)}\b/)
|
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)
|
return true if scrub && cask.versions.exclude?(cask.version)
|
||||||
|
|
||||||
if cask.version.latest?
|
if cask.version.latest?
|
||||||
cleanup_threshold = (DateTime.now - CLEANUP_DEFAULT_DAYS).to_time
|
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
|
end
|
||||||
|
|
||||||
false
|
false
|
||||||
@ -135,8 +141,6 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
using CleanupRefinement
|
|
||||||
|
|
||||||
extend Predicable
|
extend Predicable
|
||||||
|
|
||||||
PERIODIC_CLEAN_FILE = (HOMEBREW_CACHE/".cleaned").freeze
|
PERIODIC_CLEAN_FILE = (HOMEBREW_CACHE/".cleaned").freeze
|
||||||
@ -190,7 +194,7 @@ module Homebrew
|
|||||||
def self.skip_clean_formula?(formula)
|
def self.skip_clean_formula?(formula)
|
||||||
return false if Homebrew::EnvConfig.no_cleanup_formulae.blank?
|
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?
|
@skip_clean_formulae.include?(formula.name) || (@skip_clean_formulae & formula.aliases).present?
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -311,7 +315,7 @@ module Homebrew
|
|||||||
logs_days = [days, CLEANUP_DEFAULT_DAYS].min
|
logs_days = [days, CLEANUP_DEFAULT_DAYS].min
|
||||||
|
|
||||||
HOMEBREW_LOGS.subdirs.each do |dir|
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -327,7 +331,7 @@ module Homebrew
|
|||||||
.map(&:resolved_path)
|
.map(&:resolved_path)
|
||||||
|
|
||||||
(downloads - referenced_downloads).each do |download|
|
(downloads - referenced_downloads).each do |download|
|
||||||
if download.incomplete?
|
if PathnameUtils.incomplete?(download)
|
||||||
begin
|
begin
|
||||||
LockFile.new(download.basename).with_lock do
|
LockFile.new(download.basename).with_lock do
|
||||||
download.unlink
|
download.unlink
|
||||||
@ -350,11 +354,11 @@ module Homebrew
|
|||||||
entries.each do |path|
|
entries.each do |path|
|
||||||
next if path == PERIODIC_CLEAN_FILE
|
next if path == PERIODIC_CLEAN_FILE
|
||||||
|
|
||||||
FileUtils.chmod_R 0755, path if path.go_cache_directory? && !dry_run?
|
FileUtils.chmod_R 0755, path if PathnameUtils.go_cache_directory?(path) && !dry_run?
|
||||||
next cleanup_path(path) { path.unlink } if path.incomplete?
|
next cleanup_path(path) { path.unlink } if PathnameUtils.incomplete?(path)
|
||||||
next cleanup_path(path) { FileUtils.rm_rf path } if path.nested_cache?
|
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?
|
if path.file? || path.symlink?
|
||||||
cleanup_path(path) { path.unlink }
|
cleanup_path(path) { path.unlink }
|
||||||
elsif path.directory? && path.to_s.include?("--")
|
elsif path.directory? && path.to_s.include?("--")
|
||||||
@ -364,7 +368,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
# If we've specified --prune don't do the (expensive) .stale? check.
|
# 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
|
end
|
||||||
|
|
||||||
cleanup_unreferenced_downloads
|
cleanup_unreferenced_downloads
|
||||||
@ -485,7 +489,7 @@ module Homebrew
|
|||||||
if child.basename.to_s == "__pycache__"
|
if child.basename.to_s == "__pycache__"
|
||||||
child.find do |path|
|
child.find do |path|
|
||||||
next unless path.extname == ".pyc"
|
next unless path.extname == ".pyc"
|
||||||
next unless path.prune?(days)
|
next unless PathnameUtils.prune?(path, days)
|
||||||
|
|
||||||
unused_pyc_files << path
|
unused_pyc_files << path
|
||||||
end
|
end
|
||||||
|
@ -6,8 +6,6 @@ require "cleanup"
|
|||||||
require "cask/cache"
|
require "cask/cache"
|
||||||
require "fileutils"
|
require "fileutils"
|
||||||
|
|
||||||
using Homebrew::Cleanup::CleanupRefinement
|
|
||||||
|
|
||||||
describe Homebrew::Cleanup do
|
describe Homebrew::Cleanup do
|
||||||
subject(:cleanup) { described_class.new }
|
subject(:cleanup) { described_class.new }
|
||||||
|
|
||||||
@ -27,9 +25,7 @@ describe Homebrew::Cleanup do
|
|||||||
FileUtils.rm_rf HOMEBREW_LIBRARY/"Homebrew"
|
FileUtils.rm_rf HOMEBREW_LIBRARY/"Homebrew"
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "::CleanupRefinement::prune?" do
|
describe "::PathnameUtils.prune?" do
|
||||||
alias_matcher :be_pruned, :be_prune
|
|
||||||
|
|
||||||
subject(:path) { HOMEBREW_CACHE/"foo" }
|
subject(:path) { HOMEBREW_CACHE/"foo" }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@ -39,11 +35,11 @@ describe Homebrew::Cleanup do
|
|||||||
it "returns true when ctime and mtime < days_default" 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(:ctime).and_return((DateTime.now - 2).to_time)
|
||||||
allow_any_instance_of(Pathname).to receive(:mtime).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
|
end
|
||||||
|
|
||||||
it "returns false when ctime and mtime >= days_default" do
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user