Skip to content

Commit

Permalink
Avoid memozing Diff since final state can change
Browse files Browse the repository at this point in the history
  • Loading branch information
bkeepers committed Jan 25, 2024
1 parent be06c95 commit bd45591
Showing 1 changed file with 25 additions and 23 deletions.
48 changes: 25 additions & 23 deletions lib/dotenv/diff.rb
Original file line number Diff line number Diff line change
@@ -1,54 +1,56 @@
module Dotenv
# A diff between multiple states of ENV.
class Diff
# The initial state
attr_reader :a

# Create a new diff. The initial state defaults to a clone of current ENV. If given a block,
# the state of ENV will be preserved as the final state for comparison. Otherwise, the current
# ENV will be the current state.
def initialize(a: current_env, b: nil, &block)
@a, @b = a, b
if block
begin
block.call self
ensure
@b = current_env
end
end
end
# The final or current state
attr_reader :b

def b
@b || current_env
end

def current_env
ENV.to_h.freeze
# Create a new diff. If given a block, the state of ENV after the block will be preserved as
# the final state for comparison. Otherwise, the current ENV will be the final state.
#
# @param a [Hash] the initial state, defaults to a snapshot of current ENV
# @param b [Hash] the final state, defaults to the current ENV
# @yield [diff] a block to execute before recording the final state
def initialize(a: snapshot, b: ENV, &block)
@a, @b = a, b
block&.call self
ensure
@b = snapshot if block
end

# Return a Hash of keys added with their new values
def added
@added ||= b.slice(*(b.keys - a.keys))
b.slice(*(b.keys - a.keys))
end

# Returns a Hash of keys removed with their previous values
def removed
@removed ||= a.slice(*(a.keys - b.keys))
a.slice(*(a.keys - b.keys))
end

# Returns of Hash of keys changed with an array of their previous and new values
def changed
@changed ||= (b.slice(*a.keys).to_a - a.to_a).map do |(k, v)|
(b.slice(*a.keys).to_a - a.to_a).map do |(k, v)|
[k, [a[k], v]]
end.to_h
end

# Returns a Hash of all added, changed, and removed keys and their new values
def env
@env ||= b.slice(*(added.keys + changed.keys)).merge(removed.transform_values { |v| nil })
b.slice(*(added.keys + changed.keys)).merge(removed.transform_values { |v| nil })
end

# Returns true if any keys were added, removed, or changed
def any?
[added, removed, changed].any?(&:any?)
end

private

def snapshot
ENV.to_h.freeze
end
end
end

0 comments on commit bd45591

Please sign in to comment.