From bd45591ad82f8d4a06a4d5fd7d93e3d349298fb5 Mon Sep 17 00:00:00 2001 From: Brandon Keepers Date: Thu, 25 Jan 2024 10:27:19 -0500 Subject: [PATCH] Avoid memozing Diff since final state can change --- lib/dotenv/diff.rb | 48 ++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/lib/dotenv/diff.rb b/lib/dotenv/diff.rb index 91795499..329473b3 100644 --- a/lib/dotenv/diff.rb +++ b/lib/dotenv/diff.rb @@ -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