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