Skip to content

Commit 9b15518

Browse files
authored
Allow skipping an entry expansion in tree.Walk() (#838)
It is now possible to skip expanding an entry in `tree.Walk()` by returning `TreeWalkSkip`, in addition to stopping altogether by returning a non-nil error. Fixes: #837
1 parent c6da3b9 commit 9b15518

File tree

2 files changed

+90
-2
lines changed

2 files changed

+90
-2
lines changed

tree.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern int _go_git_treewalk(git_tree *tree, git_treewalk_mode mode, void *ptr);
88
import "C"
99

1010
import (
11+
"errors"
1112
"runtime"
1213
"unsafe"
1314
)
@@ -134,14 +135,29 @@ func treeWalkCallback(_root *C.char, entry *C.git_tree_entry, ptr unsafe.Pointer
134135
}
135136

136137
err := data.callback(C.GoString(_root), newTreeEntry(entry))
137-
if err != nil {
138+
if err == TreeWalkSkip {
139+
return C.int(1)
140+
} else if err != nil {
138141
*data.errorTarget = err
139142
return C.int(ErrorCodeUser)
140143
}
141144

142145
return C.int(ErrorCodeOK)
143146
}
144147

148+
// TreeWalkSkip is an error that can be returned form TreeWalkCallback to skip
149+
// a subtree from being expanded.
150+
var TreeWalkSkip = errors.New("skip")
151+
152+
// Walk traverses the entries in a tree and its subtrees in pre order.
153+
//
154+
// The entries will be traversed in the pre order, children subtrees will be
155+
// automatically loaded as required, and the callback will be called once per
156+
// entry with the current (relative) root for the entry and the entry data
157+
// itself.
158+
//
159+
// If the callback returns TreeWalkSkip, the passed entry will be skipped on
160+
// the traversal. Any other non-nil error stops the walk.
145161
func (t *Tree) Walk(callback TreeWalkCallback) error {
146162
var err error
147163
data := treeWalkCallbackData{

tree_test.go

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package git
22

3-
import "testing"
3+
import (
4+
"errors"
5+
"testing"
6+
)
47

58
func TestTreeEntryById(t *testing.T) {
69
t.Parallel()
@@ -63,3 +66,72 @@ func TestTreeBuilderInsert(t *testing.T) {
6366
t.Fatalf("got oid %v, want %v", entry.Id, blobId)
6467
}
6568
}
69+
70+
func TestTreeWalk(t *testing.T) {
71+
t.Parallel()
72+
repo, err := OpenRepository("testdata/TestGitRepository.git")
73+
checkFatal(t, err)
74+
treeID, err := NewOid("6020a3b8d5d636e549ccbd0c53e2764684bb3125")
75+
checkFatal(t, err)
76+
77+
tree, err := repo.LookupTree(treeID)
78+
checkFatal(t, err)
79+
80+
var callCount int
81+
err = tree.Walk(func(name string, entry *TreeEntry) error {
82+
callCount++
83+
84+
return nil
85+
})
86+
checkFatal(t, err)
87+
if callCount != 11 {
88+
t.Fatalf("got called %v times, want %v", callCount, 11)
89+
}
90+
}
91+
92+
func TestTreeWalkSkip(t *testing.T) {
93+
t.Parallel()
94+
repo, err := OpenRepository("testdata/TestGitRepository.git")
95+
checkFatal(t, err)
96+
treeID, err := NewOid("6020a3b8d5d636e549ccbd0c53e2764684bb3125")
97+
checkFatal(t, err)
98+
99+
tree, err := repo.LookupTree(treeID)
100+
checkFatal(t, err)
101+
102+
var callCount int
103+
err = tree.Walk(func(name string, entry *TreeEntry) error {
104+
callCount++
105+
106+
return TreeWalkSkip
107+
})
108+
checkFatal(t, err)
109+
if callCount != 4 {
110+
t.Fatalf("got called %v times, want %v", callCount, 4)
111+
}
112+
}
113+
114+
func TestTreeWalkStop(t *testing.T) {
115+
t.Parallel()
116+
repo, err := OpenRepository("testdata/TestGitRepository.git")
117+
checkFatal(t, err)
118+
treeID, err := NewOid("6020a3b8d5d636e549ccbd0c53e2764684bb3125")
119+
checkFatal(t, err)
120+
121+
tree, err := repo.LookupTree(treeID)
122+
checkFatal(t, err)
123+
124+
var callCount int
125+
stopError := errors.New("stop")
126+
err = tree.Walk(func(name string, entry *TreeEntry) error {
127+
callCount++
128+
129+
return stopError
130+
})
131+
if err != stopError {
132+
t.Fatalf("got error %v, want %v", err, stopError)
133+
}
134+
if callCount != 1 {
135+
t.Fatalf("got called %v times, want %v", callCount, 1)
136+
}
137+
}

0 commit comments

Comments
 (0)