dotenv 2.7.6 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +171 -92
- data/lib/dotenv/autorestore.rb +29 -0
- data/lib/dotenv/cli.rb +27 -48
- data/lib/dotenv/diff.rb +59 -0
- data/lib/dotenv/environment.rb +12 -15
- data/lib/dotenv/load.rb +2 -1
- data/lib/dotenv/log_subscriber.rb +61 -0
- data/lib/dotenv/missing_keys.rb +1 -1
- data/lib/dotenv/parser.rb +64 -53
- data/lib/dotenv/rails-now.rb +10 -0
- data/lib/dotenv/rails.rb +111 -0
- data/lib/dotenv/replay_logger.rb +20 -0
- data/lib/dotenv/substitutions/command.rb +4 -4
- data/lib/dotenv/substitutions/variable.rb +9 -19
- data/lib/dotenv/template.rb +27 -4
- data/lib/dotenv/version.rb +1 -1
- data/lib/dotenv.rb +112 -47
- metadata +18 -13
data/lib/dotenv.rb
CHANGED
|
@@ -1,75 +1,133 @@
|
|
|
1
|
+
require "dotenv/version"
|
|
1
2
|
require "dotenv/parser"
|
|
2
3
|
require "dotenv/environment"
|
|
3
4
|
require "dotenv/missing_keys"
|
|
5
|
+
require "dotenv/diff"
|
|
4
6
|
|
|
5
|
-
#
|
|
7
|
+
# Shim to load environment variables from `.env files into `ENV`.
|
|
6
8
|
module Dotenv
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
extend self
|
|
10
|
+
|
|
11
|
+
# An internal monitor to synchronize access to ENV in multi-threaded environments.
|
|
12
|
+
SEMAPHORE = Monitor.new
|
|
13
|
+
private_constant :SEMAPHORE
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
attr_accessor :instrumenter
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
# Loads environment variables from one or more `.env` files. See `#parse` for more details.
|
|
18
|
+
def load(*filenames, overwrite: false, ignore: true)
|
|
19
|
+
parse(*filenames, overwrite: overwrite, ignore: ignore) do |env|
|
|
20
|
+
instrument(:load, env: env) do |payload|
|
|
21
|
+
update(env, overwrite: overwrite)
|
|
18
22
|
end
|
|
19
23
|
end
|
|
20
24
|
end
|
|
21
25
|
|
|
22
|
-
#
|
|
26
|
+
# Same as `#load`, but raises Errno::ENOENT if any files don't exist
|
|
23
27
|
def load!(*filenames)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
load(*filenames, ignore: false)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# same as `#load`, but will overwrite existing values in `ENV`
|
|
32
|
+
def overwrite(*filenames)
|
|
33
|
+
load(*filenames, overwrite: true)
|
|
34
|
+
end
|
|
35
|
+
alias_method :overload, :overwrite
|
|
36
|
+
|
|
37
|
+
# same as `#overwrite`, but raises Errno::ENOENT if any files don't exist
|
|
38
|
+
def overwrite!(*filenames)
|
|
39
|
+
load(*filenames, overwrite: true, ignore: false)
|
|
28
40
|
end
|
|
41
|
+
alias_method :overload!, :overwrite!
|
|
42
|
+
|
|
43
|
+
# Parses the given files, yielding for each file if a block is given.
|
|
44
|
+
#
|
|
45
|
+
# @param filenames [String, Array<String>] Files to parse
|
|
46
|
+
# @param overwrite [Boolean] Overwrite existing `ENV` values
|
|
47
|
+
# @param ignore [Boolean] Ignore non-existent files
|
|
48
|
+
# @param block [Proc] Block to yield for each parsed `Dotenv::Environment`
|
|
49
|
+
# @return [Hash] parsed key/value pairs
|
|
50
|
+
def parse(*filenames, overwrite: false, ignore: true, &block)
|
|
51
|
+
filenames << ".env" if filenames.empty?
|
|
52
|
+
filenames = filenames.reverse if overwrite
|
|
29
53
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
54
|
+
filenames.reduce({}) do |hash, filename|
|
|
55
|
+
begin
|
|
56
|
+
env = Environment.new(File.expand_path(filename), overwrite: overwrite)
|
|
57
|
+
env = block.call(env) if block
|
|
58
|
+
rescue Errno::ENOENT, Errno::EISDIR
|
|
59
|
+
raise unless ignore
|
|
36
60
|
end
|
|
61
|
+
|
|
62
|
+
hash.merge! env || {}
|
|
37
63
|
end
|
|
38
64
|
end
|
|
39
65
|
|
|
40
|
-
#
|
|
41
|
-
def
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
instrument("dotenv.overload", env: env) { env.apply! }
|
|
66
|
+
# Save the current `ENV` to be restored later
|
|
67
|
+
def save
|
|
68
|
+
instrument(:save) do |payload|
|
|
69
|
+
@diff = payload[:diff] = Dotenv::Diff.new
|
|
45
70
|
end
|
|
46
71
|
end
|
|
47
72
|
|
|
48
|
-
#
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
73
|
+
# Restore `ENV` to a given state
|
|
74
|
+
#
|
|
75
|
+
# @param env [Hash] Hash of keys and values to restore, defaults to the last saved state
|
|
76
|
+
# @param safe [Boolean] Is it safe to modify `ENV`? Defaults to `true` in the main thread, otherwise raises an error.
|
|
77
|
+
def restore(env = @diff&.a, safe: Thread.current == Thread.main)
|
|
78
|
+
# No previously saved or provided state to restore
|
|
79
|
+
return unless env
|
|
80
|
+
|
|
81
|
+
diff = Dotenv::Diff.new(b: env)
|
|
82
|
+
return unless diff.any?
|
|
83
|
+
|
|
84
|
+
unless safe
|
|
85
|
+
raise ThreadError, <<~EOE.tr("\n", " ")
|
|
86
|
+
Dotenv.restore is not thread safe. Use `Dotenv.modify { }` to update ENV for the duration
|
|
87
|
+
of the block in a thread safe manner, or call `Dotenv.restore(safe: true)` to ignore
|
|
88
|
+
this error.
|
|
89
|
+
EOE
|
|
54
90
|
end
|
|
91
|
+
instrument(:restore, diff: diff) { ENV.replace(env) }
|
|
55
92
|
end
|
|
56
93
|
|
|
57
|
-
#
|
|
94
|
+
# Update `ENV` with the given hash of keys and values
|
|
58
95
|
#
|
|
59
|
-
#
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
96
|
+
# @param env [Hash] Hash of keys and values to set in `ENV`
|
|
97
|
+
# @param overwrite [Boolean|:warn] Overwrite existing `ENV` values
|
|
98
|
+
def update(env = {}, overwrite: false)
|
|
99
|
+
instrument(:update) do |payload|
|
|
100
|
+
diff = payload[:diff] = Dotenv::Diff.new do
|
|
101
|
+
ENV.update(env.transform_keys(&:to_s)) do |key, old_value, new_value|
|
|
102
|
+
# This block is called when a key exists. Return the new value if overwrite is true.
|
|
103
|
+
case overwrite
|
|
104
|
+
when :warn
|
|
105
|
+
# not printing the value since that could be a secret
|
|
106
|
+
warn "Warning: dotenv not overwriting ENV[#{key.inspect}]"
|
|
107
|
+
old_value
|
|
108
|
+
when true then new_value
|
|
109
|
+
when false then old_value
|
|
110
|
+
else raise ArgumentError, "Invalid value for overwrite: #{overwrite.inspect}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
diff.env
|
|
65
115
|
end
|
|
66
116
|
end
|
|
67
117
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
118
|
+
# Modify `ENV` for the block and restore it to its previous state afterwards.
|
|
119
|
+
#
|
|
120
|
+
# Note that the block is synchronized to prevent concurrent modifications to `ENV`,
|
|
121
|
+
# so multiple threads will be executed serially.
|
|
122
|
+
#
|
|
123
|
+
# @param env [Hash] Hash of keys and values to set in `ENV`
|
|
124
|
+
def modify(env = {}, &block)
|
|
125
|
+
SEMAPHORE.synchronize do
|
|
126
|
+
diff = Dotenv::Diff.new
|
|
127
|
+
update(env, overwrite: true)
|
|
128
|
+
block.call
|
|
129
|
+
ensure
|
|
130
|
+
restore(diff.a, safe: true)
|
|
73
131
|
end
|
|
74
132
|
end
|
|
75
133
|
|
|
@@ -79,8 +137,15 @@ module Dotenv
|
|
|
79
137
|
raise MissingKeys, missing_keys
|
|
80
138
|
end
|
|
81
139
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
140
|
+
private
|
|
141
|
+
|
|
142
|
+
def instrument(name, payload = {}, &block)
|
|
143
|
+
if instrumenter
|
|
144
|
+
instrumenter.instrument("#{name}.dotenv", payload, &block)
|
|
145
|
+
else
|
|
146
|
+
block&.call payload
|
|
147
|
+
end
|
|
85
148
|
end
|
|
86
149
|
end
|
|
150
|
+
|
|
151
|
+
require "dotenv/rails" if defined?(Rails::Railtie)
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dotenv
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 3.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brandon Keepers
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rake
|
|
@@ -39,19 +38,19 @@ dependencies:
|
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
39
|
version: '0'
|
|
41
40
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
41
|
+
name: standard
|
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
|
44
43
|
requirements:
|
|
45
|
-
- - "
|
|
44
|
+
- - ">="
|
|
46
45
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0
|
|
46
|
+
version: '0'
|
|
48
47
|
type: :development
|
|
49
48
|
prerelease: false
|
|
50
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
50
|
requirements:
|
|
52
|
-
- - "
|
|
51
|
+
- - ">="
|
|
53
52
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0
|
|
53
|
+
version: '0'
|
|
55
54
|
description: Loads environment variables from `.env`.
|
|
56
55
|
email:
|
|
57
56
|
- brandon@opensoul.org
|
|
@@ -64,11 +63,17 @@ files:
|
|
|
64
63
|
- README.md
|
|
65
64
|
- bin/dotenv
|
|
66
65
|
- lib/dotenv.rb
|
|
66
|
+
- lib/dotenv/autorestore.rb
|
|
67
67
|
- lib/dotenv/cli.rb
|
|
68
|
+
- lib/dotenv/diff.rb
|
|
68
69
|
- lib/dotenv/environment.rb
|
|
69
70
|
- lib/dotenv/load.rb
|
|
71
|
+
- lib/dotenv/log_subscriber.rb
|
|
70
72
|
- lib/dotenv/missing_keys.rb
|
|
71
73
|
- lib/dotenv/parser.rb
|
|
74
|
+
- lib/dotenv/rails-now.rb
|
|
75
|
+
- lib/dotenv/rails.rb
|
|
76
|
+
- lib/dotenv/replay_logger.rb
|
|
72
77
|
- lib/dotenv/substitutions/command.rb
|
|
73
78
|
- lib/dotenv/substitutions/variable.rb
|
|
74
79
|
- lib/dotenv/tasks.rb
|
|
@@ -77,8 +82,9 @@ files:
|
|
|
77
82
|
homepage: https://github.com/bkeepers/dotenv
|
|
78
83
|
licenses:
|
|
79
84
|
- MIT
|
|
80
|
-
metadata:
|
|
81
|
-
|
|
85
|
+
metadata:
|
|
86
|
+
changelog_uri: https://github.com/bkeepers/dotenv/releases
|
|
87
|
+
funding_uri: https://github.com/sponsors/bkeepers
|
|
82
88
|
rdoc_options: []
|
|
83
89
|
require_paths:
|
|
84
90
|
- lib
|
|
@@ -86,15 +92,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
86
92
|
requirements:
|
|
87
93
|
- - ">="
|
|
88
94
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '0'
|
|
95
|
+
version: '3.0'
|
|
90
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
97
|
requirements:
|
|
92
98
|
- - ">="
|
|
93
99
|
- !ruby/object:Gem::Version
|
|
94
100
|
version: '0'
|
|
95
101
|
requirements: []
|
|
96
|
-
rubygems_version: 3.
|
|
97
|
-
signing_key:
|
|
102
|
+
rubygems_version: 3.6.9
|
|
98
103
|
specification_version: 4
|
|
99
104
|
summary: Loads environment variables from `.env`.
|
|
100
105
|
test_files: []
|