From ff5150e6c9a0e9f82eb3c26df96f8839242589ca Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Tue, 8 Oct 2013 02:07:06 +0200 Subject: [PATCH 01/21] branch: Implemented branch functions. --- branch.go | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 branch.go diff --git a/branch.go b/branch.go new file mode 100644 index 0000000..8dd55a3 --- /dev/null +++ b/branch.go @@ -0,0 +1,199 @@ +package git + +/* +#cgo pkg-config: libgit2 +#include +#include +*/ +import "C" + +import ( + "errors" + "strings" + "unsafe" +) + +var ErrEUser = errors.New("Error in user callback function") + +type ListFlags uint + +type BranchT uint + +const ( + BRANCH_LOCAL BranchT = C.GIT_BRANCH_LOCAL + BRANCH_REMOTE = C.GIT_BRANCH_REMOTE +) + +const ( + REFS_DIR = "refs/" + REFS_HEADS_DIR = REFS_DIR + "heads/" + REFS_TAGS_DIR = REFS_DIR + "tags/" + REFS_REMOTES_DIR = REFS_DIR + "remotes/" +) + +type Branch struct { + Reference +} + +func (repo *Repository) BranchCreate(branchName string, target *Commit, force bool) (*Reference, error) { + ref := new(Reference) + cBranchName := C.CString(branchName) + cForce := cbool(force) + err := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.ptr, cForce) + if err < 0 { + return nil, LastError() + } + return ref, nil +} + +func (branch *Branch) BranchDelete() error { + if err := C.git_branch_delete(branch.ptr); err < 0 { + return LastError() + } + return nil +} + +type BranchForeachCB func(name string, flags ListFlags, payload interface{}) error + +func (repo *Repository) BranchForeach(flags ListFlags, callback BranchForeachCB, payload interface{}) error { + iter, err := repo.NewReferenceIterator() + if err != nil { + return err + } + + for { + ref, err := iter.Next() + if err == ErrIterOver { + break + } + + if (flags == ListFlags(BRANCH_LOCAL)) && strings.HasPrefix(ref.Name(), REFS_HEADS_DIR) { + name := strings.TrimPrefix(ref.Name(), REFS_HEADS_DIR) + err = callback(name, ListFlags(BRANCH_LOCAL), payload) + if err != nil { + return err + } + } + + if (flags == ListFlags(BRANCH_REMOTE)) && strings.HasPrefix(ref.Name(), REFS_REMOTES_DIR) { + name := strings.TrimPrefix(ref.Name(), REFS_REMOTES_DIR) + err = callback(name, ListFlags(BRANCH_REMOTE), payload) + if err != nil { + return err + } + } + } + + if err == ErrIterOver { + err = nil + } + return err +} + +func (branch *Branch) Move(newBranchName string, force bool) (*Branch, error) { + newBranch := new(Branch) + cNewBranchName := C.CString(newBranchName) + cForce := cbool(force) + + err := C.git_branch_move(&newBranch.ptr, branch.ptr, cNewBranchName, cForce) + if err < 0 { + return nil, LastError() + } + return newBranch, nil +} + +func (branch *Branch) IsHead() (bool, error) { + isHead := C.git_branch_is_head(branch.ptr) + switch isHead { + case 1: + return true, nil + case 0: + return false, nil + default: + return false, LastError() + } + +} + +func (repo *Repository) BranchLookup(branchName string, branchType BranchT) (*Branch, error) { + branch := new(Branch) + cName := C.CString(branchName) + + err := C.git_branch_lookup(&branch.ptr, repo.ptr, cName, C.git_branch_t(branchType)) + if err < 0 { + return nil, LastError() + } + return branch, nil +} + +func (branch *Branch) Name() (string, error) { + var cName *C.char + defer C.free(unsafe.Pointer(cName)) + + err := C.git_branch_name(&cName, branch.ptr) + if err < 0 { + return "", LastError() + } + + return C.GoString(cName), nil +} + +func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) { + cName := C.CString(canonicalBranchName) + + // Obtain the length of the name + ret := C.git_branch_remote_name(nil, 0, repo.ptr, cName) + if ret < 0 { + return "", LastError() + } + + cBuf := (*C.char)(C.malloc(C.size_t(ret))) + defer C.free(unsafe.Pointer(cBuf)) + + // Actually obtain the name + ret = C.git_branch_remote_name(cBuf, C.size_t(ret), repo.ptr, cName) + if ret < 0 { + return "", LastError() + } + + return C.GoString(cBuf), nil +} + +func (branch *Branch) SetUpstream(upstreamName string) error { + cName := C.CString(upstreamName) + + err := C.git_branch_set_upstream(branch.ptr, cName) + if err < 0 { + return LastError() + } + return nil +} + +func (branch *Branch) Upstream() (*Branch, error) { + upstream := new(Branch) + err := C.git_branch_upstream(&upstream.ptr, branch.ptr) + if err < 0 { + return nil, LastError() + } + return upstream, nil +} + +func (repo *Repository) UpstreamName(canonicalBranchName string) (string, error) { + cName := C.CString(canonicalBranchName) + + // Obtain the length of the name + ret := C.git_branch_upstream_name(nil, 0, repo.ptr, cName) + if ret < 0 { + return "", LastError() + } + + cBuf := (*C.char)(C.malloc(C.size_t(ret))) + defer C.free(unsafe.Pointer(cBuf)) + + // Actually obtain the name + ret = C.git_branch_upstream_name(cBuf, C.size_t(ret), repo.ptr, cName) + if ret < 0 { + return "", LastError() + } + return C.GoString(cBuf), nil +} From f03cec5375d22bda9efebb01e78d9e752ee2b498 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Tue, 8 Oct 2013 14:39:05 +0200 Subject: [PATCH 02/21] branch: Changed BranchT to BranchType --- branch.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/branch.go b/branch.go index 8dd55a3..651edb2 100644 --- a/branch.go +++ b/branch.go @@ -17,11 +17,11 @@ var ErrEUser = errors.New("Error in user callback function") type ListFlags uint -type BranchT uint +type BranchType uint const ( - BRANCH_LOCAL BranchT = C.GIT_BRANCH_LOCAL - BRANCH_REMOTE = C.GIT_BRANCH_REMOTE + BRANCH_LOCAL BranchType = C.GIT_BRANCH_LOCAL + BRANCH_REMOTE = C.GIT_BRANCH_REMOTE ) const ( @@ -115,7 +115,7 @@ func (branch *Branch) IsHead() (bool, error) { } -func (repo *Repository) BranchLookup(branchName string, branchType BranchT) (*Branch, error) { +func (repo *Repository) BranchLookup(branchName string, branchType BranchType) (*Branch, error) { branch := new(Branch) cName := C.CString(branchName) From 771e0c11bc8b1f00cdd6fdddbfe114957aa77ce2 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Tue, 8 Oct 2013 14:44:11 +0200 Subject: [PATCH 03/21] branch: Variable names don't repeat its type name any longer --- branch.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/branch.go b/branch.go index 651edb2..e431f07 100644 --- a/branch.go +++ b/branch.go @@ -46,8 +46,8 @@ func (repo *Repository) BranchCreate(branchName string, target *Commit, force bo return ref, nil } -func (branch *Branch) BranchDelete() error { - if err := C.git_branch_delete(branch.ptr); err < 0 { +func (b *Branch) BranchDelete() error { + if err := C.git_branch_delete(b.ptr); err < 0 { return LastError() } return nil @@ -90,20 +90,20 @@ func (repo *Repository) BranchForeach(flags ListFlags, callback BranchForeachCB, return err } -func (branch *Branch) Move(newBranchName string, force bool) (*Branch, error) { +func (b *Branch) Move(newBranchName string, force bool) (*Branch, error) { newBranch := new(Branch) cNewBranchName := C.CString(newBranchName) cForce := cbool(force) - err := C.git_branch_move(&newBranch.ptr, branch.ptr, cNewBranchName, cForce) + err := C.git_branch_move(&newBranch.ptr, b.ptr, cNewBranchName, cForce) if err < 0 { return nil, LastError() } return newBranch, nil } -func (branch *Branch) IsHead() (bool, error) { - isHead := C.git_branch_is_head(branch.ptr) +func (b *Branch) IsHead() (bool, error) { + isHead := C.git_branch_is_head(b.ptr) switch isHead { case 1: return true, nil @@ -115,22 +115,22 @@ func (branch *Branch) IsHead() (bool, error) { } -func (repo *Repository) BranchLookup(branchName string, branchType BranchType) (*Branch, error) { +func (repo *Repository) BranchLookup(branchName string, bt BranchType) (*Branch, error) { branch := new(Branch) cName := C.CString(branchName) - err := C.git_branch_lookup(&branch.ptr, repo.ptr, cName, C.git_branch_t(branchType)) + err := C.git_branch_lookup(&branch.ptr, repo.ptr, cName, C.git_branch_t(bt)) if err < 0 { return nil, LastError() } return branch, nil } -func (branch *Branch) Name() (string, error) { +func (b *Branch) Name() (string, error) { var cName *C.char defer C.free(unsafe.Pointer(cName)) - err := C.git_branch_name(&cName, branch.ptr) + err := C.git_branch_name(&cName, b.ptr) if err < 0 { return "", LastError() } @@ -159,19 +159,19 @@ func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) { return C.GoString(cBuf), nil } -func (branch *Branch) SetUpstream(upstreamName string) error { +func (b *Branch) SetUpstream(upstreamName string) error { cName := C.CString(upstreamName) - err := C.git_branch_set_upstream(branch.ptr, cName) + err := C.git_branch_set_upstream(b.ptr, cName) if err < 0 { return LastError() } return nil } -func (branch *Branch) Upstream() (*Branch, error) { +func (b *Branch) Upstream() (*Branch, error) { upstream := new(Branch) - err := C.git_branch_upstream(&upstream.ptr, branch.ptr) + err := C.git_branch_upstream(&upstream.ptr, b.ptr) if err < 0 { return nil, LastError() } From 6372ec052fb752122bc0662783b8450bbe2ce983 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Tue, 8 Oct 2013 14:49:03 +0200 Subject: [PATCH 04/21] branch: Renamed BranchCreate to CreateBranch --- branch.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/branch.go b/branch.go index e431f07..7a4e4cb 100644 --- a/branch.go +++ b/branch.go @@ -35,7 +35,7 @@ type Branch struct { Reference } -func (repo *Repository) BranchCreate(branchName string, target *Commit, force bool) (*Reference, error) { +func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool) (*Reference, error) { ref := new(Reference) cBranchName := C.CString(branchName) cForce := cbool(force) From 4c4da3a84621cc57e90bfe55b16342796c80aceb Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Tue, 8 Oct 2013 14:52:22 +0200 Subject: [PATCH 05/21] branch: Renamed BranchLookup to LookupBrnach --- branch.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/branch.go b/branch.go index 7a4e4cb..07f3f41 100644 --- a/branch.go +++ b/branch.go @@ -115,7 +115,7 @@ func (b *Branch) IsHead() (bool, error) { } -func (repo *Repository) BranchLookup(branchName string, bt BranchType) (*Branch, error) { +func (repo *Repository) LookupBranch(branchName string, bt BranchType) (*Branch, error) { branch := new(Branch) cName := C.CString(branchName) From ed86064871639a956beb5592dc5b64e3d536f882 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Thu, 10 Oct 2013 10:39:49 +0200 Subject: [PATCH 06/21] branch:BranchForeach: Correct handling of the ListFlags --- branch.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/branch.go b/branch.go index 07f3f41..11e12da 100644 --- a/branch.go +++ b/branch.go @@ -15,10 +15,10 @@ import ( var ErrEUser = errors.New("Error in user callback function") -type ListFlags uint - type BranchType uint +type ListFlags BranchType + const ( BRANCH_LOCAL BranchType = C.GIT_BRANCH_LOCAL BRANCH_REMOTE = C.GIT_BRANCH_REMOTE @@ -62,12 +62,18 @@ func (repo *Repository) BranchForeach(flags ListFlags, callback BranchForeachCB, } for { + var branchLocal bool + var branchRemote bool + ref, err := iter.Next() if err == ErrIterOver { break } - if (flags == ListFlags(BRANCH_LOCAL)) && strings.HasPrefix(ref.Name(), REFS_HEADS_DIR) { + if flags&ListFlags(BRANCH_LOCAL) > 0 { + branchLocal = true + } + if branchLocal && strings.HasPrefix(ref.Name(), REFS_HEADS_DIR) { name := strings.TrimPrefix(ref.Name(), REFS_HEADS_DIR) err = callback(name, ListFlags(BRANCH_LOCAL), payload) if err != nil { @@ -75,7 +81,10 @@ func (repo *Repository) BranchForeach(flags ListFlags, callback BranchForeachCB, } } - if (flags == ListFlags(BRANCH_REMOTE)) && strings.HasPrefix(ref.Name(), REFS_REMOTES_DIR) { + if flags&ListFlags(BRANCH_REMOTE) > 0 { + branchRemote = true + } + if branchRemote && strings.HasPrefix(ref.Name(), REFS_REMOTES_DIR) { name := strings.TrimPrefix(ref.Name(), REFS_REMOTES_DIR) err = callback(name, ListFlags(BRANCH_REMOTE), payload) if err != nil { From 961db94aa21da58a77968099c6b97890e6235d10 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Wed, 30 Oct 2013 15:01:08 +0100 Subject: [PATCH 07/21] branch: Deleted BranchForeach --- branch.go | 52 ---------------------------------------------------- 1 file changed, 52 deletions(-) diff --git a/branch.go b/branch.go index 11e12da..d30748f 100644 --- a/branch.go +++ b/branch.go @@ -8,17 +8,11 @@ package git import "C" import ( - "errors" - "strings" "unsafe" ) -var ErrEUser = errors.New("Error in user callback function") - type BranchType uint -type ListFlags BranchType - const ( BRANCH_LOCAL BranchType = C.GIT_BRANCH_LOCAL BRANCH_REMOTE = C.GIT_BRANCH_REMOTE @@ -53,52 +47,6 @@ func (b *Branch) BranchDelete() error { return nil } -type BranchForeachCB func(name string, flags ListFlags, payload interface{}) error - -func (repo *Repository) BranchForeach(flags ListFlags, callback BranchForeachCB, payload interface{}) error { - iter, err := repo.NewReferenceIterator() - if err != nil { - return err - } - - for { - var branchLocal bool - var branchRemote bool - - ref, err := iter.Next() - if err == ErrIterOver { - break - } - - if flags&ListFlags(BRANCH_LOCAL) > 0 { - branchLocal = true - } - if branchLocal && strings.HasPrefix(ref.Name(), REFS_HEADS_DIR) { - name := strings.TrimPrefix(ref.Name(), REFS_HEADS_DIR) - err = callback(name, ListFlags(BRANCH_LOCAL), payload) - if err != nil { - return err - } - } - - if flags&ListFlags(BRANCH_REMOTE) > 0 { - branchRemote = true - } - if branchRemote && strings.HasPrefix(ref.Name(), REFS_REMOTES_DIR) { - name := strings.TrimPrefix(ref.Name(), REFS_REMOTES_DIR) - err = callback(name, ListFlags(BRANCH_REMOTE), payload) - if err != nil { - return err - } - } - } - - if err == ErrIterOver { - err = nil - } - return err -} - func (b *Branch) Move(newBranchName string, force bool) (*Branch, error) { newBranch := new(Branch) cNewBranchName := C.CString(newBranchName) From a728f70358ab58364c643d04c94a66b3ec2cd947 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Wed, 26 Feb 2014 07:33:50 -0800 Subject: [PATCH 08/21] cleanup add-branch --- branch.go | 68 +++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/branch.go b/branch.go index d30748f..ba82f93 100644 --- a/branch.go +++ b/branch.go @@ -14,26 +14,33 @@ import ( type BranchType uint const ( - BRANCH_LOCAL BranchType = C.GIT_BRANCH_LOCAL - BRANCH_REMOTE = C.GIT_BRANCH_REMOTE + BranchLocal BranchType = C.GIT_BRANCH_LOCAL + BranchRemote = C.GIT_BRANCH_REMOTE ) const ( - REFS_DIR = "refs/" - REFS_HEADS_DIR = REFS_DIR + "heads/" - REFS_TAGS_DIR = REFS_DIR + "tags/" - REFS_REMOTES_DIR = REFS_DIR + "remotes/" + RefsDir = "refs/" + RefsHeadsDir = RefsDir + "heads/" + RefsTagsDir = RefsDir + "tags/" + RefsRemotesDir = RefsDir + "remotes/" ) type Branch struct { Reference } -func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool) (*Reference, error) { +func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool, signature *Signature, message string) (*Reference, error) { ref := new(Reference) cBranchName := C.CString(branchName) cForce := cbool(force) - err := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.ptr, cForce) + + cSignature := signature.toC() + defer C.git_signature_free(cSignature) + + cMessage := C.CString(message) + defer C.free(unsafe.Pointer(cMessage)) + + err := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.ptr, cForce, cSignature, cMessage) if err < 0 { return nil, LastError() } @@ -47,12 +54,18 @@ func (b *Branch) BranchDelete() error { return nil } -func (b *Branch) Move(newBranchName string, force bool) (*Branch, error) { +func (b *Branch) Move(newBranchName string, force bool, signature *Signature, message string) (*Branch, error) { newBranch := new(Branch) cNewBranchName := C.CString(newBranchName) cForce := cbool(force) - err := C.git_branch_move(&newBranch.ptr, b.ptr, cNewBranchName, cForce) + cSignature := signature.toC() + defer C.git_signature_free(cSignature) + + cMessage := C.CString(message) + defer C.free(unsafe.Pointer(cMessage)) + + err := C.git_branch_move(&newBranch.ptr, b.ptr, cNewBranchName, cForce, cSignature, cMessage) if err < 0 { return nil, LastError() } @@ -98,22 +111,14 @@ func (b *Branch) Name() (string, error) { func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) { cName := C.CString(canonicalBranchName) - // Obtain the length of the name - ret := C.git_branch_remote_name(nil, 0, repo.ptr, cName) - if ret < 0 { + nameBuf := C.git_buf{} + + if C.git_branch_remote_name(&nameBuf, repo.ptr, cName) < 0 { return "", LastError() } + C.git_buf_free(&nameBuf) - cBuf := (*C.char)(C.malloc(C.size_t(ret))) - defer C.free(unsafe.Pointer(cBuf)) - - // Actually obtain the name - ret = C.git_branch_remote_name(cBuf, C.size_t(ret), repo.ptr, cName) - if ret < 0 { - return "", LastError() - } - - return C.GoString(cBuf), nil + return C.GoStringN(nameBuf.ptr, C.int(nameBuf.size)), nil } func (b *Branch) SetUpstream(upstreamName string) error { @@ -138,19 +143,12 @@ func (b *Branch) Upstream() (*Branch, error) { func (repo *Repository) UpstreamName(canonicalBranchName string) (string, error) { cName := C.CString(canonicalBranchName) - // Obtain the length of the name - ret := C.git_branch_upstream_name(nil, 0, repo.ptr, cName) - if ret < 0 { + nameBuf := C.git_buf{} + + if C.git_branch_upstream_name(&nameBuf, repo.ptr, cName) < 0 { return "", LastError() } + C.git_buf_free(&nameBuf) - cBuf := (*C.char)(C.malloc(C.size_t(ret))) - defer C.free(unsafe.Pointer(cBuf)) - - // Actually obtain the name - ret = C.git_branch_upstream_name(cBuf, C.size_t(ret), repo.ptr, cName) - if ret < 0 { - return "", LastError() - } - return C.GoString(cBuf), nil + return C.GoStringN(nameBuf.ptr, C.int(nameBuf.size)), nil } From fe509411a5e8bd45a1c5607d1cc212d8ebf45541 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Wed, 26 Feb 2014 08:45:38 -0800 Subject: [PATCH 09/21] Add thread locking --- branch.go | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/branch.go b/branch.go index ba82f93..77dbbb8 100644 --- a/branch.go +++ b/branch.go @@ -8,6 +8,7 @@ package git import "C" import ( + "runtime" "unsafe" ) @@ -30,6 +31,7 @@ type Branch struct { } func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool, signature *Signature, message string) (*Reference, error) { + ref := new(Reference) cBranchName := C.CString(branchName) cForce := cbool(force) @@ -40,6 +42,9 @@ func (repo *Repository) CreateBranch(branchName string, target *Commit, force bo cMessage := C.CString(message) defer C.free(unsafe.Pointer(cMessage)) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + err := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.ptr, cForce, cSignature, cMessage) if err < 0 { return nil, LastError() @@ -47,7 +52,11 @@ func (repo *Repository) CreateBranch(branchName string, target *Commit, force bo return ref, nil } -func (b *Branch) BranchDelete() error { +func (b *Branch) Delete() error { + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + if err := C.git_branch_delete(b.ptr); err < 0 { return LastError() } @@ -65,6 +74,9 @@ func (b *Branch) Move(newBranchName string, force bool, signature *Signature, me cMessage := C.CString(message) defer C.free(unsafe.Pointer(cMessage)) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + err := C.git_branch_move(&newBranch.ptr, b.ptr, cNewBranchName, cForce, cSignature, cMessage) if err < 0 { return nil, LastError() @@ -73,6 +85,10 @@ func (b *Branch) Move(newBranchName string, force bool, signature *Signature, me } func (b *Branch) IsHead() (bool, error) { + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + isHead := C.git_branch_is_head(b.ptr) switch isHead { case 1: @@ -89,6 +105,9 @@ func (repo *Repository) LookupBranch(branchName string, bt BranchType) (*Branch, branch := new(Branch) cName := C.CString(branchName) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + err := C.git_branch_lookup(&branch.ptr, repo.ptr, cName, C.git_branch_t(bt)) if err < 0 { return nil, LastError() @@ -100,6 +119,9 @@ func (b *Branch) Name() (string, error) { var cName *C.char defer C.free(unsafe.Pointer(cName)) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + err := C.git_branch_name(&cName, b.ptr) if err < 0 { return "", LastError() @@ -113,6 +135,9 @@ func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) { nameBuf := C.git_buf{} + runtime.LockOSThread() + defer runtime.UnlockOSThread() + if C.git_branch_remote_name(&nameBuf, repo.ptr, cName) < 0 { return "", LastError() } @@ -124,6 +149,9 @@ func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) { func (b *Branch) SetUpstream(upstreamName string) error { cName := C.CString(upstreamName) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + err := C.git_branch_set_upstream(b.ptr, cName) if err < 0 { return LastError() @@ -133,6 +161,10 @@ func (b *Branch) SetUpstream(upstreamName string) error { func (b *Branch) Upstream() (*Branch, error) { upstream := new(Branch) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + err := C.git_branch_upstream(&upstream.ptr, b.ptr) if err < 0 { return nil, LastError() @@ -145,6 +177,9 @@ func (repo *Repository) UpstreamName(canonicalBranchName string) (string, error) nameBuf := C.git_buf{} + runtime.LockOSThread() + defer runtime.UnlockOSThread() + if C.git_branch_upstream_name(&nameBuf, repo.ptr, cName) < 0 { return "", LastError() } From a5df6111003cb032911a793f186aefb8f27243ef Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Wed, 26 Feb 2014 08:50:47 -0800 Subject: [PATCH 10/21] LastError -> MakeGitError --- branch.go | 58 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/branch.go b/branch.go index 77dbbb8..68e1b93 100644 --- a/branch.go +++ b/branch.go @@ -45,9 +45,9 @@ func (repo *Repository) CreateBranch(branchName string, target *Commit, force bo runtime.LockOSThread() defer runtime.UnlockOSThread() - err := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.ptr, cForce, cSignature, cMessage) - if err < 0 { - return nil, LastError() + ret := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.ptr, cForce, cSignature, cMessage) + if ret < 0 { + return nil, MakeGitError(ret) } return ref, nil } @@ -56,9 +56,9 @@ func (b *Branch) Delete() error { runtime.LockOSThread() defer runtime.UnlockOSThread() - - if err := C.git_branch_delete(b.ptr); err < 0 { - return LastError() + ret := C.git_branch_delete(b.ptr) + if ret < 0 { + return MakeGitError(ret) } return nil } @@ -77,9 +77,9 @@ func (b *Branch) Move(newBranchName string, force bool, signature *Signature, me runtime.LockOSThread() defer runtime.UnlockOSThread() - err := C.git_branch_move(&newBranch.ptr, b.ptr, cNewBranchName, cForce, cSignature, cMessage) - if err < 0 { - return nil, LastError() + ret := C.git_branch_move(&newBranch.ptr, b.ptr, cNewBranchName, cForce, cSignature, cMessage) + if ret < 0 { + return nil, MakeGitError(ret) } return newBranch, nil } @@ -89,14 +89,14 @@ func (b *Branch) IsHead() (bool, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - isHead := C.git_branch_is_head(b.ptr) - switch isHead { + ret := C.git_branch_is_head(b.ptr) + switch ret { case 1: return true, nil case 0: return false, nil default: - return false, LastError() + return false, MakeGitError(ret) } } @@ -108,9 +108,9 @@ func (repo *Repository) LookupBranch(branchName string, bt BranchType) (*Branch, runtime.LockOSThread() defer runtime.UnlockOSThread() - err := C.git_branch_lookup(&branch.ptr, repo.ptr, cName, C.git_branch_t(bt)) - if err < 0 { - return nil, LastError() + 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 } @@ -122,9 +122,9 @@ func (b *Branch) Name() (string, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - err := C.git_branch_name(&cName, b.ptr) - if err < 0 { - return "", LastError() + ret := C.git_branch_name(&cName, b.ptr) + if ret < 0 { + return "", MakeGitError(ret) } return C.GoString(cName), nil @@ -138,8 +138,9 @@ func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if C.git_branch_remote_name(&nameBuf, repo.ptr, cName) < 0 { - return "", LastError() + ret := C.git_branch_remote_name(&nameBuf, repo.ptr, cName) + if ret < 0 { + return "", MakeGitError(ret) } C.git_buf_free(&nameBuf) @@ -152,9 +153,9 @@ func (b *Branch) SetUpstream(upstreamName string) error { runtime.LockOSThread() defer runtime.UnlockOSThread() - err := C.git_branch_set_upstream(b.ptr, cName) - if err < 0 { - return LastError() + ret := C.git_branch_set_upstream(b.ptr, cName) + if ret < 0 { + return MakeGitError(ret) } return nil } @@ -165,9 +166,9 @@ func (b *Branch) Upstream() (*Branch, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - err := C.git_branch_upstream(&upstream.ptr, b.ptr) - if err < 0 { - return nil, LastError() + ret := C.git_branch_upstream(&upstream.ptr, b.ptr) + if ret < 0 { + return nil, MakeGitError(ret) } return upstream, nil } @@ -180,8 +181,9 @@ func (repo *Repository) UpstreamName(canonicalBranchName string) (string, error) runtime.LockOSThread() defer runtime.UnlockOSThread() - if C.git_branch_upstream_name(&nameBuf, repo.ptr, cName) < 0 { - return "", LastError() + ret := C.git_branch_upstream_name(&nameBuf, repo.ptr, cName) + if ret < 0 { + return "", MakeGitError(ret) } C.git_buf_free(&nameBuf) From 639b66345c2f00f15deb366cf58b22f0dbedf879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 28 Feb 2014 14:11:21 +0100 Subject: [PATCH 11/21] Fix an old error function call that snuck in --- repository.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/repository.go b/repository.go index bf6aee5..6b7345d 100644 --- a/repository.go +++ b/repository.go @@ -353,7 +353,7 @@ func (v *Repository) EnsureLog(name string) error { defer runtime.UnlockOSThread() if ret := C.git_reference_ensure_log(v.ptr, cname); ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -370,7 +370,7 @@ func (v *Repository) HasLog(name string) (bool, error) { ret := C.git_reference_has_log(v.ptr, cname) if ret < 0 { - return false, LastError() + return false, MakeGitError(ret) } return ret == 1, nil @@ -386,7 +386,7 @@ func (v *Repository) DwimReference(name string) (*Reference, error) { var ptr *C.git_reference if ret := C.git_reference_dwim(&ptr, v.ptr, cname); ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return newReferenceFromC(ptr), nil From f5f8e13744f40300864956fdceb3849c724b9bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 28 Feb 2014 14:26:03 +0100 Subject: [PATCH 12/21] Add a travis script Add a build script and ask Travis to run it. It downloads the tip of libgit2's dev branch and tests against that. --- .travis.yml | 12 ++++++++++++ script/build-libgit2.sh | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 .travis.yml create mode 100755 script/build-libgit2.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..86f8265 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: go + +go: + - 1.0 + - 1.1 + - tip + +env: + - PKG_CONFIG_PATH=libgit2/install/lib/pkgconfig LD_LIBRARY_PATH=libgit2/install/lib + +install: + - script/build-libgit2.sh diff --git a/script/build-libgit2.sh b/script/build-libgit2.sh new file mode 100755 index 0000000..aa43df5 --- /dev/null +++ b/script/build-libgit2.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +set -ex + +git clone --depth 1 --single-branch git://github.com/libgit2/libgit2 libgit2 + +cd libgit2 +cmake -DTHREADSAFE=ON \ + -DBUILD_CLAR=OFF \ + -DCMAKE_INSTALL_PREFIX=$PWD/install \ + . + +make install + +# Let the Go build system know where to find libgit2 +export LD_LIBRARY_PATH="$TMPDIR/libgit2/install/lib" +export PKG_CONFIG_PATH="$TMPDIR/libgit2/install/lib/pkgconfig" From 2c56324ca5e2513b386a7b1f94b3b62881183769 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 28 Feb 2014 10:46:57 -0800 Subject: [PATCH 13/21] fix bad git_buf handling --- branch.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/branch.go b/branch.go index 68e1b93..9f8c22b 100644 --- a/branch.go +++ b/branch.go @@ -142,9 +142,9 @@ func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) { if ret < 0 { return "", MakeGitError(ret) } - C.git_buf_free(&nameBuf) + defer C.git_buf_free(&nameBuf) - return C.GoStringN(nameBuf.ptr, C.int(nameBuf.size)), nil + return C.GoString(nameBuf.ptr), nil } func (b *Branch) SetUpstream(upstreamName string) error { @@ -185,7 +185,7 @@ func (repo *Repository) UpstreamName(canonicalBranchName string) (string, error) if ret < 0 { return "", MakeGitError(ret) } - C.git_buf_free(&nameBuf) + defer C.git_buf_free(&nameBuf) - return C.GoStringN(nameBuf.ptr, C.int(nameBuf.size)), nil + return C.GoString(nameBuf.ptr), nil } From b404c8b86250b5abdbb02714cfdc08254c67df49 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 28 Feb 2014 10:47:56 -0800 Subject: [PATCH 14/21] Remove unused consts --- branch.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/branch.go b/branch.go index 9f8c22b..eb22fde 100644 --- a/branch.go +++ b/branch.go @@ -19,13 +19,6 @@ const ( BranchRemote = C.GIT_BRANCH_REMOTE ) -const ( - RefsDir = "refs/" - RefsHeadsDir = RefsDir + "heads/" - RefsTagsDir = RefsDir + "tags/" - RefsRemotesDir = RefsDir + "remotes/" -) - type Branch struct { Reference } From d6332f9526b48e5145db4ee32d8976cdd0f5972c Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 28 Feb 2014 10:54:16 -0800 Subject: [PATCH 15/21] fix msg handling to treat empty str as nil --- branch.go | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/branch.go b/branch.go index eb22fde..777231c 100644 --- a/branch.go +++ b/branch.go @@ -23,7 +23,7 @@ type Branch struct { Reference } -func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool, signature *Signature, message string) (*Reference, error) { +func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool, signature *Signature, msg string) (*Reference, error) { ref := new(Reference) cBranchName := C.CString(branchName) @@ -32,13 +32,18 @@ func (repo *Repository) CreateBranch(branchName string, target *Commit, force bo cSignature := signature.toC() defer C.git_signature_free(cSignature) - cMessage := C.CString(message) - defer C.free(unsafe.Pointer(cMessage)) + 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, cMessage) + ret := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.ptr, cForce, cSignature, cmsg) if ret < 0 { return nil, MakeGitError(ret) } @@ -56,7 +61,7 @@ func (b *Branch) Delete() error { return nil } -func (b *Branch) Move(newBranchName string, force bool, signature *Signature, message string) (*Branch, error) { +func (b *Branch) Move(newBranchName string, force bool, signature *Signature, msg string) (*Branch, error) { newBranch := new(Branch) cNewBranchName := C.CString(newBranchName) cForce := cbool(force) @@ -64,13 +69,18 @@ func (b *Branch) Move(newBranchName string, force bool, signature *Signature, me cSignature := signature.toC() defer C.git_signature_free(cSignature) - cMessage := C.CString(message) - defer C.free(unsafe.Pointer(cMessage)) + 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, cMessage) + ret := C.git_branch_move(&newBranch.ptr, b.ptr, cNewBranchName, cForce, cSignature, cmsg) if ret < 0 { return nil, MakeGitError(ret) } From 127643eb543cbeac88466956a6394505abc1176e Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 28 Feb 2014 11:08:15 -0800 Subject: [PATCH 16/21] move return outside of switch for go 1.0 / travis --- branch.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/branch.go b/branch.go index 777231c..aee23e4 100644 --- a/branch.go +++ b/branch.go @@ -98,9 +98,8 @@ func (b *Branch) IsHead() (bool, error) { return true, nil case 0: return false, nil - default: - return false, MakeGitError(ret) } + return false, MakeGitError(ret) } From 5e163fa2e8281642dbb9dbf6229a9a20387130d2 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 7 Mar 2014 16:43:20 -0800 Subject: [PATCH 17/21] add blob chunk creation, creation of tree builders for specific trees, minor API cleanup --- blob.go | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-- repository.go | 24 +++++++++++++++---- tree.go | 38 +++++++++++++++++++++--------- walk.go | 21 ++++++++++++----- wrapper.c | 13 +++++++++++ 5 files changed, 137 insertions(+), 24 deletions(-) diff --git a/blob.go b/blob.go index b638c4f..ced2cb1 100644 --- a/blob.go +++ b/blob.go @@ -3,9 +3,18 @@ package git /* #include #include +#include + +extern int _go_git_blob_create_fromchunks(git_oid *id, + git_repository *repo, + const char *hintpath, + void *payload); + */ import "C" import ( + "io" + "runtime" "unsafe" ) @@ -13,13 +22,65 @@ type Blob struct { gitObject } -func (v Blob) Size() int64 { +func (v *Blob) Size() int64 { return int64(C.git_blob_rawsize(v.ptr)) } -func (v Blob) Contents() []byte { +func (v *Blob) Contents() []byte { size := C.int(C.git_blob_rawsize(v.ptr)) buffer := unsafe.Pointer(C.git_blob_rawcontent(v.ptr)) return C.GoBytes(buffer, size) } +func (repo *Repository) CreateBlobFromBuffer(data []byte) (*Oid, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + oid := C.git_oid{} + ecode := C.git_blob_create_frombuffer(&oid, repo.ptr, unsafe.Pointer(&data[0]), C.size_t(len(data))) + if ecode < 0 { + return nil, MakeGitError(ecode) + } + return newOidFromC(&oid), nil +} + +type BlobChunkCallback func(maxLen int) ([]byte, error) + +type BlobCallbackData struct { + Callback BlobChunkCallback + Error error +} + +//export blobChunkCb +func blobChunkCb(buffer *C.char, maxLen C.size_t, payload unsafe.Pointer) int { + data := (*BlobCallbackData)(payload) + goBuf, err := data.Callback(int(maxLen)) + if err == io.EOF { + return 1 + } else if err != nil { + data.Error = err + return -1 + } + C.memcpy(unsafe.Pointer(buffer), unsafe.Pointer(&goBuf), C.size_t(len(goBuf))) + return 0 +} + +func (repo *Repository) CreateBlobFromChunks(hintPath string, callback BlobChunkCallback) (*Oid, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var chintPath *C.char = nil + if len(hintPath) > 0 { + C.CString(hintPath) + defer C.free(unsafe.Pointer(chintPath)) + } + oid := C.git_oid{} + payload := &BlobCallbackData{Callback: callback} + ecode := C._go_git_blob_create_fromchunks(&oid, repo.ptr, chintPath, unsafe.Pointer(payload)) + if payload.Error != nil { + return nil, payload.Error + } + if ecode < 0 { + return nil, MakeGitError(ecode) + } + return newOidFromC(&oid), nil +} diff --git a/repository.go b/repository.go index 6b7345d..d6eadc8 100644 --- a/repository.go +++ b/repository.go @@ -206,19 +206,18 @@ func (v *Repository) CreateSymbolicReference(name, target string, force bool, si } func (v *Repository) Walk() (*RevWalk, error) { - walk := new(RevWalk) + + var walkPtr *C.git_revwalk runtime.LockOSThread() defer runtime.UnlockOSThread() - ecode := C.git_revwalk_new(&walk.ptr, v.ptr) + ecode := C.git_revwalk_new(&walkPtr, v.ptr) if ecode < 0 { return nil, MakeGitError(ecode) } - walk.repo = v - runtime.SetFinalizer(walk, freeRevWalk) - return walk, nil + return revWalkFromC(v, walkPtr), nil } func (v *Repository) CreateCommit( @@ -326,6 +325,21 @@ func (v *Repository) TreeBuilder() (*TreeBuilder, error) { return bld, nil } +func (v *Repository) TreeBuilderFromTree(tree *Tree) (*TreeBuilder, error) { + bld := new(TreeBuilder) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if ret := C.git_treebuilder_create(&bld.ptr, tree.ptr); ret < 0 { + return nil, MakeGitError(ret) + } + runtime.SetFinalizer(bld, (*TreeBuilder).Free) + + bld.repo = v + return bld, nil +} + func (v *Repository) RevparseSingle(spec string) (Object, error) { cspec := C.CString(spec) defer C.free(unsafe.Pointer(cspec)) diff --git a/tree.go b/tree.go index b3340d6..7070ac7 100644 --- a/tree.go +++ b/tree.go @@ -14,13 +14,14 @@ import ( ) type Filemode int + const ( - FilemodeNew Filemode = C.GIT_FILEMODE_NEW - FilemodeTree = C.GIT_FILEMODE_TREE - FilemodeBlob = C.GIT_FILEMODE_BLOB - FilemodeBlobExecutable = C.GIT_FILEMODE_BLOB_EXECUTABLE - FilemodeLink = C.GIT_FILEMODE_LINK - FilemodeCommit = C.GIT_FILEMODE_COMMIT + FilemodeNew Filemode = C.GIT_FILEMODE_NEW + FilemodeTree = C.GIT_FILEMODE_TREE + FilemodeBlob = C.GIT_FILEMODE_BLOB + FilemodeBlobExecutable = C.GIT_FILEMODE_BLOB_EXECUTABLE + FilemodeLink = C.GIT_FILEMODE_LINK + FilemodeCommit = C.GIT_FILEMODE_COMMIT ) type Tree struct { @@ -28,9 +29,9 @@ type Tree struct { } type TreeEntry struct { - Name string - Id *Oid - Type ObjectType + Name string + Id *Oid + Type ObjectType Filemode int } @@ -116,7 +117,7 @@ func (t Tree) Walk(callback TreeWalkCallback) error { } type TreeBuilder struct { - ptr *C.git_treebuilder + ptr *C.git_treebuilder repo *Repository } @@ -125,7 +126,7 @@ func (v *TreeBuilder) Free() { C.git_treebuilder_free(v.ptr) } -func (v *TreeBuilder) Insert(filename string, id *Oid, filemode int) (error) { +func (v *TreeBuilder) Insert(filename string, id *Oid, filemode int) error { cfilename := C.CString(filename) defer C.free(unsafe.Pointer(cfilename)) @@ -140,6 +141,21 @@ func (v *TreeBuilder) Insert(filename string, id *Oid, filemode int) (error) { return nil } +func (v *TreeBuilder) Remove(filename string) error { + cfilename := C.CString(filename) + defer C.free(unsafe.Pointer(cfilename)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := C.git_treebuilder_remove(v.ptr, cfilename) + if err < 0 { + return MakeGitError(err) + } + + return nil +} + func (v *TreeBuilder) Write() (*Oid, error) { oid := new(Oid) diff --git a/walk.go b/walk.go index cdc1a20..71df7bb 100644 --- a/walk.go +++ b/walk.go @@ -14,11 +14,12 @@ import ( // RevWalk type SortType uint + const ( - SortNone SortType = C.GIT_SORT_NONE - SortTopological = C.GIT_SORT_TOPOLOGICAL - SortTime = C.GIT_SORT_TIME - SortReverse = C.GIT_SORT_REVERSE + SortNone SortType = C.GIT_SORT_NONE + SortTopological = C.GIT_SORT_TOPOLOGICAL + SortTime = C.GIT_SORT_TIME + SortReverse = C.GIT_SORT_REVERSE ) type RevWalk struct { @@ -26,6 +27,12 @@ type RevWalk struct { repo *Repository } +func revWalkFromC(repo *Repository, c *C.git_revwalk) *RevWalk { + v := &RevWalk{ptr: c, repo: repo} + runtime.SetFinalizer(v, (*RevWalk).Free) + return v +} + func (v *RevWalk) Reset() { C.git_revwalk_reset(v.ptr) } @@ -92,6 +99,8 @@ func (v *RevWalk) Sorting(sm SortType) { C.git_revwalk_sorting(v.ptr, C.uint(sm)) } -func freeRevWalk(walk *RevWalk) { - C.git_revwalk_free(walk.ptr) +func (v *RevWalk) Free() { + + runtime.SetFinalizer(v, nil) + C.git_revwalk_free(v.ptr) } diff --git a/wrapper.c b/wrapper.c index 2af3974..4ce4c5c 100644 --- a/wrapper.c +++ b/wrapper.c @@ -24,4 +24,17 @@ int _go_git_odb_foreach(git_odb *db, void *payload) { return git_odb_foreach(db, (git_odb_foreach_cb)&odbForEachCb, payload); } + +int _go_blob_chunk_cb(char *buffer, size_t maxLen, void *payload) +{ + return blobChunkCb(buffer, maxLen, payload); +} + +int _go_git_blob_create_fromchunks(git_oid *id, + git_repository *repo, + const char *hintpath, + void *payload) +{ + return git_blob_create_fromchunks(id, repo, hintpath, _go_blob_chunk_cb, payload); +} /* EOF */ From 42fce02197789a1577ff7130f7f46ce47e584aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 11 Mar 2014 03:09:48 +0100 Subject: [PATCH 18/21] Adjust to checkout_opts -> checkout_options --- checkout.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/checkout.go b/checkout.go index d3cd47b..5becd0e 100644 --- a/checkout.go +++ b/checkout.go @@ -2,8 +2,8 @@ package git /* #include -git_checkout_opts git_checkout_opts_init() { - git_checkout_opts ret = GIT_CHECKOUT_OPTS_INIT; +git_checkout_options git_checkout_opts_init() { + git_checkout_options ret = GIT_CHECKOUT_OPTIONS_INIT; return ret; } */ @@ -43,7 +43,7 @@ type CheckoutOpts struct { } // Convert the CheckoutOpts struct to the corresponding C-struct -func populateCheckoutOpts(ptr *C.git_checkout_opts, opts *CheckoutOpts) { +func populateCheckoutOpts(ptr *C.git_checkout_options, opts *CheckoutOpts) { *ptr = C.git_checkout_opts_init() if opts == nil { return @@ -57,7 +57,7 @@ func populateCheckoutOpts(ptr *C.git_checkout_opts, opts *CheckoutOpts) { // 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 + var copts C.git_checkout_options populateCheckoutOpts(&copts, opts) runtime.LockOSThread() @@ -73,7 +73,7 @@ func (v *Repository) Checkout(opts *CheckoutOpts) error { // Updates files in the working tree to match the content of the index. func (v *Repository) CheckoutIndex(index *Index, opts *CheckoutOpts) error { - var copts C.git_checkout_opts + var copts C.git_checkout_options populateCheckoutOpts(&copts, opts) runtime.LockOSThread() From b5b0f3f50e151ef67f8cd7b10044c81920093a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 11 Mar 2014 03:14:36 +0100 Subject: [PATCH 19/21] Remove custom checkout opts init function --- checkout.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/checkout.go b/checkout.go index 5becd0e..0f112a7 100644 --- a/checkout.go +++ b/checkout.go @@ -2,10 +2,6 @@ package git /* #include -git_checkout_options git_checkout_opts_init() { - git_checkout_options ret = GIT_CHECKOUT_OPTIONS_INIT; - return ret; -} */ import "C" import ( @@ -44,7 +40,7 @@ type CheckoutOpts struct { // Convert the CheckoutOpts struct to the corresponding C-struct func populateCheckoutOpts(ptr *C.git_checkout_options, opts *CheckoutOpts) { - *ptr = C.git_checkout_opts_init() + C.git_checkout_init_opts(ptr, 1) if opts == nil { return } From b09c6d8bbe874d6a08e0c91ad3f11bceb74414b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 11 Mar 2014 03:27:35 +0100 Subject: [PATCH 20/21] Move checkout functions options more in line with the library Afjust Checkout -> CheckoutHead and pass nil if the options structure is nil so as not to overide the library's decisions. --- checkout.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/checkout.go b/checkout.go index 0f112a7..5753b09 100644 --- a/checkout.go +++ b/checkout.go @@ -38,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_options, opts *CheckoutOpts) { - C.git_checkout_init_opts(ptr, 1) +// 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 { +// the commit pointed at by HEAD. opts may be nil. +func (v *Repository) CheckoutHead(opts *CheckoutOpts) error { var copts C.git_checkout_options - populateCheckoutOpts(&copts, opts) + + 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) } @@ -67,15 +73,16 @@ 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. opts may be nil. func (v *Repository) CheckoutIndex(index *Index, opts *CheckoutOpts) error { var copts C.git_checkout_options - populateCheckoutOpts(&copts, opts) + ptr := populateCheckoutOpts(&copts, opts) runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_checkout_index(v.ptr, index.ptr, &copts) + ret := C.git_checkout_index(v.ptr, index.ptr, ptr) if ret < 0 { return MakeGitError(ret) } From 263884a908873803cb8a37f80ba89e7b98001f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 11 Mar 2014 03:30:56 +0100 Subject: [PATCH 21/21] CheckoutIndex: allow for index to be nil Allow for the index to be nil and pass that to the library to use the repository's index. --- checkout.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/checkout.go b/checkout.go index 5753b09..5b72b9a 100644 --- a/checkout.go +++ b/checkout.go @@ -74,15 +74,21 @@ func (v *Repository) CheckoutHead(opts *CheckoutOpts) error { } // Updates files in the working tree to match the content of the given -// index. opts may be nil. +// 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_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, ptr) + ret := C.git_checkout_index(v.ptr, iptr, ptr) if ret < 0 { return MakeGitError(ret) }