Push path writes pack- prefixed manifest checksums (bucket contract violation + duplicate packs) #205
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub#205
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found while investigating #203 (not its cause — separate issue, separate fix).
The wire contract (docs/go/02_storage_protobuf.md: PackRef.checksum = 'pack trailing SHA, hex; key = wal/.pack'; MASTER_RUST_SPEC §5.1:
wal/<checksum>.pack) requires BARE-hex checksums. The push path violates it:internal/server/bind_wal.go newLocalPack:sum := strings.TrimSuffix(name, '.idx')on git's on-diskpack-<hex>.idxkeeps thepack-infix →PreparedPack.Checksum = 'pack-<hex>'→ manifest entry + bucket keywal/pack-<hex>.pack. Worse,PackPathis built aspackDir + '/' + checksum + '.pack'=pack-pack-<hex>.pack, which never exists for a fresh ingest → Stat fails → PackPath='' →uploadPackSILENTLY SKIPS the pack-body upload.internal/repoimport/task.go:345andcmd/walhub/ops.go:439(diff.New basenames arepack-<hex>.idx).checksumFromPackPathstrips the infix,localPackStatestrips it,installPackFileprependspack-, compact.go keep-list prependspack-).Live evidence (bucket of acme/demo): manifest lists THREE packs —
pack-30d755…,pack-7a9ac6…, ANDpack-pack-7a9ac6…(same bytes as the second, re-uploaded under a doubly-prefixed key after a materialized file was re-ingested as 'new'). Readers stay self-consistent (keys derive from stored checksums), but manifests bloat with duplicates, every push risks another prefix layer, and buckets are Rust-incompatible.Fix sketch: strip the
pack-infix at the three producers + build local paths aspack-<bare>.pack/.idxin newLocalPack. Readers are shape-agnostic (all derive from the stored checksum), so mixed old/new manifests keep working; a repair/fsck pass could dedupe + rewrite old entries.Fix open as PR #207 (branch fix/issue-205): bare-hex checksums at all three producers + upload-skip fixed + same-file install no-op. Readers verified shape-agnostic (no changes); repair/fsck pass decided out of scope (compaction converges, documented in 02). All -race suites green, cover gate holds.
REVIEW PR #207 (fix/issue-205, commit
bb74dd7) — PUSH path + bucket contract. Verdict: READY TO MERGE (no blocking issues; no code changes made by reviewer).Walked in scratch worktree /tmp/pr207 (since removed); main worktree left clean.
SEMANTICS
pack-pack-<hex>.idxstrips one layer →pack-<hex>= stored checksum, never re-prefixed. Triple-prefixed on-disk names (hand-producible only; git never writes them) would claim a new self-consistent entry that compaction converges — acceptable, noted not fixed.pack-<hex>stored, materializedpack-pack-<hex>→ known), bare (direct), and doubled-legacy cases — no republish storms; fresh bare content alongside legacy converges via compaction.READERS SHAPE-AGNOSTIC — enumerated, all derive from stored checksum: wal/reconcile.go presence/materialize/side-files/gcSuperseded-delete, maintain/compact.go keep list, revindex.go, rebuild.go, maintain/util.go localPackState (single-strip, consistent with helper), store.PackKey/IdxKey pure derivations. No hex/length validation of checksums in prod code. Mixed old/new manifests pinned by TestPublish_LegacyPrefixedChecksumReads (legacy materializes under
pack-pack-<hex>, coexists + syncs with bare). Compaction supersede/delete keys derive from stored values, so prefixed keys are handled; repair/fsck deferral documented in 02 and sane (old entries self-consistent, live sets converge on bare).UPLOAD-SKIP FIX verified by tests, not just code-read: TestReceivePackPushBareChecksums asserts wal/.pack+.idx exist in store + zero
pack-\*keys under wal/ after two real HTTP receive-pack pushes; x_gaps FindIngestedPack now stats PackPath and asserts manifest + store keys.X_GAPS UPDATES legitimate (strengthened, not weakened): x_gaps7 pins nil for pack-less idx (behavior change, correct); x_gaps8 writes complete pairs (adaptation, same skip-known-and-dirs coverage); x_gaps FindIngestedPack 'latent no-commit' fix genuine — seed fetch creates refs/heads/main locally so old err-only assert passed on Seq-0 per-ref conflict; new asserts res.Seq!=0 + bare manifest + store keys. packName gen→pack mirrors ingest canonical names.
GATES (scratch worktree, -race): git ok; wal ok; repoimport ok; maintain ok; cmd/walhub ok; server ok except pre-existing TestUIAssetConcepts env failure (missing
make webconcepts/*.gif — fails identically without this PR; PR touches no UI serving). Coverage: git 95.1 / wal 95.4 / server 95.6 / repoimport 95.7 / maintain 96.5 (≥95 holds); cmd/walhub 15.8% pre-existing (gate covers internal/... only). gofmt clean, go vet clean, no new non-stdlib imports (diff adds none). make e2e not run (noted as optional); HTTP-push + import e2e in-suite cover the paths with real git packs.DOCS accurate: 02 wire-contract note, 04 single-strip rationale, 05 SameFile, 06 newLocalPack, 11 CLI, features/10 — all match the code. No main-worktree modifications.
Fixed by PR #207 (review: strip semantics, completeness rule, reader agnosticism, no republish storms verified; all gates green), merged. Closing.