aboutsummaryrefslogtreecommitdiff
path: root/internal/commitquery
diff options
context:
space:
mode:
Diffstat (limited to 'internal/commitquery')
-rw-r--r--internal/commitquery/ancestor.go30
-rw-r--r--internal/commitquery/bits.go14
-rw-r--r--internal/commitquery/commit.go17
-rw-r--r--internal/commitquery/compare.go25
-rw-r--r--internal/commitquery/context.go32
-rw-r--r--internal/commitquery/errors.go5
-rw-r--r--internal/commitquery/generation.go43
-rw-r--r--internal/commitquery/graph_pos.go107
-rw-r--r--internal/commitquery/load.go14
-rw-r--r--internal/commitquery/marks.go67
-rw-r--r--internal/commitquery/merge_bases.go116
-rw-r--r--internal/commitquery/node.go39
-rw-r--r--internal/commitquery/oid.go94
-rw-r--r--internal/commitquery/parent.go27
-rw-r--r--internal/commitquery/populate.go42
-rw-r--r--internal/commitquery/priority_queue.go68
-rw-r--r--internal/commitquery/reduce.go166
17 files changed, 0 insertions, 906 deletions
diff --git a/internal/commitquery/ancestor.go b/internal/commitquery/ancestor.go
deleted file mode 100644
index d050ce08..00000000
--- a/internal/commitquery/ancestor.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package commitquery
-
-// IsAncestor reports whether ancestor is reachable from descendant through
-// commit parent edges.
-func IsAncestor(ctx *Context, ancestor, descendant NodeIndex) (bool, error) {
- if ancestor == descendant {
- return true, nil
- }
-
- ancestorGeneration := ctx.EffectiveGeneration(ancestor)
- descendantGeneration := ctx.EffectiveGeneration(descendant)
-
- if ancestorGeneration != generationInfinity &&
- descendantGeneration != generationInfinity &&
- ancestorGeneration > descendantGeneration {
- return false, nil
- }
-
- minGeneration := uint64(0)
- if ancestorGeneration != generationInfinity {
- minGeneration = ancestorGeneration
- }
-
- err := paintDownToCommon(ctx, ancestor, []NodeIndex{descendant}, minGeneration)
- if err != nil {
- return false, err
- }
-
- return ctx.HasAnyMarks(ancestor, markRight), nil
-}
diff --git a/internal/commitquery/bits.go b/internal/commitquery/bits.go
deleted file mode 100644
index 36ffff29..00000000
--- a/internal/commitquery/bits.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package commitquery
-
-type markBits uint8
-
-const (
- markLeft markBits = 1 << iota
- markRight
- markStale
- markResult
-)
-
-const (
- allMarks = markLeft | markRight | markStale | markResult
-)
diff --git a/internal/commitquery/commit.go b/internal/commitquery/commit.go
deleted file mode 100644
index fccd52b2..00000000
--- a/internal/commitquery/commit.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package commitquery
-
-import (
- commitgraphread "codeberg.org/lindenii/furgit/commitgraph/read"
- "codeberg.org/lindenii/furgit/objectid"
-)
-
-// Commit stores the metadata needed by commit-domain queries.
-type Commit struct {
- ID objectid.ObjectID
- Parents []Parent
- CommitTime int64
- Generation uint64
- HasGeneration bool
- GraphPos commitgraphread.Position
- HasGraphPos bool
-}
diff --git a/internal/commitquery/compare.go b/internal/commitquery/compare.go
deleted file mode 100644
index 748ef712..00000000
--- a/internal/commitquery/compare.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package commitquery
-
-import "codeberg.org/lindenii/furgit/objectid"
-
-// Compare compares two internal nodes using merge-base queue ordering.
-func (ctx *Context) Compare(left, right NodeIndex) int {
- leftGeneration := ctx.EffectiveGeneration(left)
- rightGeneration := ctx.EffectiveGeneration(right)
-
- switch {
- case leftGeneration < rightGeneration:
- return -1
- case leftGeneration > rightGeneration:
- return 1
- }
-
- switch {
- case ctx.nodes[left].commitTime < ctx.nodes[right].commitTime:
- return -1
- case ctx.nodes[left].commitTime > ctx.nodes[right].commitTime:
- return 1
- }
-
- return objectid.Compare(ctx.nodes[left].id, ctx.nodes[right].id)
-}
diff --git a/internal/commitquery/context.go b/internal/commitquery/context.go
deleted file mode 100644
index bafbb5c4..00000000
--- a/internal/commitquery/context.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Package commitquery provides private commit-domain query routines.
-package commitquery
-
-import (
- commitgraphread "codeberg.org/lindenii/furgit/commitgraph/read"
- "codeberg.org/lindenii/furgit/objectid"
- "codeberg.org/lindenii/furgit/objectstore"
-)
-
-// Context owns the mutable node arena for one commit query.
-type Context struct {
- store objectstore.Store
- graph *commitgraphread.Reader
-
- nodes []node
-
- byOID map[objectid.ObjectID]NodeIndex
- byGraphPos map[commitgraphread.Position]NodeIndex
-
- markPhase uint32
- touched []NodeIndex
-}
-
-// NewContext builds one empty query context over one object store and optional commit-graph reader.
-func NewContext(store objectstore.Store, graph *commitgraphread.Reader) *Context {
- return &Context{
- store: store,
- graph: graph,
- byOID: make(map[objectid.ObjectID]NodeIndex),
- byGraphPos: make(map[commitgraphread.Position]NodeIndex),
- }
-}
diff --git a/internal/commitquery/errors.go b/internal/commitquery/errors.go
deleted file mode 100644
index e99011d0..00000000
--- a/internal/commitquery/errors.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package commitquery
-
-import "errors"
-
-var errBadGenerationOrder = errors.New("commitquery: priority queue violated generation ordering")
diff --git a/internal/commitquery/generation.go b/internal/commitquery/generation.go
deleted file mode 100644
index c5edcd9f..00000000
--- a/internal/commitquery/generation.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package commitquery
-
-import (
- "math"
-
- "codeberg.org/lindenii/furgit/objectid"
-)
-
-// EffectiveGeneration returns one node's generation value.
-func (ctx *Context) EffectiveGeneration(idx NodeIndex) uint64 {
- if !ctx.nodes[idx].hasGeneration {
- return generationInfinity
- }
-
- return ctx.nodes[idx].generation
-}
-
-const (
- generationInfinity = uint64(math.MaxUint64)
-)
-
-func compareByGeneration(ctx *Context) func(NodeIndex, NodeIndex) int {
- return func(left, right NodeIndex) int {
- leftGeneration := ctx.EffectiveGeneration(left)
- rightGeneration := ctx.EffectiveGeneration(right)
-
- switch {
- case leftGeneration < rightGeneration:
- return -1
- case leftGeneration > rightGeneration:
- return 1
- }
-
- switch {
- case ctx.nodes[left].commitTime < ctx.nodes[right].commitTime:
- return -1
- case ctx.nodes[left].commitTime > ctx.nodes[right].commitTime:
- return 1
- }
-
- return objectid.Compare(ctx.nodes[left].id, ctx.nodes[right].id)
- }
-}
diff --git a/internal/commitquery/graph_pos.go b/internal/commitquery/graph_pos.go
deleted file mode 100644
index 437f86e6..00000000
--- a/internal/commitquery/graph_pos.go
+++ /dev/null
@@ -1,107 +0,0 @@
-package commitquery
-
-import commitgraphread "codeberg.org/lindenii/furgit/commitgraph/read"
-
-// ResolveGraphPos resolves one commit-graph position to one internal query node.
-func (ctx *Context) ResolveGraphPos(pos commitgraphread.Position) (NodeIndex, error) {
- idx, ok := ctx.byGraphPos[pos]
- if ok {
- err := ctx.ensureLoaded(idx)
- if err != nil {
- return 0, err
- }
-
- return idx, nil
- }
-
- commit, err := ctx.graph.CommitAt(pos)
- if err != nil {
- return 0, err
- }
-
- idx, ok = ctx.byOID[commit.OID]
- if !ok {
- idx = ctx.newNode(commit.OID)
- ctx.byOID[commit.OID] = idx
- }
-
- ctx.byGraphPos[pos] = idx
- ctx.nodes[idx].graphPos = pos
- ctx.nodes[idx].hasGraphPos = true
-
- err = ctx.loadCommitAtGraphPos(idx, pos)
- if err != nil {
- delete(ctx.byGraphPos, pos)
-
- return 0, err
- }
-
- return idx, nil
-}
-
-// loadByGraphPos populates one node from a commit-graph position.
-func (ctx *Context) loadByGraphPos(idx NodeIndex) error {
- pos := ctx.nodes[idx].graphPos
-
- return ctx.loadCommitAtGraphPos(idx, pos)
-}
-
-func (ctx *Context) loadCommitAtGraphPos(idx NodeIndex, pos commitgraphread.Position) error {
- commit, err := ctx.graph.CommitAt(pos)
- if err != nil {
- return err
- }
-
- parents := make([]Parent, 0, 2+len(commit.ExtraParents))
-
- if commit.Parent1.Valid {
- parentOID, err := ctx.graph.OIDAt(commit.Parent1.Pos)
- if err != nil {
- return err
- }
-
- parents = append(parents, Parent{
- ID: parentOID,
- GraphPos: commit.Parent1.Pos,
- HasGraphPos: true,
- })
- }
-
- if commit.Parent2.Valid {
- parentOID, err := ctx.graph.OIDAt(commit.Parent2.Pos)
- if err != nil {
- return err
- }
-
- parents = append(parents, Parent{
- ID: parentOID,
- GraphPos: commit.Parent2.Pos,
- HasGraphPos: true,
- })
- }
-
- for _, parentPos := range commit.ExtraParents {
- parentOID, err := ctx.graph.OIDAt(parentPos)
- if err != nil {
- return err
- }
-
- parents = append(parents, Parent{
- ID: parentOID,
- GraphPos: parentPos,
- HasGraphPos: true,
- })
- }
-
- data := Commit{
- ID: commit.OID,
- Parents: parents,
- CommitTime: commit.CommitTimeUnix,
- Generation: commit.GenerationV2,
- HasGeneration: commit.GenerationV2 != 0,
- GraphPos: pos,
- HasGraphPos: true,
- }
-
- return ctx.populateNode(idx, data)
-}
diff --git a/internal/commitquery/load.go b/internal/commitquery/load.go
deleted file mode 100644
index b795f7d9..00000000
--- a/internal/commitquery/load.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package commitquery
-
-// ensureLoaded completes one node's metadata load if it has not been loaded yet.
-func (ctx *Context) ensureLoaded(idx NodeIndex) error {
- if ctx.nodes[idx].loaded {
- return nil
- }
-
- if ctx.nodes[idx].hasGraphPos {
- return ctx.loadByGraphPos(idx)
- }
-
- return ctx.loadByOID(idx)
-}
diff --git a/internal/commitquery/marks.go b/internal/commitquery/marks.go
deleted file mode 100644
index f88fdf25..00000000
--- a/internal/commitquery/marks.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package commitquery
-
-// Marks returns the mark bits of one internal node.
-func (ctx *Context) Marks(idx NodeIndex) markBits {
- return ctx.nodes[idx].marks
-}
-
-// HasAnyMarks reports whether one internal node has any requested bit.
-func (ctx *Context) HasAnyMarks(idx NodeIndex, bits markBits) bool {
- return ctx.nodes[idx].marks&bits != 0
-}
-
-// HasAllMarks reports whether one internal node already has all requested bits.
-func (ctx *Context) HasAllMarks(idx NodeIndex, bits markBits) bool {
- return ctx.nodes[idx].marks&bits == bits
-}
-
-// SetMarks ORs one set of mark bits into one internal node.
-func (ctx *Context) SetMarks(idx NodeIndex, bits markBits) {
- newBits := bits &^ ctx.nodes[idx].marks
- if newBits == 0 {
- return
- }
-
- ctx.trackTouched(idx)
- ctx.nodes[idx].marks |= bits
-}
-
-// ClearMarks removes one set of mark bits from one internal node.
-func (ctx *Context) ClearMarks(idx NodeIndex, bits markBits) {
- if ctx.nodes[idx].marks&bits == 0 {
- return
- }
-
- ctx.trackTouched(idx)
- ctx.nodes[idx].marks &^= bits
-}
-
-// BeginMarkPhase starts one tracked mark-mutation phase.
-func (ctx *Context) BeginMarkPhase() {
- ctx.markPhase++
- if ctx.markPhase == 0 {
- ctx.markPhase++
- for i := range ctx.nodes {
- ctx.nodes[i].touchedPhase = 0
- }
- }
-
- ctx.touched = ctx.touched[:0]
-}
-
-// ClearTouchedMarks clears the provided bits from all nodes touched in the
-// current mark phase.
-func (ctx *Context) ClearTouchedMarks(bits markBits) {
- for _, idx := range ctx.touched {
- ctx.nodes[idx].marks &^= bits
- }
-}
-
-func (ctx *Context) trackTouched(idx NodeIndex) {
- if ctx.nodes[idx].touchedPhase == ctx.markPhase {
- return
- }
-
- ctx.nodes[idx].touchedPhase = ctx.markPhase
- ctx.touched = append(ctx.touched, idx)
-}
diff --git a/internal/commitquery/merge_bases.go b/internal/commitquery/merge_bases.go
deleted file mode 100644
index 62ab9bd6..00000000
--- a/internal/commitquery/merge_bases.go
+++ /dev/null
@@ -1,116 +0,0 @@
-package commitquery
-
-import "slices"
-
-// MergeBases computes fully reduced merge bases using one query context.
-func MergeBases(ctx *Context, left, right NodeIndex) ([]NodeIndex, error) {
- if left == right {
- return []NodeIndex{left}, nil
- }
-
- err := paintDownToCommon(ctx, left, []NodeIndex{right}, 0)
- if err != nil {
- return nil, err
- }
-
- candidates := collectMarkedResults(ctx)
-
- if len(candidates) <= 1 {
- slices.SortFunc(candidates, ctx.Compare)
-
- return candidates, nil
- }
-
- ctx.ClearTouchedMarks(allMarks)
-
- reduced, err := removeRedundant(ctx, candidates)
- if err != nil {
- return nil, err
- }
-
- slices.SortFunc(reduced, ctx.Compare)
-
- return reduced, nil
-}
-
-func paintDownToCommon(ctx *Context, left NodeIndex, rights []NodeIndex, minGeneration uint64) error {
- ctx.BeginMarkPhase()
-
- ctx.SetMarks(left, markLeft)
-
- if len(rights) == 0 {
- ctx.SetMarks(left, markResult)
-
- return nil
- }
-
- queue := newPriorityQueue(ctx)
- queue.PushNode(left)
-
- for _, right := range rights {
- ctx.SetMarks(right, markRight)
- queue.PushNode(right)
- }
-
- lastGeneration := generationInfinity
-
- for queueHasNonStale(ctx, queue) {
- idx := queue.PopNode()
-
- generation := ctx.EffectiveGeneration(idx)
- if generation > lastGeneration {
- return errBadGenerationOrder
- }
-
- lastGeneration = generation
- if generation < minGeneration {
- break
- }
-
- flags := ctx.Marks(idx) & (markLeft | markRight | markStale)
- if flags == (markLeft | markRight) {
- ctx.SetMarks(idx, markResult)
-
- flags |= markStale
- }
-
- for _, parent := range ctx.Parents(idx) {
- if ctx.HasAllMarks(parent, flags) {
- continue
- }
-
- ctx.SetMarks(parent, flags)
- queue.PushNode(parent)
- }
- }
-
- return nil
-}
-
-func queueHasNonStale(ctx *Context, queue *priorityQueue) bool {
- for _, idx := range queue.items {
- if !ctx.HasAnyMarks(idx, markStale) {
- return true
- }
- }
-
- return false
-}
-
-func collectMarkedResults(ctx *Context) []NodeIndex {
- out := make([]NodeIndex, 0, 4)
-
- for _, idx := range ctx.touched {
- if !ctx.HasAnyMarks(idx, markResult) {
- continue
- }
-
- if ctx.HasAnyMarks(idx, markStale) {
- continue
- }
-
- out = append(out, idx)
- }
-
- return out
-}
diff --git a/internal/commitquery/node.go b/internal/commitquery/node.go
deleted file mode 100644
index f4979bfe..00000000
--- a/internal/commitquery/node.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package commitquery
-
-import (
- commitgraphread "codeberg.org/lindenii/furgit/commitgraph/read"
- "codeberg.org/lindenii/furgit/objectid"
-)
-
-// NodeIndex identifies one internal query node.
-type NodeIndex int
-
-// node stores one mutable commit traversal node.
-type node struct {
- id objectid.ObjectID
-
- parents []NodeIndex
-
- commitTime int64
- generation uint64
-
- hasGeneration bool
- hasGraphPos bool
- loaded bool
-
- graphPos commitgraphread.Position
- marks markBits
-
- touchedPhase uint32
-}
-
-// newNode allocates one empty internal node.
-func (ctx *Context) newNode(id objectid.ObjectID) NodeIndex {
- count := len(ctx.nodes)
-
- idx := NodeIndex(count)
-
- ctx.nodes = append(ctx.nodes, node{id: id})
-
- return idx
-}
diff --git a/internal/commitquery/oid.go b/internal/commitquery/oid.go
deleted file mode 100644
index 927c0220..00000000
--- a/internal/commitquery/oid.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package commitquery
-
-import (
- stderrors "errors"
-
- commitgraphread "codeberg.org/lindenii/furgit/commitgraph/read"
- giterrors "codeberg.org/lindenii/furgit/errors"
- "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 {
- if _, ok := stderrors.AsType[*commitgraphread.NotFoundError](err); !ok {
- 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)
-}
diff --git a/internal/commitquery/parent.go b/internal/commitquery/parent.go
deleted file mode 100644
index 809a1fd5..00000000
--- a/internal/commitquery/parent.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package commitquery
-
-import (
- commitgraphread "codeberg.org/lindenii/furgit/commitgraph/read"
- "codeberg.org/lindenii/furgit/objectid"
-)
-
-// Parent references one commit parent.
-type Parent struct {
- ID objectid.ObjectID
- GraphPos commitgraphread.Position
- HasGraphPos bool
-}
-
-// Parents returns resolved parent node indices for one internal node.
-func (ctx *Context) Parents(idx NodeIndex) []NodeIndex {
- return ctx.nodes[idx].parents
-}
-
-// resolveParent resolves one parent descriptor to one internal node.
-func (ctx *Context) resolveParent(parent Parent) (NodeIndex, error) {
- if parent.HasGraphPos {
- return ctx.ResolveGraphPos(parent.GraphPos)
- }
-
- return ctx.ResolveOID(parent.ID)
-}
diff --git a/internal/commitquery/populate.go b/internal/commitquery/populate.go
deleted file mode 100644
index 87d65bf8..00000000
--- a/internal/commitquery/populate.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package commitquery
-
-import "fmt"
-
-// populateNode fills one node's metadata and resolves its parents.
-func (ctx *Context) populateNode(idx NodeIndex, commit Commit) error {
- if ctx.nodes[idx].loaded {
- if ctx.nodes[idx].id != commit.ID {
- return fmt.Errorf("commitquery: node identity mismatch: have %s, got %s", ctx.nodes[idx].id, commit.ID)
- }
-
- return nil
- }
-
- ctx.nodes[idx].id = commit.ID
- ctx.nodes[idx].commitTime = commit.CommitTime
- ctx.nodes[idx].generation = commit.Generation
- ctx.nodes[idx].hasGeneration = commit.HasGeneration
-
- if commit.HasGraphPos {
- ctx.nodes[idx].graphPos = commit.GraphPos
- ctx.nodes[idx].hasGraphPos = true
- ctx.byGraphPos[commit.GraphPos] = idx
- }
-
- ctx.nodes[idx].loaded = true
- ctx.nodes[idx].parents = ctx.nodes[idx].parents[:0]
-
- for _, parent := range commit.Parents {
- parentIdx, err := ctx.resolveParent(parent)
- if err != nil {
- ctx.nodes[idx].loaded = false
- ctx.nodes[idx].parents = nil
-
- return err
- }
-
- ctx.nodes[idx].parents = append(ctx.nodes[idx].parents, parentIdx)
- }
-
- return nil
-}
diff --git a/internal/commitquery/priority_queue.go b/internal/commitquery/priority_queue.go
deleted file mode 100644
index d6dbf54f..00000000
--- a/internal/commitquery/priority_queue.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package commitquery
-
-import "container/heap"
-
-// priorityQueue orders internal nodes using one query context's comparator.
-type priorityQueue struct {
- ctx *Context
- items []NodeIndex
-}
-
-// newPriorityQueue builds one empty priority queue over one query context.
-func newPriorityQueue(ctx *Context) *priorityQueue {
- queue := &priorityQueue{ctx: ctx}
- heap.Init(queue)
-
- return queue
-}
-
-// Len reports the number of queued items.
-func (queue *priorityQueue) Len() int {
- return len(queue.items)
-}
-
-// Less reports whether one heap slot sorts ahead of another.
-func (queue *priorityQueue) Less(left, right int) bool {
- return queue.ctx.Compare(queue.items[left], queue.items[right]) > 0
-}
-
-// Swap exchanges two heap slots.
-func (queue *priorityQueue) Swap(left, right int) {
- queue.items[left], queue.items[right] = queue.items[right], queue.items[left]
-}
-
-// Push appends one heap element.
-func (queue *priorityQueue) Push(item any) {
- idx, ok := item.(NodeIndex)
- if !ok {
- panic("commitquery: heap push item is not a NodeIndex")
- }
-
- queue.items = append(queue.items, idx)
-}
-
-// Pop removes one heap element.
-func (queue *priorityQueue) Pop() any {
- last := len(queue.items) - 1
- item := queue.items[last]
- queue.items = queue.items[:last]
-
- return item
-}
-
-// PushNode inserts one internal node.
-func (queue *priorityQueue) PushNode(idx NodeIndex) {
- heap.Push(queue, idx)
-}
-
-// PopNode removes the highest-priority internal node.
-func (queue *priorityQueue) PopNode() NodeIndex {
- item := heap.Pop(queue)
-
- idx, ok := item.(NodeIndex)
- if !ok {
- panic("commitquery: heap pop item is not a NodeIndex")
- }
-
- return idx
-}
diff --git a/internal/commitquery/reduce.go b/internal/commitquery/reduce.go
deleted file mode 100644
index 917f2fa2..00000000
--- a/internal/commitquery/reduce.go
+++ /dev/null
@@ -1,166 +0,0 @@
-package commitquery
-
-import (
- "slices"
-)
-
-// removeRedundant removes redundant merge-base candidates.
-func removeRedundant(ctx *Context, candidates []NodeIndex) ([]NodeIndex, error) {
- for _, idx := range candidates {
- if ctx.EffectiveGeneration(idx) != generationInfinity {
- return removeRedundantWithGen(ctx, candidates), nil
- }
- }
-
- return removeRedundantNoGen(ctx, candidates)
-}
-
-func removeRedundantNoGen(ctx *Context, candidates []NodeIndex) ([]NodeIndex, error) {
- redundant := make([]bool, len(candidates))
- work := make([]NodeIndex, 0, len(candidates)-1)
- filledIndex := make([]int, 0, len(candidates)-1)
-
- for i, candidate := range candidates {
- if redundant[i] {
- continue
- }
-
- work = work[:0]
- filledIndex = filledIndex[:0]
-
- minGeneration := ctx.EffectiveGeneration(candidate)
-
- for j, other := range candidates {
- if i == j || redundant[j] {
- continue
- }
-
- work = append(work, other)
- filledIndex = append(filledIndex, j)
-
- otherGeneration := ctx.EffectiveGeneration(other)
- if otherGeneration < minGeneration {
- minGeneration = otherGeneration
- }
- }
-
- err := paintDownToCommon(ctx, candidate, work, minGeneration)
- if err != nil {
- return nil, err
- }
-
- if ctx.HasAnyMarks(candidate, markRight) {
- redundant[i] = true
- }
-
- for j, other := range work {
- if ctx.HasAnyMarks(other, markLeft) {
- redundant[filledIndex[j]] = true
- }
- }
-
- ctx.ClearTouchedMarks(allMarks)
- }
-
- out := make([]NodeIndex, 0, len(candidates))
- for i, idx := range candidates {
- if !redundant[i] {
- out = append(out, idx)
- }
- }
-
- return out, nil
-}
-
-func removeRedundantWithGen(ctx *Context, candidates []NodeIndex) []NodeIndex {
- sorted := append([]NodeIndex(nil), candidates...)
- slices.SortFunc(sorted, compareByGeneration(ctx))
-
- minGeneration := ctx.EffectiveGeneration(sorted[0])
- minGenPos := 0
- countStillIndependent := len(candidates)
-
- ctx.BeginMarkPhase()
-
- walkStart := make([]NodeIndex, 0, len(candidates)*2)
-
- for _, idx := range candidates {
- ctx.SetMarks(idx, markResult)
-
- for _, parent := range ctx.Parents(idx) {
- if ctx.HasAnyMarks(parent, markStale) {
- continue
- }
-
- ctx.SetMarks(parent, markStale)
- walkStart = append(walkStart, parent)
- }
- }
-
- slices.SortFunc(walkStart, compareByGeneration(ctx))
-
- for _, idx := range walkStart {
- ctx.ClearMarks(idx, markStale)
- }
-
- for i := len(walkStart) - 1; i >= 0 && countStillIndependent > 1; i-- {
- stack := []NodeIndex{walkStart[i]}
- ctx.SetMarks(walkStart[i], markStale)
-
- for len(stack) > 0 {
- top := stack[len(stack)-1]
-
- if ctx.HasAnyMarks(top, markResult) {
- ctx.ClearMarks(top, markResult)
-
- countStillIndependent--
- if countStillIndependent <= 1 {
- break
- }
-
- if top == sorted[minGenPos] {
- for minGenPos < len(sorted)-1 && ctx.HasAnyMarks(sorted[minGenPos], markStale) {
- minGenPos++
- }
-
- minGeneration = ctx.EffectiveGeneration(sorted[minGenPos])
- }
- }
-
- if ctx.EffectiveGeneration(top) < minGeneration {
- stack = stack[:len(stack)-1]
-
- continue
- }
-
- pushed := false
-
- for _, parent := range ctx.Parents(top) {
- if ctx.HasAnyMarks(parent, markStale) {
- continue
- }
-
- ctx.SetMarks(parent, markStale)
- stack = append(stack, parent)
- pushed = true
-
- break
- }
-
- if !pushed {
- stack = stack[:len(stack)-1]
- }
- }
- }
-
- out := make([]NodeIndex, 0, len(candidates))
- for _, idx := range candidates {
- if !ctx.HasAnyMarks(idx, markStale) {
- out = append(out, idx)
- }
- }
-
- ctx.ClearTouchedMarks(markStale | markResult)
-
- return out
-}