module R10K::Util::Purgeable
Mixin for purging stale directory contents.
@abstract Classes using this mixin need to implement {#managed_directory} and
{#desired_contents}
Constants
- FN_MATCH_OPTS
- HIDDEN_FILE
Public Instance Methods
@return [Array<String>] The present directory entries in `self.managed_directories`
# File lib/r10k/util/purgeable.rb, line 37 def current_contents(recurse) dirs = self.managed_directories dirs.flat_map do |dir| if recurse glob_exp = File.join(dir, '**', '{*,.[^.]*}') else glob_exp = File.join(dir, '*') end Dir.glob(glob_exp) end end
# File lib/r10k/util/purgeable.rb, line 58 def matches?(test, path) if test == path true elsif File.fnmatch?(test, path, FN_MATCH_OPTS) true else false end end
@deprecated Unused helper function
@return [Array<String>] Directory contents that are expected but not present
# File lib/r10k/util/purgeable.rb, line 54 def pending_contents(recurse) desired_contents - current_contents(recurse) end
A method to collect potentially purgeable content without searching into ignored directories when recursively searching.
@param dir [String, Pathname] The directory to search for purgeable content @param exclusion_gobs [Array<String>] A list of file paths or File globs
to exclude from recursion (These are generated by the classes that mix this module into them and are typically programatically generated)
@param allowed_gobs [Array<String>] A list of file paths or File globs to exclude
from recursion (These are passed in by the caller of purge! and typically are user supplied configuration values)
@param desireds_not_to_recurse_into [Array<String>] A list of file paths not to
recurse into. These are programatically generated, these exist to maintain
backwards compatibility with previous implementations that used File.globs
for "recursion", ie "**/{*,.[^.]*}" which would not recurse into dot directories.
@param recurse [Boolean] Whether or not to recurse into child directories that do
not match other filters.
@return [Array<String>] Contents which may be purged.
# File lib/r10k/util/purgeable.rb, line 86 def potentially_purgeable(dir, exclusion_globs, allowed_globs, desireds_not_to_recurse_into, recurse) children = Pathname.new(dir).children.reject do |path| path = path.to_s if exclusion_match = exclusion_globs.find { |exclusion| matches?(exclusion, path) } logger.debug2 _("Not purging %{path} due to internal exclusion match: %{exclusion_match}") % {path: path, exclusion_match: exclusion_match} elsif allowlist_match = allowed_globs.find { |allowed| matches?(allowed, path) } logger.debug _("Not purging %{path} due to whitelist match: %{allowlist_match}") % {path: path, allowlist_match: allowlist_match} else desired_match = desireds_not_to_recurse_into.grep(path).first end !!exclusion_match || !!allowlist_match || !!desired_match end children.flat_map do |child| if File.directory?(child) && !File.symlink?(child) && recurse potentially_purgeable(child, exclusion_globs, allowed_globs, desireds_not_to_recurse_into, recurse) << child.to_s else child.to_s end end end
Forcibly remove all unmanaged content in `self.managed_directories`
# File lib/r10k/util/purgeable.rb, line 128 def purge!(opts={}) recurse = opts[:recurse] || false whitelist = opts[:whitelist] || [] exclusions = self.respond_to?(:purge_exclusions) ? purge_exclusions : [] stale = stale_contents(recurse, exclusions, whitelist) if stale.empty? logger.debug1 _("No unmanaged contents in %{managed_dirs}, nothing to purge") % {managed_dirs: managed_directories.join(', ')} else stale.each do |fpath| begin FileUtils.rm_r(fpath, :secure => true) logger.info _("Removing unmanaged path %{path}") % {path: fpath} rescue Errno::ENOENT # Don't log on ENOENT since we may encounter that from recursively deleting # this item's parent earlier in the purge. rescue logger.debug1 _("Unable to remove unmanaged path: %{path}") % {path: fpath} end end end end
@return [Array<String>] Directory contents that are present but not expected
# File lib/r10k/util/purgeable.rb, line 111 def stale_contents(recurse, exclusions, whitelist) dirs = self.managed_directories desireds = self.desired_contents hidden_desireds, regular_desireds = desireds.partition do |desired| HIDDEN_FILE.match(File.basename(desired)) end initial_purgelist = dirs.flat_map do |dir| potentially_purgeable(dir, exclusions, whitelist, hidden_desireds, recurse) end initial_purgelist.reject do |path| regular_desireds.any? { |desired| matches?(desired, path) } end end