Skip to content

Commit f505e39

Browse files
committed
Add a test and some comments as to the ugly pointer arithmetic
1 parent 8ff5e43 commit f505e39

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed

repository.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,12 +412,19 @@ func (v *Repository) CreateCommitFromIds(
412412

413413
nparents := len(parents)
414414
if nparents > 0 {
415-
parentsarg = (**C.git_oid)(C.malloc(C.size_t(unsafe.Sizeof(uintptr(0)) * uintptr(nparents))))
415+
// All this awful pointer arithmetic is needed to avoid passing a Go
416+
// pointer to Go pointer into C. Other methods (like CreateCommits) are
417+
// fine without this workaround because they are just passing Go pointers
418+
// to C pointers, but arrays-of-pointers-to-git_oid are a bit special since
419+
// both the array and the objects are allocated from Go.
420+
var emptyOidPtr *C.git_oid
421+
sizeofOidPtr := unsafe.Sizeof(emptyOidPtr)
422+
parentsarg = (**C.git_oid)(C.calloc(C.size_t(uintptr(nparents)), C.size_t(sizeofOidPtr)))
416423
defer C.free(unsafe.Pointer(parentsarg))
417424
parentsptr := uintptr(unsafe.Pointer(parentsarg))
418425
for _, v := range parents {
419426
*(**C.git_oid)(unsafe.Pointer(parentsptr)) = v.toC()
420-
parentsptr += unsafe.Sizeof(uintptr(0))
427+
parentsptr += sizeofOidPtr
421428
}
422429
}
423430

repository_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package git
2+
3+
import (
4+
"testing"
5+
"time"
6+
)
7+
8+
func TestCreateCommitFromIds(t *testing.T) {
9+
t.Parallel()
10+
repo := createTestRepo(t)
11+
defer cleanupTestRepo(t, repo)
12+
13+
loc, err := time.LoadLocation("Europe/Berlin")
14+
checkFatal(t, err)
15+
sig := &Signature{
16+
Name: "Rand Om Hacker",
17+
18+
When: time.Date(2013, 03, 06, 14, 30, 0, 0, loc),
19+
}
20+
21+
idx, err := repo.Index()
22+
checkFatal(t, err)
23+
err = idx.AddByPath("README")
24+
checkFatal(t, err)
25+
err = idx.Write()
26+
checkFatal(t, err)
27+
treeId, err := idx.WriteTree()
28+
checkFatal(t, err)
29+
30+
message := "This is a commit\n"
31+
tree, err := repo.LookupTree(treeId)
32+
checkFatal(t, err)
33+
expectedCommitId, err := repo.CreateCommit("HEAD", sig, sig, message, tree)
34+
checkFatal(t, err)
35+
36+
commitId, err := repo.CreateCommitFromIds("", sig, sig, message, treeId)
37+
checkFatal(t, err)
38+
39+
if !expectedCommitId.Equal(commitId) {
40+
t.Errorf("mismatched commit ids, expected %v, got %v", expectedCommitId.String(), commitId.String())
41+
}
42+
}

0 commit comments

Comments
 (0)