diff options
| author | 2026-03-06 21:19:56 +0800 | |
|---|---|---|
| committer | 2026-03-07 00:34:30 +0800 | |
| commit | 01d15bccf3b1dcc51516b1f64d50950b31d7f8fb (patch) | |
| tree | e491fcc762c67c1ef4ce54faafc5dafdb734ae8a /internal/commitquery/oid.go | |
| parent | objectstored/refstore: Weird ireturn behavior (diff) | |
| signature | No signature | |
Urgh I made some wrong amends and I'm too tired to separate the commits out this time
ancestor: Split out of reachability
mergebase: Add merge base routines
internal/commitquery: Add commit query context engine thingy
internal/peel: Shared tag peeling
errors: Shared object query errors
internal/testgit: Add rooted repo helpers; remove raw path access
objectstore/memory: Add in-memory object store
objectid: Add Compare helper
Diffstat (limited to 'internal/commitquery/oid.go')
| -rw-r--r-- | internal/commitquery/oid.go | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/internal/commitquery/oid.go b/internal/commitquery/oid.go new file mode 100644 index 00000000..7ba05eb5 --- /dev/null +++ b/internal/commitquery/oid.go @@ -0,0 +1,95 @@ +package commitquery + +import ( + stderrors "errors" + + giterrors "codeberg.org/lindenii/furgit/errors" + commitgraphread "codeberg.org/lindenii/furgit/format/commitgraph/read" + "codeberg.org/lindenii/furgit/object" + "codeberg.org/lindenii/furgit/objectid" + "codeberg.org/lindenii/furgit/objectstore" + "codeberg.org/lindenii/furgit/objecttype" +) + +// ID returns the canonical object ID of one internal node. +func (ctx *Context) ID(idx NodeIndex) objectid.ObjectID { + return ctx.nodes[idx].id +} + +// CommitTime returns the committer timestamp used for one internal node. +func (ctx *Context) CommitTime(idx NodeIndex) int64 { + return ctx.nodes[idx].commitTime +} + +// ResolveOID resolves one commit object ID to one internal query node. +func (ctx *Context) ResolveOID(id objectid.ObjectID) (NodeIndex, error) { + idx, ok := ctx.byOID[id] + if ok { + err := ctx.ensureLoaded(idx) + if err != nil { + return 0, err + } + + return idx, nil + } + + idx = ctx.newNode(id) + ctx.byOID[id] = idx + + err := ctx.loadByOID(idx) + if err != nil { + delete(ctx.byOID, id) + + return 0, err + } + + return idx, nil +} + +// loadByOID populates one node from an object ID. +func (ctx *Context) loadByOID(idx NodeIndex) error { + id := ctx.nodes[idx].id + + if ctx.graph != nil { + pos, err := ctx.graph.Lookup(id) + if err != nil { + var notFound *commitgraphread.NotFoundError + if !stderrors.As(err, ¬Found) { + return err + } + } else { + return ctx.loadCommitAtGraphPos(idx, pos) + } + } + + ty, content, err := ctx.store.ReadBytesContent(id) + if err != nil { + if stderrors.Is(err, objectstore.ErrObjectNotFound) { + return &giterrors.ObjectMissingError{OID: id} + } + + return err + } + + if ty != objecttype.TypeCommit { + return &giterrors.ObjectTypeError{OID: id, Got: ty, Want: objecttype.TypeCommit} + } + + commitObj, err := object.ParseCommit(content, id.Algorithm()) + if err != nil { + return err + } + + parents := make([]Parent, 0, len(commitObj.Parents)) + for _, parentID := range commitObj.Parents { + parents = append(parents, Parent{ID: parentID}) + } + + commit := Commit{ + ID: id, + Parents: parents, + CommitTime: commitObj.Committer.WhenUnix, + } + + return ctx.populateNode(idx, commit) +} |
