aboutsummaryrefslogtreecommitdiff
path: root/internal/commitquery/oid.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-06 21:19:56 +0800
committerGravatar Runxi Yu2026-03-07 00:34:30 +0800
commit01d15bccf3b1dcc51516b1f64d50950b31d7f8fb (patch)
treee491fcc762c67c1ef4ce54faafc5dafdb734ae8a /internal/commitquery/oid.go
parentobjectstored/refstore: Weird ireturn behavior (diff)
signatureNo 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.go95
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, &notFound) {
+ 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)
+}