module Dotenv
def instrument(name, payload = {}, &block)
def instrument(name, payload = {}, &block) if instrumenter instrumenter.instrument("#{name}.dotenv", payload, &block) else block&.call payload end end
def load(*filenames, overwrite: false, ignore: true)
def load(*filenames, overwrite: false, ignore: true) parse(*filenames, overwrite: overwrite, ignore: ignore) do |env| instrument(:load, env: env) do |payload| update(env, overwrite: overwrite) end end end
def load!(*filenames)
def load!(*filenames) load(*filenames, ignore: false) end
def modify(env = {}, &block)
-
env
(Hash
) -- Hash of keys and values to set in `ENV`
def modify(env = {}, &block) SEMAPHORE.synchronize do diff = Dotenv::Diff.new update(env, overwrite: true) block.call ensure restore(diff.a, safe: true) end end
def overwrite(*filenames)
def overwrite(*filenames) load(*filenames, overwrite: true) end
def overwrite!(*filenames)
def overwrite!(*filenames) load(*filenames, overwrite: true, ignore: false) end
def parse(*filenames, overwrite: false, ignore: true, &block)
-
(Hash)
- parsed key/value pairs
Parameters:
-
block
(Proc
) -- Block to yield for each parsed `Dotenv::Environment` -
ignore
(Boolean
) -- Ignore non-existent files -
overwrite
(Boolean
) -- Overwrite existing `ENV` values -
filenames
(String, Array
) -- Files to parse
def parse(*filenames, overwrite: false, ignore: true, &block) filenames << ".env" if filenames.empty? filenames = filenames.reverse if overwrite filenames.reduce({}) do |hash, filename| begin env = Environment.new(File.expand_path(filename), overwrite: overwrite) env = block.call(env) if block rescue Errno::ENOENT, Errno::EISDIR raise unless ignore end hash.merge! env || {} end end
def require_keys(*keys)
def require_keys(*keys) missing_keys = keys.flatten - ::ENV.keys return if missing_keys.empty? raise MissingKeys, missing_keys end
def restore(env = @diff&.a, safe: Thread.current == Thread.main)
-
safe
(Boolean
) -- Is it safe to modify `ENV`? Defaults to `true` in the main thread, otherwise raises an error. -
env
(Hash
) -- Hash of keys and values to restore, defaults to the last saved state
def restore(env = @diff&.a, safe: Thread.current == Thread.main) # No previously saved or provided state to restore return unless env diff = Dotenv::Diff.new(b: env) return unless diff.any? unless safe raise ThreadError, <<~EOE.tr("\n", " ") Dotenv.restore is not thread safe. Use `Dotenv.modify { }` to update ENV for the duration of the block in a thread safe manner, or call `Dotenv.restore(safe: true)` to ignore this error. EOE end instrument(:restore, diff: diff) { ENV.replace(env) } end
def save
def save instrument(:save) do |payload| @diff = payload[:diff] = Dotenv::Diff.new end end
def update(env = {}, overwrite: false)
-
overwrite
(Boolean
) -- Overwrite existing `ENV` values -
env
(Hash
) -- Hash of keys and values to set in `ENV`
def update(env = {}, overwrite: false) instrument(:update) do |payload| diff = payload[:diff] = Dotenv::Diff.new do ENV.update(env.transform_keys(&:to_s)) do |key, old_value, new_value| # This block is called when a key exists. Return the new value if overwrite is true. overwrite ? new_value : old_value end end diff.env end end