feat(sync): :gl pull — fetch + fast-forward only on the git thread
The git channel now carries GitRequest::{Publish,Pull} with a shared
ensure_online preamble (Wi-Fi/clock/TLS once per session). pull_once
fetches origin — refreshing the tracking ref so the radio-free
up-to-date check stays honest — and maps four shapes: up to date,
LocalAhead (stranded commit, :sync's job), clean fast-forward,
Diverged (refused; no merge on the device). The fast-forward is a SAFE
checkout then ref move: it refuses to overwrite content that differs
from HEAD, the belt under the UI gate that refuses :gl while the dirty
journal is non-empty. A RAM-dirty buffer doesn't gate — its edits win
(last-writer-wins, like the reconcile).
After a pull the UI drops clean parked buffers, re-reads the clean
active buffer in place (Editor::refresh_active), and re-walks the
palette list. Firmware 0.6.0 -> 0.7.0. On-device verification pending.
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
> [qfd.md](qfd.md). Load-bearing decisions: [adr.md](adr.md).
|
||||
|
||||
**Status:** **`/` search + `n N` done in core** (2026-07-13, host-tested — 207
|
||||
editor tests). The **`:gl` pull command landed in the editor** (2026-07-11,
|
||||
host-tested) — `Effect::Pull` + a firmware stub; the on-device fetch +
|
||||
fast-forward is still to build.
|
||||
editor tests). **`:gl` pull BUILT end-to-end 2026-07-14** (firmware 0.7.0,
|
||||
compiles clean; editor refresh hooks host-tested, 209 tests) — **on-device
|
||||
verification pending** (needs Wi-Fi + a remote that moved).
|
||||
|
||||
- [x] `/` forward search, `n N` — done in core 2026-07-13 (host-tested).
|
||||
Literal, case-sensitive substring (no regex on-device, no smartcase
|
||||
@@ -20,8 +20,29 @@ fast-forward is still to build.
|
||||
over them); deliberately **not** operator targets (`dn` out of scope).
|
||||
- [~] `:gl` — pull: fetch + **fast-forward only**, refuse on divergence and
|
||||
surface it (renamed from the planned `:Gpull`). Editor command +
|
||||
`Effect::Pull` done 2026-07-11 (host-tested); the git-thread
|
||||
fetch/fast-forward in `git_sync` remains (only push is wired today).
|
||||
`Effect::Pull` done 2026-07-11; **the git-thread fetch/fast-forward is
|
||||
BUILT 2026-07-14** — on-device verification pending. How it works:
|
||||
- The git thread takes a `GitRequest::Pull` on the same channel as publish
|
||||
(shared `ensure_online` Wi-Fi/clock/TLS preamble). `pull_once` fetches
|
||||
origin (the fetch also refreshes the remote-tracking ref, keeping
|
||||
publish's radio-free up-to-date check honest), then maps the four shapes:
|
||||
up to date / **LocalAhead** (stranded commit — `:sync`'s job) / clean
|
||||
fast-forward / **Diverged** (refused, no merge on the device).
|
||||
- The fast-forward is checkout-then-ref-move with a **SAFE** checkout: it
|
||||
refuses to overwrite a file whose content differs from HEAD (belt; the UI
|
||||
gate is the braces). FAT caveat: the splice never updates the index, so
|
||||
SAFE re-hashes each file the pull changes — O(changed), never O(tree).
|
||||
- UI gate: `:gl` is refused while the dirty journal is non-empty
|
||||
("unsynced changes - :sync first") — an unpublished save would fight the
|
||||
checkout, and sync-then-pull is the single-writer appliance's natural
|
||||
order. A RAM-dirty (never-saved) buffer does *not* gate: its edits simply
|
||||
win over the pulled state (last-writer-wins, like the reconcile).
|
||||
- After a `Pulled` outcome the UI drops clean parked buffers (next switch
|
||||
re-reads the disk), re-reads the clean active buffer in place
|
||||
(`Editor::refresh_active` — boot posture, undo cleared), keeps a
|
||||
RAM-dirty active buffer untouched, and re-walks the palette file list.
|
||||
Snackbar: `pulled <oid>` / `up to date` / `ahead - :sync to publish` /
|
||||
`diverged - resolve on a computer` / `pull: <reason>`.
|
||||
|
||||
Sync performance — inherited from the
|
||||
[real-repo-sync kaizen](kaizen/real-repo-sync.md) (closed 2026-07-13 at
|
||||
|
||||
Reference in New Issue
Block a user