Skip to content

Layer 4 Local Save and Pull

abduznik edited this page Jul 15, 2026 · 1 revision

Layer 4 — Local Save and Pull

The core operations for versioning saves locally — atomic copy-out to the magazine and atomic copy-in from the magazine.

Save

sv_save(reg, opts, &out_result) performs an atomic copy-out from live_path into a new magazine entry (never overwrites an existing entry).

  • Computes content_hash and integrity_ok
  • Default behavior: skips creating a new entry if the hash matches the most recent one (avoids pointless duplication/retention churn)
  • opts.force = true overrides dedup — always creates a new entry regardless of hash match
  • Force still respects the retention cap — it bypasses dedup, not rotation

Pull

sv_pull(reg, opts, &out_result) performs an atomic copy-in of the most recent magazine entry to live_path.

  • Conflict-checked: if the live file changed since the last known sync point, default is report-don't-clobber (SV_PULL_ON_CONFLICT_REPORT)
  • Explicit override required to proceed
  • Even on override, the about-to-be-overwritten live data is itself snapshotted first — overrides are never truly destructive

Pull Select

sv_pull_select(reg, entry_id, opts, &out_result) — identical mechanics to pull(), but targets a specific entry instead of "latest." Pairs with sv_list_entries() for building a version picker UI.

List and Inspect

  • sv_list_registrations() / sv_read_registration(id) — enumerate and inspect registrations
  • sv_list_entries(reg_id | NULL) / sv_read_entry(entry_id) — enumerate and inspect magazine entries; passing a null/sentinel reg_id lists orphaned entries

Reparent

sv_reparent_entry(entry_id, new_parent_reg_id) — explicitly re-links an entry to a different (or recovered) registration. This is the "the father can change" mechanism — e.g. a ROM was re-dumped/re-identified, or a user reclaims an orphan.

Delete

sv_delete_entry(entry_id) — the only manual hard-delete path, used for cleaning up orphans. Never invoked implicitly by any other function.

Conflict-Handling Philosophy

Every operation that could clobber existing data follows the same pattern:

  1. Detect conflict (live file changed since last sync)
  2. Report by default (never silently resolve)
  3. Require explicit on_conflict policy to proceed
  4. Even on override, snapshot the live data first

This ensures the library is always safe to use, even with default options.


See also: Architecture-Overview | Layer-5-Retention-and-Rotation | API-Reference

Clone this wiki locally