aboutsummaryrefslogtreecommitdiff
path: root/objectstore/packed/delta_plan.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-02-21 05:35:12 +0800
committerGravatar Runxi Yu2026-02-21 11:15:18 +0800
commitae879b8cf5a87199802a33d6b15c76afafa8002b (patch)
treea93e9486a9610b78823e157c68b75e0724366217 /objectstore/packed/delta_plan.go
parentcache/lru: Add basic LRU (diff)
signatureNo signature
objectstore/packed: Add initial pack reading support
Diffstat (limited to 'objectstore/packed/delta_plan.go')
-rw-r--r--objectstore/packed/delta_plan.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/objectstore/packed/delta_plan.go b/objectstore/packed/delta_plan.go
new file mode 100644
index 00000000..e55400aa
--- /dev/null
+++ b/objectstore/packed/delta_plan.go
@@ -0,0 +1,81 @@
+package packed
+
+import (
+ "fmt"
+
+ "codeberg.org/lindenii/furgit/objecttype"
+)
+
+// deltaFrame describes one delta payload to apply during reconstruction.
+type deltaFrame struct {
+ // packName identifies where the delta payload lives.
+ packName string
+ // dataOffset points to the start of the delta zlib payload in pack.
+ dataOffset int
+}
+
+// deltaPlan describes how to reconstruct one requested object.
+type deltaPlan 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.
+ baseType objecttype.Type
+ // frames contains deltas from target down toward base.
+ frames []deltaFrame
+}
+
+// deltaPlanFor walks one object's chain and builds a delta reconstruction plan.
+func (store *Store) deltaPlanFor(start location) (deltaPlan, error) {
+ visited := make(map[location]struct{})
+ current := start
+
+ var plan deltaPlan
+ plan.declaredSize = -1
+
+ for {
+ if _, ok := visited[current]; ok {
+ return deltaPlan{}, fmt.Errorf("objectstore/packed: delta cycle while resolving object")
+ }
+ visited[current] = struct{}{}
+
+ _, meta, err := store.entryMetaAt(current)
+ if err != nil {
+ return deltaPlan{}, err
+ }
+ if plan.declaredSize < 0 {
+ plan.declaredSize = meta.size
+ }
+
+ if isBaseObjectType(meta.ty) {
+ plan.baseLoc = current
+ plan.baseType = meta.ty
+ return plan, nil
+ }
+
+ switch meta.ty {
+ case objecttype.TypeRefDelta:
+ plan.frames = append(plan.frames, deltaFrame{
+ packName: current.packName,
+ dataOffset: meta.dataOffset,
+ })
+ next, err := store.lookup(meta.baseRefID)
+ if err != nil {
+ return deltaPlan{}, err
+ }
+ current = next
+ case objecttype.TypeOfsDelta:
+ plan.frames = append(plan.frames, deltaFrame{
+ packName: current.packName,
+ dataOffset: meta.dataOffset,
+ })
+ current = location{
+ packName: current.packName,
+ offset: meta.baseOfs,
+ }
+ default:
+ return deltaPlan{}, fmt.Errorf("objectstore/packed: unsupported pack type %d", meta.ty)
+ }
+ }
+}