fix(sync): survive push heap exhaustion and instrument the push path

Run 4 (2026-07-13): remote.push() consumed ~6 MB of PSRAM over 66 s and
the UI thread aborted on Frame::new_white's per-draw vec![0xFF; 26928].
Run 5 confirmed the UI now survives, but the push still exhausts both
pools (a ~7 KB inflateInit fails inside the pack build) and the heap
telemetry never fired — hence the telemetry rework.

- display/editor: Editor::draw_into() renders into a caller-owned
  Frame; main.rs keeps two boot-time frames (shown/back) and mem::swaps
  on success, so steady-state repaints never allocate.
- git_sync: odb cache capped at 1 MB via raw libgit2-sys opts (git2
  0.20 doesn't wrap the total cap); log_push_heap at pre-push,
  post-push and push-failure with largest-PSRAM-block and per-pool
  min-evers; pack_progress logging is now time-gated (2 s) — the
  count gate (+256 objects) never fired because AddingObjects reports
  total=0 and a small push inserts only dozens of objects.
- editor: empty/whitespace snippets file parses as 0 snippets instead
  of a JSON error at boot.
- build.rs: refuse a git-feature build with unset TW_* publish vars —
  a bare `cargo build --features git` baked empty creds and produced a
  firmware whose :sync could never work.
This commit is contained in:
Julien Calixte
2026-07-13 21:04:18 +02:00
parent 05706478a2
commit f79d13453a
6 changed files with 182 additions and 23 deletions

View File

@@ -47,6 +47,30 @@ fn main() {
println!("cargo:rerun-if-env-changed={var}");
}
// A git-feature build with an empty publish config can only ever fail at
// runtime (git_sync's publish_cycle guard), so refuse it here instead.
// env!() bakes the values at compile time and only `just` dotenv-loads
// firmware/.env — a plain `cargo build --features git` in a bare shell
// silently produced a firmware whose `:sync` could never work (bit the
// 2026-07-13 flash). TW_WIFI_PASS may be legitimately empty (open network)
// and TW_AUTHOR_* have runtime defaults, so only the four required vars
// are checked.
if std::env::var("CARGO_FEATURE_GIT").is_ok() {
let missing: Vec<&str> = ["TW_WIFI_SSID", "TW_REMOTE_URL", "TW_GH_USER", "TW_PAT"]
.into_iter()
.filter(|v| std::env::var(v).map_or(true, |val| val.is_empty()))
.collect();
if !missing.is_empty() {
panic!(
"git-feature build without publish config: {} unset/empty. \
Build through `just build` (dotenv-loads firmware/.env), or \
source firmware/.env into this shell. For a no-git editor \
build use `just build-light` (drops --features git).",
missing.join(", ")
);
}
}
// Pointing rerun-if-changed at a file that never exists forces this
// script to rerun on every build, keeping BUILD_TIME fresh.
println!("cargo:rerun-if-changed=.force-build-stamp");