Skip to content

fix(auto-sync): reliable cross-platform post-commit auto-update#211

Merged
RaghavChamadiya merged 1 commit into
mainfrom
fix/auto-sync-cross-platform
May 18, 2026
Merged

fix(auto-sync): reliable cross-platform post-commit auto-update#211
RaghavChamadiya merged 1 commit into
mainfrom
fix/auto-sync-cross-platform

Conversation

@RaghavChamadiya
Copy link
Copy Markdown
Member

Summary

The post-commit hook installed by repowise hook install was racing with itself: concurrent repowise update invocations from rapid commits all started from the same stale base, took 12+ minutes each, never converged, and discarded all output to /dev/null. The augment staleness warning then fired noisily for every tool call while zombie updates piled up in the background.

This PR makes auto-sync reliable on Windows, macOS, and Linux.

Changes

  • Single-flight enforcement. Both repowise update (single-repo) and the workspace update path check .repowise/.update.lock before starting. If another update is running, the new invocation writes .update.pending with the current HEAD and exits cleanly; the running update rolls forward to that HEAD when it finishes.
  • Queued marker before background spawn. The hook writes .update.queued synchronously, then backgrounds the heavy work. The augment hook treats the queued marker the same as a held lock, closing the 1–5s race window during Python start-up.
  • Better augment messaging. When a lock or queued marker is present, the agent sees Wiki update in background — started Ns ago, target X instead of Wiki is stale. Falls through to the stale warning only when no update is in flight (or the marker is past its staleness window: 30 min for the lock, 5 min for the queued marker).
  • Diagnosable hook output. Hook captures stdout/stderr to .repowise/.update.log (rotated to a 64 KB tail when it exceeds 256 KB) instead of /dev/null.
  • In-place hook upgrade. When the marker block exists but its body differs from the current _HOOK_SCRIPT, install replaces the block in place (preserving surrounding hook content) and returns upgraded. Previously it bailed with already installed, leaving users stuck on the buggy hook after a repowise upgrade.
  • re.sub backslash-escape fix. Passing the hook script as a string repl silently turned literal \n (inside a printf format) into real newlines, breaking shell quoting. The replacement now uses a callable repl to bypass escape processing.

Cross-platform notes

Git always runs hooks under POSIX sh (/bin/sh on Linux/macOS, git-bash on Windows), so the same script body is correct on all three platforms — no platform detection needed. The hook stays POSIX-clean (no [[ ]], no <( ), no arrays), verified by a sanity test.

Test plan

  • tests/unit/cli/test_helpers.py — queued/pending marker round-trips, log rotation
  • tests/unit/cli/test_hooks_legacy_migration.py — legacy strip, in-place upgrade, surrounding-hook preservation, POSIX-clean sanity check
  • tests/unit/cli/test_augment_staleness.py — in-flight notice for lock and queued marker, fall-through to stale warning when markers are old, per-HEAD dedupe still works
  • Manual end-to-end: fresh install, upgrade install over old marker body, hook fires correctly, queued marker written, log file populated, single-flight kicks in on rapid commits

The post-commit hook was racing with itself: concurrent `repowise update`
invocations from rapid commits all started from the same stale base, took
12+ minutes each, never converged, and discarded all output to /dev/null.
The augment staleness warning then fired noisily for every tool call
while the zombie updates ran in the background.

Changes:

- Single-flight enforcement: `repowise update` (single-repo and workspace
  paths) checks `.repowise/.update.lock` before starting. If another
  update is running, the new invocation writes `.update.pending` with the
  current HEAD and exits; the running update rolls forward to it.

- Hook pre-writes `.update.queued` synchronously before backgrounding, so
  the augment hook sees an in-flight marker during the 1-5s start-up
  window before the real lock file lands on disk.

- Augment hook emits "Wiki update in background — started Ns ago, target
  X" instead of "Wiki is stale" when a lock or queued marker is present.
  Falls through to the stale warning only when no update is in flight
  (or the marker is older than its staleness window).

- Hook captures stdout/stderr to `.repowise/.update.log` (rotated to
  64KB tail when it exceeds 256KB) instead of /dev/null, so silent
  failures are diagnosable.

- Hook installer upgrades the marker block in place when the body
  differs from the current `_HOOK_SCRIPT`, preserving any surrounding
  hook content. Previously it bailed with "already installed" and left
  users stuck on the buggy hook after a repowise upgrade.

- Fix `re.sub` backslash-escape bug: passing the hook script as a string
  repl silently turned literal `\n` (inside the printf format) into real
  newlines, breaking shell quoting. Use a callable repl to bypass.

Cross-platform: git always runs hooks under POSIX sh (/bin/sh on
Linux/macOS, git-bash on Windows), so the same script body works on all
three platforms — no platform detection needed.
@RaghavChamadiya RaghavChamadiya requested a review from swati510 as a code owner May 18, 2026 11:04
@RaghavChamadiya RaghavChamadiya merged commit ea379b1 into main May 18, 2026
5 checks passed
@RaghavChamadiya RaghavChamadiya deleted the fix/auto-sync-cross-platform branch May 18, 2026 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants