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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
package commitgraph
import (
"fmt"
"time"
"github.com/go-git/go-git/v5/plumbing"
commitgraph "github.com/go-git/go-git/v5/plumbing/format/commitgraph/v2"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/storer"
)
// graphCommitNode is a reduced representation of Commit as presented in the commit
// graph file (commitgraph.Node). It is merely useful as an optimization for walking
// the commit graphs.
//
// graphCommitNode implements the CommitNode interface.
type graphCommitNode struct {
// Hash for the Commit object
hash plumbing.Hash
// Index of the node in the commit graph file
index uint32
commitData *commitgraph.CommitData
gci *graphCommitNodeIndex
}
// graphCommitNodeIndex is an index that can load CommitNode objects from both the commit
// graph files and the object store.
//
// graphCommitNodeIndex implements the CommitNodeIndex interface
type graphCommitNodeIndex struct {
commitGraph commitgraph.Index
s storer.EncodedObjectStorer
}
// NewGraphCommitNodeIndex returns CommitNodeIndex implementation that uses commit-graph
// files as backing storage and falls back to object storage when necessary
func NewGraphCommitNodeIndex(commitGraph commitgraph.Index, s storer.EncodedObjectStorer) CommitNodeIndex {
return &graphCommitNodeIndex{commitGraph, s}
}
func (gci *graphCommitNodeIndex) Get(hash plumbing.Hash) (CommitNode, error) {
if gci.commitGraph != nil {
// Check the commit graph first
parentIndex, err := gci.commitGraph.GetIndexByHash(hash)
if err == nil {
parent, err := gci.commitGraph.GetCommitDataByIndex(parentIndex)
if err != nil {
return nil, err
}
return &graphCommitNode{
hash: hash,
index: parentIndex,
commitData: parent,
gci: gci,
}, nil
}
}
// Fallback to loading full commit object
commit, err := object.GetCommit(gci.s, hash)
if err != nil {
return nil, err
}
return &objectCommitNode{
nodeIndex: gci,
commit: commit,
}, nil
}
func (c *graphCommitNode) ID() plumbing.Hash {
return c.hash
}
func (c *graphCommitNode) Tree() (*object.Tree, error) {
return object.GetTree(c.gci.s, c.commitData.TreeHash)
}
func (c *graphCommitNode) CommitTime() time.Time {
return c.commitData.When
}
func (c *graphCommitNode) NumParents() int {
return len(c.commitData.ParentIndexes)
}
func (c *graphCommitNode) ParentNodes() CommitNodeIter {
return newParentgraphCommitNodeIter(c)
}
func (c *graphCommitNode) ParentNode(i int) (CommitNode, error) {
if i < 0 || i >= len(c.commitData.ParentIndexes) {
return nil, object.ErrParentNotFound
}
parent, err := c.gci.commitGraph.GetCommitDataByIndex(c.commitData.ParentIndexes[i])
if err != nil {
return nil, err
}
return &graphCommitNode{
hash: c.commitData.ParentHashes[i],
index: c.commitData.ParentIndexes[i],
commitData: parent,
gci: c.gci,
}, nil
}
func (c *graphCommitNode) ParentHashes() []plumbing.Hash {
return c.commitData.ParentHashes
}
func (c *graphCommitNode) Generation() uint64 {
// If the commit-graph file was generated with older Git version that
// set the generation to zero for every commit the generation assumption
// is still valid. It is just less useful.
return c.commitData.Generation
}
func (c *graphCommitNode) GenerationV2() uint64 {
// If the commit-graph file was generated with older Git version that
// set the generation to zero for every commit the generation assumption
// is still valid. It is just less useful.
return c.commitData.GenerationV2
}
func (c *graphCommitNode) Commit() (*object.Commit, error) {
return object.GetCommit(c.gci.s, c.hash)
}
func (c *graphCommitNode) String() string {
return fmt.Sprintf(
"%s %s\nDate: %s",
plumbing.CommitObject, c.ID(),
c.CommitTime().Format(object.DateFormat),
)
}
|