aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/object/commitnode_walker_ctime.go
diff options
context:
space:
mode:
authorFilip Navara <filip.navara@gmail.com>2019-04-23 19:11:43 +0200
committerFilip Navara <filip.navara@gmail.com>2019-04-24 10:48:45 +0200
commitec65d90feaf3172a8bd1bf51bb85e7bdaaf28a54 (patch)
treef14412df58fb713e2b9698ebe2408ce4dfa82c40 /plumbing/object/commitnode_walker_ctime.go
parent4a6229296f5d8991d46e581d331e4e889a5a87ec (diff)
downloadgo-git-ec65d90feaf3172a8bd1bf51bb85e7bdaaf28a54.tar.gz
plumbing: object, add APIs for traversing over commit graphs
Signed-off-by: Filip Navara <filip.navara@gmail.com>
Diffstat (limited to 'plumbing/object/commitnode_walker_ctime.go')
-rw-r--r--plumbing/object/commitnode_walker_ctime.go108
1 files changed, 108 insertions, 0 deletions
diff --git a/plumbing/object/commitnode_walker_ctime.go b/plumbing/object/commitnode_walker_ctime.go
new file mode 100644
index 0000000..86b6c57
--- /dev/null
+++ b/plumbing/object/commitnode_walker_ctime.go
@@ -0,0 +1,108 @@
+package object
+
+import (
+ "io"
+
+ "github.com/emirpasic/gods/trees/binaryheap"
+
+ "gopkg.in/src-d/go-git.v4/plumbing"
+ "gopkg.in/src-d/go-git.v4/plumbing/storer"
+)
+
+type commitNodeIteratorByCTime struct {
+ heap *binaryheap.Heap
+ seenExternal map[plumbing.Hash]bool
+ seen map[plumbing.Hash]bool
+ nodeIndex CommitNodeIndex
+}
+
+// NewCommitNodeIterCTime returns a CommitNodeIter that walks the commit history,
+// starting at the given commit and visiting its parents while preserving Committer Time order.
+// this appears to be the closest order to `git log`
+// The given callback will be called for each visited commit. Each commit will
+// be visited only once. If the callback returns an error, walking will stop
+// and will return the error. Other errors might be returned if the history
+// cannot be traversed (e.g. missing objects). Ignore allows to skip some
+// commits from being iterated.
+func NewCommitNodeIterCTime(
+ c CommitNode,
+ nodeIndex CommitNodeIndex,
+ seenExternal map[plumbing.Hash]bool,
+ ignore []plumbing.Hash,
+) CommitNodeIter {
+ seen := make(map[plumbing.Hash]bool)
+ for _, h := range ignore {
+ seen[h] = true
+ }
+
+ heap := binaryheap.NewWith(func(a, b interface{}) int {
+ if a.(CommitNode).CommitTime().Before(b.(CommitNode).CommitTime()) {
+ return 1
+ }
+ return -1
+ })
+
+ heap.Push(c)
+
+ return &commitNodeIteratorByCTime{
+ heap: heap,
+ seenExternal: seenExternal,
+ seen: seen,
+ nodeIndex: nodeIndex,
+ }
+}
+
+func (w *commitNodeIteratorByCTime) Next() (CommitNode, error) {
+ var c CommitNode
+ for {
+ cIn, ok := w.heap.Pop()
+ if !ok {
+ return nil, io.EOF
+ }
+ c = cIn.(CommitNode)
+ cID := c.ID()
+
+ if w.seen[cID] || w.seenExternal[cID] {
+ continue
+ }
+
+ w.seen[cID] = true
+
+ for i, h := range w.nodeIndex.ParentHashes(c) {
+ if w.seen[h] || w.seenExternal[h] {
+ continue
+ }
+ pc, err := w.nodeIndex.ParentNode(c, i)
+ if err != nil {
+ return nil, err
+ }
+ w.heap.Push(pc)
+ }
+
+ return c, nil
+ }
+}
+
+func (w *commitNodeIteratorByCTime) ForEach(cb func(CommitNode) error) error {
+ for {
+ c, err := w.Next()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ err = cb(c)
+ if err == storer.ErrStop {
+ break
+ }
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (w *commitNodeIteratorByCTime) Close() {}