Skip to content

Commit c8ce59d

Browse files
authored
Add support for Repository.ReachableFromAny() (#826)
This change exposes the binding for `git_graph_reachable_from_any()`.
1 parent 922f2f7 commit c8ce59d

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

graph.go

+27
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,30 @@ func (repo *Repository) AheadBehind(local, upstream *Oid) (ahead, behind int, er
4040

4141
return int(aheadT), int(behindT), nil
4242
}
43+
44+
// ReachableFromAny returns whether a commit is reachable from any of a list of
45+
// commits by following parent edges.
46+
func (repo *Repository) ReachableFromAny(commit *Oid, descendants []*Oid) (bool, error) {
47+
if len(descendants) == 0 {
48+
return false, nil
49+
}
50+
51+
coids := make([]C.git_oid, len(descendants))
52+
for i := 0; i < len(descendants); i++ {
53+
coids[i] = *descendants[i].toC()
54+
}
55+
56+
runtime.LockOSThread()
57+
defer runtime.UnlockOSThread()
58+
59+
ret := C.git_graph_reachable_from_any(repo.ptr, commit.toC(), &coids[0], C.size_t(len(descendants)))
60+
runtime.KeepAlive(repo)
61+
runtime.KeepAlive(commit)
62+
runtime.KeepAlive(coids)
63+
runtime.KeepAlive(descendants)
64+
if ret < 0 {
65+
return false, MakeGitError(ret)
66+
}
67+
68+
return (ret > 0), nil
69+
}

graph_test.go

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package git
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestReachableFromAny(t *testing.T) {
8+
repo, err := OpenRepository("testdata/TestGitRepository.git")
9+
checkFatal(t, err)
10+
defer repo.Free()
11+
12+
for name, tc := range map[string]struct {
13+
reachable bool
14+
commit string
15+
descendants []string
16+
}{
17+
"empty": {
18+
reachable: false,
19+
commit: "49322bb17d3acc9146f98c97d078513228bbf3c0",
20+
},
21+
"same": {
22+
reachable: true,
23+
commit: "49322bb17d3acc9146f98c97d078513228bbf3c0",
24+
descendants: []string{"49322bb17d3acc9146f98c97d078513228bbf3c0"},
25+
},
26+
"unreachable": {
27+
reachable: false,
28+
commit: "ac7e7e44c1885efb472ad54a78327d66bfc4ecef",
29+
descendants: []string{"58be4659bb571194ed4562d04b359d26216f526e"},
30+
},
31+
"unreachable-reverse": {
32+
reachable: false,
33+
commit: "58be4659bb571194ed4562d04b359d26216f526e",
34+
descendants: []string{"ac7e7e44c1885efb472ad54a78327d66bfc4ecef"},
35+
},
36+
"root": {
37+
reachable: false,
38+
commit: "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1",
39+
descendants: []string{
40+
"ac7e7e44c1885efb472ad54a78327d66bfc4ecef",
41+
"d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864",
42+
"f73b95671f326616d66b2afb3bdfcdbbce110b44",
43+
"d0114ab8ac326bab30e3a657a0397578c5a1af88",
44+
},
45+
},
46+
"head": {
47+
reachable: false,
48+
commit: "49322bb17d3acc9146f98c97d078513228bbf3c0",
49+
descendants: []string{
50+
"ac7e7e44c1885efb472ad54a78327d66bfc4ecef",
51+
"d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864",
52+
"f73b95671f326616d66b2afb3bdfcdbbce110b44",
53+
"d0114ab8ac326bab30e3a657a0397578c5a1af88",
54+
},
55+
},
56+
} {
57+
tc := tc
58+
t.Run(name, func(t *testing.T) {
59+
commit, err := NewOid(tc.commit)
60+
checkFatal(t, err)
61+
62+
descendants := make([]*Oid, len(tc.descendants))
63+
for i, o := range tc.descendants {
64+
descendants[i], err = NewOid(o)
65+
checkFatal(t, err)
66+
}
67+
reachable, err := repo.ReachableFromAny(commit, descendants)
68+
checkFatal(t, err)
69+
70+
if reachable != tc.reachable {
71+
t.Errorf("ReachableFromAny(%s, %v) = %v, wanted %v", tc.commit, tc.descendants, reachable, tc.reachable)
72+
}
73+
})
74+
}
75+
}

0 commit comments

Comments
 (0)