ref: fd55beb6188350974afd93dfffcef973ebdad6e8
parent: b480c5c4dfaddb9b137f50b1a7651e3bce2ecb98
author: Runxi Yu <me@runxiyu.org>
date: Sat Feb 21 15:40:05 EST 2026
objectstore/packed: Don't use full delta reconstruction just to read headers
--- a/objectstore/packed/delta_apply.go
+++ b/objectstore/packed/delta_apply.go
@@ -14,11 +14,22 @@
if err != nil {return objecttype.TypeInvalid, nil, err
}
- return store.deltaResolveChain(chain)
+ pack, meta, err := store.entryMetaAt(start)
+ if err != nil {+ return objecttype.TypeInvalid, nil, err
+ }
+ declaredSize := meta.size
+ if !packfmt.IsBaseObjectType(meta.ty) {+ declaredSize, err = deltaDeclaredSizeAt(pack, meta.dataOffset)
+ if err != nil {+ return objecttype.TypeInvalid, nil, err
+ }
+ }
+ return store.deltaResolveChain(chain, declaredSize)
}
// deltaResolveChain resolves one object chain into content bytes.
-func (store *Store) deltaResolveChain(chain deltaChain) (objecttype.Type, []byte, error) {+func (store *Store) deltaResolveChain(chain deltaChain, declaredSize int64) (objecttype.Type, []byte, error) {ty, out, nextDelta, err := store.deltaResolveChainStart(chain)
if err != nil {return objecttype.TypeInvalid, nil, err
@@ -47,11 +58,11 @@
store.cacheMu.Unlock()
}
- if int64(len(out)) != chain.declaredSize {+ if int64(len(out)) != declaredSize {return objecttype.TypeInvalid, nil, fmt.Errorf(
"objectstore/packed: resolved content size mismatch: got %d want %d",
len(out),
- chain.declaredSize,
+ declaredSize,
)
}
if ty != chain.baseType {--- a/objectstore/packed/delta_plan.go
+++ b/objectstore/packed/delta_plan.go
@@ -18,8 +18,6 @@
// deltaChain describes how to reconstruct one requested object.
type deltaChain struct {- // declaredSize is the target object's declared content size.
- declaredSize int64
// baseLoc points to the innermost base object.
baseLoc location
// baseType is the canonical object type resolved from baseLoc.
@@ -34,7 +32,6 @@
current := start
var chain deltaChain
- chain.declaredSize = -1
for { if _, ok := visited[current]; ok {@@ -42,20 +39,9 @@
}
visited[current] = struct{}{}- pack, meta, err := store.entryMetaAt(current)
+ _, meta, err := store.entryMetaAt(current)
if err != nil { return deltaChain{}, err- }
- if chain.declaredSize < 0 {- if packfmt.IsBaseObjectType(meta.ty) {- chain.declaredSize = meta.size
- } else {- declaredSize, err := deltaDeclaredSizeAt(pack, meta.dataOffset)
- if err != nil {- return deltaChain{}, err- }
- chain.declaredSize = declaredSize
- }
}
if packfmt.IsBaseObjectType(meta.ty) {--- a/objectstore/packed/entry_parse.go
+++ b/objectstore/packed/entry_parse.go
@@ -56,6 +56,12 @@
return zero, fmt.Errorf("objectstore/packed: pack %q has invalid ofs-delta base", pack.name)}
meta.baseOfs = offset - entry.OfsBaseDistance
+ case objecttype.TypeCommit, objecttype.TypeTree, objecttype.TypeBlob, objecttype.TypeTag:
+ // Base object types do not have delta base metadata.
+ case objecttype.TypeInvalid, objecttype.TypeFuture:
+ return zero, fmt.Errorf("objectstore/packed: pack %q has unsupported entry type %d", pack.name, meta.ty)+ default:
+ return zero, fmt.Errorf("objectstore/packed: pack %q has unsupported entry type %d", pack.name, meta.ty)}
return meta, nil
}
--- a/objectstore/packed/read_header.go
+++ b/objectstore/packed/read_header.go
@@ -11,9 +11,5 @@
if err != nil {return objecttype.TypeInvalid, 0, err
}
- chain, err := store.deltaBuildChain(loc)
- if err != nil {- return objecttype.TypeInvalid, 0, err
- }
- return chain.baseType, chain.declaredSize, nil
+ return store.resolveHeaderAt(loc)
}
--- /dev/null
+++ b/objectstore/packed/read_header_resolve.go
@@ -1,0 +1,61 @@
+package packed
+
+import (
+ "fmt"
+
+ packfmt "codeberg.org/lindenii/furgit/format/pack"
+ "codeberg.org/lindenii/furgit/objecttype"
+)
+
+// resolveHeaderAt resolves one object's canonical type and declared content size.
+func (store *Store) resolveHeaderAt(start location) (objecttype.Type, int64, error) {+ visited := make(map[location]struct{})+ current := start
+ declaredSize := int64(-1)
+
+ for {+ if _, ok := visited[current]; ok {+ return objecttype.TypeInvalid, 0, fmt.Errorf("objectstore/packed: delta cycle while resolving object header")+ }
+ visited[current] = struct{}{}+
+ pack, meta, err := store.entryMetaAt(current)
+ if err != nil {+ return objecttype.TypeInvalid, 0, err
+ }
+ if declaredSize < 0 {+ if packfmt.IsBaseObjectType(meta.ty) {+ declaredSize = meta.size
+ } else {+ size, err := deltaDeclaredSizeAt(pack, meta.dataOffset)
+ if err != nil {+ return objecttype.TypeInvalid, 0, err
+ }
+ declaredSize = size
+ }
+ }
+ if packfmt.IsBaseObjectType(meta.ty) {+ return meta.ty, declaredSize, nil
+ }
+
+ switch meta.ty {+ case objecttype.TypeRefDelta:
+ next, err := store.lookup(meta.baseRefID)
+ if err != nil {+ return objecttype.TypeInvalid, 0, err
+ }
+ current = next
+ case objecttype.TypeOfsDelta:
+ current = location{+ packName: current.packName,
+ offset: meta.baseOfs,
+ }
+ case objecttype.TypeCommit, objecttype.TypeTree, objecttype.TypeBlob, objecttype.TypeTag:
+ return objecttype.TypeInvalid, 0, fmt.Errorf("objectstore/packed: internal invariant violation for base type %d", meta.ty)+ case objecttype.TypeInvalid, objecttype.TypeFuture:
+ return objecttype.TypeInvalid, 0, fmt.Errorf("objectstore/packed: unsupported pack type %d", meta.ty)+ default:
+ return objecttype.TypeInvalid, 0, fmt.Errorf("objectstore/packed: unsupported pack type %d", meta.ty)+ }
+ }
+}
--
⑨