Add support for Repository.ReachableFromAny() (#826)

This change exposes the binding for `git_graph_reachable_from_any()`.
This commit is contained in:
lhchavez 2021-09-05 20:06:56 -07:00 committed by GitHub
parent 922f2f7487
commit c8ce59d4eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 0 deletions

View File

@ -40,3 +40,30 @@ func (repo *Repository) AheadBehind(local, upstream *Oid) (ahead, behind int, er
return int(aheadT), int(behindT), nil return int(aheadT), int(behindT), nil
} }
// ReachableFromAny returns whether a commit is reachable from any of a list of
// commits by following parent edges.
func (repo *Repository) ReachableFromAny(commit *Oid, descendants []*Oid) (bool, error) {
if len(descendants) == 0 {
return false, nil
}
coids := make([]C.git_oid, len(descendants))
for i := 0; i < len(descendants); i++ {
coids[i] = *descendants[i].toC()
}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_graph_reachable_from_any(repo.ptr, commit.toC(), &coids[0], C.size_t(len(descendants)))
runtime.KeepAlive(repo)
runtime.KeepAlive(commit)
runtime.KeepAlive(coids)
runtime.KeepAlive(descendants)
if ret < 0 {
return false, MakeGitError(ret)
}
return (ret > 0), nil
}

75
graph_test.go Normal file
View File

@ -0,0 +1,75 @@
package git
import (
"testing"
)
func TestReachableFromAny(t *testing.T) {
repo, err := OpenRepository("testdata/TestGitRepository.git")
checkFatal(t, err)
defer repo.Free()
for name, tc := range map[string]struct {
reachable bool
commit string
descendants []string
}{
"empty": {
reachable: false,
commit: "49322bb17d3acc9146f98c97d078513228bbf3c0",
},
"same": {
reachable: true,
commit: "49322bb17d3acc9146f98c97d078513228bbf3c0",
descendants: []string{"49322bb17d3acc9146f98c97d078513228bbf3c0"},
},
"unreachable": {
reachable: false,
commit: "ac7e7e44c1885efb472ad54a78327d66bfc4ecef",
descendants: []string{"58be4659bb571194ed4562d04b359d26216f526e"},
},
"unreachable-reverse": {
reachable: false,
commit: "58be4659bb571194ed4562d04b359d26216f526e",
descendants: []string{"ac7e7e44c1885efb472ad54a78327d66bfc4ecef"},
},
"root": {
reachable: false,
commit: "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1",
descendants: []string{
"ac7e7e44c1885efb472ad54a78327d66bfc4ecef",
"d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864",
"f73b95671f326616d66b2afb3bdfcdbbce110b44",
"d0114ab8ac326bab30e3a657a0397578c5a1af88",
},
},
"head": {
reachable: false,
commit: "49322bb17d3acc9146f98c97d078513228bbf3c0",
descendants: []string{
"ac7e7e44c1885efb472ad54a78327d66bfc4ecef",
"d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864",
"f73b95671f326616d66b2afb3bdfcdbbce110b44",
"d0114ab8ac326bab30e3a657a0397578c5a1af88",
},
},
} {
tc := tc
t.Run(name, func(t *testing.T) {
commit, err := NewOid(tc.commit)
checkFatal(t, err)
descendants := make([]*Oid, len(tc.descendants))
for i, o := range tc.descendants {
descendants[i], err = NewOid(o)
checkFatal(t, err)
}
reachable, err := repo.ReachableFromAny(commit, descendants)
checkFatal(t, err)
if reachable != tc.reachable {
t.Errorf("ReachableFromAny(%s, %v) = %v, wanted %v", tc.commit, tc.descendants, reachable, tc.reachable)
}
})
}
}