package git /* #include */ import "C" import ( "runtime" "unsafe" ) type BranchType uint const ( BranchAll BranchType = C.GIT_BRANCH_ALL BranchLocal BranchType = C.GIT_BRANCH_LOCAL BranchRemote BranchType = C.GIT_BRANCH_REMOTE ) type Branch struct { doNotCompare *Reference } func (r *Reference) Branch() *Branch { return &Branch{Reference: r} } type BranchIterator struct { doNotCompare ptr *C.git_branch_iterator repo *Repository } type BranchIteratorFunc func(*Branch, BranchType) error func newBranchIteratorFromC(repo *Repository, ptr *C.git_branch_iterator) *BranchIterator { i := &BranchIterator{repo: repo, ptr: ptr} runtime.SetFinalizer(i, (*BranchIterator).Free) return i } func (i *BranchIterator) Next() (*Branch, BranchType, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() var refPtr *C.git_reference var refType C.git_branch_t ecode := C.git_branch_next(&refPtr, &refType, i.ptr) if ecode < 0 { return nil, BranchLocal, MakeGitError(ecode) } branch := newReferenceFromC(refPtr, i.repo).Branch() return branch, BranchType(refType), nil } func (i *BranchIterator) Free() { runtime.SetFinalizer(i, nil) C.git_branch_iterator_free(i.ptr) } func (i *BranchIterator) ForEach(f BranchIteratorFunc) error { b, t, err := i.Next() for err == nil { err = f(b, t) if err == nil { b, t, err = i.Next() } } if err != nil && IsErrorCode(err, ErrorCodeIterOver) { return nil } return err } func (repo *Repository) NewBranchIterator(flags BranchType) (*BranchIterator, error) { refType := C.git_branch_t(flags) var ptr *C.git_branch_iterator runtime.LockOSThread() defer runtime.UnlockOSThread() ecode := C.git_branch_iterator_new(&ptr, repo.ptr, refType) runtime.KeepAlive(repo) if ecode < 0 { return nil, MakeGitError(ecode) } return newBranchIteratorFromC(repo, ptr), nil } func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool) (*Branch, error) { var ptr *C.git_reference cBranchName := C.CString(branchName) defer C.free(unsafe.Pointer(cBranchName)) cForce := cbool(force) runtime.LockOSThread() 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) } return newReferenceFromC(ptr, repo).Branch(), nil } 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) } return nil } func (b *Branch) Move(newBranchName string, force bool) (*Branch, error) { var ptr *C.git_reference cNewBranchName := C.CString(newBranchName) defer C.free(unsafe.Pointer(cNewBranchName)) cForce := cbool(force) runtime.LockOSThread() 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) } return newReferenceFromC(ptr, b.repo).Branch(), nil } func (b *Branch) IsHead() (bool, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_branch_is_head(b.Reference.ptr) runtime.KeepAlive(b.Reference) switch ret { case 1: return true, nil case 0: return false, nil } return false, MakeGitError(ret) } func (repo *Repository) LookupBranch(branchName string, bt BranchType) (*Branch, error) { var ptr *C.git_reference cName := C.CString(branchName) defer C.free(unsafe.Pointer(cName)) runtime.LockOSThread() 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) } return newReferenceFromC(ptr, repo).Branch(), nil } func (b *Branch) Name() (string, error) { var cName *C.char defer C.free(unsafe.Pointer(cName)) runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_branch_name(&cName, b.Reference.ptr) runtime.KeepAlive(b.Reference) if ret < 0 { return "", MakeGitError(ret) } return C.GoString(cName), nil } func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) { cName := C.CString(canonicalBranchName) defer C.free(unsafe.Pointer(cName)) nameBuf := C.git_buf{} runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_branch_remote_name(&nameBuf, repo.ptr, cName) runtime.KeepAlive(repo) if ret < 0 { return "", MakeGitError(ret) } defer C.git_buf_dispose(&nameBuf) return C.GoString(nameBuf.ptr), nil } func (b *Branch) SetUpstream(upstreamName string) error { cName := C.CString(upstreamName) defer C.free(unsafe.Pointer(cName)) runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_branch_set_upstream(b.Reference.ptr, cName) runtime.KeepAlive(b.Reference) if ret < 0 { return MakeGitError(ret) } return nil } func (b *Branch) Upstream() (*Reference, error) { var ptr *C.git_reference runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_branch_upstream(&ptr, b.Reference.ptr) runtime.KeepAlive(b.Reference) if ret < 0 { return nil, MakeGitError(ret) } return newReferenceFromC(ptr, b.repo), nil } func (repo *Repository) UpstreamName(canonicalBranchName string) (string, error) { cName := C.CString(canonicalBranchName) defer C.free(unsafe.Pointer(cName)) nameBuf := C.git_buf{} runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_branch_upstream_name(&nameBuf, repo.ptr, cName) runtime.KeepAlive(repo) if ret < 0 { return "", MakeGitError(ret) } defer C.git_buf_dispose(&nameBuf) return C.GoString(nameBuf.ptr), nil }