summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--branch.go193
-rw-r--r--checkout.go43
2 files changed, 219 insertions, 17 deletions
diff --git a/branch.go b/branch.go
new file mode 100644
index 0000000..aee23e4
--- /dev/null
+++ b/branch.go
@@ -0,0 +1,193 @@
+package git
+
+/*
+#cgo pkg-config: libgit2
+#include <git2.h>
+#include <git2/errors.h>
+*/
+import "C"
+
+import (
+ "runtime"
+ "unsafe"
+)
+
+type BranchType uint
+
+const (
+ BranchLocal BranchType = C.GIT_BRANCH_LOCAL
+ BranchRemote = C.GIT_BRANCH_REMOTE
+)
+
+type Branch struct {
+ Reference
+}
+
+func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool, signature *Signature, msg string) (*Reference, error) {
+
+ ref := new(Reference)
+ cBranchName := C.CString(branchName)
+ cForce := cbool(force)
+
+ cSignature := signature.toC()
+ defer C.git_signature_free(cSignature)
+
+ var cmsg *C.char
+ if msg == "" {
+ cmsg = nil
+ } else {
+ cmsg = C.CString(msg)
+ defer C.free(unsafe.Pointer(cmsg))
+ }
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.ptr, cForce, cSignature, cmsg)
+ if ret < 0 {
+ return nil, MakeGitError(ret)
+ }
+ return ref, nil
+}
+
+func (b *Branch) Delete() error {
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+ ret := C.git_branch_delete(b.ptr)
+ if ret < 0 {
+ return MakeGitError(ret)
+ }
+ return nil
+}
+
+func (b *Branch) Move(newBranchName string, force bool, signature *Signature, msg string) (*Branch, error) {
+ newBranch := new(Branch)
+ cNewBranchName := C.CString(newBranchName)
+ cForce := cbool(force)
+
+ cSignature := signature.toC()
+ defer C.git_signature_free(cSignature)
+
+ var cmsg *C.char
+ if msg == "" {
+ cmsg = nil
+ } else {
+ cmsg = C.CString(msg)
+ defer C.free(unsafe.Pointer(cmsg))
+ }
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_branch_move(&newBranch.ptr, b.ptr, cNewBranchName, cForce, cSignature, cmsg)
+ if ret < 0 {
+ return nil, MakeGitError(ret)
+ }
+ return newBranch, nil
+}
+
+func (b *Branch) IsHead() (bool, error) {
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_branch_is_head(b.ptr)
+ 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) {
+ branch := new(Branch)
+ cName := C.CString(branchName)
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_branch_lookup(&branch.ptr, repo.ptr, cName, C.git_branch_t(bt))
+ if ret < 0 {
+ return nil, MakeGitError(ret)
+ }
+ return 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.ptr)
+ if ret < 0 {
+ return "", MakeGitError(ret)
+ }
+
+ return C.GoString(cName), nil
+}
+
+func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) {
+ cName := C.CString(canonicalBranchName)
+
+ nameBuf := C.git_buf{}
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_branch_remote_name(&nameBuf, repo.ptr, cName)
+ if ret < 0 {
+ return "", MakeGitError(ret)
+ }
+ defer C.git_buf_free(&nameBuf)
+
+ return C.GoString(nameBuf.ptr), nil
+}
+
+func (b *Branch) SetUpstream(upstreamName string) error {
+ cName := C.CString(upstreamName)
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_branch_set_upstream(b.ptr, cName)
+ if ret < 0 {
+ return MakeGitError(ret)
+ }
+ return nil
+}
+
+func (b *Branch) Upstream() (*Branch, error) {
+ upstream := new(Branch)
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_branch_upstream(&upstream.ptr, b.ptr)
+ if ret < 0 {
+ return nil, MakeGitError(ret)
+ }
+ return upstream, nil
+}
+
+func (repo *Repository) UpstreamName(canonicalBranchName string) (string, error) {
+ cName := C.CString(canonicalBranchName)
+
+ nameBuf := C.git_buf{}
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_branch_upstream_name(&nameBuf, repo.ptr, cName)
+ if ret < 0 {
+ return "", MakeGitError(ret)
+ }
+ defer C.git_buf_free(&nameBuf)
+
+ return C.GoString(nameBuf.ptr), nil
+}
diff --git a/checkout.go b/checkout.go
index d3cd47b..5b72b9a 100644
--- a/checkout.go
+++ b/checkout.go
@@ -2,10 +2,6 @@ package git
/*
#include <git2.h>
-git_checkout_opts git_checkout_opts_init() {
- git_checkout_opts ret = GIT_CHECKOUT_OPTS_INIT;
- return ret;
-}
*/
import "C"
import (
@@ -42,28 +38,34 @@ type CheckoutOpts struct {
FileOpenFlags int // Default is O_CREAT | O_TRUNC | O_WRONLY
}
-// Convert the CheckoutOpts struct to the corresponding C-struct
-func populateCheckoutOpts(ptr *C.git_checkout_opts, opts *CheckoutOpts) {
- *ptr = C.git_checkout_opts_init()
+// 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.
+func populateCheckoutOpts(ptr *C.git_checkout_options, opts *CheckoutOpts) *C.git_checkout_options {
if opts == nil {
- return
+ return nil
}
+
+ C.git_checkout_init_opts(ptr, 1)
ptr.checkout_strategy = C.uint(opts.Strategy)
ptr.disable_filters = cbool(opts.DisableFilters)
ptr.dir_mode = C.uint(opts.DirMode.Perm())
ptr.file_mode = C.uint(opts.FileMode.Perm())
+
+ return ptr
}
// Updates files in the index and the working tree to match the content of
-// the commit pointed at by HEAD.
-func (v *Repository) Checkout(opts *CheckoutOpts) error {
- var copts C.git_checkout_opts
- populateCheckoutOpts(&copts, opts)
+// the commit pointed at by HEAD. opts may be nil.
+func (v *Repository) CheckoutHead(opts *CheckoutOpts) error {
+ var copts C.git_checkout_options
+
+ ptr := populateCheckoutOpts(&copts, opts)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_checkout_head(v.ptr, &copts)
+ ret := C.git_checkout_head(v.ptr, ptr)
if ret < 0 {
return MakeGitError(ret)
}
@@ -71,15 +73,22 @@ func (v *Repository) Checkout(opts *CheckoutOpts) error {
return nil
}
-// Updates files in the working tree to match the content of the index.
+// Updates files in the working tree to match the content of the given
+// index. If index is nil, the repository's index will be used. opts
+// may be nil.
func (v *Repository) CheckoutIndex(index *Index, opts *CheckoutOpts) error {
- var copts C.git_checkout_opts
- populateCheckoutOpts(&copts, opts)
+ var copts C.git_checkout_options
+ ptr := populateCheckoutOpts(&copts, opts)
+
+ var iptr *C.git_index = nil
+ if index != nil {
+ iptr = index.ptr
+ }
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_checkout_index(v.ptr, index.ptr, &copts)
+ ret := C.git_checkout_index(v.ptr, iptr, ptr)
if ret < 0 {
return MakeGitError(ret)
}