From 2ad3dc1d4bb3279005e59dcd5324d4b90887c06e Mon Sep 17 00:00:00 2001 From: Chris Badahdah Date: Tue, 27 Jun 2023 12:01:15 -0700 Subject: [PATCH] Diff / preserve metadata on collections --- CHANGELOG.md | 2 + src/lambdaisland/deep_diff2/diff_impl.cljc | 68 ++++++++++++--------- test/lambdaisland/deep_diff2/diff_test.cljc | 9 +++ 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1041b8f..52ffcbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Added +- Diff / preserve metadata on collections + ## Fixed Varying key order in maps should produce a consistent diff (#47) diff --git a/src/lambdaisland/deep_diff2/diff_impl.cljc b/src/lambdaisland/deep_diff2/diff_impl.cljc index ce90472..4e87b40 100644 --- a/src/lambdaisland/deep_diff2/diff_impl.cljc +++ b/src/lambdaisland/deep_diff2/diff_impl.cljc @@ -3,7 +3,7 @@ [clojure.set :as set] [lambdaisland.clj-diff.core :as seq-diff])) -(declare diff diff-similar) +(declare diff diff-similar diff-meta) (defrecord Mismatch [- +]) (defrecord Deletion [-]) @@ -92,40 +92,50 @@ (defn diff-seq [exp act] (let [[rep del ins] (replacements (del+ins exp act))] - (->> exp - (diff-seq-replacements rep) - (diff-seq-deletions del) - (diff-seq-insertions ins) - (into [])))) + (with-meta + (->> exp + (diff-seq-replacements rep) + (diff-seq-deletions del) + (diff-seq-insertions ins) + (into [])) + (diff-meta exp act)))) (defn diff-set [exp act] - (into - (into #{} - (map (fn [e] - (if (contains? act e) - e - (->Deletion e)))) - exp) - (map ->Insertion) - (remove #(contains? exp %) act))) + (with-meta + (into + (into #{} + (map (fn [e] + (if (contains? act e) + e + (->Deletion e)))) + exp) + (map ->Insertion) + (remove #(contains? exp %) act)) + (diff-meta exp act))) (defn diff-map [exp act] - (let [exp-ks (set (keys exp)) - act-ks (set (keys act))] - (reduce - (fn [m k] - (case [(contains? exp-ks k) (contains? act-ks k)] - [true false] - (assoc m (->Deletion k) (get exp k)) - [false true] - (assoc m (->Insertion k) (get act k)) - [true true] - (assoc m k (diff (get exp k) (get act k))) + (with-meta + (let [exp-ks (set (keys exp)) + act-ks (set (keys act))] + (reduce + (fn [m k] + (case [(contains? exp-ks k) (contains? act-ks k)] + [true false] + (assoc m (->Deletion k) (get exp k)) + [false true] + (assoc m (->Insertion k) (get act k)) + [true true] + (assoc m k (diff (get exp k) (get act k))) ; `[false false]` will never occur because `k` necessarily ; originated from at least one of the two sets - )) - {} - (set/union exp-ks act-ks)))) + )) + {} + (set/union exp-ks act-ks))) + (diff-meta exp act))) + +(defn diff-meta [exp act] + (when (or (meta exp) (meta act)) + (diff-map (meta exp) (meta act)))) (defn primitive? [x] (or (number? x) (string? x) (boolean? x) (inst? x) (keyword? x) (symbol? x))) diff --git a/test/lambdaisland/deep_diff2/diff_test.cljc b/test/lambdaisland/deep_diff2/diff_test.cljc index 766546f..fa0a238 100644 --- a/test/lambdaisland/deep_diff2/diff_test.cljc +++ b/test/lambdaisland/deep_diff2/diff_test.cljc @@ -31,6 +31,9 @@ (is (= [] (diff/diff [] []))) + (is (= {:meta true} + (meta (diff/diff ^:meta [] ^:meta [])))) + (is (= [1 2 3] (diff/diff (into-array [1 2 3]) [1 2 3]))) @@ -68,6 +71,9 @@ (is (= #{:a} (diff/diff #{:a} #{:a}))) + (is (= {:meta true} + (meta (diff/diff ^:meta #{} ^:meta #{})))) + (is (= #{(diff/->Insertion :a)} (diff/diff #{} #{:a}))) @@ -80,6 +86,9 @@ (testing "maps" (is (= {} (diff/diff {} {}))) + (is (= {:meta true} + (meta (diff/diff ^:meta {} ^:meta {})))) + (is (= {:a (diff/->Mismatch 1 2)} (diff/diff {:a 1} {:a 2})))