class Puppet::FileServing::Fileset

Operate recursively on a path, returning a set of file paths.

Constants

FileSetEntry

Attributes

checksum_type[RW]
ignore[R]
max_files[RW]
path[R]
recurse[RW]
recurselimit[RW]

Public Class Methods

merge(*filesets) click to toggle source

Produce a hash of files, with merged so that earlier files with the same postfix win. E.g., /dir1/subfile beats /dir2/subfile. It's a hash because we need to know the relative path of each file, and the base directory.

This will probably only ever be used for searching for plugins.
   # File lib/puppet/file_serving/fileset.rb
16 def self.merge(*filesets)
17   result = {}
18 
19   filesets.each do |fileset|
20     fileset.files.each do |file|
21       result[file] ||= fileset.path
22     end
23   end
24 
25   result
26 end
new(path, options = {}) click to toggle source
   # File lib/puppet/file_serving/fileset.rb
28 def initialize(path, options = {})
29   if Puppet::Util::Platform.windows?
30     # REMIND: UNC path
31     path = path.chomp(File::SEPARATOR) unless path =~ /^[A-Za-z]:\/$/
32   else
33     path = path.chomp(File::SEPARATOR) unless path == File::SEPARATOR
34   end
35   raise ArgumentError.new(_("Fileset paths must be fully qualified: %{path}") % { path: path }) unless Puppet::Util.absolute_path?(path)
36 
37   @path = path
38 
39   # Set our defaults.
40   self.ignore = []
41   self.links = :manage
42   @recurse = false
43   @recurselimit = :infinite
44   @max_files = 0
45 
46   if options.is_a?(Puppet::Indirector::Request)
47     initialize_from_request(options)
48   else
49     initialize_from_hash(options)
50   end
51 
52   raise ArgumentError.new(_("Fileset paths must exist")) unless valid?(path)
53   #TRANSLATORS "recurse" and "recurselimit" are parameter names and should not be translated
54   raise ArgumentError.new(_("Fileset recurse parameter must not be a number anymore, please use recurselimit")) if @recurse.is_a?(Integer)
55 end

Public Instance Methods

files() click to toggle source

Return a list of all files in our fileset. This is different from the normal definition of find in that we support specific levels of recursion, which means we need to know when we're going another level deep, which Find doesn't do.

   # File lib/puppet/file_serving/fileset.rb
61 def files
62   files = perform_recursion
63   soft_max_files = 1000
64 
65   # munged_max_files is needed since puppet http handler is keeping negative numbers as strings
66   # https://github.com/puppetlabs/puppet/blob/main/lib/puppet/network/http/handler.rb#L196-L197
67   munged_max_files = max_files == '-1' ? -1 : max_files
68 
69   if munged_max_files > 0 && files.size > munged_max_files
70     raise Puppet::Error.new _("The directory '%{path}' contains %{entries} entries, which exceeds the limit of %{munged_max_files} specified by the max_files parameter for this resource. The limit may be increased, but be aware that large number of file resources can result in excessive resource consumption and degraded performance. Consider using an alternate method to manage large directory trees") % { path: path, entries: files.size, munged_max_files: munged_max_files }
71   elsif munged_max_files == 0 && files.size > soft_max_files
72     Puppet.warning _("The directory '%{path}' contains %{entries} entries, which exceeds the default soft limit %{soft_max_files} and may cause excessive resource consumption and degraded performance. To remove this warning set a value for `max_files` parameter or consider using an alternate method to manage large directory trees") % { path: path, entries: files.size, soft_max_files: soft_max_files }
73   end
74 
75   # Now strip off the leading path, so each file becomes relative, and remove
76   # any slashes that might end up at the beginning of the path.
77   result = files.collect { |file| file.sub(%r{^#{Regexp.escape(@path)}/*}, '') }
78 
79   # And add the path itself.
80   result.unshift(".")
81 
82   result
83 end
ignore=(values) click to toggle source
   # File lib/puppet/file_serving/fileset.rb
85 def ignore=(values)
86   values = [values] unless values.is_a?(Array)
87   @ignore = values.collect(&:to_s)
88 end

Private Instance Methods

continue_recursion_at?(depth) click to toggle source
    # File lib/puppet/file_serving/fileset.rb
183 def continue_recursion_at?(depth)
184   # recurse if told to, and infinite recursion or current depth not at the limit
185   self.recurse && (self.recurselimit == :infinite || depth <= self.recurselimit)
186 end
initialize_from_hash(options) click to toggle source
    # File lib/puppet/file_serving/fileset.rb
100 def initialize_from_hash(options)
101   options.each do |option, value|
102     method = option.to_s + "="
103     begin
104       send(method, value)
105     rescue NoMethodError
106       raise ArgumentError, _("Invalid option '%{option}'") % { option: option }, $!.backtrace
107     end
108   end
109 end
initialize_from_request(request) click to toggle source
    # File lib/puppet/file_serving/fileset.rb
111 def initialize_from_request(request)
112   [:links, :ignore, :recurse, :recurselimit, :max_files, :checksum_type].each do |param|
113     if request.options.include?(param) # use 'include?' so the values can be false
114       value = request.options[param]
115     elsif request.options.include?(param.to_s)
116       value = request.options[param.to_s]
117     end
118     next if value.nil?
119     value = true if value == "true"
120     value = false if value == "false"
121     value = Integer(value) if value.is_a?(String) and value =~ /^\d+$/
122     send(param.to_s + "=", value)
123   end
124 end
perform_recursion() click to toggle source

Pull the recursion logic into one place. It's moderately hairy, and this allows us to keep the hairiness apart from what we do with the files.

    # File lib/puppet/file_serving/fileset.rb
159 def perform_recursion
160   current_dirs = [FileSetEntry.new(0, @path, @ignore, @stat_method)]
161 
162   result = []
163 
164   while entry = current_dirs.shift #rubocop:disable Lint/AssignmentInCondition
165     if continue_recursion_at?(entry.depth + 1)
166       entry.children.each do |child|
167         result << child.path
168         current_dirs << child
169       end
170     end
171   end
172 
173   result
174 end
valid?(path) click to toggle source
    # File lib/puppet/file_serving/fileset.rb
176 def valid?(path)
177   Puppet::FileSystem.send(@stat_method, path)
178   true
179 rescue Errno::ENOENT, Errno::EACCES
180   false
181 end