ref: 1fedf54fa79d5bdf67971d89924653e3bac7179e
parent: 83c03b605df05ee4c3b60f1aea0411a0636ca0b5
author: Runxi Yu <me@runxiyu.org>
date: Sat Feb 21 13:18:43 EST 2026
objectstore/{loose,packed}: Use iolimit
--- a/objectstore/loose/parse.go
+++ b/objectstore/loose/parse.go
@@ -34,16 +34,16 @@
return ty, content, nil
}
-// readHeader reads and parses a loose object header from br.
-// br must be positioned at the start of decoded loose object bytes.
-func readHeader(br *bufio.Reader) (objecttype.Type, int64, error) {+// readHeader reads and parses a loose object header from br, and returns
+// the raw header bytes including the trailing NUL.
+func readHeader(br *bufio.Reader) ([]byte, objecttype.Type, int64, error) {header, err := br.ReadSlice(0)
if err != nil {- return objecttype.TypeInvalid, 0, err
+ return nil, objecttype.TypeInvalid, 0, err
}
ty, size, _, ok := objectheader.Parse(header)
if !ok {- return objecttype.TypeInvalid, 0, errors.New("objectstore/loose: malformed object header")+ return nil, objecttype.TypeInvalid, 0, errors.New("objectstore/loose: malformed object header")}
- return ty, size, nil
+ return header, ty, size, nil
}
--- a/objectstore/loose/read_header.go
+++ b/objectstore/loose/read_header.go
@@ -22,7 +22,7 @@
}
defer func() { _ = zr.Close() }()- ty, size, err := readHeader(bufio.NewReader(zr))
+ _, ty, size, err := readHeader(bufio.NewReader(zr))
if err != nil {return objecttype.TypeInvalid, 0, err
}
--- a/objectstore/loose/read_reader.go
+++ b/objectstore/loose/read_reader.go
@@ -2,18 +2,19 @@
import (
"bufio"
+ "bytes"
"compress/zlib"
"errors"
"io"
"os"
+ "codeberg.org/lindenii/furgit/internal/iolimit"
"codeberg.org/lindenii/furgit/objectid"
"codeberg.org/lindenii/furgit/objecttype"
)
type objectReader struct {- // reader is the stream exposed by Read. It may be the raw zlib reader
- // (full object) or a buffered reader positioned at content bytes only.
+ // reader is the stream exposed by Read.
reader io.Reader
// file is the underlying loose object file and is closed by Close.
file *os.File
@@ -53,10 +54,22 @@
if err != nil {return nil, err
}
+
+ br := bufio.NewReader(zr)
+ header, _, size, err := readHeader(br)
+ if err != nil {+ _ = zr.Close()
+ _ = file.Close()
+ return nil, err
+ }
+
return &objectReader{- reader: zr,
- file: file,
- zr: zr,
+ reader: io.MultiReader(
+ bytes.NewReader(header),
+ iolimit.ExpectLengthReader(br, size),
+ ),
+ file: file,
+ zr: zr,
}, nil
}
@@ -69,7 +82,7 @@
}
br := bufio.NewReader(zr)
- ty, size, err := readHeader(br)
+ _, ty, size, err := readHeader(br)
if err != nil {_ = zr.Close()
_ = file.Close()
@@ -77,7 +90,7 @@
}
return ty, size, &objectReader{- reader: br,
+ reader: iolimit.ExpectLengthReader(br, size),
file: file,
zr: zr,
}, nil
--- a/objectstore/packed/read_reader.go
+++ b/objectstore/packed/read_reader.go
@@ -5,6 +5,7 @@
"fmt"
"io"
+ "codeberg.org/lindenii/furgit/internal/iolimit"
"codeberg.org/lindenii/furgit/objectheader"
"codeberg.org/lindenii/furgit/objectid"
"codeberg.org/lindenii/furgit/objecttype"
@@ -45,7 +46,7 @@
return objecttype.TypeInvalid, 0, nil, err
}
return meta.ty, meta.size, &readCloser{- reader: io.LimitReader(zr, meta.size),
+ reader: iolimit.ExpectLengthReader(zr, meta.size),
closer: zr,
}, nil
}
@@ -80,7 +81,7 @@
return nil, err
}
return &readCloser{- reader: io.MultiReader(bytes.NewReader(header), io.LimitReader(zr, meta.size)),
+ reader: io.MultiReader(bytes.NewReader(header), iolimit.ExpectLengthReader(zr, meta.size)),
closer: zr,
}, nil
}
--
⑨