shithub: furgit

ref: 2a5c12f0152240f54d01653b70b7605103393afd
dir: /object/storer/packed/delta_resolve_chain.go/

View raw version
package packed

import (
	"fmt"

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

// 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(
			"objectstorer/packed: resolved content size mismatch: got %d want %d",
			len(out),
			declaredSize,
		)
	}

	if ty != chain.baseType {
		return objecttype.TypeInvalid, nil, fmt.Errorf(
			"objectstorer/packed: resolved content type mismatch: got %d want %d",
			ty,
			chain.baseType,
		)
	}

	return ty, out, nil
}