aboutsummaryrefslogtreecommitdiff
path: root/objectstore/packed
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-22 17:33:27 +0000
committerGravatar Runxi Yu2026-03-22 17:33:27 +0000
commitd314d1f7e933ca83081eec289aa0cb6e75a7eeac (patch)
treeacd567019d1253d23bcebf6fe8ab9df54d24d3d0 /objectstore/packed
parentobjectstore{,/loose}: Document contracts more clearly (diff)
signatureNo signature
objectstore{,/packed}: Document lifetime and integrity behavior
Diffstat (limited to 'objectstore/packed')
-rw-r--r--objectstore/packed/close.go10
-rw-r--r--objectstore/packed/read_header.go4
-rw-r--r--objectstore/packed/read_reader.go19
-rw-r--r--objectstore/packed/read_size.go4
-rw-r--r--objectstore/packed/read_test.go5
-rw-r--r--objectstore/packed/store.go2
6 files changed, 28 insertions, 16 deletions
diff --git a/objectstore/packed/close.go b/objectstore/packed/close.go
index 2bb98232..d83245c5 100644
--- a/objectstore/packed/close.go
+++ b/objectstore/packed/close.go
@@ -1,16 +1,10 @@
package packed
// Close releases mapped pack/index resources associated with the store.
+//
+// Repeated calls to Close are undefined behavior.
func (store *Store) Close() error {
store.stateMu.Lock()
-
- if store.closed {
- store.stateMu.Unlock()
-
- return nil
- }
-
- store.closed = true
root := store.root
packs := store.packs
store.stateMu.Unlock()
diff --git a/objectstore/packed/read_header.go b/objectstore/packed/read_header.go
index 5eb37c92..5070c98b 100644
--- a/objectstore/packed/read_header.go
+++ b/objectstore/packed/read_header.go
@@ -6,6 +6,10 @@ import (
)
// ReadHeader reads an object's type and declared content size.
+//
+// It resolves header metadata only. It does not verify that the full pack entry
+// payload is readable and does not verify any zlib Adler-32 trailer for
+// compressed entry data.
func (store *Store) ReadHeader(id objectid.ObjectID) (objecttype.Type, int64, error) {
loc, err := store.lookup(id)
if err != nil {
diff --git a/objectstore/packed/read_reader.go b/objectstore/packed/read_reader.go
index cbecaf2c..5c9ac8f4 100644
--- a/objectstore/packed/read_reader.go
+++ b/objectstore/packed/read_reader.go
@@ -12,9 +12,18 @@ import (
packfmt "codeberg.org/lindenii/furgit/packfile"
)
-// ReadReaderContent reads an object's type, declared content size, and content stream.
+// ReadReaderContent reads an object's type, declared content size, and content
+// stream.
//
// The caller must close the returned reader.
+//
+// For base pack entries, the returned reader borrows store-owned mapped pack
+// data and is only valid until the store is closed.
+//
+// Close releases reader-local resources only. It does not drain unread data for
+// additional validation. In particular, malformed trailing compressed data,
+// trailing bytes past the declared object size, and the zlib Adler-32 trailer
+// may go unverified unless the caller reads to io.EOF.
func (store *Store) ReadReaderContent(id objectid.ObjectID) (objecttype.Type, int64, io.ReadCloser, error) {
loc, err := store.lookup(id)
if err != nil {
@@ -49,6 +58,14 @@ func (store *Store) ReadReaderContent(id objectid.ObjectID) (objecttype.Type, in
// ReadReaderFull reads a full serialized object stream as "type size\0content".
//
// The caller must close the returned reader.
+//
+// For base pack entries, the returned reader borrows store-owned mapped pack
+// data and is only valid until the store is closed.
+//
+// Close releases reader-local resources only. It does not drain unread data for
+// additional validation. In particular, malformed trailing compressed data,
+// trailing bytes past the declared object size, and the zlib Adler-32 trailer
+// may go unverified unless the caller reads to io.EOF.
func (store *Store) ReadReaderFull(id objectid.ObjectID) (io.ReadCloser, error) {
loc, err := store.lookup(id)
if err != nil {
diff --git a/objectstore/packed/read_size.go b/objectstore/packed/read_size.go
index 8581b01b..4afa6fed 100644
--- a/objectstore/packed/read_size.go
+++ b/objectstore/packed/read_size.go
@@ -9,6 +9,10 @@ import (
)
// ReadSize reads an object's declared content size.
+//
+// Like ReadHeader, it resolves header metadata only. It does not verify that
+// the full pack entry payload is readable and does not verify any zlib
+// Adler-32 trailer for compressed entry data.
func (store *Store) ReadSize(id objectid.ObjectID) (int64, error) {
loc, err := store.lookup(id)
if err != nil {
diff --git a/objectstore/packed/read_test.go b/objectstore/packed/read_test.go
index 0e5da5d8..2f6b4979 100644
--- a/objectstore/packed/read_test.go
+++ b/objectstore/packed/read_test.go
@@ -177,11 +177,6 @@ func TestPackedStoreNewValidation(t *testing.T) {
if err != nil {
t.Fatalf("Close: %v", err)
}
-
- err = store.Close()
- if err != nil {
- t.Fatalf("Close second: %v", err)
- }
})
}
diff --git a/objectstore/packed/store.go b/objectstore/packed/store.go
index 1c6082f6..58534709 100644
--- a/objectstore/packed/store.go
+++ b/objectstore/packed/store.go
@@ -46,8 +46,6 @@ type Store struct {
packs map[string]*packFile
// deltaCache caches resolved base objects by pack location.
deltaCache *deltaCache
- // closed reports whether Close has been called.
- closed bool
}
var _ objectstore.Store = (*Store)(nil)