fix: designspace saves preserve project structure with atomic writes (re-target)#124
Merged
Conversation
Source now carries a role (Master vs Layer) and an optional UFO layer binding. The UFO reader marks synthesized non-default-layer sources as layer-only, the designspace reader records each <source layer="..."> binding, and the UFO writer returns layer-bound data to the layer it came from instead of the source name.
…writes
The designspace writer previously collapsed every project into a single
{stem}.ufo with all non-default sources as layers, restructuring
multi-UFO projects and leaving the original master UFOs stale on disk.
Sources are now grouped by their stored filename and written back to
the UFO files they came from, mirroring the declared layer shape;
masters created inside Shift get deterministic collision-safe
filenames. Layer-only sources are written as UFO layers without
gaining <source> entries.
The designspace XML itself now goes through a shared crash-safe helper
(temp file + fsync + rename + platform-gated parent fsync, extracted
from the UFO writer) instead of a direct overwrite, and is always
written after the UFO data so the pointer file never references
half-written masters.
…otion Covers the multi-UFO round trip (same UFO filenames, source-to-file- to-layer assignment, locations, and geometry after reopen), that a failed save leaves the existing designspace XML intact, and that plain UFO extra layers stay UFO layers instead of becoming designspace masters, with and without axes.
The master-vs-layer distinction and designspace layer bindings now survive both persistence layers: the SQLite store gains a layer_name column and writes the real source kind instead of hardcoding 'master', and .shift's sources.json carries role and layerName. Both default to Master/absent so existing data reads unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Re-targeted copy of #123, which was accidentally merged into its stacked base branch (
fix/ufo-preservation) after that base had already merged to main via #119 — so its content never reached main. Same four commits, now against main directly (they apply cleanly: the branch is based on #119's commits, which are in main verbatim).See #123 for the full description: multi-UFO write-back using stored source filenames, atomic
.designspaceXML via the sharedwrite_file_atomichelper, data-before-pointer ordering with documented mid-save failure state,SourceRolemaster/layer distinction persisted through SQLite and.shift, and the multi-UFO round-trip / atomicity / no-phantom-master test suite.cargo test --workspace: 311 passed, 0 failed at branch tip; clippy zero warnings.Known remaining reader-side gap tracked in #122.
🤖 Generated with Claude Code