mirror of
https://github.com/penpot/penpot.git
synced 2026-10-28 21:40:34 +00:00
🐛 Fix legacy path migration crash on paths without points (#12357)
The legacy-6 migration read the rect of each path from its points and checked whether the width or height was close to zero. A path with missing or empty points has no rect, so the check got nil and threw a NullPointerException. The migration then failed on every load of that file, and get-team-shared-files returned 500 for the whole team, so the "Add library" modal could not open. Treat a missing rect like a degenerate one and rebuild the selrect and points from the path content. Closes #12343 AI-assisted-by: claude-opus-5-5
This commit is contained in:
parent
a53481c3b7
commit
0d9b1c48fc
@ -223,8 +223,10 @@
|
||||
[data _]
|
||||
(letfn [(fix-line-paths [shape]
|
||||
(if (= (:type shape) :path)
|
||||
(let [{:keys [width height]} (grc/points->rect (:points shape))]
|
||||
(if (or (mth/almost-zero? width) (mth/almost-zero? height))
|
||||
;; A path with missing or empty points has no rect; rebuild
|
||||
;; its geometry from the content as for line-like paths.
|
||||
(let [{:keys [width height] :as rect} (grc/points->rect (:points shape))]
|
||||
(if (or (nil? rect) (mth/almost-zero? width) (mth/almost-zero? height))
|
||||
(let [selrect (path.segment/content->selrect (:content shape))
|
||||
points (grc/rect->points selrect)
|
||||
transform (gmt/matrix)
|
||||
|
||||
@ -605,3 +605,45 @@
|
||||
data' (cfm/migrate-data data migration-id)]
|
||||
|
||||
(t/is (= [child-id] (get-in data' [:components component-id :objects main-id :shapes])))))
|
||||
|
||||
(defn- make-path-shape
|
||||
[shape-id]
|
||||
(cts/setup-shape {:id shape-id
|
||||
:type :path
|
||||
:content [{:command :move-to :params {:x 10 :y 20}}
|
||||
{:command :line-to :params {:x 110 :y 70}}]}))
|
||||
|
||||
(t/deftest migration-legacy-6-repairs-paths-without-points
|
||||
(let [migration-id "legacy-6"
|
||||
page-id (uuid/next)
|
||||
shape-id (uuid/next)
|
||||
shape (make-path-shape shape-id)]
|
||||
|
||||
(doseq [points [nil []]]
|
||||
(let [data {:pages-index {page-id {:objects {shape-id (assoc shape :points points)}}}}
|
||||
data' (cfm/migrate-data data migration-id)
|
||||
shape' (get-in data' [:pages-index page-id :objects shape-id])]
|
||||
|
||||
(t/is (= (:points shape) (:points shape'))
|
||||
(str "points rebuilt from content when they were " (pr-str points)))
|
||||
(t/is (= (:selrect shape) (:selrect shape'))
|
||||
"selrect rebuilt from content")))))
|
||||
|
||||
(t/deftest migration-legacy-6-runs-through-file-migration
|
||||
;; A file saved before version 6 runs every migration from legacy-6 on,
|
||||
;; and the whole chain must succeed for the file to load.
|
||||
(let [migration-id "legacy-6"
|
||||
shape-id (uuid/next)
|
||||
file (ctf/make-file {:name "Legacy path without points"})
|
||||
page-id (first (get-in file [:data :pages]))
|
||||
shape (-> (make-path-shape shape-id)
|
||||
(assoc :points []))
|
||||
file (-> file
|
||||
(dissoc :migrations)
|
||||
(assoc :version 5)
|
||||
(assoc-in [:data :pages-index page-id :objects shape-id] shape))
|
||||
file' (cfm/migrate-file file (delay {}))]
|
||||
|
||||
(t/is (contains? (:migrations file') migration-id) "migration id persisted")
|
||||
(t/is (= 4 (count (get-in file' [:data :pages-index page-id :objects shape-id :points])))
|
||||
"path points repaired before schema validation")))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user