fork of go-git with some jj specific features
at main 2.3 kB view raw
1package commitgraph 2 3import ( 4 "io" 5 6 "github.com/go-git/go-git/v5/plumbing" 7 "github.com/go-git/go-git/v5/plumbing/storer" 8 9 "github.com/emirpasic/gods/trees/binaryheap" 10) 11 12type commitNodeIteratorByCTime struct { 13 heap *binaryheap.Heap 14 seenExternal map[plumbing.Hash]bool 15 seen map[plumbing.Hash]bool 16} 17 18// NewCommitNodeIterCTime returns a CommitNodeIter that walks the commit history, 19// starting at the given commit and visiting its parents while preserving Committer Time order. 20// this is close in order to `git log` but does not guarantee topological order and will 21// order things incorrectly occasionally. 22// The given callback will be called for each visited commit. Each commit will 23// be visited only once. If the callback returns an error, walking will stop 24// and will return the error. Other errors might be returned if the history 25// cannot be traversed (e.g. missing objects). Ignore allows to skip some 26// commits from being iterated. 27func NewCommitNodeIterCTime( 28 c CommitNode, 29 seenExternal map[plumbing.Hash]bool, 30 ignore []plumbing.Hash, 31) CommitNodeIter { 32 seen := make(map[plumbing.Hash]bool) 33 for _, h := range ignore { 34 seen[h] = true 35 } 36 37 heap := binaryheap.NewWith(func(a, b interface{}) int { 38 if a.(CommitNode).CommitTime().Before(b.(CommitNode).CommitTime()) { 39 return 1 40 } 41 return -1 42 }) 43 44 heap.Push(c) 45 46 return &commitNodeIteratorByCTime{ 47 heap: heap, 48 seenExternal: seenExternal, 49 seen: seen, 50 } 51} 52 53func (w *commitNodeIteratorByCTime) Next() (CommitNode, error) { 54 var c CommitNode 55 for { 56 cIn, ok := w.heap.Pop() 57 if !ok { 58 return nil, io.EOF 59 } 60 c = cIn.(CommitNode) 61 cID := c.ID() 62 63 if w.seen[cID] || w.seenExternal[cID] { 64 continue 65 } 66 67 w.seen[cID] = true 68 69 for i, h := range c.ParentHashes() { 70 if w.seen[h] || w.seenExternal[h] { 71 continue 72 } 73 pc, err := c.ParentNode(i) 74 if err != nil { 75 return nil, err 76 } 77 w.heap.Push(pc) 78 } 79 80 return c, nil 81 } 82} 83 84func (w *commitNodeIteratorByCTime) ForEach(cb func(CommitNode) error) error { 85 for { 86 c, err := w.Next() 87 if err == io.EOF { 88 break 89 } 90 if err != nil { 91 return err 92 } 93 94 err = cb(c) 95 if err == storer.ErrStop { 96 break 97 } 98 if err != nil { 99 return err 100 } 101 } 102 103 return nil 104} 105 106func (w *commitNodeIteratorByCTime) Close() {}