Update stdlib
[mirror/dsa-puppet.git] / 3rdparty / modules / stdlib / lib / puppet / provider / file_line / ruby.rb
1 Puppet::Type.type(:file_line).provide(:ruby) do
2   def exists?
3     found = false
4     lines_count = 0
5     lines.each do |line|
6       found = line.chomp == resource[:line]
7       if found
8         lines_count += 1
9       end
10     end
11     if resource[:match] == nil
12       found = lines_count > 0
13     else
14       match_count = count_matches(new_match_regex)
15       if resource[:append_on_no_match].to_s == 'false'
16         found = true
17       elsif resource[:replace].to_s == 'true'
18         found = lines_count > 0 && lines_count == match_count
19       else
20         found = match_count > 0
21       end
22     end
23     found
24   end
25
26   def create
27     unless resource[:replace].to_s != 'true' && count_matches(new_match_regex) > 0
28       if resource[:match]
29         handle_create_with_match
30       elsif resource[:after]
31         handle_create_with_after
32       else
33         handle_append_line
34       end
35     end
36   end
37
38   def destroy
39     if resource[:match_for_absence].to_s == 'true' && resource[:match]
40       handle_destroy_with_match
41     else
42       handle_destroy_line
43     end
44   end
45
46   private
47
48   def lines
49     # If this type is ever used with very large files, we should
50     #  write this in a different way, using a temp
51     #  file; for now assuming that this type is only used on
52     #  small-ish config files that can fit into memory without
53     #  too much trouble.
54     begin
55       @lines ||= File.readlines(resource[:path], :encoding => resource[:encoding])
56     rescue TypeError => e
57       # Ruby 1.8 doesn't support open_args
58       @lines ||= File.readlines(resource[:path])
59     end
60   end
61
62   def new_after_regex
63     resource[:after] ? Regexp.new(resource[:after]) : nil
64   end
65
66   def new_match_regex
67     resource[:match] ? Regexp.new(resource[:match]) : nil
68   end
69
70   def count_matches(regex)
71     lines.select{ |line| line.match(regex) }.size
72   end
73
74   def handle_create_with_match()
75     after_regex = new_after_regex
76     match_regex = new_match_regex
77     match_count = count_matches(new_match_regex)
78
79     if match_count > 1 && resource[:multiple].to_s != 'true'
80      raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
81     end
82
83     File.open(resource[:path], 'w') do |fh|
84       lines.each do |line|
85         fh.puts(match_regex.match(line) ? resource[:line] : line)
86         if match_count == 0 && after_regex
87           if after_regex.match(line)
88             fh.puts(resource[:line])
89             match_count += 1 # Increment match_count to indicate that the new line has been inserted.
90           end
91         end
92       end
93
94       if (match_count == 0)
95         fh.puts(resource[:line])
96       end
97     end
98   end
99
100   def handle_create_with_after
101     after_regex = new_after_regex
102     after_count = count_matches(after_regex)
103
104     if after_count > 1 && resource[:multiple].to_s != 'true'
105       raise Puppet::Error, "#{after_count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern."
106     end
107
108     File.open(resource[:path],'w') do |fh|
109       lines.each do |line|
110         fh.puts(line)
111         if after_regex.match(line)
112           fh.puts(resource[:line])
113         end
114       end
115
116       if (after_count == 0)
117         fh.puts(resource[:line])
118       end
119     end
120   end
121
122   def handle_destroy_with_match
123     match_regex = new_match_regex
124     match_count = count_matches(match_regex)
125     if match_count > 1 && resource[:multiple].to_s != 'true'
126      raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
127     end
128
129     local_lines = lines
130     File.open(resource[:path],'w') do |fh|
131       fh.write(local_lines.reject{ |line| match_regex.match(line) }.join(''))
132     end
133   end
134
135   def handle_destroy_line
136     local_lines = lines
137     File.open(resource[:path],'w') do |fh|
138       fh.write(local_lines.reject{ |line| line.chomp == resource[:line] }.join(''))
139     end
140   end
141
142   def handle_append_line
143     File.open(resource[:path],'w') do |fh|
144       lines.each do |line|
145         fh.puts(line)
146       end
147       fh.puts(resource[:line])
148     end
149   end
150 end