dotenv 2.2.1 → 2.8.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 95698b07caac9203e94c95ae1075999dedcbd920
4
- data.tar.gz: b072b014503b4c1c528de3b757f04285edf4099d
2
+ SHA256:
3
+ metadata.gz: ac1a9e8e04f95f111da23bf2541070f2617864fc3c55ac4e11e6b91c78d11a9b
4
+ data.tar.gz: 24bf24be5be7020e72877e32d8cd2d9cf022a74b182569c77b2c81c0d482696b
5
5
  SHA512:
6
- metadata.gz: 580b4fa8f27c2739b43e84eac9cb12b0febb59300db9f717630b249fdecfa4015098faf840106012e9fac8b68e522c383ac01098c18dd6771bfe75a46912cd2d
7
- data.tar.gz: 8e8d92bc27cd525d6019bcea29235b330c37d8b123bc801bdb3509344a41c0e758718c1e530c8d7bf2c98b0d4686f59749a18dc2729fe1d3cd27748733668539
6
+ metadata.gz: 1f8d6ae3bfd67c1b57bc4d72346d670c02570d07cee953930d6b7f9018cc053ac42624d1bc4d59dd112abe5ba711d551199ff92a2672d5434577356b0a24d0c0
7
+ data.tar.gz: 38488d0f24d6f6014f87415775f94969cd56236bcb848c77b5dd4d066285ec47993006f87f1ab1afb50a033db101fe206741ec8e561de602a88717ad6fff3bdf
data/README.md CHANGED
@@ -1,6 +1,4 @@
1
- # dotenv [![Build Status](https://secure.travis-ci.org/bkeepers/dotenv.png?branch=master)](https://travis-ci.org/bkeepers/dotenv)
2
-
3
- [![Join the chat at https://gitter.im/bkeepers/dotenv](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bkeepers/dotenv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
1
+ # dotenv [![Gem Version](https://badge.fury.io/rb/dotenv.svg)](https://badge.fury.io/rb/dotenv) [![Join the chat at https://gitter.im/bkeepers/dotenv](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bkeepers/dotenv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
2
 
5
3
  Shim to load environment variables from `.env` into `ENV` in *development*.
6
4
 
@@ -32,7 +30,10 @@ dotenv is initialized in your Rails app during the `before_configuration` callba
32
30
  # config/application.rb
33
31
  Bundler.require(*Rails.groups)
34
32
 
35
- Dotenv::Railtie.load
33
+ # Load dotenv only in development or test environment
34
+ if ['development', 'test'].include? ENV['RAILS_ENV']
35
+ Dotenv::Railtie.load
36
+ end
36
37
 
37
38
  HOSTNAME = ENV['HOSTNAME']
38
39
  ```
@@ -64,7 +65,7 @@ Dotenv.load
64
65
 
65
66
  By default, `load` will look for a file called `.env` in the current working directory. Pass in multiple files and they will be loaded in order. The first value set for a variable will win.
66
67
 
67
- ```
68
+ ```ruby
68
69
  require 'dotenv'
69
70
  Dotenv.load('file1.env', 'file2.env')
70
71
  ```
@@ -72,7 +73,13 @@ Dotenv.load('file1.env', 'file2.env')
72
73
  Alternatively, you can use the `dotenv` executable to launch your application:
73
74
 
74
75
  ```shell
75
- $ dotenv ./script.py
76
+ $ dotenv ./script.rb
77
+ ```
78
+
79
+ The `dotenv` executable also accepts a single flag, `-f`. Its value should be a comma-separated list of configuration files, in the order of most important to least. All of the files must exist. There _must_ be a space between the flag and its value.
80
+
81
+ ```
82
+ $ dotenv -f ".env.local,.env" ./script.rb
76
83
  ```
77
84
 
78
85
  To ensure `.env` is loaded in rake, load the tasks:
@@ -112,9 +119,21 @@ export SECRET_KEY=YOURSECRETKEYGOESHERE
112
119
  If you need multiline variables, for example private keys, you can double quote strings and use the `\n` character for newlines:
113
120
 
114
121
  ```shell
115
- PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nHkVN9…\n-----END DSA PRIVATE KEY-----\n"
122
+ PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nHkVN9...\n-----END DSA PRIVATE KEY-----\n"
123
+ ```
124
+
125
+ Alternatively, multi-line values with line breaks are now supported for quoted values.
126
+
127
+ ```shell
128
+ PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
129
+ ...
130
+ HkVN9...
131
+ ...
132
+ -----END DSA PRIVATE KEY-----"
116
133
  ```
117
134
 
135
+ This is particularly helpful when using the Heroku command line plugin [`heroku-config`](https://github.com/xavdid/heroku-config) to pull configuration variables down that may have line breaks.
136
+
118
137
  ### Command Substitution
119
138
 
120
139
  You need to add the output of a command in one of your variables? Simply add it with `$(your_command)`:
@@ -147,6 +166,31 @@ SECRET_KEY=YOURSECRETKEYGOESHERE # comment
147
166
  SECRET_HASH="something-with-a-#-hash"
148
167
  ```
149
168
 
169
+ ### Required Keys
170
+
171
+ If a particular configuration value is required but not set, it's appropriate to raise an error.
172
+
173
+ To require configuration keys:
174
+
175
+ ```ruby
176
+ # config/initializers/dotenv.rb
177
+
178
+ Dotenv.require_keys("SERVICE_APP_ID", "SERVICE_KEY", "SERVICE_SECRET")
179
+ ```
180
+
181
+ If any of the configuration keys above are not set, your application will raise an error during initialization. This method is preferred because it prevents runtime errors in a production application due to improper configuration.
182
+
183
+ ### Parsing
184
+
185
+ To parse a list of env files for programmatic inspection without modifying the ENV:
186
+
187
+ ```ruby
188
+ Dotenv.parse(".env.local", ".env")
189
+ # => {'S3_BUCKET' => 'YOURS3BUCKET', 'SECRET_KEY' => 'YOURSECRETKEYGOESHERE', ...}
190
+ ```
191
+
192
+ This method returns a hash of the ENV var name/value pairs.
193
+
150
194
  ## Frequently Answered Questions
151
195
 
152
196
  ### Can I use dotenv in production?
@@ -159,23 +203,58 @@ If you use this gem to handle env vars for multiple Rails environments (developm
159
203
 
160
204
  ### What other .env* files can I use?
161
205
 
162
- `dotenv-rails` will load the following files, starting from the bottom. The first value set (or those already defined in the environment) take precedence:
206
+ `dotenv-rails` will override in the following order (highest defined variable overrides lower):
207
+
208
+ | Hierarchy Priority | Filename | Environment | Should I `.gitignore`it? | Notes |
209
+ | ------------------ | ------------------------ | -------------------- | --------------------------------------------------- | ------------------------------------------------------------ |
210
+ | 1st (highest) | `.env.development.local` | Development | Yes! | Local overrides of environment-specific settings. |
211
+ | 1st | `.env.test.local` | Test | Yes! | Local overrides of environment-specific settings. |
212
+ | 1st | `.env.production.local` | Production | Yes! | Local overrides of environment-specific settings. |
213
+ | 2nd | `.env.local` | Wherever the file is | Definitely. | Local overrides. This file is loaded for all environments _except_ `test`. |
214
+ | 3rd | `.env.development` | Development | No. | Shared environment-specific settings |
215
+ | 3rd | `.env.test` | Test | No. | Shared environment-specific settings |
216
+ | 3rd | `.env.production` | Production | No. | Shared environment-specific settings |
217
+ | Last | `.env` | All Environments | Depends (See [below](#should-i-commit-my-env-file)) | The Original® |
163
218
 
164
- - `.env` - The Original®
165
- - `.env.development`, `.env.test`, `.env.production` - Environment-specific settings.
166
- - `.env.local` - Local overrides. This file is loaded for all environments _except_ `test`.
167
- - `.env.development.local`, `.env.test.local`, `.env.production.local` - Local overrides of environment-specific settings.
168
219
 
169
220
  ### Should I commit my .env file?
170
221
 
171
222
  Credentials should only be accessible on the machines that need access to them. Never commit sensitive information to a repository that is not needed by every development machine and server.
172
223
 
224
+
225
+ You can use the `-t` or `--template` flag on the dotenv cli to create a template of your `.env` file.
226
+ ```shell
227
+ $ dotenv -t .env
228
+ ```
229
+ A template will be created in your working directory named `{FINAME}.template`. So in the above example, it would create a `.env.template` file.
230
+
231
+ The template will contain all the environment variables in your `.env` file but with their values set to the variable names.
232
+
233
+ ```shell
234
+ # .env
235
+ S3_BUCKET=YOURS3BUCKET
236
+ SECRET_KEY=YOURSECRETKEYGOESHERE
237
+ ```
238
+
239
+ Would become
240
+
241
+ ```shell
242
+ # .env.template
243
+ S3_BUCKET=S3_BUCKET
244
+ SECRET_KEY=SECRET_KEY
245
+ ```
246
+
173
247
  Personally, I prefer to commit the `.env` file with development-only settings. This makes it easy for other developers to get started on the project without compromising credentials for other environments. If you follow this advice, make sure that all the credentials for your development environment are different from your other deployments and that the development credentials do not have access to any confidential data.
174
248
 
175
249
  ### Why is it not overriding existing `ENV` variables?
176
250
 
177
251
  By default, it **won't** overwrite existing environment variables as dotenv assumes the deployment environment has more knowledge about configuration than the application does. To overwrite existing environment variables you can use `Dotenv.overload`.
178
252
 
253
+ You can also use the `-o` or `--overload` flag on the dotenv cli to override existing `ENV` variables.
254
+ ```shell
255
+ $ dotenv -o -f ".env.local,.env"
256
+ ```
257
+
179
258
  ## Contributing
180
259
 
181
260
  If you want a better idea of how dotenv works, check out the [Ruby Rogues Code Reading of dotenv](https://www.youtube.com/watch?v=lKmY_0uY86s).
data/lib/dotenv/cli.rb CHANGED
@@ -1,36 +1,57 @@
1
1
  require "dotenv"
2
+ require "dotenv/version"
3
+ require "dotenv/template"
4
+ require "optparse"
2
5
 
3
6
  module Dotenv
4
- # The CLI is a class responsible of handling all the command line interface
5
- # logic.
6
- class CLI
7
- attr_reader :argv
7
+ # The command line interface
8
+ class CLI < OptionParser
9
+ attr_reader :argv, :filenames, :overload
8
10
 
9
11
  def initialize(argv = [])
10
12
  @argv = argv.dup
13
+ @filenames = []
14
+ @overload = false
15
+
16
+ super "Usage: dotenv [options]"
17
+ separator ""
18
+
19
+ on("-f FILES", Array, "List of env files to parse") do |list|
20
+ @filenames = list
21
+ end
22
+
23
+ on("-o", "--overload", "override existing ENV variables") do
24
+ @overload = true
25
+ end
26
+
27
+ on("-h", "--help", "Display help") do
28
+ puts self
29
+ exit
30
+ end
31
+
32
+ on("-v", "--version", "Show version") do
33
+ puts "dotenv #{Dotenv::VERSION}"
34
+ exit
35
+ end
36
+
37
+ on("-t", "--template=FILE", "Create a template env file") do |file|
38
+ template = Dotenv::EnvTemplate.new(file)
39
+ template.create_template
40
+ end
41
+
42
+ order!(@argv)
11
43
  end
12
44
 
13
45
  def run
14
- filenames = parse_filenames || []
15
- begin
16
- Dotenv.load!(*filenames)
17
- rescue Errno::ENOENT => e
18
- abort e.message
46
+ if @overload
47
+ Dotenv.overload!(*@filenames)
19
48
  else
20
- exec(*argv) unless argv.empty?
49
+ Dotenv.load!(*@filenames)
21
50
  end
22
- end
23
-
24
- private
25
-
26
- def parse_filenames
27
- pos = argv.index("-f")
28
- return nil unless pos
29
- # drop the -f
30
- argv.delete_at pos
31
- # parse one or more comma-separated .env files
32
- require "csv"
33
- CSV.parse_line argv.delete_at(pos)
51
+ rescue Errno::ENOENT => e
52
+ abort e.message
53
+ else
54
+ exec(*@argv) unless @argv.empty?
34
55
  end
35
56
  end
36
57
  end
@@ -4,13 +4,13 @@ module Dotenv
4
4
  class Environment < Hash
5
5
  attr_reader :filename
6
6
 
7
- def initialize(filename)
7
+ def initialize(filename, is_load = false)
8
8
  @filename = filename
9
- load
9
+ load(is_load)
10
10
  end
11
11
 
12
- def load
13
- update Parser.call(read)
12
+ def load(is_load = false)
13
+ update Parser.call(read, is_load)
14
14
  end
15
15
 
16
16
  def read
@@ -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
data/lib/dotenv/parser.rb CHANGED
@@ -12,38 +12,46 @@ module Dotenv
12
12
  [Dotenv::Substitutions::Variable, Dotenv::Substitutions::Command]
13
13
 
14
14
  LINE = /
15
- \A
16
- \s*
17
- (?:export\s+)? # optional export
18
- ([\w\.]+) # key
19
- (?:\s*=\s*|:\s+?) # separator
20
- ( # optional value begin
21
- '(?:\'|[^'])*' # single quoted value
22
- | # or
23
- "(?:\"|[^"])*" # double quoted value
24
- | # or
25
- [^#\n]+ # unquoted value
26
- )? # value end
27
- \s*
28
- (?:\#.*)? # optional comment
29
- \z
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
30
  /x
31
31
 
32
32
  class << self
33
33
  attr_reader :substitutions
34
34
 
35
- def call(string)
36
- new(string).call
35
+ def call(string, is_load = false)
36
+ new(string, is_load).call
37
37
  end
38
38
  end
39
39
 
40
- def initialize(string)
40
+ def initialize(string, is_load = false)
41
41
  @string = string
42
42
  @hash = {}
43
+ @is_load = is_load
43
44
  end
44
45
 
45
46
  def call
46
- @string.split(/[\n\r]+/).each do |line|
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|
47
55
  parse_line(line)
48
56
  end
49
57
  @hash
@@ -52,32 +60,19 @@ module Dotenv
52
60
  private
53
61
 
54
62
  def parse_line(line)
55
- if (match = line.match(LINE))
56
- key, value = match.captures
57
- @hash[key] = parse_value(value || "")
58
- elsif line.split.first == "export"
63
+ if line.split.first == "export"
59
64
  if variable_not_set?(line)
60
65
  raise FormatError, "Line #{line.inspect} has an unset variable"
61
66
  end
62
- elsif line !~ /\A\s*(?:#.*)?\z/ # not comment or blank line
63
- raise FormatError, "Line #{line.inspect} doesn't match format"
64
67
  end
65
68
  end
66
69
 
67
70
  def parse_value(value)
68
71
  # Remove surrounding quotes
69
- value = value.strip.sub(/\A(['"])(.*)\1\z/, '\2')
70
-
71
- if Regexp.last_match(1) == '"'
72
- value = unescape_characters(expand_newlines(value))
73
- end
74
-
75
- if Regexp.last_match(1) != "'"
76
- self.class.substitutions.each do |proc|
77
- value = proc.call(value, @hash)
78
- end
79
- end
80
- value
72
+ value = value.strip.sub(/\A(['"])(.*)\1\z/m, '\2')
73
+ maybe_quote = Regexp.last_match(1)
74
+ value = unescape_value(value, maybe_quote)
75
+ perform_substitutions(value, maybe_quote)
81
76
  end
82
77
 
83
78
  def unescape_characters(value)
@@ -91,5 +86,24 @@ module Dotenv
91
86
  def variable_not_set?(line)
92
87
  !line.split[1..-1].all? { |var| @hash.member?(var) }
93
88
  end
89
+
90
+ def unescape_value(value, maybe_quote)
91
+ if maybe_quote == '"'
92
+ unescape_characters(expand_newlines(value))
93
+ elsif maybe_quote.nil?
94
+ unescape_characters(value)
95
+ else
96
+ value
97
+ end
98
+ end
99
+
100
+ def perform_substitutions(value, maybe_quote)
101
+ if maybe_quote != "'"
102
+ self.class.substitutions.each do |proc|
103
+ value = proc.call(value, @hash, @is_load)
104
+ end
105
+ end
106
+ value
107
+ end
94
108
  end
95
109
  end
@@ -13,14 +13,14 @@ module Dotenv
13
13
  \$ # literal $
14
14
  (?<cmd> # collect command content for eval
15
15
  \( # require opening paren
16
- ([^()]|\g<cmd>)+ # allow any number of non-parens, or balanced
16
+ (?:[^()]|\g<cmd>)+ # allow any number of non-parens, or balanced
17
17
  # parens (by nesting the <cmd> expression
18
18
  # recursively)
19
19
  \) # require closing paren
20
20
  )
21
21
  /x
22
22
 
23
- def call(value, _env)
23
+ def call(value, _env, _is_load)
24
24
  # Process interpolated shell commands
25
25
  value.gsub(INTERPOLATED_SHELL_COMMAND) do |*|
26
26
  # Eliminate opening and closing parentheses
@@ -18,17 +18,23 @@ module Dotenv
18
18
  \}? # closing brace
19
19
  /xi
20
20
 
21
- def call(value, env)
21
+ def call(value, env, is_load)
22
+ combined_env = is_load ? env.merge(ENV) : ENV.to_h.merge(env)
22
23
  value.gsub(VARIABLE) do |variable|
23
24
  match = $LAST_MATCH_INFO
25
+ substitute(match, variable, combined_env)
26
+ end
27
+ end
28
+
29
+ private
24
30
 
25
- if match[1] == '\\'
26
- variable[1..-1]
27
- elsif match[3]
28
- env.fetch(match[3]) { ENV[match[3]] }
29
- else
30
- variable
31
- end
31
+ def substitute(match, variable, env)
32
+ if match[1] == "\\"
33
+ variable[1..-1]
34
+ elsif match[3]
35
+ env.fetch(match[3], "")
36
+ else
37
+ variable
32
38
  end
33
39
  end
34
40
  end
@@ -0,0 +1,26 @@
1
+ module Dotenv
2
+ EXPORT_COMMAND = "export ".freeze
3
+ # Class for creating a template from a env file
4
+ class EnvTemplate
5
+ def initialize(env_file)
6
+ @env_file = env_file
7
+ end
8
+
9
+ def create_template
10
+ File.open(@env_file, "r") do |env_file|
11
+ File.open("#{@env_file}.template", "w") do |env_template|
12
+ env_file.each do |line|
13
+ env_template.puts template_line(line)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def template_line(line)
20
+ var, value = line.split("=")
21
+ template = var.gsub(EXPORT_COMMAND, "")
22
+ is_a_comment = var.strip[0].eql?("#")
23
+ value.nil? || is_a_comment ? line : "#{var}=#{template}"
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module Dotenv
2
- VERSION = "2.2.1".freeze
2
+ VERSION = "2.8.1".freeze
3
3
  end
data/lib/dotenv.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "dotenv/parser"
2
2
  require "dotenv/environment"
3
+ require "dotenv/missing_keys"
3
4
 
4
5
  # The top level Dotenv module. The entrypoint for the application logic.
5
6
  module Dotenv
@@ -12,7 +13,7 @@ module Dotenv
12
13
  def load(*filenames)
13
14
  with(*filenames) do |f|
14
15
  ignoring_nonexistent_files do
15
- env = Environment.new(f)
16
+ env = Environment.new(f, true)
16
17
  instrument("dotenv.load", env: env) { env.apply }
17
18
  end
18
19
  end
@@ -21,7 +22,7 @@ module Dotenv
21
22
  # same as `load`, but raises Errno::ENOENT if any files don't exist
22
23
  def load!(*filenames)
23
24
  with(*filenames) do |f|
24
- env = Environment.new(f)
25
+ env = Environment.new(f, true)
25
26
  instrument("dotenv.load", env: env) { env.apply }
26
27
  end
27
28
  end
@@ -30,12 +31,29 @@ module Dotenv
30
31
  def overload(*filenames)
31
32
  with(*filenames) do |f|
32
33
  ignoring_nonexistent_files do
33
- env = Environment.new(f)
34
+ env = Environment.new(f, false)
34
35
  instrument("dotenv.overload", env: env) { env.apply! }
35
36
  end
36
37
  end
37
38
  end
38
39
 
40
+ # same as `overload`, but raises Errno::ENOENT if any files don't exist
41
+ def overload!(*filenames)
42
+ with(*filenames) do |f|
43
+ env = Environment.new(f, false)
44
+ instrument("dotenv.overload", env: env) { env.apply! }
45
+ end
46
+ end
47
+
48
+ # returns a hash of parsed key/value pairs but does not modify ENV
49
+ def parse(*filenames)
50
+ with(*filenames) do |f|
51
+ ignoring_nonexistent_files do
52
+ Environment.new(f, false)
53
+ end
54
+ end
55
+ end
56
+
39
57
  # Internal: Helper to expand list of filenames.
40
58
  #
41
59
  # Returns a hash of all the loaded environment variables.
@@ -55,6 +73,12 @@ module Dotenv
55
73
  end
56
74
  end
57
75
 
76
+ def require_keys(*keys)
77
+ missing_keys = keys.flatten - ::ENV.keys
78
+ return if missing_keys.empty?
79
+ raise MissingKeys, missing_keys
80
+ end
81
+
58
82
  def ignoring_nonexistent_files
59
83
  yield
60
84
  rescue Errno::ENOENT
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dotenv
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Keepers
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-28 00:00:00.000000000 Z
11
+ date: 2022-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -39,19 +39,19 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rubocop
42
+ name: standard
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 0.40.0
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 0.40.0
54
+ version: '0'
55
55
  description: Loads environment variables from `.env`.
56
56
  email:
57
57
  - brandon@opensoul.org
@@ -67,16 +67,18 @@ files:
67
67
  - lib/dotenv/cli.rb
68
68
  - lib/dotenv/environment.rb
69
69
  - lib/dotenv/load.rb
70
+ - lib/dotenv/missing_keys.rb
70
71
  - lib/dotenv/parser.rb
71
72
  - lib/dotenv/substitutions/command.rb
72
73
  - lib/dotenv/substitutions/variable.rb
73
74
  - lib/dotenv/tasks.rb
75
+ - lib/dotenv/template.rb
74
76
  - lib/dotenv/version.rb
75
77
  homepage: https://github.com/bkeepers/dotenv
76
78
  licenses:
77
79
  - MIT
78
80
  metadata: {}
79
- post_install_message:
81
+ post_install_message:
80
82
  rdoc_options: []
81
83
  require_paths:
82
84
  - lib
@@ -91,9 +93,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
93
  - !ruby/object:Gem::Version
92
94
  version: '0'
93
95
  requirements: []
94
- rubyforge_project:
95
- rubygems_version: 2.6.8
96
- signing_key:
96
+ rubygems_version: 3.2.32
97
+ signing_key:
97
98
  specification_version: 4
98
99
  summary: Loads environment variables from `.env`.
99
100
  test_files: []