From e53719f2b70a001476bf8126c6588cb7e4ba31cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Tejero=20Cantero?= Date: Wed, 28 Oct 2026 11:42:49 +0100 Subject: [PATCH] :bug: Keep a page reorder on main visible to a bounded compare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The page order lives in the document root, not in a page fragment, so a reorder on main moves no fragment, and a compare bounded to the moved pages compared the order of no page at all. moved-pages now leaves the whole-file comparison in place when main orders the pages it shares with the base differently from the base. AI-assisted-by: claude-opus-5-5 Signed-off-by: Álvaro Tejero Cantero --- backend/src/app/rpc/commands/files_branch.clj | 25 +++++++++++-------- .../branch_pointer_base_test.clj | 18 +++++++++++++ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/backend/src/app/rpc/commands/files_branch.clj b/backend/src/app/rpc/commands/files_branch.clj index 8493fe86e3..a5f4cc585c 100644 --- a/backend/src/app/rpc/commands/files_branch.clj +++ b/backend/src/app/rpc/commands/files_branch.clj @@ -351,15 +351,20 @@ (defn- moved-pages "The pages on which main can differ from a branch's base: every page - whose fragment main does not share with the base. Nil when fragment ids - cannot tell, because main or the base holds no pointers, which leaves - the whole-file comparison in place. `stored` is main's `:data` with its - pointers unrealized, and `base-ids` the `::bfc/base-page-pointers` of - the branch read." - [stored base-ids] + whose fragment main does not share with the base. Nil when that set + cannot bound a comparison, which leaves the whole-file comparison in + place: main or the base holds no pointers, or main ordered the pages + both hold differently from the base. The page order lives in the + document root rather than in a page's fragment, and a bounded + comparison only orders the pages it covers. `stored` is main's `:data` + with its pointers unrealized, `base` the comparison's base, and + `base-ids` the `::bfc/base-page-pointers` of the branch read." + [stored base base-ids] (when (seq base-ids) - (let [main-ids (fdata/get-page-pointer-ids stored)] - (when (seq main-ids) + (let [main-ids (fdata/get-page-pointer-ids stored) + both (set/intersection (set (:pages stored)) (set (:pages base)))] + (when (and (seq main-ids) + (= (filterv both (:pages stored)) (filterv both (:pages base)))) (into #{} (remove (fn [page-id] (let [id (get main-ids page-id)] @@ -374,7 +379,7 @@ is the comparison's base, in main's id space." [cfg source-file-id branch-file base-data] (let [stored (bfc/get-file cfg source-file-id) - moved (moved-pages (:data stored) (::bfc/base-page-pointers branch-file)) + moved (moved-pages (:data stored) base-data (::bfc/base-page-pointers branch-file)) shared (fn [pages page-id page] (if (contains? moved page-id) (assoc pages page-id page) @@ -770,7 +775,7 @@ ;; the stored document is a handful of pointers, read only ;; when the base holds pointers to compare them with (seq base-ids) - [main-data (moved-pages (:data (bfc/get-file cfg source-file-id)) base-ids)] + [main-data (moved-pages (:data (bfc/get-file cfg source-file-id)) base-data base-ids)] :else [main-data nil]) diff --git a/backend/test/backend_tests/branch_pointer_base_test.clj b/backend/test/backend_tests/branch_pointer_base_test.clj index 75b89c473b..6f95db3bf8 100644 --- a/backend/test/backend_tests/branch_pointer_base_test.clj +++ b/backend/test/backend_tests/branch_pointer_base_test.clj @@ -282,3 +282,21 @@ (t/is (= 1 (count (:conflicts eager))))) (t/testing (str dir " loads the base's six pages and main's two moved ones") (t/is (= 8 @loads)))))))) + +(t/deftest compare-reports-a-page-reorder-on-main + ;; the page order lives in the document root, not in a page's fragment, + ;; so a reorder moves no fragment and must not bound the comparison + (with-redefs [cf/flags (conj cf/flags :branching)] + (let [{:keys [profile-id file-id]} (setup) + page-b (uuid/random) + _ (update-file! profile-id file-id [{:type :add-page :id page-b :name "B"}]) + branch (create-branch! profile-id file-id "reorder")] + (update-file! profile-id file-id [{:type :mov-page :id page-b :index 0}]) + (let [out (th/command! {::th/type :get-branch-diff + ::rpc/profile-id profile-id + :branch-id (:id branch) + :direction :main->branch}) + eager (eager-compare file-id (:branch-file-id branch) :main->branch)] + (t/is (nil? (:error out))) + (t/is (seq (:changes eager))) + (t/is (= (:changes eager) (:changes (:result out))))))))