Commit 1ad35fd4 authored by Maximiliano Curia's avatar Maximiliano Curia

Update upstream source from tag 'upstream/0.26+git20170902.0.eb0bf212'

Update to upstream version '0.26+git20170902.0.eb0bf212'
with Debian dir 65c010ff038bacee7a67540a73477780f3336fa8
parents 2fa17d3b 7bacee4b
[submodule "vendor/libgit2"]
path = vendor/libgit2
url = https://github.com/libgit2/libgit2
language: go
sudo: required
install: ./script/install-libgit2.sh
go:
- 1.1
- 1.2
- 1.3
- 1.4
- 1.5
- 1.6
- 1.7
- 1.8
- tip
script: make test-static
matrix:
allow_failures:
- go: tip
git:
submodules: false
before_install:
- git submodule update --init
branches:
only:
- master
- /v\d+/
- next
default: test
test:
test: build-libgit2
go run script/check-MakeGitError-thread-lock.go
go test ./...
install:
install: build-libgit2
go install ./...
build-libgit2:
./script/build-libgit2-static.sh
install-static: build-libgit2
go install --tags "static" ./...
test-static: build-libgit2
go run script/check-MakeGitError-thread-lock.go
go test --tags "static" ./...
......@@ -2,57 +2,59 @@ git2go
======
[![GoDoc](https://godoc.org/github.com/libgit2/git2go?status.svg)](http://godoc.org/github.com/libgit2/git2go) [![Build Status](https://travis-ci.org/libgit2/git2go.svg?branch=master)](https://travis-ci.org/libgit2/git2go)
Go bindings for [libgit2](http://libgit2.github.com/).
Go bindings for [libgit2](http://libgit2.github.com/). The `master` branch follows the latest libgit2 release. The versioned branches indicate which libgit2 version they work against.
### Which branch to use
Installing
----------
The numbered branches work against the version of libgit2 as specified by their number. You can import them in your project via gopkg.in, e.g. if you have libgit2 v0.25 installed you'd import with
This project wraps the functionality provided by libgit2. If you're using a stable version, install it to your system via your system's package manager and then install git2go as usual.
import "gopkg.in/libgit2/git2go.v25"
Otherwise (`next` which tracks an unstable version), we need to build libgit2 as well. In order to build it, you need `cmake`, `pkg-config` and a C compiler. You will also need the development packages for OpenSSL and LibSSH2 installed if you want libgit2 to support HTTPS and SSH respectively.
which will ensure there are no sudden changes to the API.
### Stable version
The `master` branch follows the tip of libgit2 itself (with some lag) and as such has no guarantees on its own API nor does it have expectations the stability of libgit2's. Thus this only supports statically linking against libgit2.
git2go has `master` which tracks the latest release of libgit2, and versioned branches which indicate which version of libgit2 they work against. Install the development package on your system via your favourite package manager or from source and you can use a service like gopkg.in to use the appropriate version. For the libgit2 v0.22 case, you can use
Installing
----------
import "gopkg.in/libgit2/git2go.v22"
This project wraps the functionality provided by libgit2. It thus needs it in order to perform the work.
to use a version of git2go which will work against libgit2 v0.22 and dynamically link to the library. You can use
This project wraps the functionality provided by libgit2. If you're using a versioned branch, install it to your system via your system's package manager and then install git2go.
import "github.com/libgit2/git2go"
to use the version which works against the latest release.
### Versioned branch, dynamic linking
### From `next`
When linking dynamically against a released version of libgit2, install it via your system's package manager. CGo will take care of finding its pkg-config file and set up the linking. Import via gopkg.in, e.g. to work against libgit2 v0.25
The `next` branch follows libgit2's master branch, which means there is no stable API or ABI to link against. git2go can statically link against a vendored version of libgit2.
import "gopkg.in/libgit2/git2go.v25"
### Master branch, or static linking
If using `master` or building a branch statically, we need to build libgit2 first. In order to build it, you need `cmake`, `pkg-config` and a C compiler. You will also need the development packages for OpenSSL (outside of Windows or macOS) and LibSSH2 installed if you want libgit2 to support HTTPS and SSH respectively. Note that even if libgit2 is included in the resulting binary, its dependencies will not be.
Run `go get -d github.com/libgit2/git2go` to download the code and go to your `$GOPATH/src/github.com/libgit2/git2go` directory. From there, we need to build the C code and put it into the resulting go binary.
git checkout next
git submodule update --init # get libgit2
make install
will compile libgit2. Run `go install` so that it's statically linked to the git2go package.
will compile libgit2, link it into git2go and install it.
Parallelism and network operations
----------------------------------
libgit2 uses OpenSSL and LibSSH2 for performing encrypted network connections. For now, git2go asks libgit2 to set locking for OpenSSL. This makes HTTPS connections thread-safe, but it is fragile and will likely stop doing it soon. This may also make SSH connections thread-safe if your copy of libssh2 is linked against OpenSSL. Check libgit2's `THREADSAFE.md` for more information.
libgit2 may use OpenSSL and LibSSH2 for performing encrypted network connections. For now, git2go asks libgit2 to set locking for OpenSSL. This makes HTTPS connections thread-safe, but it is fragile and will likely stop doing it soon. This may also make SSH connections thread-safe if your copy of libssh2 is linked against OpenSSL. Check libgit2's `THREADSAFE.md` for more information.
Running the tests
-----------------
For the stable version, `go test` will work as usual. For the `next` branch, similarly to installing, running the tests requires linking against the local libgit2 library, so the Makefile provides a wrapper
For the stable version, `go test` will work as usual. For the `next` branch, similarly to installing, running the tests requires building a local libgit2 library, so the Makefile provides a wrapper that makes sure it's built
make test
Alternatively, if you want to pass arguments to `go test`, you can use the script that sets it all up
./script/with-static.sh go test -v
Alternatively, you can build the library manually first and then run the tests
which will run the specified arguments with the correct environment variables.
./script/build-libgit2-static.sh
go test -v
License
-------
......
......@@ -76,6 +76,7 @@ func (v *Repository) BlameFile(path string, opts *BlameOptions) (*Blame, error)
defer runtime.UnlockOSThread()
ecode := C.git_blame_file(&blamePtr, v.ptr, cpath, copts)
runtime.KeepAlive(v)
if ecode < 0 {
return nil, MakeGitError(ecode)
}
......@@ -88,11 +89,15 @@ type Blame struct {
}
func (blame *Blame) HunkCount() int {
return int(C.git_blame_get_hunk_count(blame.ptr))
ret := int(C.git_blame_get_hunk_count(blame.ptr))
runtime.KeepAlive(blame)
return ret
}
func (blame *Blame) HunkByIndex(index int) (BlameHunk, error) {
ptr := C.git_blame_get_hunk_byindex(blame.ptr, C.uint32_t(index))
runtime.KeepAlive(blame)
if ptr == nil {
return BlameHunk{}, ErrInvalid
}
......@@ -101,6 +106,7 @@ func (blame *Blame) HunkByIndex(index int) (BlameHunk, error) {
func (blame *Blame) HunkByLine(lineno int) (BlameHunk, error) {
ptr := C.git_blame_get_hunk_byline(blame.ptr, C.size_t(lineno))
runtime.KeepAlive(blame)
if ptr == nil {
return BlameHunk{}, ErrInvalid
}
......
......@@ -4,15 +4,13 @@ package git
#include <git2.h>
#include <string.h>
extern int _go_git_blob_create_fromchunks(git_oid *id,
git_repository *repo,
const char *hintpath,
void *payload);
int _go_git_writestream_write(git_writestream *stream, const char *buffer, size_t len);
void _go_git_writestream_free(git_writestream *stream);
*/
import "C"
import (
"io"
"reflect"
"runtime"
"unsafe"
)
......@@ -23,13 +21,19 @@ type Blob struct {
}
func (v *Blob) Size() int64 {
return int64(C.git_blob_rawsize(v.cast_ptr))
ret := int64(C.git_blob_rawsize(v.cast_ptr))
runtime.KeepAlive(v)
return ret
}
func (v *Blob) Contents() []byte {
size := C.int(C.git_blob_rawsize(v.cast_ptr))
buffer := unsafe.Pointer(C.git_blob_rawcontent(v.cast_ptr))
return C.GoBytes(buffer, size)
goBytes := C.GoBytes(buffer, size)
runtime.KeepAlive(v)
return goBytes
}
func (repo *Repository) CreateBlobFromBuffer(data []byte) (*Oid, error) {
......@@ -55,6 +59,7 @@ func (repo *Repository) CreateBlobFromBuffer(data []byte) (*Oid, error) {
}
ecode := C.git_blob_create_frombuffer(&id, repo.ptr, unsafe.Pointer(&data[0]), size)
runtime.KeepAlive(repo)
if ecode < 0 {
return nil, MakeGitError(ecode)
}
......@@ -87,27 +92,75 @@ func blobChunkCb(buffer *C.char, maxLen C.size_t, handle unsafe.Pointer) int {
return len(goBuf)
}
func (repo *Repository) CreateBlobFromChunks(hintPath string, callback BlobChunkCallback) (*Oid, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
func (repo *Repository) CreateFromStream(hintPath string) (*BlobWriteStream, error) {
var chintPath *C.char = nil
var stream *C.git_writestream
if len(hintPath) > 0 {
chintPath = C.CString(hintPath)
defer C.free(unsafe.Pointer(chintPath))
}
oid := C.git_oid{}
payload := &BlobCallbackData{Callback: callback}
handle := pointerHandles.Track(payload)
defer pointerHandles.Untrack(handle)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_blob_create_fromstream(&stream, repo.ptr, chintPath)
if ecode < 0 {
return nil, MakeGitError(ecode)
}
return newBlobWriteStreamFromC(stream, repo), nil
}
type BlobWriteStream struct {
ptr *C.git_writestream
repo *Repository
}
func newBlobWriteStreamFromC(ptr *C.git_writestream, repo *Repository) *BlobWriteStream {
stream := &BlobWriteStream{
ptr: ptr,
repo: repo,
}
runtime.SetFinalizer(stream, (*BlobWriteStream).Free)
return stream
}
// Implement io.Writer
func (stream *BlobWriteStream) Write(p []byte) (int, error) {
header := (*reflect.SliceHeader)(unsafe.Pointer(&p))
ptr := (*C.char)(unsafe.Pointer(header.Data))
size := C.size_t(header.Len)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C._go_git_blob_create_fromchunks(&oid, repo.ptr, chintPath, handle)
if payload.Error != nil {
return nil, payload.Error
ecode := C._go_git_writestream_write(stream.ptr, ptr, size)
runtime.KeepAlive(stream)
if ecode < 0 {
return 0, MakeGitError(ecode)
}
return len(p), nil
}
func (stream *BlobWriteStream) Free() {
runtime.SetFinalizer(stream, nil)
C._go_git_writestream_free(stream.ptr)
}
func (stream *BlobWriteStream) Commit() (*Oid, error) {
oid := C.git_oid{}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_blob_create_fromstream_commit(&oid, stream.ptr)
runtime.KeepAlive(stream)
if ecode < 0 {
return nil, MakeGitError(ecode)
}
return newOidFromC(&oid), nil
}
......@@ -88,6 +88,7 @@ func (repo *Repository) NewBranchIterator(flags BranchType) (*BranchIterator, er
defer runtime.UnlockOSThread()
ecode := C.git_branch_iterator_new(&ptr, repo.ptr, refType)
runtime.KeepAlive(repo)
if ecode < 0 {
return nil, MakeGitError(ecode)
}
......@@ -106,6 +107,8 @@ func (repo *Repository) CreateBranch(branchName string, target *Commit, force bo
defer runtime.UnlockOSThread()
ret := C.git_branch_create(&ptr, repo.ptr, cBranchName, target.cast_ptr, cForce)
runtime.KeepAlive(repo)
runtime.KeepAlive(target)
if ret < 0 {
return nil, MakeGitError(ret)
}
......@@ -117,6 +120,7 @@ func (b *Branch) Delete() error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_branch_delete(b.Reference.ptr)
runtime.KeepAlive(b.Reference)
if ret < 0 {
return MakeGitError(ret)
}
......@@ -133,6 +137,7 @@ func (b *Branch) Move(newBranchName string, force bool) (*Branch, error) {
defer runtime.UnlockOSThread()
ret := C.git_branch_move(&ptr, b.Reference.ptr, cNewBranchName, cForce)
runtime.KeepAlive(b.Reference)
if ret < 0 {
return nil, MakeGitError(ret)
}
......@@ -145,6 +150,7 @@ func (b *Branch) IsHead() (bool, error) {
defer runtime.UnlockOSThread()
ret := C.git_branch_is_head(b.Reference.ptr)
runtime.KeepAlive(b.Reference)
switch ret {
case 1:
return true, nil
......@@ -165,6 +171,7 @@ func (repo *Repository) LookupBranch(branchName string, bt BranchType) (*Branch,
defer runtime.UnlockOSThread()
ret := C.git_branch_lookup(&ptr, repo.ptr, cName, C.git_branch_t(bt))
runtime.KeepAlive(repo)
if ret < 0 {
return nil, MakeGitError(ret)
}
......@@ -179,6 +186,7 @@ func (b *Branch) Name() (string, error) {
defer runtime.UnlockOSThread()
ret := C.git_branch_name(&cName, b.Reference.ptr)
runtime.KeepAlive(b.Reference)
if ret < 0 {
return "", MakeGitError(ret)
}
......@@ -196,6 +204,7 @@ func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) {
defer runtime.UnlockOSThread()
ret := C.git_branch_remote_name(&nameBuf, repo.ptr, cName)
runtime.KeepAlive(repo)
if ret < 0 {
return "", MakeGitError(ret)
}
......@@ -212,6 +221,7 @@ func (b *Branch) SetUpstream(upstreamName string) error {
defer runtime.UnlockOSThread()
ret := C.git_branch_set_upstream(b.Reference.ptr, cName)
runtime.KeepAlive(b.Reference)
if ret < 0 {
return MakeGitError(ret)
}
......@@ -225,6 +235,7 @@ func (b *Branch) Upstream() (*Reference, error) {
defer runtime.UnlockOSThread()
ret := C.git_branch_upstream(&ptr, b.Reference.ptr)
runtime.KeepAlive(b.Reference)
if ret < 0 {
return nil, MakeGitError(ret)
}
......@@ -241,6 +252,7 @@ func (repo *Repository) UpstreamName(canonicalBranchName string) (string, error)
defer runtime.UnlockOSThread()
ret := C.git_branch_upstream_name(&nameBuf, repo.ptr, cName)
runtime.KeepAlive(repo)
if ret < 0 {
return "", MakeGitError(ret)
}
......
......@@ -2,6 +2,8 @@ package git
/*
#include <git2.h>
extern void _go_git_populate_checkout_cb(git_checkout_options *opts);
*/
import "C"
import (
......@@ -10,9 +12,18 @@ import (
"unsafe"
)
type CheckoutNotifyType uint
type CheckoutStrategy uint
const (
CheckoutNotifyNone CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_NONE
CheckoutNotifyConflict CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_CONFLICT
CheckoutNotifyDirty CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_DIRTY
CheckoutNotifyUpdated CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_UPDATED
CheckoutNotifyUntracked CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_UNTRACKED
CheckoutNotifyIgnored CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_IGNORED
CheckoutNotifyAll CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_ALL
CheckoutNone CheckoutStrategy = C.GIT_CHECKOUT_NONE // Dry run, no actual updates
CheckoutSafe CheckoutStrategy = C.GIT_CHECKOUT_SAFE // Allow safe updates that cannot overwrite uncommitted data
CheckoutForce CheckoutStrategy = C.GIT_CHECKOUT_FORCE // Allow all updates to force working directory to look like index
......@@ -37,15 +48,21 @@ const (
CheckoutUpdateSubmodulesIfChanged CheckoutStrategy = C.GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED // Recursively checkout submodules if HEAD moved in super repo (NOT IMPLEMENTED)
)
type CheckoutNotifyCallback func(why CheckoutNotifyType, path string, baseline, target, workdir DiffFile) ErrorCode
type CheckoutProgressCallback func(path string, completed, total uint) ErrorCode
type CheckoutOpts struct {
Strategy CheckoutStrategy // Default will be a dry run
DisableFilters bool // Don't apply filters like CRLF conversion
DirMode os.FileMode // Default is 0755
FileMode os.FileMode // Default is 0644 or 0755 as dictated by blob
FileOpenFlags int // Default is O_CREAT | O_TRUNC | O_WRONLY
TargetDirectory string // Alternative checkout path to workdir
Paths []string
Baseline *Tree
Strategy CheckoutStrategy // Default will be a dry run
DisableFilters bool // Don't apply filters like CRLF conversion
DirMode os.FileMode // Default is 0755
FileMode os.FileMode // Default is 0644 or 0755 as dictated by blob
FileOpenFlags int // Default is O_CREAT | O_TRUNC | O_WRONLY
NotifyFlags CheckoutNotifyType // Default will be none
NotifyCallback CheckoutNotifyCallback
ProgressCallback CheckoutProgressCallback
TargetDirectory string // Alternative checkout path to workdir
Paths []string
Baseline *Tree
}
func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts {
......@@ -55,6 +72,13 @@ func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts {
opts.DirMode = os.FileMode(c.dir_mode)
opts.FileMode = os.FileMode(c.file_mode)
opts.FileOpenFlags = int(c.file_open_flags)
opts.NotifyFlags = CheckoutNotifyType(c.notify_flags)
if c.notify_payload != nil {
opts.NotifyCallback = pointerHandles.Get(c.notify_payload).(*CheckoutOpts).NotifyCallback
}
if c.progress_payload != nil {
opts.ProgressCallback = pointerHandles.Get(c.progress_payload).(*CheckoutOpts).ProgressCallback
}
if c.target_directory != nil {
opts.TargetDirectory = C.GoString(c.target_directory)
}
......@@ -70,6 +94,38 @@ func (opts *CheckoutOpts) toC() *C.git_checkout_options {
return &c
}
//export checkoutNotifyCallback
func checkoutNotifyCallback(why C.git_checkout_notify_t, cpath *C.char, cbaseline, ctarget, cworkdir, data unsafe.Pointer) int {
if data == nil {
return 0
}
path := C.GoString(cpath)
var baseline, target, workdir DiffFile
if cbaseline != nil {
baseline = diffFileFromC((*C.git_diff_file)(cbaseline))
}
if ctarget != nil {
target = diffFileFromC((*C.git_diff_file)(ctarget))
}
if cworkdir != nil {
workdir = diffFileFromC((*C.git_diff_file)(cworkdir))
}
opts := pointerHandles.Get(data).(*CheckoutOpts)
if opts.NotifyCallback == nil {
return 0
}
return int(opts.NotifyCallback(CheckoutNotifyType(why), path, baseline, target, workdir))
}
//export checkoutProgressCallback
func checkoutProgressCallback(path *C.char, completed_steps, total_steps C.size_t, data unsafe.Pointer) int {
opts := pointerHandles.Get(data).(*CheckoutOpts)
if opts.ProgressCallback == nil {
return 0
}
return int(opts.ProgressCallback(C.GoString(path), uint(completed_steps), uint(total_steps)))
}
// Convert the CheckoutOpts struct to the corresponding
// C-struct. Returns a pointer to ptr, or nil if opts is nil, in order
// to help with what to pass.
......@@ -83,6 +139,17 @@ func populateCheckoutOpts(ptr *C.git_checkout_options, opts *CheckoutOpts) *C.gi
ptr.disable_filters = cbool(opts.DisableFilters)
ptr.dir_mode = C.uint(opts.DirMode.Perm())
ptr.file_mode = C.uint(opts.FileMode.Perm())
ptr.notify_flags = C.uint(opts.NotifyFlags)
if opts.NotifyCallback != nil || opts.ProgressCallback != nil {
C._go_git_populate_checkout_cb(ptr)
}
payload := pointerHandles.Track(opts)
if opts.NotifyCallback != nil {
ptr.notify_payload = payload
}
if opts.ProgressCallback != nil {
ptr.progress_payload = payload
}
if opts.TargetDirectory != "" {
ptr.target_directory = C.CString(opts.TargetDirectory)
}
......@@ -106,6 +173,9 @@ func freeCheckoutOpts(ptr *C.git_checkout_options) {
if ptr.paths.count > 0 {
freeStrarray(&ptr.paths)
}
if ptr.notify_payload != nil {
pointerHandles.Untrack(ptr.notify_payload)
}
}
// Updates files in the index and the working tree to match the content of
......@@ -118,6 +188,7 @@ func (v *Repository) CheckoutHead(opts *CheckoutOpts) error {
defer freeCheckoutOpts(cOpts)
ret := C.git_checkout_head(v.ptr, cOpts)
runtime.KeepAlive(v)
if ret < 0 {
return MakeGitError(ret)
}
......@@ -141,6 +212,7 @@ func (v *Repository) CheckoutIndex(index *Index, opts *CheckoutOpts) error {
defer freeCheckoutOpts(cOpts)
ret := C.git_checkout_index(v.ptr, iptr, cOpts)
runtime.KeepAlive(v)
if ret < 0 {
return MakeGitError(ret)
}
......@@ -156,6 +228,7 @@ func (v *Repository) CheckoutTree(tree *Tree, opts *CheckoutOpts) error {
defer freeCheckoutOpts(cOpts)
ret := C.git_checkout_tree(v.ptr, tree.ptr, cOpts)
runtime.KeepAlive(v)
if ret < 0 {
return MakeGitError(ret)
}
......
......@@ -66,6 +66,8 @@ func (v *Repository) Cherrypick(commit *Commit, opts CherrypickOptions) error {
defer freeCherrypickOpts(cOpts)
ecode := C.git_cherrypick(v.ptr, commit.cast_ptr, cOpts)
runtime.KeepAlive(v)
runtime.KeepAlive(commit)
if ecode < 0 {
return MakeGitError(ecode)
}
......
......@@ -41,7 +41,6 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error)
var ptr *C.git_repository
ret := C.git_clone(&ptr, curl, cpath, copts)
freeCheckoutOpts(&copts.checkout_opts)
if ret < 0 {
return nil, MakeGitError(ret)
......
......@@ -22,6 +22,33 @@ func (c Commit) Message() string {
return C.GoString(C.git_commit_message(c.cast_ptr))
}
func (c Commit) RawMessage() string {
return C.GoString(C.git_commit_message_raw(c.cast_ptr))
}
func (c Commit) ExtractSignature() (string, string, error) {
var c_signed C.git_buf
defer C.git_buf_free(&c_signed)
var c_signature C.git_buf
defer C.git_buf_free(&c_signature)
oid := c.Id()
repo := C.git_commit_owner(c.cast_ptr)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_commit_extract_signature(&c_signature, &c_signed, repo, oid.toC(), nil)
if ret < 0 {
return "", "", MakeGitError(ret)
} else {
return C.GoString(c_signature.ptr), C.GoString(c_signed.ptr), nil
}
}
func (c Commit) Summary() string {
return C.GoString(C.git_commit_summary(c.cast_ptr))
}
......@@ -61,15 +88,21 @@ func (c *Commit) Parent(n uint) *Commit {
return nil
}
return allocCommit(cobj, c.repo)
parent := allocCommit(cobj, c.repo)
runtime.KeepAlive(c)
return parent
}
func (c *Commit) ParentId(n uint) *Oid {
return newOidFromC(C.git_commit_parent_id(c.cast_ptr, C.uint(n)))
ret := newOidFromC(C.git_commit_parent_id(c.cast_ptr, C.uint(n)))
runtime.KeepAlive(c)
return ret
}
func (c *Commit) ParentCount() uint {
return uint(C.git_commit_parentcount(c.cast_ptr))
ret := uint(C.git_commit_parentcount(c.cast_ptr))
runtime.KeepAlive(c)
return ret
}
func (c *Commit) Amend(refname string, author, committer *Signature, message string, tree *Tree) (*Oid, error) {
......@@ -102,6 +135,9 @@ func (c *Commit) Amend(refname string, author, committer *Signature, message str
oid := new(Oid)
cerr := C.git_commit_amend(oid.toC(), c.cast_ptr, cref, authorSig, committerSig, nil, cmsg, tree.cast_ptr)
runtime.KeepAlive(oid)
runtime.KeepAlive(c)
runtime.KeepAlive(tree)
if cerr < 0 {
return nil, MakeGitError(cerr)
}
......
......@@ -78,6 +78,7 @@ func (c *Config) AddFile(path string, level ConfigLevel, force bool) error {
defer runtime.UnlockOSThread()
ret := C.git_config_add_file_ondisk(c.ptr, cpath, C.git_config_level_t(level), cbool(force))
runtime.KeepAlive(c)
if ret < 0 {
return MakeGitError(ret)
}
......@@ -94,6 +95,7 @@ func (c *Config) LookupInt32(name string) (int32, error) {
defer runtime.UnlockOSThread()
ret := C.git_config_get_int32(&out, c.ptr, cname)
runtime.KeepAlive(c)
if ret < 0 {
return 0, MakeGitError(ret)
}
......@@ -110,6 +112,7 @@ func (c *Config) LookupInt64(name string) (int64, error) {
defer runtime.UnlockOSThread()
ret := C.git_config_get_int64(&out, c.ptr, cname)
runtime.KeepAlive(c)
if ret < 0 {
return 0, MakeGitError(ret)
}
......@@ -126,7 +129,9 @@ func (c *Config) LookupString(name string) (string, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if ret := C.git_config_get_string_buf(&valBuf, c.ptr, cname); ret < 0 {
ret := C.git_config_get_string_buf(&valBuf, c.ptr, cname)
runtime.KeepAlive(c)
if ret < 0 {
return "", MakeGitError(ret)
}
defer C.git_buf_free(&valBuf)
......@@ -143,6 +148,7 @@ func (c *Config) LookupBool(name string) (bool, error) {
defer runtime.UnlockOSThread()
ret := C.git_config_get_bool(&out, c.ptr, cname)
runtime.KeepAlive(c)
if ret < 0 {
return false, MakeGitError(ret)
}
......@@ -162,7 +168,7 @@ func (c *Config) NewMultivarIterator(name, regexp string) (*ConfigIterator, erro
defer C.free(unsafe.Pointer(cregexp))
}
iter := new(ConfigIterator)
iter := &ConfigIterator{cfg: c}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
......@@ -179,7 +185,7 @@ func (c *Config) NewMultivarIterator(name, regexp string) (*ConfigIterator, erro
// NewIterator creates an iterator over each entry in the
// configuration
func (c *Config) NewIterator() (*ConfigIterator, error) {
iter := new(ConfigIterator)
iter := &ConfigIterator{cfg: c}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
......@@ -195,7 +201,7 @@ func (c *Config) NewIterator() (*ConfigIterator, error) {
// NewIteratorGlob creates an iterator over each entry in the
// configuration whose name matches the given regular expression
func (c *Config) NewIteratorGlob(regexp string) (*ConfigIterator, error) {
iter := new(ConfigIterator)
iter := &ConfigIterator{cfg: c}
cregexp := C.CString(regexp)
defer C.free(unsafe.Pointer(cregexp))
......@@ -221,6 +227,7 @@ func (c *Config) SetString(name, value string) (err error) {
defer runtime.UnlockOSThread()
ret := C.git_config_set_string(c.ptr, cname, cvalue)
runtime.KeepAlive(c)
if ret < 0 {
return MakeGitError(ret)
}
......@@ -241,6 +248,7 @@ func (c *Config) SetInt32(name string, value int32) (err error) {
defer runtime.UnlockOSThread()
ret := C.git_config_set_int32(c.ptr, cname, C.int32_t(value))
runtime.KeepAlive(c)
if ret < 0 {
return MakeGitError(ret)
}
......@@ -256,6 +264,7 @@ func (c *Config) SetInt64(name string, value int64) (err error) {
defer runtime.UnlockOSThread()
ret := C.git_config_set_int64(c.ptr, cname, C.int64_t(value))
runtime.KeepAlive(c)
if ret < 0 {
return MakeGitError(ret)
}
......@@ -271,6 +280,7 @@ func (c *Config) SetBool(name string, value bool) (err error) {
defer runtime.UnlockOSThread()
ret := C.git_config_set_bool(c.ptr, cname, cbool(value))
runtime.KeepAlive(c)
if ret < 0 {
return MakeGitError(ret)