fork of go-git with some jj specific features
at main 3.9 kB view raw
1package commitgraph 2 3import ( 4 "fmt" 5 "time" 6 7 "github.com/go-git/go-git/v5/plumbing" 8 commitgraph "github.com/go-git/go-git/v5/plumbing/format/commitgraph/v2" 9 "github.com/go-git/go-git/v5/plumbing/object" 10 "github.com/go-git/go-git/v5/plumbing/storer" 11) 12 13// graphCommitNode is a reduced representation of Commit as presented in the commit 14// graph file (commitgraph.Node). It is merely useful as an optimization for walking 15// the commit graphs. 16// 17// graphCommitNode implements the CommitNode interface. 18type graphCommitNode struct { 19 // Hash for the Commit object 20 hash plumbing.Hash 21 // Index of the node in the commit graph file 22 index uint32 23 24 commitData *commitgraph.CommitData 25 gci *graphCommitNodeIndex 26} 27 28// graphCommitNodeIndex is an index that can load CommitNode objects from both the commit 29// graph files and the object store. 30// 31// graphCommitNodeIndex implements the CommitNodeIndex interface 32type graphCommitNodeIndex struct { 33 commitGraph commitgraph.Index 34 s storer.EncodedObjectStorer 35} 36 37// NewGraphCommitNodeIndex returns CommitNodeIndex implementation that uses commit-graph 38// files as backing storage and falls back to object storage when necessary 39func NewGraphCommitNodeIndex(commitGraph commitgraph.Index, s storer.EncodedObjectStorer) CommitNodeIndex { 40 return &graphCommitNodeIndex{commitGraph, s} 41} 42 43func (gci *graphCommitNodeIndex) Get(hash plumbing.Hash) (CommitNode, error) { 44 if gci.commitGraph != nil { 45 // Check the commit graph first 46 parentIndex, err := gci.commitGraph.GetIndexByHash(hash) 47 if err == nil { 48 parent, err := gci.commitGraph.GetCommitDataByIndex(parentIndex) 49 if err != nil { 50 return nil, err 51 } 52 53 return &graphCommitNode{ 54 hash: hash, 55 index: parentIndex, 56 commitData: parent, 57 gci: gci, 58 }, nil 59 } 60 } 61 62 // Fallback to loading full commit object 63 commit, err := object.GetCommit(gci.s, hash) 64 if err != nil { 65 return nil, err 66 } 67 68 return &objectCommitNode{ 69 nodeIndex: gci, 70 commit: commit, 71 }, nil 72} 73 74func (c *graphCommitNode) ID() plumbing.Hash { 75 return c.hash 76} 77 78func (c *graphCommitNode) Tree() (*object.Tree, error) { 79 return object.GetTree(c.gci.s, c.commitData.TreeHash) 80} 81 82func (c *graphCommitNode) CommitTime() time.Time { 83 return c.commitData.When 84} 85 86func (c *graphCommitNode) NumParents() int { 87 return len(c.commitData.ParentIndexes) 88} 89 90func (c *graphCommitNode) ParentNodes() CommitNodeIter { 91 return newParentgraphCommitNodeIter(c) 92} 93 94func (c *graphCommitNode) ParentNode(i int) (CommitNode, error) { 95 if i < 0 || i >= len(c.commitData.ParentIndexes) { 96 return nil, object.ErrParentNotFound 97 } 98 99 parent, err := c.gci.commitGraph.GetCommitDataByIndex(c.commitData.ParentIndexes[i]) 100 if err != nil { 101 return nil, err 102 } 103 104 return &graphCommitNode{ 105 hash: c.commitData.ParentHashes[i], 106 index: c.commitData.ParentIndexes[i], 107 commitData: parent, 108 gci: c.gci, 109 }, nil 110} 111 112func (c *graphCommitNode) ParentHashes() []plumbing.Hash { 113 return c.commitData.ParentHashes 114} 115 116func (c *graphCommitNode) Generation() uint64 { 117 // If the commit-graph file was generated with older Git version that 118 // set the generation to zero for every commit the generation assumption 119 // is still valid. It is just less useful. 120 return c.commitData.Generation 121} 122 123func (c *graphCommitNode) GenerationV2() uint64 { 124 // If the commit-graph file was generated with older Git version that 125 // set the generation to zero for every commit the generation assumption 126 // is still valid. It is just less useful. 127 return c.commitData.GenerationV2 128} 129 130func (c *graphCommitNode) Commit() (*object.Commit, error) { 131 return object.GetCommit(c.gci.s, c.hash) 132} 133 134func (c *graphCommitNode) String() string { 135 return fmt.Sprintf( 136 "%s %s\nDate: %s", 137 plumbing.CommitObject, c.ID(), 138 c.CommitTime().Format(object.DateFormat), 139 ) 140}