dotenv 0.9.0 → 2.7.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,76 +1,28 @@
1
- require 'dotenv/format_error'
2
-
3
1
  module Dotenv
2
+ # This class inherits from Hash and represents the environment into which
3
+ # Dotenv will load key value pairs from a file.
4
4
  class Environment < Hash
5
- LINE = /
6
- \A
7
- (?:export\s+)? # optional export
8
- ([\w\.]+) # key
9
- (?:\s*=\s*|:\s+?) # separator
10
- ( # optional value begin
11
- '(?:\'|[^'])*' # single quoted value
12
- | # or
13
- "(?:\"|[^"])*" # double quoted value
14
- | # or
15
- [^#\n]+ # unquoted value
16
- )? # value end
17
- (?:\s*\#.*)? # optional comment
18
- \z
19
- /x
20
- VARIABLE = /
21
- (\\)?
22
- (\$)
23
- ( # collect braces with var for sub
24
- \{? # allow brace wrapping
25
- ([A-Z0-9_]+) # match the variable
26
- \}? # closing brace
27
- )
28
- /xi
5
+ attr_reader :filename
29
6
 
30
- def initialize(filename)
7
+ def initialize(filename, is_load = false)
31
8
  @filename = filename
32
- load
9
+ load(is_load)
33
10
  end
34
11
 
35
- def load
36
- read.each do |line|
37
- if match = line.match(LINE)
38
- key, value = match.captures
39
-
40
- value ||= ''
41
- # Remove surrounding quotes
42
- value = value.strip.sub(/\A(['"])(.*)\1\z/, '\2')
43
-
44
- if $1 == '"'
45
- value = value.gsub('\n', "\n")
46
- # Unescape all characters except $ so variables can be escaped properly
47
- value = value.gsub(/\\([^$])/, '\1')
48
- end
49
-
50
- # Process embedded variables
51
- value.scan(VARIABLE).each do |parts|
52
- if parts.first == '\\'
53
- replace = parts[1...-1].join('')
54
- else
55
- replace = self.fetch(parts.last) { ENV[parts.last] }
56
- end
57
-
58
- value = value.sub(parts[0...-1].join(''), replace || '')
59
- end
60
-
61
- self[key] = value
62
- elsif line !~ /\A\s*(?:#.*)?\z/ # not comment or blank line
63
- raise FormatError, "Line #{line.inspect} doesn't match format"
64
- end
65
- end
12
+ def load(is_load = false)
13
+ update Parser.call(read, is_load)
66
14
  end
67
15
 
68
16
  def read
69
- File.read(@filename).split("\n")
17
+ File.open(@filename, "rb:bom|utf-8", &:read)
70
18
  end
71
19
 
72
20
  def apply
73
- each { |k,v| ENV[k] ||= v }
21
+ each { |k, v| ENV[k] ||= v }
22
+ end
23
+
24
+ def apply!
25
+ each { |k, v| ENV[k] = v }
74
26
  end
75
27
  end
76
28
  end
@@ -0,0 +1,2 @@
1
+ require "dotenv"
2
+ Dotenv.load
@@ -0,0 +1,10 @@
1
+ module Dotenv
2
+ class Error < StandardError; end
3
+
4
+ class MissingKeys < Error # :nodoc:
5
+ def initialize(keys)
6
+ key_word = "key#{keys.size > 1 ? 's' : ''}"
7
+ super("Missing required configuration #{key_word}: #{keys.inspect}")
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,98 @@
1
+ require "dotenv/substitutions/variable"
2
+ require "dotenv/substitutions/command" if RUBY_VERSION > "1.8.7"
3
+
4
+ module Dotenv
5
+ class FormatError < SyntaxError; end
6
+
7
+ # This class enables parsing of a string for key value pairs to be returned
8
+ # and stored in the Environment. It allows for variable substitutions and
9
+ # exporting of variables.
10
+ class Parser
11
+ @substitutions =
12
+ [Dotenv::Substitutions::Variable, Dotenv::Substitutions::Command]
13
+
14
+ LINE = /
15
+ (?:^|\A) # beginning of line
16
+ \s* # leading whitespace
17
+ (?:export\s+)? # optional export
18
+ ([\w\.]+) # key
19
+ (?:\s*=\s*?|:\s+?) # separator
20
+ ( # optional value begin
21
+ \s*'(?:\\'|[^'])*' # single quoted value
22
+ | # or
23
+ \s*"(?:\\"|[^"])*" # double quoted value
24
+ | # or
25
+ [^\#\r\n]+ # unquoted value
26
+ )? # value end
27
+ \s* # trailing whitespace
28
+ (?:\#.*)? # optional comment
29
+ (?:$|\z) # end of line
30
+ /x
31
+
32
+ class << self
33
+ attr_reader :substitutions
34
+
35
+ def call(string, is_load = false)
36
+ new(string, is_load).call
37
+ end
38
+ end
39
+
40
+ def initialize(string, is_load = false)
41
+ @string = string
42
+ @hash = {}
43
+ @is_load = is_load
44
+ end
45
+
46
+ def call
47
+ # Convert line breaks to same format
48
+ lines = @string.gsub(/\r\n?/, "\n")
49
+ # Process matches
50
+ lines.scan(LINE).each do |key, value|
51
+ @hash[key] = parse_value(value || "")
52
+ end
53
+ # Process non-matches
54
+ lines.gsub(LINE, "").split(/[\n\r]+/).each do |line|
55
+ parse_line(line)
56
+ end
57
+ @hash
58
+ end
59
+
60
+ private
61
+
62
+ def parse_line(line)
63
+ if line.split.first == "export"
64
+ if variable_not_set?(line)
65
+ raise FormatError, "Line #{line.inspect} has an unset variable"
66
+ end
67
+ end
68
+ end
69
+
70
+ def parse_value(value)
71
+ # Remove surrounding quotes
72
+ value = value.strip.sub(/\A(['"])(.*)\1\z/m, '\2')
73
+
74
+ if Regexp.last_match(1) == '"'
75
+ value = unescape_characters(expand_newlines(value))
76
+ end
77
+
78
+ if Regexp.last_match(1) != "'"
79
+ self.class.substitutions.each do |proc|
80
+ value = proc.call(value, @hash, @is_load)
81
+ end
82
+ end
83
+ value
84
+ end
85
+
86
+ def unescape_characters(value)
87
+ value.gsub(/\\([^$])/, '\1')
88
+ end
89
+
90
+ def expand_newlines(value)
91
+ value.gsub('\n', "\n").gsub('\r', "\r")
92
+ end
93
+
94
+ def variable_not_set?(line)
95
+ !line.split[1..-1].all? { |var| @hash.member?(var) }
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,41 @@
1
+ require "English"
2
+
3
+ module Dotenv
4
+ module Substitutions
5
+ # Substitute shell commands in a value.
6
+ #
7
+ # SHA=$(git rev-parse HEAD)
8
+ #
9
+ module Command
10
+ class << self
11
+ INTERPOLATED_SHELL_COMMAND = /
12
+ (?<backslash>\\)? # is it escaped with a backslash?
13
+ \$ # literal $
14
+ (?<cmd> # collect command content for eval
15
+ \( # require opening paren
16
+ ([^()]|\g<cmd>)+ # allow any number of non-parens, or balanced
17
+ # parens (by nesting the <cmd> expression
18
+ # recursively)
19
+ \) # require closing paren
20
+ )
21
+ /x
22
+
23
+ def call(value, _env, _is_load)
24
+ # Process interpolated shell commands
25
+ value.gsub(INTERPOLATED_SHELL_COMMAND) do |*|
26
+ # Eliminate opening and closing parentheses
27
+ command = $LAST_MATCH_INFO[:cmd][1..-2]
28
+
29
+ if $LAST_MATCH_INFO[:backslash]
30
+ # Command is escaped, don't replace it.
31
+ $LAST_MATCH_INFO[0][1..-1]
32
+ else
33
+ # Execute the command and return the value
34
+ `#{command}`.chomp
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ require "English"
2
+
3
+ module Dotenv
4
+ module Substitutions
5
+ # Substitute variables in a value.
6
+ #
7
+ # HOST=example.com
8
+ # URL="https://$HOST"
9
+ #
10
+ module Variable
11
+ class << self
12
+ VARIABLE = /
13
+ (\\)? # is it escaped with a backslash?
14
+ (\$) # literal $
15
+ (?!\() # shouldnt be followed by paranthesis
16
+ \{? # allow brace wrapping
17
+ ([A-Z0-9_]+)? # optional alpha nums
18
+ \}? # closing brace
19
+ /xi
20
+
21
+ def call(value, env, is_load)
22
+ combined_env = if is_load
23
+ env.merge(ENV)
24
+ else
25
+ ENV.to_h.merge(env)
26
+ end
27
+ value.gsub(VARIABLE) do |variable|
28
+ match = $LAST_MATCH_INFO
29
+ substitute(match, variable, combined_env)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def substitute(match, variable, env)
36
+ if match[1] == '\\'
37
+ variable[1..-1]
38
+ elsif match[3]
39
+ env.fetch(match[3], "")
40
+ else
41
+ variable
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
data/lib/dotenv/tasks.rb CHANGED
@@ -1,7 +1,7 @@
1
- desc 'Load environment settings from .env'
1
+ desc "Load environment settings from .env"
2
2
  task :dotenv do
3
- require 'dotenv'
3
+ require "dotenv"
4
4
  Dotenv.load
5
5
  end
6
6
 
7
- task :environment => :dotenv
7
+ task environment: :dotenv
@@ -0,0 +1,21 @@
1
+ module Dotenv
2
+ # Class for creating a template from a env file
3
+ class EnvTemplate
4
+ def initialize(env_file)
5
+ @env_file = env_file
6
+ end
7
+
8
+ def create_template
9
+ File.open(@env_file, "r") do |env_file|
10
+ File.open("#{@env_file}.template", "w") do |env_template|
11
+ env_file.each do |line|
12
+ var, value = line.split("=")
13
+ is_a_comment = var.strip[0].eql?("#")
14
+ line_transform = value.nil? || is_a_comment ? line : "#{var}=#{var}"
15
+ env_template.puts line_transform
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module Dotenv
2
- VERSION = '0.9.0'
2
+ VERSION = "2.7.6".freeze
3
3
  end
metadata CHANGED
@@ -1,48 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dotenv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
5
- prerelease:
4
+ version: 2.7.6
6
5
  platform: ruby
7
6
  authors:
8
7
  - Brandon Keepers
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-08-29 00:00:00.000000000 Z
11
+ date: 2020-07-11 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rspec
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.40.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.40.0
46
55
  description: Loads environment variables from `.env`.
47
56
  email:
48
57
  - brandon@opensoul.org
@@ -51,63 +60,41 @@ executables:
51
60
  extensions: []
52
61
  extra_rdoc_files: []
53
62
  files:
54
- - .env
55
- - .gitignore
56
- - .travis.yml
57
- - Changelog.md
58
- - Gemfile
59
- - Guardfile
60
63
  - LICENSE
61
64
  - README.md
62
- - Rakefile
63
65
  - bin/dotenv
64
- - dotenv-rails.gemspec
65
- - dotenv.gemspec
66
- - lib/dotenv-rails.rb
67
66
  - lib/dotenv.rb
68
- - lib/dotenv/capistrano.rb
69
- - lib/dotenv/capistrano/recipes.rb
67
+ - lib/dotenv/cli.rb
70
68
  - lib/dotenv/environment.rb
71
- - lib/dotenv/format_error.rb
72
- - lib/dotenv/railtie.rb
69
+ - lib/dotenv/load.rb
70
+ - lib/dotenv/missing_keys.rb
71
+ - lib/dotenv/parser.rb
72
+ - lib/dotenv/substitutions/command.rb
73
+ - lib/dotenv/substitutions/variable.rb
73
74
  - lib/dotenv/tasks.rb
75
+ - lib/dotenv/template.rb
74
76
  - lib/dotenv/version.rb
75
- - spec/dotenv/environment_spec.rb
76
- - spec/dotenv_spec.rb
77
- - spec/fixtures/exported.env
78
- - spec/fixtures/plain.env
79
- - spec/fixtures/quoted.env
80
- - spec/fixtures/yaml.env
81
- - spec/spec_helper.rb
82
77
  homepage: https://github.com/bkeepers/dotenv
83
- licenses: []
78
+ licenses:
79
+ - MIT
80
+ metadata: {}
84
81
  post_install_message:
85
82
  rdoc_options: []
86
83
  require_paths:
87
84
  - lib
88
85
  required_ruby_version: !ruby/object:Gem::Requirement
89
- none: false
90
86
  requirements:
91
- - - ! '>='
87
+ - - ">="
92
88
  - !ruby/object:Gem::Version
93
89
  version: '0'
94
90
  required_rubygems_version: !ruby/object:Gem::Requirement
95
- none: false
96
91
  requirements:
97
- - - ! '>='
92
+ - - ">="
98
93
  - !ruby/object:Gem::Version
99
94
  version: '0'
100
95
  requirements: []
101
- rubyforge_project:
102
- rubygems_version: 1.8.23
96
+ rubygems_version: 3.0.3
103
97
  signing_key:
104
- specification_version: 3
98
+ specification_version: 4
105
99
  summary: Loads environment variables from `.env`.
106
- test_files:
107
- - spec/dotenv/environment_spec.rb
108
- - spec/dotenv_spec.rb
109
- - spec/fixtures/exported.env
110
- - spec/fixtures/plain.env
111
- - spec/fixtures/quoted.env
112
- - spec/fixtures/yaml.env
113
- - spec/spec_helper.rb
100
+ test_files: []