# module Puppet::Util::FileParsing

### Attributes

line_separator[W]
trailing_separator[W]

### Public Instance Methods

clear_records() click to toggle source

Clear all existing record definitions. Only used for testing.

    # File lib/puppet/util/fileparsing.rb, line 125
    def clear_records
      @record_types.clear
      @record_order.clear
    end

fields(type) click to toggle source

    # File lib/puppet/util/fileparsing.rb, line 130
    def fields(type)
      if record = record_type(type)
        record.fields.dup
      else
        nil
      end
    end

handle_record_line(line, record) click to toggle source

Try to match a record.

    # File lib/puppet/util/fileparsing.rb, line 144
    def handle_record_line(line, record)
      ret = nil
      if record.respond_to?(:process)
        if ret = record.send(:process, line.dup)
          unless ret.is_a?(Hash)
            raise Puppet::DevError,
              "Process record type #{record.name} returned non-hash"
          end
        else
          return nil
        end
      elsif regex = record.match
        # In this case, we try to match the whole line and then use the
        # match captures to get our fields.
        if match = regex.match(line)
          fields = []
          ret = {}
          record.fields.zip(match.captures).each do |field, value|
            if value == record.absent
              ret[field] = :absent
            else
              ret[field] = value
            end
          end
        else
          nil
        end
      else
        ret = {}
        sep = record.separator

        # String "helpfully" replaces ' ' with /\s+/ in splitting, so we
        # have to work around it.
        if sep == " "
          sep = / /
        end
        line_fields = line.split(sep)
        record.fields.each do |param|
          value = line_fields.shift
          if value and value != record.absent
            ret[param] = value
          else
            ret[param] = :absent
          end
        end

        if record.rollup and ! line_fields.empty?
          last_field = record.fields[-1]
          val = ([ret[last_field]] + line_fields).join(record.joiner)
          ret[last_field] = val
        end
      end

      if ret
        ret[:record_type] = record.name
        return ret
      else
        return nil
      end
    end

handle_text_line(line, record) click to toggle source

Try to match a specific text line.

    # File lib/puppet/util/fileparsing.rb, line 139
    def handle_text_line(line, record)
      line =~ record.match ? {:record_type => record.name, :line => line} : nil
    end

line_separator() click to toggle source

    # File lib/puppet/util/fileparsing.rb, line 205
    def line_separator
      @line_separator ||= "\n"

      @line_separator
    end

lines(text) click to toggle source

Split text into separate lines using the record separator.

    # File lib/puppet/util/fileparsing.rb, line 212
    def lines(text)
      # Remove any trailing separators, and then split based on them
      # LAK:NOTE See http://snurl.com/21zf8  [groups_google_com]
      x = text.sub(/#{self.line_separator}\Q/,'').split(self.line_separator)
    end

parse(text) click to toggle source

Split a bunch of text into lines and then parse them individually.

    # File lib/puppet/util/fileparsing.rb, line 219
    def parse(text)
      count = 1
      lines(text).collect do |line|
        count += 1
        if val = parse_line(line)
          val
        else
          error = Puppet::ResourceError.new("Could not parse line #{line.inspect}")
          error.line = count
          raise error
        end
      end
    end

parse_line(line) click to toggle source

Handle parsing a single line.

    # File lib/puppet/util/fileparsing.rb, line 234
    def parse_line(line)
      raise Puppet::DevError, "No record types defined; cannot parse lines" unless records?

      @record_order.each do |record|
        # These are basically either text or record lines.
        method = "handle_#{record.type}_line"
        if respond_to?(method)
          if result = send(method, line, record)
            record.send(:post_parse, result) if record.respond_to?(:post_parse)
            return result
          end
        else
          raise Puppet::DevError,
            "Somehow got invalid line type #{record.type}"
        end
      end

      nil
    end

record_line(name, options, &block) click to toggle source

Define a new type of record. These lines get split into hashes. Valid options are:

- `:absent`: What to use as value within a line, when a field is absent. Note that in the record object, the literal :absent symbol is used, and not this value. Defaults to "".

- `:fields`: The list of fields, as an array. By default, all fields are considered required.

- `:joiner`: How to join fields together. Defaults to 't'.

- `:optional`: Which fields are optional. If these are missing, you'll just get the 'absent' value instead of an ArgumentError.

- `:rts`: Whether to remove trailing whitespace. Defaults to false. If true, whitespace will be removed; if a regex, then whatever matches the regex will be removed.

- `:separator`: The record separator. Defaults to /s+/.

    # File lib/puppet/util/fileparsing.rb, line 268
    def record_line(name, options, &block)
      raise ArgumentError, "Must include a list of fields" unless options.include?(:fields)

      record = FileRecord.new(:record, options, &block)
      record.name = name.intern

      new_line_type(record)
    end

records?() click to toggle source

Are there any record types defined?

    # File lib/puppet/util/fileparsing.rb, line 278
    def records?
      defined?(@record_types) and ! @record_types.empty?
    end

text_line(name, options, &block) click to toggle source

Define a new type of text record.

    # File lib/puppet/util/fileparsing.rb, line 283
    def text_line(name, options, &block)
      raise ArgumentError, "You must provide a :match regex for text lines" unless options.include?(:match)

      record = FileRecord.new(:text, options, &block)
      record.name = name.intern

      new_line_type(record)
    end

to_file(records) click to toggle source

Generate a file from a bunch of hash records.

    # File lib/puppet/util/fileparsing.rb, line 293
    def to_file(records)
      text = records.collect { |record| to_line(record) }.join(line_separator)

      text += line_separator if trailing_separator

      text
    end

to_line(details) click to toggle source

Convert our parsed record into a text record.

    # File lib/puppet/util/fileparsing.rb, line 302
    def to_line(details)
      unless record = record_type(details[:record_type])
        raise ArgumentError, "Invalid record type #{details[:record_type].inspect}"
      end

      if record.respond_to?(:pre_gen)
        details = details.dup
        record.send(:pre_gen, details)
      end

      case record.type
      when :text; return details[:line]
      else
        return record.to_line(details) if record.respond_to?(:to_line)

        line = record.join(details)

        if regex = record.rts
          # If they say true, then use whitespace; else, use their regex.
          if regex == true
            regex = /\s+$/
          end
          return line.sub(regex,'')
        else
          return line
        end
      end
    end

trailing_separator() click to toggle source

Whether to add a trailing separator to the file. Defaults to true

    # File lib/puppet/util/fileparsing.rb, line 332
    def trailing_separator
      if defined?(@trailing_separator)
        return @trailing_separator
      else
        return true
      end
    end

valid_attr?(type, attr) click to toggle source

    # File lib/puppet/util/fileparsing.rb, line 340
    def valid_attr?(type, attr)
      type = type.intern
      if record = record_type(type) and record.fields.include?(attr.intern)
        return true
      else
        if attr.intern == :ensure
          return true
        else
          false
        end
      end
    end