1
0
Fork 0
mirror of https://github.com/imjasonh/infinite-git synced 2026-07-18 06:45:05 +00:00

Fix four bugs: packfile offset tracking, HTTP error ordering, ref ordering, and race condition

- packfile.go: ReadObject now uses a countingReader to track compressed
  bytes consumed and properly advances r.offset, fixing sequential
  multi-object reads.
- handlers.go: Use commitSHA from GenerateCommit directly instead of
  re-reading refs, which fixes both the HTTP error-after-body-written
  issue and ensures HEAD is always advertised first (Git protocol
  requirement).
- commit.go: GenerateCommit now holds the repo lock for the entire
  read-modify-write cycle, preventing concurrent generates from reading
  the same parent and losing ref updates.
- repo.go: Added Lock/Unlock/GetRefsLocked methods to support holding
  the mutex across multiple repo operations.

https://claude.ai/code/session_015F9BYQoCy2P2zYZBuVeXHH
This commit is contained in:
Claude 2026-04-02 05:52:24 +00:00
parent 09281ac00c
commit 29666530cc
No known key found for this signature in database
4 changed files with 60 additions and 36 deletions

View file

@ -147,8 +147,9 @@ func (r *Reader) ReadObject() (objType int, data []byte, err error) {
return 0, nil, err
}
// Read compressed data
zr, err := zlib.NewReader(bytes.NewReader(r.data[r.offset:]))
// Wrap the remaining data in a counting reader to track compressed bytes consumed.
cr := &countingReader{reader: bytes.NewReader(r.data[r.offset:])}
zr, err := zlib.NewReader(cr)
if err != nil {
return 0, nil, fmt.Errorf("creating decompressor: %w", err)
}
@ -159,13 +160,23 @@ func (r *Reader) ReadObject() (objType int, data []byte, err error) {
return 0, nil, fmt.Errorf("decompressing object: %w", err)
}
// Update offset past compressed data
// This is tricky - we need to figure out how much compressed data we read
// For now, we'll use a simple approach and skip this optimization
// In a real implementation, we'd track the compressed size properly
// For now, just consume the rest
var buf bytes.Buffer
io.Copy(&buf, zr)
// Drain the zlib reader so cr.n reflects all compressed bytes consumed.
io.Copy(io.Discard, zr)
// Advance offset past the compressed data.
r.offset += int(cr.n)
return objType, data, nil
}
// countingReader wraps an io.Reader and counts bytes read.
type countingReader struct {
reader io.Reader
n int64
}
func (c *countingReader) Read(p []byte) (int, error) {
n, err := c.reader.Read(p)
c.n += int64(n)
return n, err
}