aboutsummaryrefslogtreecommitdiff
path: root/obj.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2025-11-22 08:00:00 +0800
committerGravatar Runxi Yu2025-11-22 08:00:00 +0800
commit3a4b0c924197ba6d9570c8ac338c32b8093398da (patch)
tree69bd345fcdef55062368ee3280a8bc7497fb5329 /obj.go
parentobj: Return ErrNotFound, not ErrInvalidObject, when not found in packs (diff)
signatureNo signature
obj: Add ReadObjectTypeRaw
Diffstat (limited to 'obj.go')
-rw-r--r--obj.go26
1 files changed, 26 insertions, 0 deletions
diff --git a/obj.go b/obj.go
index 4f43b8ad..41400985 100644
--- a/obj.go
+++ b/obj.go
@@ -116,6 +116,32 @@ func (repo *Repository) ReadObject(id Hash) (StoredObject, error) {
return obj, parseErr
}
+// ReadObjectTypeRaw reads the object type and raw body.
+func (repo *Repository) ReadObjectTypeRaw(id Hash) (ObjectType, []byte, error) {
+ ty, body, err := repo.looseRead(id)
+ if err == nil {
+ return ty, body.Bytes(), nil
+ }
+ if !errors.Is(err, ErrNotFound) {
+ return ObjectTypeInvalid, nil, err
+ }
+ ty, body, err = repo.packRead(id)
+ if errors.Is(err, ErrNotFound) {
+ return ObjectTypeInvalid, nil, ErrNotFound
+ }
+ if err != nil {
+ return ObjectTypeInvalid, nil, err
+ }
+ return ty, body.Bytes(), nil
+ // note to self: It always feels wrong to not call .Release in places like
+ // this but this is actually correct; we're returning the underlying buffer
+ // to the user who should not be aware of our internal buffer pooling.
+ // Releasing this buffer back to the pool would lead to a use-after-free;
+ // not releasing it as we do here, means it gets GC'ed.
+ // Copying into a newly allocated buffer is even worse as it incurs
+ // unnecessary copy overhead.
+}
+
// ReadObjectTypeSize reports the object type and size.
//
// Typicall, this is more efficient than reading the full object,