aboutsummaryrefslogtreecommitdiff
path: root/object/store/packed/read_header_resolve.go
blob: 849cfbc738c969aeceba1f397e08067b15b70fae (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package packed

import (
	"fmt"

	objecttype "codeberg.org/lindenii/furgit/object/type"
)

// resolveHeaderAt resolves one object's canonical type and declared content size.
func (store *Store) resolveHeaderAt(start location) (objecttype.Type, int64, error) {
	visited := make(map[location]struct{})
	current := start
	declaredSize := int64(-1)

	for {
		if _, ok := visited[current]; ok {
			return objecttype.TypeInvalid, 0, fmt.Errorf("objectstore/packed: delta cycle while resolving object header")
		}

		visited[current] = struct{}{}

		pack, meta, err := store.entryMetaAt(current)
		if err != nil {
			return objecttype.TypeInvalid, 0, err
		}

		if declaredSize < 0 {
			if meta.ty.IsBaseObject() {
				declaredSize = meta.size
			} else {
				size, err := deltaDeclaredSizeAt(pack, meta.dataOffset)
				if err != nil {
					return objecttype.TypeInvalid, 0, err
				}

				declaredSize = size
			}
		}

		if meta.ty.IsBaseObject() {
			return meta.ty, declaredSize, nil
		}

		switch meta.ty {
		case objecttype.TypeRefDelta:
			next, err := store.lookup(meta.baseRefID)
			if err != nil {
				return objecttype.TypeInvalid, 0, err
			}

			current = next
		case objecttype.TypeOfsDelta:
			current = location{
				packName: current.packName,
				offset:   meta.baseOfs,
			}
		case objecttype.TypeCommit, objecttype.TypeTree, objecttype.TypeBlob, objecttype.TypeTag:
			return objecttype.TypeInvalid, 0, fmt.Errorf("objectstore/packed: internal invariant violation for base type %d", meta.ty)
		case objecttype.TypeInvalid, objecttype.TypeFuture:
			return objecttype.TypeInvalid, 0, fmt.Errorf("objectstore/packed: unsupported pack type %d", meta.ty)
		default:
			return objecttype.TypeInvalid, 0, fmt.Errorf("objectstore/packed: unsupported pack type %d", meta.ty)
		}
	}
}