Module: Capistrano::Node::Dotenv::Parser

Defined in:
lib/capistrano/node/dotenv/parser.rb

Instance Method Summary collapse

Instance Method Details

#build_dotenv_result(global_env, stage_env, stage_name) ⇒ Object



54
55
56
# File 'lib/capistrano/node/dotenv/parser.rb', line 54

def build_dotenv_result(global_env, stage_env, stage_name)
  global_env.sort.to_h.merge(stage_name.to_s => stage_env.sort.to_h)
end

#collect_dotenv_pair(stripped, global_env, stage_env, current_section, markers_found) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/capistrano/node/dotenv/parser.rb', line 41

def collect_dotenv_pair(stripped, global_env, stage_env, current_section, markers_found)
  parsed_line = parse_dotenv_line(stripped)
  return unless parsed_line

  key, value = parsed_line
  if markers_found
    global_env[key] = value if current_section == :global
    stage_env[key]  = value if current_section == :stage
  else
    stage_env[key] = value
  end
end

#generate_dotenv_content(global_env_hash, env_hash) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/capistrano/node/dotenv/parser.rb', line 80

def generate_dotenv_content(global_env_hash, env_hash)
  date = Time.now.strftime('%Y-%m-%d %H:%M:%S')
  global_start = "# Begin global envs #{date}\n"
  global_end = "# End global envs #{date}\n"
  stage_start = "# Begin #{fetch(:dotenv_env) || fetch(:stage)} envs #{date}\n"
  stage_end = "# End #{fetch(:dotenv_env) || fetch(:stage)} envs #{date}\n"

  content = global_start
  global_env_hash.each do |key, value|
    content += "#{key}=#{value}\n"
  end
  content += global_end
  content += stage_start
  env_hash.each do |key, value|
    content += "#{key}=#{value}\n"
  end
  content += stage_end
  content
end

#parse_dotenv(content, stage_name) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/capistrano/node/dotenv/parser.rb', line 7

def parse_dotenv(content, stage_name)
  global_env = {}
  stage_env  = {}
  current_section = :stage
  markers_found = false

  content.each_line do |line|
    new_section, is_marker = resolve_section_marker(line.strip, stage_name)
    if is_marker
      current_section = new_section
      markers_found = true
      next
    end

    collect_dotenv_pair(line.strip, global_env, stage_env, current_section, markers_found)
  end

  build_dotenv_result(global_env, stage_env, stage_name)
end

#parse_dotenv_line(line) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/capistrano/node/dotenv/parser.rb', line 58

def parse_dotenv_line(line)
  return nil if line.empty? || line.start_with?('#')

  stripped = line.sub(/\Aexport\s+/, '')
  key, raw_value = stripped.split('=', 2)
  return nil if key.nil? || raw_value.nil?

  parsed_key = key.strip
  value = raw_value.strip

  if value.start_with?('"') && value.end_with?('"')
    value = value[1..-2]
    value = value.gsub('\\n', "\n").gsub('\\"', '"').gsub('\\\\', '\\')
  elsif value.start_with?("'") && value.end_with?("'")
    value = value[1..-2]
  else
    value = value.sub(/\s+#.*\z/, '').strip
  end

  [parsed_key, value]
end

#resolve_section_marker(stripped, stage_name) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/capistrano/node/dotenv/parser.rb', line 27

def resolve_section_marker(stripped, stage_name)
  return [:global, true] if stripped.match?(/\A#\s*Begin\s+global\s+envs\b/i)
  return [nil, true]     if stripped.match?(/\A#\s*End\s+global\s+envs\b/i)
  return [nil, true]     if stripped.match?(/\A#\s*End\s+.+?\s+envs\b/i)

  stage_begin = stripped.match(/\A#\s*Begin\s+(.+?)\s+envs\b/i)
  if stage_begin
    section = stage_begin[1].strip.casecmp(stage_name.to_s).zero? ? :stage : nil
    return [section, true]
  end

  [nil, false]
end