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
15 def self.merge(*filesets)
16   result = {}
17 
18   filesets.each do |fileset|
19     fileset.files.each do |file|
20       result[file] ||= fileset.path
21     end
22   end
23 
24   result
25 end
new(path, options = {}) click to toggle source
   # File lib/puppet/file_serving/fileset.rb
27 def initialize(path, options = {})
28   if Puppet::Util::Platform.windows?
29     # REMIND: UNC path
30     path = path.chomp(File::SEPARATOR) unless path =~ /^[A-Za-z]:\/$/
31   else
32     path = path.chomp(File::SEPARATOR) unless path == File::SEPARATOR
33   end
34   raise ArgumentError.new(_("Fileset paths must be fully qualified: %{path}") % { path: path }) unless Puppet::Util.absolute_path?(path)
35 
36   @path = path
37 
38   # Set our defaults.
39   self.ignore = []
40   self.links = :manage
41   @recurse = false
42   @recurselimit = :infinite
43   @max_files = 0
44 
45   if options.is_a?(Puppet::Indirector::Request)
46     initialize_from_request(options)
47   else
48     initialize_from_hash(options)
49   end
50 
51   raise ArgumentError.new(_("Fileset paths must exist")) unless valid?(path)
52   #TRANSLATORS "recurse" and "recurselimit" are parameter names and should not be translated
53   raise ArgumentError.new(_("Fileset recurse parameter must not be a number anymore, please use recurselimit")) if @recurse.is_a?(Integer)
54 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
60 def files
61   files = perform_recursion
62   soft_max_files = 1000
63 
64   # munged_max_files is needed since puppet http handler is keeping negative numbers as strings
65   # https://github.com/puppetlabs/puppet/blob/main/lib/puppet/network/http/handler.rb#L196-L197
66   munged_max_files = max_files == '-1' ? -1 : max_files
67 
68   if munged_max_files > 0 && files.size > munged_max_files
69     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 }
70   elsif munged_max_files == 0 && files.size > soft_max_files
71     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 }
72   end
73 
74   # Now strip off the leading path, so each file becomes relative, and remove
75   # any slashes that might end up at the beginning of the path.
76   result = files.collect { |file| file.sub(%r{^#{Regexp.escape(@path)}/*}, '') }
77 
78   # And add the path itself.
79   result.unshift(".")
80 
81   result
82 end
ignore=(values) click to toggle source
   # File lib/puppet/file_serving/fileset.rb
84 def ignore=(values)
85   values = [values] unless values.is_a?(Array)
86   @ignore = values.collect(&:to_s)
87 end

Private Instance Methods

continue_recursion_at?(depth) click to toggle source
    # File lib/puppet/file_serving/fileset.rb
182 def continue_recursion_at?(depth)
183   # recurse if told to, and infinite recursion or current depth not at the limit
184   self.recurse && (self.recurselimit == :infinite || depth <= self.recurselimit)
185 end
initialize_from_hash(options) click to toggle source
    # File lib/puppet/file_serving/fileset.rb
 99 def initialize_from_hash(options)
100   options.each do |option, value|
101     method = option.to_s + "="
102     begin
103       send(method, value)
104     rescue NoMethodError
105       raise ArgumentError, _("Invalid option '%{option}'") % { option: option }, $!.backtrace
106     end
107   end
108 end
initialize_from_request(request) click to toggle source
    # File lib/puppet/file_serving/fileset.rb
110 def initialize_from_request(request)
111   [:links, :ignore, :recurse, :recurselimit, :max_files, :checksum_type].each do |param|
112     if request.options.include?(param) # use 'include?' so the values can be false
113       value = request.options[param]
114     elsif request.options.include?(param.to_s)
115       value = request.options[param.to_s]
116     end
117     next if value.nil?
118     value = true if value == "true"
119     value = false if value == "false"
120     value = Integer(value) if value.is_a?(String) and value =~ /^\d+$/
121     send(param.to_s + "=", value)
122   end
123 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
158 def perform_recursion
159   current_dirs = [FileSetEntry.new(0, @path, @ignore, @stat_method)]
160 
161   result = []
162 
163   while entry = current_dirs.shift #rubocop:disable Lint/AssignmentInCondition
164     if continue_recursion_at?(entry.depth + 1)
165       entry.children.each do |child|
166         result << child.path
167         current_dirs << child
168       end
169     end
170   end
171 
172   result
173 end
valid?(path) click to toggle source
    # File lib/puppet/file_serving/fileset.rb
175 def valid?(path)
176   Puppet::FileSystem.send(@stat_method, path)
177   true
178 rescue Errno::ENOENT, Errno::EACCES
179   false
180 end