aboutsummaryrefslogtreecommitdiff
path: root/format/packfile/ingest/entry.go
diff options
context:
space:
mode:
Diffstat (limited to 'format/packfile/ingest/entry.go')
-rw-r--r--format/packfile/ingest/entry.go92
1 files changed, 92 insertions, 0 deletions
diff --git a/format/packfile/ingest/entry.go b/format/packfile/ingest/entry.go
new file mode 100644
index 00000000..4e2cab55
--- /dev/null
+++ b/format/packfile/ingest/entry.go
@@ -0,0 +1,92 @@
+package ingest
+
+import (
+ "fmt"
+
+ objecttype "codeberg.org/lindenii/furgit/object/type"
+ packfmt "codeberg.org/lindenii/furgit/format/packfile"
+)
+
+// scanOneEntry scans one pack entry from stream and appends one record.
+func scanOneEntry(state *ingestState, startOffset uint64) (uint64, error) {
+ state.stream.beginEntryCRC()
+
+ record, err := parseEntryPrefix(state, startOffset)
+ if err != nil {
+ return 0, err
+ }
+
+ payloadStartConsumed := state.stream.consumed
+
+ contentLen, oid, err := drainEntryPayload(state, record)
+ if err != nil {
+ return 0, err
+ }
+
+ consumedInput := state.stream.consumed - payloadStartConsumed
+
+ if contentLen != record.declaredSize {
+ return 0, &MalformedPackEntryError{
+ Offset: startOffset,
+ Reason: fmt.Sprintf("inflated size mismatch got %d want %d", contentLen, record.declaredSize),
+ }
+ }
+
+ endOffset := startOffset + uint64(record.headerLen) + consumedInput
+ if endOffset > state.stream.consumed {
+ return 0, &MalformedPackEntryError{
+ Offset: startOffset,
+ Reason: fmt.Sprintf("entry end offset overflow got %d > stream %d", endOffset, state.stream.consumed),
+ }
+ }
+
+ record.packedLen = endOffset - startOffset
+
+ record.dataOffset = startOffset + uint64(record.headerLen)
+ if record.packedLen < uint64(record.headerLen) {
+ return 0, &MalformedPackEntryError{Offset: startOffset, Reason: "negative payload span"}
+ }
+
+ crc, err := state.stream.endEntryCRC()
+ if err != nil {
+ return 0, err
+ }
+
+ record.crc32 = crc
+
+ if packfmt.IsBaseObjectType(record.packedType) {
+ record.objectID = oid
+ record.realType = record.packedType
+ record.resolved = true
+ }
+
+ recordIdx := len(state.records)
+ state.records = append(state.records, record)
+
+ state.offsetToRecord[record.offset] = recordIdx
+ if record.resolved {
+ state.objectToRecord[record.objectID] = recordIdx
+ }
+
+ switch record.packedType {
+ case objecttype.TypeOfsDelta:
+ state.ofsDeltas = append(state.ofsDeltas, ofsDeltaRef{
+ baseOffset: record.baseOffset,
+ recordIdx: recordIdx,
+ })
+ case objecttype.TypeRefDelta:
+ state.refDeltas = append(state.refDeltas, refDeltaRef{
+ baseObject: record.baseObject,
+ recordIdx: recordIdx,
+ })
+ case objecttype.TypeInvalid,
+ objecttype.TypeCommit,
+ objecttype.TypeTree,
+ objecttype.TypeBlob,
+ objecttype.TypeTag,
+ objecttype.TypeFuture:
+ default:
+ }
+
+ return endOffset, nil
+}