1package commitgraph
2
3import (
4 "github.com/go-git/go-git/v5/plumbing"
5
6 "github.com/emirpasic/gods/trees/binaryheap"
7)
8
9// NewCommitNodeIterAuthorDateOrder returns a CommitNodeIter that walks the commit history,
10// starting at the given commit and visiting its parents in Author Time order but with the
11// constraint that no parent is emitted before its children are emitted.
12//
13// This matches `git log --author-order`
14//
15// This ordering requires that commit objects need to be loaded into memory - thus this
16// ordering is likely to be slower than other orderings.
17func NewCommitNodeIterAuthorDateOrder(c CommitNode,
18 seenExternal map[plumbing.Hash]bool,
19 ignore []plumbing.Hash,
20) CommitNodeIter {
21 seen := make(map[plumbing.Hash]struct{})
22 for _, h := range ignore {
23 seen[h] = struct{}{}
24 }
25 for h, ext := range seenExternal {
26 if ext {
27 seen[h] = struct{}{}
28 }
29 }
30 inCounts := make(map[plumbing.Hash]int)
31
32 exploreHeap := &commitNodeHeap{binaryheap.NewWith(generationAndDateOrderComparator)}
33 exploreHeap.Push(c)
34
35 visitHeap := &commitNodeHeap{binaryheap.NewWith(func(left, right interface{}) int {
36 leftCommit, err := left.(CommitNode).Commit()
37 if err != nil {
38 return -1
39 }
40 rightCommit, err := right.(CommitNode).Commit()
41 if err != nil {
42 return -1
43 }
44
45 switch {
46 case rightCommit.Author.When.Before(leftCommit.Author.When):
47 return -1
48 case leftCommit.Author.When.Before(rightCommit.Author.When):
49 return 1
50 }
51 return 0
52 })}
53 visitHeap.Push(c)
54
55 return &commitNodeIteratorTopological{
56 exploreStack: exploreHeap,
57 visitStack: visitHeap,
58 inCounts: inCounts,
59 ignore: seen,
60 }
61}