Update stdlib and concat to 6.1.0 both
[mirror/dsa-puppet.git] / 3rdparty / modules / stdlib / lib / puppet / provider / file_line / ruby.rb
index e7854f0..f85ae85 100644 (file)
 Puppet::Type.type(:file_line).provide(:ruby) do
+  desc <<-DOC
+    @summary
+      This type allows puppet to manage small config files.
+
+    The implementation matches the full line, including whitespace at the
+    beginning and end.  If the line is not contained in the given file, Puppet
+    will append the line to the end of the file to ensure the desired state.
+    Multiple resources may be declared to manage multiple lines in the same file.
+  DOC
   def exists?
-    lines.find do |line|
-      line.chomp == resource[:line].chomp
+    found = false
+    lines_count = 0
+    lines.each do |line|
+      found = line.chomp == resource[:line]
+      if found
+        lines_count += 1
+      end
     end
+    return found = lines_count > 0 if resource[:match].nil?
+
+    match_count = count_matches(new_match_regex)
+    found = if resource[:ensure] == :present
+              if match_count.zero?
+                if lines_count.zero? && resource[:append_on_no_match].to_s == 'false'
+                  true # lies, but gets the job done
+                elsif lines_count.zero? && resource[:append_on_no_match].to_s != 'false'
+                  false
+                else
+                  true
+                end
+              elsif resource[:replace_all_matches_not_matching_line].to_s == 'true'
+                false # maybe lies, but knows there's still work to do
+              elsif lines_count.zero?
+                resource[:replace].to_s == 'false'
+              else
+                true
+              end
+            elsif match_count.zero?
+              if lines_count.zero?
+                false
+              else
+                true
+              end
+            elsif lines_count.zero?
+              resource[:match_for_absence].to_s == 'true'
+            else
+              true
+            end
   end
 
   def create
+    return if resource[:replace].to_s != 'true' && count_matches(new_match_regex) > 0
     if resource[:match]
       handle_create_with_match
     elsif resource[:after]
       handle_create_with_after
     else
-      append_line
+      handle_append_line
     end
   end
 
   def destroy
-    local_lines = lines
-    File.open(resource[:path],'w') do |fh|
-      fh.write(local_lines.reject{|l| l.chomp == resource[:line] }.join(''))
+    if resource[:match_for_absence].to_s == 'true' && resource[:match]
+      handle_destroy_with_match
+    else
+      handle_destroy_line
     end
   end
 
   private
+
   def lines
     # If this type is ever used with very large files, we should
     #  write this in a different way, using a temp
     #  file; for now assuming that this type is only used on
     #  small-ish config files that can fit into memory without
     #  too much trouble.
+
+    @lines ||= File.readlines(resource[:path], :encoding => resource[:encoding])
+  rescue TypeError => _e
+    # Ruby 1.8 doesn't support open_args
     @lines ||= File.readlines(resource[:path])
   end
 
-  def handle_create_with_match()
-    regex = resource[:match] ? Regexp.new(resource[:match]) : nil
-    regex_after = resource[:after] ? Regexp.new(resource[:after]) : nil
-    match_count = count_matches(regex)
+  def new_after_regex
+    resource[:after] ? Regexp.new(resource[:after]) : nil
+  end
+
+  def new_match_regex
+    resource[:match] ? Regexp.new(resource[:match]) : nil
+  end
+
+  def count_matches(regex)
+    lines.select { |line|
+      if resource[:replace_all_matches_not_matching_line].to_s == 'true'
+        line.match(regex) unless line.chomp == resource[:line]
+      else
+        line.match(regex)
+      end
+    }.size
+  end
+
+  def handle_create_with_match
+    after_regex = new_after_regex
+    match_regex = new_match_regex
+    match_count = count_matches(new_match_regex)
 
     if match_count > 1 && resource[:multiple].to_s != 'true'
-     raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
+      raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
     end
 
     File.open(resource[:path], 'w') do |fh|
-      lines.each do |l|
-        fh.puts(regex.match(l) ? resource[:line] : l)
-        if (match_count == 0 and regex_after)
-          if regex_after.match(l)
-            fh.puts(resource[:line])
-            match_count += 1 #Increment match_count to indicate that the new line has been inserted.
-          end
+      lines.each do |line|
+        fh.puts(match_regex.match(line) ? resource[:line] : line)
+        next unless match_count.zero? && after_regex
+        if after_regex.match(line)
+          fh.puts(resource[:line])
+          match_count += 1 # Increment match_count to indicate that the new line has been inserted.
         end
       end
 
-      if (match_count == 0)
+      if match_count.zero?
         fh.puts(resource[:line])
       end
     end
   end
 
   def handle_create_with_after
-    regex = Regexp.new(resource[:after])
-    count = count_matches(regex)
-    case count
-    when 1 # find the line to put our line after
-      File.open(resource[:path], 'w') do |fh|
-        lines.each do |l|
-          fh.puts(l)
-          if regex.match(l) then
-            fh.puts(resource[:line])
-          end
+    after_regex = new_after_regex
+    after_count = count_matches(after_regex)
+
+    if after_count > 1 && resource[:multiple].to_s != 'true'
+      raise Puppet::Error, "#{after_count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern."
+    end
+
+    File.open(resource[:path], 'w') do |fh|
+      lines.each do |line|
+        fh.puts(line)
+        if after_regex.match(line)
+          fh.puts(resource[:line])
         end
       end
-    when 0 # append the line to the end of the file
-      append_line
-    else
-      raise Puppet::Error, "#{count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'.  One or no line must match the pattern."
+
+      if after_count.zero?
+        fh.puts(resource[:line])
+      end
     end
   end
 
-  def count_matches(regex)
-    lines.select{|l| l.match(regex)}.size
+  def handle_destroy_with_match
+    match_regex = new_match_regex
+    match_count = count_matches(match_regex)
+    if match_count > 1 && resource[:multiple].to_s != 'true'
+      raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
+    end
+
+    local_lines = lines
+    File.open(resource[:path], 'w') do |fh|
+      fh.write(local_lines.reject { |line| match_regex.match(line) }.join(''))
+    end
   end
 
-  ##
-  # append the line to the file.
-  #
-  # @api private
-  def append_line
+  def handle_destroy_line
+    local_lines = lines
+    File.open(resource[:path], 'w') do |fh|
+      fh.write(local_lines.reject { |line| line.chomp == resource[:line] }.join(''))
+    end
+  end
+
+  def handle_append_line
+    local_lines = lines
     File.open(resource[:path], 'w') do |fh|
-      lines.each do |l|
-        fh.puts(l)
+      local_lines.each do |line|
+        fh.puts(line)
       end
-      fh.puts resource[:line]
+      fh.puts(resource[:line])
     end
   end
 end