diff options
Diffstat (limited to 'object/store/packed/delta_resolve_chain.go')
| -rw-r--r-- | object/store/packed/delta_resolve_chain.go | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/object/store/packed/delta_resolve_chain.go b/object/store/packed/delta_resolve_chain.go new file mode 100644 index 00000000..f988a9fb --- /dev/null +++ b/object/store/packed/delta_resolve_chain.go @@ -0,0 +1,61 @@ +package packed + +import ( + "fmt" + + deltaapply "codeberg.org/lindenii/furgit/delta/apply" + objecttype "codeberg.org/lindenii/furgit/object/type" +) + +// deltaResolveChain resolves one object chain into content bytes. +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 + } + + for i := nextDelta; i >= 0; i-- { + node := chain.deltas[i] + + pack, err := store.openPack(node.loc.packName) + if err != nil { + return objecttype.TypeInvalid, nil, err + } + + delta, err := inflateAt(pack, node.dataOffset, -1) + if err != nil { + return objecttype.TypeInvalid, nil, err + } + + out, err = deltaapply.Apply(out, delta) + if err != nil { + return objecttype.TypeInvalid, nil, err + } + + store.cacheMu.Lock() + store.deltaCache.add( + deltaBaseKey{packName: node.loc.packName, offset: node.loc.offset}, + ty, + out, + ) + store.cacheMu.Unlock() + } + + if int64(len(out)) != declaredSize { + return objecttype.TypeInvalid, nil, fmt.Errorf( + "objectstore/packed: resolved content size mismatch: got %d want %d", + len(out), + declaredSize, + ) + } + + if ty != chain.baseType { + return objecttype.TypeInvalid, nil, fmt.Errorf( + "objectstore/packed: resolved content type mismatch: got %d want %d", + ty, + chain.baseType, + ) + } + + return ty, out, nil +} |
