Module: R10K::Util::Purgeable Abstract

Includes:
Logging
Included in:
Environment::Git, Environment::WithModules, Puppetfile, Basedir, Cleaner
Defined in:
lib/r10k/util/purgeable.rb

Overview

This module is abstract.

Classes using this mixin need to implement #managed_directory and #desired_contents

Mixin for purging stale directory contents.

Constant Summary collapse

HIDDEN_FILE =
/\.[^.]+/
FN_MATCH_OPTS =
File::FNM_PATHNAME | File::FNM_DOTMATCH

Constants included from Logging

Logging::LOG_LEVELS

Instance Method Summary collapse

Methods included from Logging

debug_formatter, default_formatter, default_outputter, #logger_name, parse_level

Instance Method Details

#current_contents(recurse) ⇒ Array<String>

Returns The present directory entries in ‘self.managed_directories`.

Returns:

  • (Array<String>)

    The present directory entries in ‘self.managed_directories`



37
38
39
40
41
42
43
44
45
46
47
48
49
# 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

#desired_contentsArray<String>

This method is abstract.

Including classes must implement this method to list the expected filenames of managed_directories

Returns The full paths to all the content this object is managing.

Returns:

  • (Array<String>)

    The full paths to all the content this object is managing



# File 'lib/r10k/util/purgeable.rb', line 26

#loggerLog4r::Logger

This method is abstract.

Including classes must provide a logger method

Returns:

  • (Log4r::Logger)


# File 'lib/r10k/util/purgeable.rb', line 20

#managed_directoriesArray<String>

This method is abstract.

Including classes must implement this method to return an array of paths that can be purged

Returns The paths to the directories to be purged.

Returns:

  • (Array<String>)

    The paths to the directories to be purged



# File 'lib/r10k/util/purgeable.rb', line 31

#matches?(test, path) ⇒ Boolean

Returns:

  • (Boolean)


58
59
60
61
62
63
64
65
66
# 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

#pending_contents(recurse) ⇒ Array<String>

Deprecated.

Unused helper function

Returns Directory contents that are expected but not present.

Returns:

  • (Array<String>)

    Directory contents that are expected but not present



54
55
56
# File 'lib/r10k/util/purgeable.rb', line 54

def pending_contents(recurse)
  desired_contents - current_contents(recurse)
end

#potentially_purgeable(dir, exclusion_globs, allowed_globs, desireds_not_to_recurse_into, recurse) ⇒ Array<String>

A method to collect potentially purgeable content without searching into ignored directories when recursively searching.

Parameters:

  • dir (String, Pathname)

    The directory to search for purgeable content

  • 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)

  • 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)

  • 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 “*/R10K::Util::Purgeable.</strong>,</strong>,.[^</strong>,.[^.]*” which would not recurse into dot directories.

  • recurse (Boolean)

    Whether or not to recurse into child directories that do not match other filters.

Returns:

  • (Array<String>)

    Contents which may be purged.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# 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) && recurse
      potentially_purgeable(child, exclusion_globs, allowed_globs, desireds_not_to_recurse_into, recurse)
    else
      child.to_s
    end
  end
end

#purge!(opts = {}) ⇒ Object

Forcibly remove all unmanaged content in ‘self.managed_directories`



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# 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

#stale_contents(recurse, exclusions, whitelist) ⇒ Array<String>

Returns Directory contents that are present but not expected.

Returns:

  • (Array<String>)

    Directory contents that are present but not expected



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# 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