Merge pull request #466 from lhchavez/repository-create_commit_from_ids
Add support for CreateCommitFromIds
(cherry picked from commit 8766f9f36c
)
This commit is contained in:
parent
9fd0d987ae
commit
c1c2b5a730
|
@ -3,6 +3,8 @@ package git
|
||||||
/*
|
/*
|
||||||
#include <git2.h>
|
#include <git2.h>
|
||||||
#include <git2/sys/repository.h>
|
#include <git2/sys/repository.h>
|
||||||
|
#include <git2/sys/commit.h>
|
||||||
|
#include <string.h>
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
|
@ -389,6 +391,74 @@ func (v *Repository) CreateCommit(
|
||||||
return oid, nil
|
return oid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *Repository) CreateCommitFromIds(
|
||||||
|
refname string, author, committer *Signature,
|
||||||
|
message string, tree *Oid, parents ...*Oid) (*Oid, error) {
|
||||||
|
|
||||||
|
oid := new(Oid)
|
||||||
|
|
||||||
|
var cref *C.char
|
||||||
|
if refname == "" {
|
||||||
|
cref = nil
|
||||||
|
} else {
|
||||||
|
cref = C.CString(refname)
|
||||||
|
defer C.free(unsafe.Pointer(cref))
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsg := C.CString(message)
|
||||||
|
defer C.free(unsafe.Pointer(cmsg))
|
||||||
|
|
||||||
|
var parentsarg **C.git_oid = nil
|
||||||
|
|
||||||
|
nparents := len(parents)
|
||||||
|
if nparents > 0 {
|
||||||
|
// All this awful pointer arithmetic is needed to avoid passing a Go
|
||||||
|
// pointer to Go pointer into C. Other methods (like CreateCommits) are
|
||||||
|
// fine without this workaround because they are just passing Go pointers
|
||||||
|
// to C pointers, but arrays-of-pointers-to-git_oid are a bit special since
|
||||||
|
// both the array and the objects are allocated from Go.
|
||||||
|
var emptyOidPtr *C.git_oid
|
||||||
|
sizeofOidPtr := unsafe.Sizeof(emptyOidPtr)
|
||||||
|
parentsarg = (**C.git_oid)(C.calloc(C.size_t(uintptr(nparents)), C.size_t(sizeofOidPtr)))
|
||||||
|
defer C.free(unsafe.Pointer(parentsarg))
|
||||||
|
parentsptr := uintptr(unsafe.Pointer(parentsarg))
|
||||||
|
for _, v := range parents {
|
||||||
|
*(**C.git_oid)(unsafe.Pointer(parentsptr)) = v.toC()
|
||||||
|
parentsptr += sizeofOidPtr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authorSig, err := author.toC()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer C.git_signature_free(authorSig)
|
||||||
|
|
||||||
|
committerSig, err := committer.toC()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer C.git_signature_free(committerSig)
|
||||||
|
|
||||||
|
runtime.LockOSThread()
|
||||||
|
defer runtime.UnlockOSThread()
|
||||||
|
|
||||||
|
ret := C.git_commit_create_from_ids(
|
||||||
|
oid.toC(), v.ptr, cref,
|
||||||
|
authorSig, committerSig,
|
||||||
|
nil, cmsg, tree.toC(), C.size_t(nparents), parentsarg)
|
||||||
|
|
||||||
|
runtime.KeepAlive(v)
|
||||||
|
runtime.KeepAlive(oid)
|
||||||
|
runtime.KeepAlive(tree)
|
||||||
|
runtime.KeepAlive(parents)
|
||||||
|
if ret < 0 {
|
||||||
|
return nil, MakeGitError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
return oid, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (v *Odb) Free() {
|
func (v *Odb) Free() {
|
||||||
runtime.SetFinalizer(v, nil)
|
runtime.SetFinalizer(v, nil)
|
||||||
C.git_odb_free(v.ptr)
|
C.git_odb_free(v.ptr)
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCreateCommitFromIds(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
repo := createTestRepo(t)
|
||||||
|
defer cleanupTestRepo(t, repo)
|
||||||
|
|
||||||
|
loc, err := time.LoadLocation("Europe/Berlin")
|
||||||
|
checkFatal(t, err)
|
||||||
|
sig := &Signature{
|
||||||
|
Name: "Rand Om Hacker",
|
||||||
|
Email: "random@hacker.com",
|
||||||
|
When: time.Date(2013, 03, 06, 14, 30, 0, 0, loc),
|
||||||
|
}
|
||||||
|
|
||||||
|
idx, err := repo.Index()
|
||||||
|
checkFatal(t, err)
|
||||||
|
err = idx.AddByPath("README")
|
||||||
|
checkFatal(t, err)
|
||||||
|
err = idx.Write()
|
||||||
|
checkFatal(t, err)
|
||||||
|
treeId, err := idx.WriteTree()
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
message := "This is a commit\n"
|
||||||
|
tree, err := repo.LookupTree(treeId)
|
||||||
|
checkFatal(t, err)
|
||||||
|
expectedCommitId, err := repo.CreateCommit("HEAD", sig, sig, message, tree)
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
commitId, err := repo.CreateCommitFromIds("", sig, sig, message, treeId)
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
if !expectedCommitId.Equal(commitId) {
|
||||||
|
t.Errorf("mismatched commit ids, expected %v, got %v", expectedCommitId.String(), commitId.String())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue