class Dotenv::Parser

Parses the ‘.env` file format into key/value pairs. It allows for variable substitutions, command substitutions, and exporting of variables.

Constants

LINE
QUOTED_STRING

Attributes

substitutions[R]

Public Class Methods

call(...) click to toggle source
# File lib/dotenv/parser.rb, line 39
def call(...)
  new(...).call
end
new(string, overwrite: false) click to toggle source
# File lib/dotenv/parser.rb, line 44
def initialize(string, overwrite: false)
  # Convert line breaks to same format
  @string = string.gsub(/\r\n?/, "\n")
  @hash = {}
  @overwrite = overwrite
end

Public Instance Methods

call() click to toggle source
# File lib/dotenv/parser.rb, line 51
def call
  @string.scan(LINE) do
    match = $LAST_MATCH_INFO

    if existing?(match[:key])
      # Use value from already defined variable
      @hash[match[:key]] = ENV[match[:key]]
    elsif match[:export] && !match[:value]
      # Check for exported variable with no value
      if !@hash.member?(match[:key])
        raise FormatError, "Line #{match.to_s.inspect} has an unset variable"
      end
    else
      @hash[match[:key]] = parse_value(match[:value] || "")
    end
  end

  @hash
end

Private Instance Methods

existing?(key) click to toggle source

Determine if a variable is already defined and should not be overwritten.

# File lib/dotenv/parser.rb, line 74
def existing?(key)
  !@overwrite && key != "DOTENV_LINEBREAK_MODE" && ENV.key?(key)
end
expand_newlines(value) click to toggle source
# File lib/dotenv/parser.rb, line 100
def expand_newlines(value)
  if (@hash["DOTENV_LINEBREAK_MODE"] || ENV["DOTENV_LINEBREAK_MODE"]) == "legacy"
    value.gsub('\n', "\n").gsub('\r', "\r")
  else
    value.gsub('\n', "\\\\\\n").gsub('\r', "\\\\\\r")
  end
end
parse_value(value) click to toggle source
# File lib/dotenv/parser.rb, line 79
def parse_value(value)
  # Remove surrounding quotes
  value = value.strip.sub(QUOTED_STRING, '\2')
  maybe_quote = Regexp.last_match(1)

  # Expand new lines in double quoted values
  value = expand_newlines(value) if maybe_quote == '"'

  # Unescape characters and performs substitutions unless value is single quoted
  if maybe_quote != "'"
    value = unescape_characters(value)
    self.class.substitutions.each { |proc| value = proc.call(value, @hash) }
  end

  value
end
unescape_characters(value) click to toggle source
# File lib/dotenv/parser.rb, line 96
def unescape_characters(value)
  value.gsub(/\\([^$])/, '\1')
end