shithub: furgit

ref: 803089a76171db1dd5b891fb6dfa1b7e7f3d50d2
dir: /objectstore/packed/delta_resolve_chain.go/

View raw version
package packed

import (
	"fmt"

	deltaapply "codeberg.org/lindenii/furgit/delta/apply"
	"codeberg.org/lindenii/furgit/objecttype"
)

// 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
}