Enforce the materialized object limit while the pack streams

Commit

Soph2w ago

FetchToStore filled the in-memory store with no cap. The object limit (--materialized-max-objects, default 500,000) was checked against the object closure once the fetch had already finished, so it reported an overrun rather than preventing one: by then the objects were resident and the process may have died getting there. The constant's own comment says "fail early rather than OOM", which the ordering did not deliver, and README's "guarded by an explicit object-count limit" overstated it.

The store is now wrapped so the count is enforced as objects are decoded, failing the write that would exceed the limit. RawObjectWriter is the choke point: go-git's pack scanner routes every object through it, and memory storage's implementation only reaches SetEncodedObject via its own internal closer, which never passes back through the wrapper — so counting in both places would risk double-counting rather than add coverage. Reads pass straight through, leaving planning and the push path seeing the store exactly as before.

No new default was needed. The streaming guard reuses the limit that was already configured and documented, so this changes when the existing limit bites, not what the limit is.

Errors carry an ErrObjectLimit sentinel and an *ObjectLimitError holding the limit, so callers can branch without matching message text, and the message names the flag to raise. The closure check in the materialized strategy stays in place as a second line of defence for the case where a closure is large without the fetch itself exceeding the cap.

The integration test that covered this asserted the old post-hoc message; it now asserts the sentinel plus an actionable message, which is both stronger and independent of wording. A new unit test decodes a 50-object pack into a store bounded at 10 and verifies the decode fails, the error carries the sentinel and limit, and the store admitted no more than the limit — the property the old ordering could not provide.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com Entire-Checkpoint: 01M0D2W9V8DXHFAKZX62Z7D3KB

Checkpoints

Security Review and Vulnerability Fixes

Claude CodeOpus 5.[1m]
View session
Checkpoint 1