diff options
| author | 2026-06-08 07:06:05 +0000 | |
|---|---|---|
| committer | 2026-06-08 07:06:05 +0000 | |
| commit | bff6e1ba9f2a0c579850a21ef4738f2eb7cc2ca2 (patch) | |
| tree | 2dfd6f8e02b2ca6ee875974fe9994a1522346afd /object/fetch | |
| parent | object/fetch: Port commit (diff) | |
object/fetch: Port tree
Diffstat (limited to 'object/fetch')
| -rw-r--r-- | object/fetch/tree.go | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/object/fetch/tree.go b/object/fetch/tree.go new file mode 100644 index 00000000..ef0f9e77 --- /dev/null +++ b/object/fetch/tree.go @@ -0,0 +1,86 @@ +package fetch + +import ( + "lindenii.org/go/furgit/errs" + "lindenii.org/go/furgit/object/commit" + oid "lindenii.org/go/furgit/object/id" + "lindenii.org/go/furgit/object/stored" + "lindenii.org/go/furgit/object/tag" + "lindenii.org/go/furgit/object/tree" + "lindenii.org/go/furgit/object/typ" +) + +// ExactTree reads, parses, and wraps the tree at id. +// +// Labels: Life-Parent. +func (r *Fetcher) ExactTree(id oid.ObjectID) (*stored.Stored[*tree.Tree], error) { + parsed, err := r.parseObject(id) + if err != nil { + return nil, err + } + + tree, ok := parsed.(*tree.Tree) + if !ok { + return nil, &errs.ObjectTypeError{OID: id, Got: parsed.ObjectType(), Want: typ.TypeTree} + } + + return stored.New(id, tree), nil +} + +// PeelToTree peels tags until it reaches a tree or commit. If it reaches a +// commit, it returns the commit's root tree. +// +// Labels: Life-Parent. +func (r *Fetcher) PeelToTree(id oid.ObjectID) (*stored.Stored[*tree.Tree], error) { + for { + obj, err := r.ExactObject(id) + if err != nil { + return nil, err + } + + switch parsed := obj.Object().(type) { + case *tree.Tree: + return stored.New(id, parsed), nil + case *commit.Commit: + return r.ExactTree(parsed.Tree) + case *tag.Tag: + id = parsed.TargetID + default: + return nil, &errs.ObjectTypeError{OID: id, Got: parsed.ObjectType(), Want: typ.TypeTree} + } + } +} + +// PeelToTreeID peels tags until it reaches a tree object ID, or a commit whose +// root tree object ID is then returned. +func (r *Fetcher) PeelToTreeID(id oid.ObjectID) (oid.ObjectID, error) { + for { + ty, _, err := r.Header(id) + if err != nil { + return oid.ObjectID{}, err + } + + switch ty { + case typ.TypeTree: + return id, nil + case typ.TypeCommit: + commit, err := r.ExactCommit(id) + if err != nil { + return oid.ObjectID{}, err + } + + return commit.Object().Tree, nil + case typ.TypeTag: + tag, err := r.ExactTag(id) + if err != nil { + return oid.ObjectID{}, err + } + + id = tag.Object().TargetID + case typ.TypeUnknown, typ.TypeBlob: + return oid.ObjectID{}, &errs.ObjectTypeError{OID: id, Got: ty, Want: typ.TypeTree} + default: + return oid.ObjectID{}, &errs.ObjectTypeError{OID: id, Got: ty, Want: typ.TypeTree} + } + } +} |
