- Branch per issue. Every change lives on its own feature branch tied to a GitHub issue; do not commit directly to
main. - Branch naming:
fix/<issue-number>-<slug>orfeat/<issue-number>-<slug>(e.g.fix/14-filter-ordering). - Open a PR against
mainwhen the branch is ready; reference the issue so it auto-closes on merge. - If there is no tracking issue for the work, open one first.
go build ./...— build all packagesgo test ./...— run all testsGOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o esync-darwin-arm64 .— trimmed release binary
/usr/bin/rsyncis Apple'sopenrsync— it lacks--info=progress2and other modern flagsrsyncBin()ininternal/syncer/syncer.goresolves to homebrew rsync (/opt/homebrew/bin/rsync) when availableexec.Commanddoes not use shell aliases, so the binary path must be resolved explicitlyCheckRsync()validates rsync >= 3.1.0 on startup
- With
--info=progress2, both per-file and overall progress lines containxfr#/to-chk= - In
extractFiles(), the 100% size-extraction check MUST come before the progress2 skip guard, or per-file sizes are lost - Fast transfers may skip the 100% progress line entirely, leaving per-file
Bytes: 0 - When per-file sizes are missing,
cmd/sync.godistributesBytesTotalacross groups weighted by file count extractStats()must matchTotal transferred file size:(actual bytes sent), NOTTotal file size:(entire source tree size)
- Status-only messages use
"status:..."prefix (e.g."status:syncing 45%") - Channel sends from the sync handler use non-blocking
select/defaultto avoid deadlocks syncEventsandlogEntrieschannels are buffered (capacity 64)