diff options
Diffstat (limited to 'lib/puppet/util/ini_file.rb')
-rw-r--r-- | lib/puppet/util/ini_file.rb | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/lib/puppet/util/ini_file.rb b/lib/puppet/util/ini_file.rb new file mode 100644 index 0000000..75d8a9f --- /dev/null +++ b/lib/puppet/util/ini_file.rb @@ -0,0 +1,132 @@ +require 'puppet/util/external_iterator' +require 'puppet/util/ini_file/section' + +module Puppet +module Util + class IniFile + + SECTION_REGEX = /^\s*\[([\w\d\.]+)\]\s*$/ + SETTING_REGEX = /^\s*([\w\d\.]+)\s*=\s*([\w\d\.]+)\s*$/ + + def initialize(path) + @path = path + @section_names = [] + @sections_hash = {} + + parse_file + end + + def section_names + @section_names + end + + def get_value(section_name, setting) + if (@sections_hash.has_key?(section_name)) + @sections_hash[section_name].get_value(setting) + end + end + + def set_value(section_name, setting, value) + unless (@sections_hash.has_key?(section_name)) + add_section(Section.new(section_name, nil, nil, nil)) + end + + section = @sections_hash[section_name] + if (section.has_existing_setting?(setting)) + update_line(section, setting, value) + section.update_existing_setting(setting, value) + else + section.set_additional_setting(setting, value) + end + end + + def save + File.open(@path, 'w') do |fh| + first_section = @sections_hash[@section_names[0]] + (0..first_section.start_line - 1).each do |line_num| + fh.puts(lines[line_num]) + end + + @section_names.each do |name| + section = @sections_hash[name] + + if (section.start_line.nil?) + fh.puts("\n[#{section.name}]") + else + (section.start_line..section.end_line).each do |line_num| + fh.puts(lines[line_num]) + end + end + + section.additional_settings.each_pair do |key, value| + fh.puts("#{key} = #{value}") + end + end + end + end + + + private + def add_section(section) + @sections_hash[section.name] = section + @section_names << section.name + end + + def parse_file + line_iter = create_line_iter + line, line_num = line_iter.next + while line + if (match = SECTION_REGEX.match(line)) + section = read_section(match[1], line_num, line_iter) + add_section(section) + end + line, line_num = line_iter.next + end + end + + def read_section(name, start_line, line_iter) + settings = {} + while true + line, line_num = line_iter.peek + if (line.nil? or match = SECTION_REGEX.match(line)) + return Section.new(name, start_line, line_num - 1, settings) + elsif (match = SETTING_REGEX.match(line)) + settings[match[1]] = match[2] + end + + line_iter.next + end + end + + def update_line(section, setting, value) + (section.start_line..section.end_line).each do |line_num| + if (match = SETTING_REGEX.match(lines[line_num])) + if (match[1] == setting) + lines[line_num] = "#{setting} = #{value}" + end + end + end + end + + def create_line_iter + ExternalIterator.new(lines) + end + + def lines + @lines ||= IniFile.readlines(@path) + end + + # This is mostly here because it makes testing easier--we don't have + # to try to stub any methods on File. + def self.readlines(path) + # 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. + File.readlines(path) + end + + end +end +end
\ No newline at end of file |