From 179b69ce21fd1742c4f51e4ae0f2c1ef6929019e Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Wed, 22 May 2013 14:41:42 +0200 Subject: Support for index-entries --- index.go | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/index.go b/index.go index 72b1d5b..90a49de 100644 --- a/index.go +++ b/index.go @@ -7,7 +7,9 @@ package git */ import "C" import ( + "fmt" "runtime" + "time" "unsafe" ) @@ -15,6 +17,18 @@ type Index struct { ptr *C.git_index } +type IndexEntry struct { + ptr *C.git_index_entry + Ctime time.Time + Mtime time.Time + Mode uint + Uid uint + Gid uint + Size uint + Oid *Oid + Path string +} + func newIndexFromC(ptr *C.git_index) *Index { idx := &Index{ptr} runtime.SetFinalizer(idx, (*Index).Free) @@ -47,3 +61,29 @@ func (v *Index) Free() { runtime.SetFinalizer(v, nil) C.git_index_free(v.ptr) } + +func (v *Index) EntryCount() uint { + return uint(C.git_index_entrycount(v.ptr)) +} + +func newIndexEntryFromC(entry *C.git_index_entry) *IndexEntry { + return &IndexEntry{ + entry, + time.Unix(int64(entry.ctime.seconds), int64(entry.ctime.nanoseconds)), + time.Unix(int64(entry.mtime.seconds), int64(entry.mtime.nanoseconds)), + uint(entry.mode), + uint(entry.uid), + uint(entry.gid), + uint(entry.file_size), + newOidFromC(&entry.oid), + C.GoString(entry.path), + } +} + +func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) { + centry := C.git_index_get_byindex(v.ptr, C.size_t(index)) + if centry == nil { + return nil, fmt.Errorf("Index out of Bounds") + } + return newIndexEntryFromC(centry), nil +} -- cgit v1.2.3 From ff5150e6c9a0e9f82eb3c26df96f8839242589ca Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Tue, 8 Oct 2013 02:07:06 +0200 Subject: 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 +} -- cgit v1.2.3 From f03cec5375d22bda9efebb01e78d9e752ee2b498 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Tue, 8 Oct 2013 14:39:05 +0200 Subject: 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) -- cgit v1.2.3 From 771e0c11bc8b1f00cdd6fdddbfe114957aa77ce2 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Tue, 8 Oct 2013 14:44:11 +0200 Subject: 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() } -- cgit v1.2.3 From 6372ec052fb752122bc0662783b8450bbe2ce983 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Tue, 8 Oct 2013 14:49:03 +0200 Subject: 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) -- cgit v1.2.3 From 4c4da3a84621cc57e90bfe55b16342796c80aceb Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Tue, 8 Oct 2013 14:52:22 +0200 Subject: 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) -- cgit v1.2.3 From ed86064871639a956beb5592dc5b64e3d536f882 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Thu, 10 Oct 2013 10:39:49 +0200 Subject: 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 { -- cgit v1.2.3 From 961db94aa21da58a77968099c6b97890e6235d10 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Wed, 30 Oct 2013 15:01:08 +0100 Subject: 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) -- cgit v1.2.3 From 313e1126dd0c974910de74f1b6bbc0fdcbbfd06b Mon Sep 17 00:00:00 2001 From: Jason Toffaletti Date: Thu, 2 Jan 2014 23:33:08 +0000 Subject: add git_submodule_recurse_t type --- submodule.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/submodule.go b/submodule.go index 48ea151..dadc785 100644 --- a/submodule.go +++ b/submodule.go @@ -56,6 +56,13 @@ const ( SubmoduleStatusWdUntracked = C.GIT_SUBMODULE_STATUS_WD_UNTRACKED ) +type SubmoduleRecurse int +const ( + SubmoduleRecurseNo SubmoduleRecurse = C.GIT_SUBMODULE_RECURSE_NO + SubmoduleRecurseYes = C.GIT_SUBMODULE_RECURSE_YES + SubmoduleRecurseOnDemand = C.GIT_SUBMODULE_RECURSE_ONDEMAND +) + func SubmoduleStatusIsUnmodified(status int) bool { o := SubmoduleStatus(status) & ^(SubmoduleStatusInHead | SubmoduleStatusInIndex | SubmoduleStatusInConfig | SubmoduleStatusInWd) @@ -236,11 +243,11 @@ func (sub *Submodule) FetchRecurseSubmodules() bool { return true } -func (sub *Submodule) SetFetchRecurseSubmodules(v bool) error { +func (sub *Submodule) SetFetchRecurseSubmodules(v SubmoduleRecurse) error { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_submodule_set_fetch_recurse_submodules(sub.ptr, cbool(v)) + ret := C.git_submodule_set_fetch_recurse_submodules(sub.ptr, C.git_submodule_recurse_t(v)) if ret < 0 { return LastError() } -- cgit v1.2.3 From e825d66fba2cb4169c7f3b0a43c491cf9e8c0738 Mon Sep 17 00:00:00 2001 From: Jason Toffaletti Date: Sat, 4 Jan 2014 00:40:21 +0000 Subject: work in progress wrapping git_clone --- clone.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ git.go | 2 +- remote.go | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ wrapper.c | 14 +++++++++++ 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 clone.go create mode 100644 remote.go diff --git a/clone.go b/clone.go new file mode 100644 index 0000000..672c325 --- /dev/null +++ b/clone.go @@ -0,0 +1,69 @@ +package git + +/* +#include +#include + +static git_clone_options git_clone_options_init() { + git_clone_options ret = GIT_CLONE_OPTIONS_INIT; + return ret; +} + +*/ +import "C" +import ( + "runtime" + "unsafe" +) + +type CloneOptions struct { + *CheckoutOpts + *RemoteCallbacks + Bare bool + IgnoreCertErrors bool + RemoteName string + CheckoutBranch string +} + +func Clone(url string, path string, options *CloneOptions) (*Repository, error) { + repo := new(Repository) + + curl := C.CString(url) + defer C.free(unsafe.Pointer(curl)) + + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + var copts C.git_clone_options + populateCloneOptions(&copts, options) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_clone(&repo.ptr, curl, cpath, &copts) + if ret < 0 { + return nil, LastError() + } + + runtime.SetFinalizer(repo, (*Repository).Free) + return repo, nil +} + +func populateCloneOptions(ptr *C.git_clone_options, opts *CloneOptions) { + *ptr = C.git_clone_options_init() + if opts == nil { + return + } + populateCheckoutOpts(&ptr.checkout_opts, opts.CheckoutOpts) + populateRemoteCallbacks(&ptr.remote_callbacks, opts.RemoteCallbacks) + if opts.Bare { + ptr.bare = 1 + } else { + ptr.bare = 0 + } + if opts.IgnoreCertErrors { + ptr.ignore_cert_errors = 1 + } else { + ptr.ignore_cert_errors = 0 + } +} + diff --git a/git.go b/git.go index 28196c8..07892e4 100644 --- a/git.go +++ b/git.go @@ -1,7 +1,7 @@ package git /* -#cgo pkg-config: libgit2 +#cgo pkg-config: --static libgit2 #include #include */ diff --git a/remote.go b/remote.go new file mode 100644 index 0000000..47866ed --- /dev/null +++ b/remote.go @@ -0,0 +1,85 @@ +package git + +/* +#include +#include + +static git_remote_callbacks git_remote_callbacks_init() { + git_remote_callbacks ret = GIT_REMOTE_CALLBACKS_INIT; + return ret; +} + +extern void _setup_callbacks(git_remote_callbacks *callbacks); + +*/ +import "C" +import ( + "unsafe" +) + +type RemoteCompletion uint +const ( + RemoteCompletionDownload RemoteCompletion = C.GIT_REMOTE_COMPLETION_DOWNLOAD + RemoteCompletionIndexing = C.GIT_REMOTE_COMPLETION_INDEXING + RemoteCompletionError = C.GIT_REMOTE_COMPLETION_ERROR +) + +type ProgressCallback func(str string) int +type CompletionCallback func(RemoteCompletion) int +type CredentialsCallback func(url string, username_from_url string, allowed_types uint) int // FIXME +type TransferProgressCallback func() int // FIXME +type UpdateTipsCallback func(refname string, a *Oid, b *Oid) int + +//export progressCallback +func progressCallback(_str *C.char, _len C.int, data unsafe.Pointer) int { + callbacks := (*RemoteCallbacks)(data) + str := C.GoStringN(_str, _len) + return callbacks.ProgressCallback(str) +} + +//export completionCallback +func completionCallback(completion_type C.git_remote_completion_type, data unsafe.Pointer) int { + callbacks := (*RemoteCallbacks)(data) + return callbacks.CompletionCallback((RemoteCompletion)(completion_type)) +} + +//export credentialsCallback +func credentialsCallback(_cred **C.git_cred, _url *C.char, _username_from_url *C.char, allowed_types uint, data unsafe.Pointer) int { + callbacks := (*RemoteCallbacks)(data) + //cred := C.GoString(_cred) + url := C.GoString(_url) + username_from_url := C.GoString(_username_from_url) + return callbacks.CredentialsCallback(url, username_from_url, allowed_types) +} + +//export transferProgressCallback +func transferProgressCallback(stats C.git_transfer_progress, data unsafe.Pointer) int { + callbacks := (*RemoteCallbacks)(data) + return callbacks.TransferProgressCallback() +} + +//export updateTipsCallback +func updateTipsCallback(_refname *C.char, _a *C.git_oid, _b *C.git_oid, data unsafe.Pointer) int { + callbacks := (*RemoteCallbacks)(data) + refname := C.GoString(_refname) + a := newOidFromC(_a) + b := newOidFromC(_b) + return callbacks.UpdateTipsCallback(refname, a, b) +} + +type RemoteCallbacks struct { + ProgressCallback + CompletionCallback + CredentialsCallback + TransferProgressCallback + UpdateTipsCallback +} + +func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) { + *ptr = C.git_remote_callbacks_init() + if callbacks == nil { + return + } + C._setup_callbacks(ptr) + ptr.payload = unsafe.Pointer(callbacks) +} diff --git a/wrapper.c b/wrapper.c index 2af3974..ef05c2d 100644 --- a/wrapper.c +++ b/wrapper.c @@ -24,4 +24,18 @@ int _go_git_odb_foreach(git_odb *db, void *payload) { return git_odb_foreach(db, (git_odb_foreach_cb)&odbForEachCb, payload); } + +void _setup_callbacks(git_remote_callbacks *callbacks) { + typedef int (*progress_cb)(const char *str, int len, void *data); + typedef int (*completion_cb)(git_remote_completion_type type, void *data); + typedef int (*credentials_cb)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); + typedef int (*transfer_progress_cb)(const git_transfer_progress *stats, void *data); + typedef int (*update_tips_cb)(const char *refname, const git_oid *a, const git_oid *b, void *data); + callbacks->progress = (progress_cb)progressCallback; + callbacks->completion = (completion_cb)completionCallback; + callbacks->credentials = (credentials_cb)credentialsCallback; + callbacks->transfer_progress = (transfer_progress_cb)transferProgressCallback; + callbacks->update_tips = (update_tips_cb)updateTipsCallback; +} + /* EOF */ -- cgit v1.2.3 From 5d8a14d108ac963a4865cd03e20e56b28ee9626e Mon Sep 17 00:00:00 2001 From: Jason Toffaletti Date: Sun, 5 Jan 2014 20:55:32 +0000 Subject: wrappers for git_cred, git_transfer_progress. don't call nil callbacks. --- remote.go | 90 ++++++++++++++++++++++++++++++++++++++++++++---------------- transport.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 23 deletions(-) create mode 100644 transport.go diff --git a/remote.go b/remote.go index 47866ed..ebf1fd4 100644 --- a/remote.go +++ b/remote.go @@ -13,9 +13,11 @@ extern void _setup_callbacks(git_remote_callbacks *callbacks); */ import "C" -import ( - "unsafe" -) +import "unsafe" + +type TransferProgress struct { + ptr *C.git_transfer_progress +} type RemoteCompletion uint const ( @@ -26,60 +28,102 @@ const ( type ProgressCallback func(str string) int type CompletionCallback func(RemoteCompletion) int -type CredentialsCallback func(url string, username_from_url string, allowed_types uint) int // FIXME -type TransferProgressCallback func() int // FIXME +type CredentialsCallback func(url string, username_from_url string, allowed_types CredType) (int, Cred) +type TransferProgressCallback func(stats TransferProgress) int type UpdateTipsCallback func(refname string, a *Oid, b *Oid) int +type RemoteCallbacks struct { + ProgressCallback + CompletionCallback + CredentialsCallback + TransferProgressCallback + UpdateTipsCallback +} + +func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) { + *ptr = C.git_remote_callbacks_init() + if callbacks == nil { + return + } + C._setup_callbacks(ptr) + ptr.payload = unsafe.Pointer(callbacks) +} + //export progressCallback func progressCallback(_str *C.char, _len C.int, data unsafe.Pointer) int { callbacks := (*RemoteCallbacks)(data) - str := C.GoStringN(_str, _len) + if callbacks.ProgressCallback == nil { + return 0 + } + str := C.GoStringN(_str, _len) return callbacks.ProgressCallback(str) } //export completionCallback func completionCallback(completion_type C.git_remote_completion_type, data unsafe.Pointer) int { callbacks := (*RemoteCallbacks)(data) + if callbacks.CompletionCallback == nil { + return 0 + } return callbacks.CompletionCallback((RemoteCompletion)(completion_type)) } //export credentialsCallback func credentialsCallback(_cred **C.git_cred, _url *C.char, _username_from_url *C.char, allowed_types uint, data unsafe.Pointer) int { callbacks := (*RemoteCallbacks)(data) - //cred := C.GoString(_cred) + if callbacks.CredentialsCallback == nil { + return 0 + } url := C.GoString(_url) username_from_url := C.GoString(_username_from_url) - return callbacks.CredentialsCallback(url, username_from_url, allowed_types) + ret, cred := callbacks.CredentialsCallback(url, username_from_url, (CredType)(allowed_types)) + if gcred, ok := cred.(gitCred); ok { + *_cred = gcred.ptr + } + return ret } //export transferProgressCallback -func transferProgressCallback(stats C.git_transfer_progress, data unsafe.Pointer) int { +func transferProgressCallback(stats *C.git_transfer_progress, data unsafe.Pointer) int { callbacks := (*RemoteCallbacks)(data) - return callbacks.TransferProgressCallback() + if callbacks.TransferProgressCallback == nil { + return 0 + } + return callbacks.TransferProgressCallback(TransferProgress{stats}) } //export updateTipsCallback func updateTipsCallback(_refname *C.char, _a *C.git_oid, _b *C.git_oid, data unsafe.Pointer) int { callbacks := (*RemoteCallbacks)(data) + if callbacks.UpdateTipsCallback == nil { + return 0 + } refname := C.GoString(_refname) a := newOidFromC(_a) b := newOidFromC(_b) return callbacks.UpdateTipsCallback(refname, a, b) } -type RemoteCallbacks struct { - ProgressCallback - CompletionCallback - CredentialsCallback - TransferProgressCallback - UpdateTipsCallback +func (o TransferProgress) TotalObjects() uint { + return uint(o.ptr.total_objects) } -func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) { - *ptr = C.git_remote_callbacks_init() - if callbacks == nil { - return - } - C._setup_callbacks(ptr) - ptr.payload = unsafe.Pointer(callbacks) +func (o TransferProgress) IndexedObjects() uint { + return uint(o.ptr.indexed_objects) +} + +func (o TransferProgress) ReceivedObjects() uint { + return uint(o.ptr.received_objects) +} + +func (o TransferProgress) LocalObjects() uint { + return uint(o.ptr.local_objects) +} + +func (o TransferProgress) TotalDeltas() uint { + return uint(o.ptr.total_deltas) +} + +func (o TransferProgress) ReceivedBytes() uint { + return uint(o.ptr.received_bytes) } diff --git a/transport.go b/transport.go new file mode 100644 index 0000000..e97a70c --- /dev/null +++ b/transport.go @@ -0,0 +1,79 @@ +package git + +/* +#include +#include +*/ +import "C" +import "unsafe" + +type CredType uint +const ( + CredTypeUserpassPlaintext CredType = C.GIT_CREDTYPE_USERPASS_PLAINTEXT + CredTypeSshKey = C.GIT_CREDTYPE_SSH_KEY + CredTypeSshCustom = C.GIT_CREDTYPE_SSH_CUSTOM + CredTypeDefault = C.GIT_CREDTYPE_DEFAULT +) + +type Cred interface { + HasUsername() bool + Type() CredType +} + +type gitCred struct { + ptr *C.git_cred +} + +func (o gitCred) HasUsername() bool { + if C.git_cred_has_username(o.ptr) == 1 { + return true + } + return false +} + +func (o gitCred) Type() CredType { + return (CredType)(o.ptr.credtype); +} + +func credFromC(ptr *C.git_cred) Cred { + return gitCred{ptr} +} + +func NewCredUserpassPlaintext(username string, password string) (int, Cred) { + cred := gitCred{} + cusername := C.CString(username) + defer C.free(unsafe.Pointer(cusername)) + cpassword := C.CString(password) + defer C.free(unsafe.Pointer(cpassword)) + ret := C.git_cred_userpass_plaintext_new(&cred.ptr, cusername, cpassword) + return int(ret), cred +} + +func NewCredSshKey(username string, publickey string, privatekey string, passphrase string) (int, Cred) { + cred := gitCred{} + cusername := C.CString(username) + defer C.free(unsafe.Pointer(cusername)) + cpublickey := C.CString(publickey) + defer C.free(unsafe.Pointer(cpublickey)) + cprivatekey := C.CString(privatekey) + defer C.free(unsafe.Pointer(cprivatekey)) + cpassphrase := C.CString(passphrase) + defer C.free(unsafe.Pointer(cpassphrase)) + ret := C.git_cred_ssh_key_new(&cred.ptr, cusername, cpublickey, cprivatekey, cpassphrase) + return int(ret), cred +} + +func NewCredSshKeyFromAgent(username string) (int, Cred) { + cred := gitCred{} + cusername := C.CString(username) + defer C.free(unsafe.Pointer(cusername)) + ret := C.git_cred_ssh_key_from_agent(&cred.ptr, cusername) + return int(ret), cred +} + +func NewCredDefault() (int, Cred) { + cred := gitCred{} + ret := C.git_cred_default_new(&cred.ptr) + return int(ret), cred +} + -- cgit v1.2.3 From d1245446685ccdc632b6a9cee65391cbe4eac4df Mon Sep 17 00:00:00 2001 From: Jason Toffaletti Date: Mon, 6 Jan 2014 16:55:29 +0000 Subject: minor --- remote.go | 12 ++++-------- wrapper.c | 7 ++++++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/remote.go b/remote.go index ebf1fd4..0645291 100644 --- a/remote.go +++ b/remote.go @@ -4,12 +4,8 @@ package git #include #include -static git_remote_callbacks git_remote_callbacks_init() { - git_remote_callbacks ret = GIT_REMOTE_CALLBACKS_INIT; - return ret; -} - -extern void _setup_callbacks(git_remote_callbacks *callbacks); +extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks); +extern git_remote_callbacks _go_git_remote_callbacks_init(); */ import "C" @@ -41,11 +37,11 @@ type RemoteCallbacks struct { } func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) { - *ptr = C.git_remote_callbacks_init() + *ptr = C._go_git_remote_callbacks_init() if callbacks == nil { return } - C._setup_callbacks(ptr) + C._go_git_setup_callbacks(ptr) ptr.payload = unsafe.Pointer(callbacks) } diff --git a/wrapper.c b/wrapper.c index ef05c2d..4543822 100644 --- a/wrapper.c +++ b/wrapper.c @@ -25,7 +25,7 @@ int _go_git_odb_foreach(git_odb *db, void *payload) return git_odb_foreach(db, (git_odb_foreach_cb)&odbForEachCb, payload); } -void _setup_callbacks(git_remote_callbacks *callbacks) { +void _go_git_setup_callbacks(git_remote_callbacks *callbacks) { typedef int (*progress_cb)(const char *str, int len, void *data); typedef int (*completion_cb)(git_remote_completion_type type, void *data); typedef int (*credentials_cb)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); @@ -38,4 +38,9 @@ void _setup_callbacks(git_remote_callbacks *callbacks) { callbacks->update_tips = (update_tips_cb)updateTipsCallback; } +git_remote_callbacks _go_git_remote_callbacks_init() { + git_remote_callbacks ret = GIT_REMOTE_CALLBACKS_INIT; + return ret; +} + /* EOF */ -- cgit v1.2.3 From 32bf5f0a234e0c3cd00dc8eec349ee820f765f19 Mon Sep 17 00:00:00 2001 From: Jason Toffaletti Date: Mon, 6 Jan 2014 20:05:35 +0000 Subject: wip wrapping git_remote --- clone.go | 11 ++++ remote.go | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ wrapper.c | 8 +++ 3 files changed, 212 insertions(+) diff --git a/clone.go b/clone.go index 672c325..425e179 100644 --- a/clone.go +++ b/clone.go @@ -37,6 +37,17 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error) var copts C.git_clone_options populateCloneOptions(&copts, options) + // finish populating clone options here so we can defer CString free + if len(options.RemoteName) != 0 { + copts.remote_name = C.CString(options.RemoteName) + defer C.free(unsafe.Pointer(copts.remote_name)) + } + + if len(options.CheckoutBranch) != 0 { + copts.checkout_branch = C.CString(options.CheckoutBranch) + defer C.free(unsafe.Pointer(copts.checkout_branch)) + } + runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_clone(&repo.ptr, curl, cpath, &copts) diff --git a/remote.go b/remote.go index 0645291..5300c42 100644 --- a/remote.go +++ b/remote.go @@ -6,10 +6,13 @@ package git extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks); extern git_remote_callbacks _go_git_remote_callbacks_init(); +extern void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n); +extern char *_go_git_get_strarray_n(git_strarray *array, size_t n); */ import "C" import "unsafe" +import "runtime" type TransferProgress struct { ptr *C.git_transfer_progress @@ -36,6 +39,30 @@ type RemoteCallbacks struct { UpdateTipsCallback } +type Remote interface { + Save() int + Owner() Repository + Name() string + Url() string + PushUrl() string + + SetUrl(url string) int + SetPushUrl(url string) int + + AddFetch(refspec string) int + GetFetchRefspecs() (err int, refspecs []string) + SetFetchRefspecs(refspecs []string) int + AddPush(refspec string) int + GetPushRefspecs() (err int, refspecs []string) + SetPushRefspecs(refspecs []string) int + ClearRefspecs() + RefspecCount() uint +} + +type gitRemote struct { + ptr *C.git_remote +} + func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) { *ptr = C._go_git_remote_callbacks_init() if callbacks == nil { @@ -123,3 +150,169 @@ func (o TransferProgress) TotalDeltas() uint { func (o TransferProgress) ReceivedBytes() uint { return uint(o.ptr.received_bytes) } + +func RemoteIsValidName(name string) bool { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + if C.git_remote_is_valid_name(cname) == 1 { + return true + } + return false +} + +func freeRemote(o *gitRemote) { + C.git_remote_free(o.ptr) +} + +func CreateRemote(repo *Repository, name string, url string) (int, Remote) { + remote := &gitRemote{} + runtime.SetFinalizer(remote, freeRemote) + + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + curl := C.CString(url) + defer C.free(unsafe.Pointer(curl)) + + ret := C.git_remote_create(&remote.ptr, repo.ptr, cname, curl) + return int(ret), remote +} + +func CreateRemoteWithFetchspec(repo *Repository, name string, url string, fetch string) (int, Remote) { + remote := &gitRemote{} + runtime.SetFinalizer(remote, freeRemote) + + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + curl := C.CString(url) + defer C.free(unsafe.Pointer(curl)) + cfetch := C.CString(fetch) + defer C.free(unsafe.Pointer(cfetch)) + + ret := C.git_remote_create_with_fetchspec(&remote.ptr, repo.ptr, cname, curl, cfetch) + return int(ret), remote +} + +func CreateRemoteInMemory(repo *Repository, fetch string, url string) (int, Remote) { + remote := &gitRemote{} + runtime.SetFinalizer(remote, freeRemote) + + curl := C.CString(url) + defer C.free(unsafe.Pointer(curl)) + cfetch := C.CString(fetch) + defer C.free(unsafe.Pointer(cfetch)) + + ret := C.git_remote_create_inmemory(&remote.ptr, repo.ptr, cfetch, curl) + return int(ret), remote +} + +func LoadRemote(repo *Repository, name string) (int, Remote) { + remote := &gitRemote{} + runtime.SetFinalizer(remote, freeRemote) + + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + ret := C.git_remote_load(&remote.ptr, repo.ptr, cname) + return int(ret), remote +} + +func (o *gitRemote) Save() int { + return int(C.git_remote_save(o.ptr)) +} + +func (o *gitRemote) Owner() Repository { + return Repository{C.git_remote_owner(o.ptr)} +} + +func (o *gitRemote) Name() string { + return C.GoString(C.git_remote_name(o.ptr)) +} + +func (o *gitRemote) Url() string { + return C.GoString(C.git_remote_url(o.ptr)) +} + +func (o *gitRemote) PushUrl() string { + return C.GoString(C.git_remote_pushurl(o.ptr)) +} + +func (o *gitRemote) SetUrl(url string) int { + curl := C.CString(url) + defer C.free(unsafe.Pointer(curl)) + return int(C.git_remote_set_url(o.ptr, curl)) +} + +func (o *gitRemote) SetPushUrl(url string) int { + curl := C.CString(url) + defer C.free(unsafe.Pointer(curl)) + return int(C.git_remote_set_pushurl(o.ptr, curl)) +} + +func (o *gitRemote) AddFetch(refspec string) int { + crefspec := C.CString(refspec) + defer C.free(unsafe.Pointer(crefspec)) + return int(C.git_remote_add_fetch(o.ptr, crefspec)) +} + +func (o *gitRemote) GetFetchRefspecs() (err int, refspecs []string) { + crefspecs := C.git_strarray{} + err = int(C.git_remote_get_fetch_refspecs(&crefspecs, o.ptr)) + defer C.git_strarray_free(&crefspecs) + refspecs = make([]string, crefspecs.count) + + for i := 0; i < int(crefspecs.count); i++ { + refspecs[i] = C.GoString(C._go_git_get_strarray_n(&crefspecs, C.size_t(i))) + } + return +} + +func (o *gitRemote) SetFetchRefspecs(refspecs []string) int { + crefspecs := C.git_strarray{} + crefspecs.count = C.size_t(len(refspecs)) + crefspecs.strings = (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(crefspecs.count)))) + for i, refspec := range refspecs { + C._go_git_set_strarray_n(&crefspecs, C.CString(refspec), C.size_t(i)) + } + defer C.git_strarray_free(&crefspecs) + + return int(C.git_remote_set_fetch_refspecs(o.ptr, &crefspecs)) +} + +func (o *gitRemote) AddPush(refspec string) int { + crefspec := C.CString(refspec) + defer C.free(unsafe.Pointer(crefspec)) + return int(C.git_remote_add_push(o.ptr, crefspec)) +} + +func (o *gitRemote) GetPushRefspecs() (err int, refspecs []string) { + crefspecs := C.git_strarray{} + err = int(C.git_remote_get_push_refspecs(&crefspecs, o.ptr)) + defer C.git_strarray_free(&crefspecs) + refspecs = make([]string, crefspecs.count) + + for i := 0; i < int(crefspecs.count); i++ { + refspecs[i] = C.GoString(C._go_git_get_strarray_n(&crefspecs, C.size_t(i))) + } + return +} + +func (o *gitRemote) SetPushRefspecs(refspecs []string) int { + crefspecs := C.git_strarray{} + crefspecs.count = C.size_t(len(refspecs)) + crefspecs.strings = (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(crefspecs.count)))) + for i, refspec := range refspecs { + C._go_git_set_strarray_n(&crefspecs, C.CString(refspec), C.size_t(i)) + } + defer C.git_strarray_free(&crefspecs) + + return int(C.git_remote_set_push_refspecs(o.ptr, &crefspecs)) +} + +func (o *gitRemote) ClearRefspecs() { + C.git_remote_clear_refspecs(o.ptr) +} + +func (o *gitRemote) RefspecCount() uint { + return uint(C.git_remote_refspec_count(o.ptr)) +} + diff --git a/wrapper.c b/wrapper.c index 4543822..7519a96 100644 --- a/wrapper.c +++ b/wrapper.c @@ -43,4 +43,12 @@ git_remote_callbacks _go_git_remote_callbacks_init() { return ret; } +void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n) { + array->strings[n] = str; +} + +char *_go_git_get_strarray_n(git_strarray *array, size_t n) { + return array->strings[n]; +} + /* EOF */ -- cgit v1.2.3 From fbd8698002c3eb398215f6dd6778a34edff5c2be Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 11 Sep 2013 23:31:24 +0200 Subject: Add a few missing config setters and getters --- config.go | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/config.go b/config.go index 2aa073a..adaa069 100644 --- a/config.go +++ b/config.go @@ -14,7 +14,7 @@ type Config struct { ptr *C.git_config } -func (c *Config) LookupInt32(name string) (v int32, err error) { +func (c *Config) LookupInt32(name string) (int32, error) { var out C.int32_t cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -30,7 +30,7 @@ func (c *Config) LookupInt32(name string) (v int32, err error) { return int32(out), nil } -func (c *Config) LookupInt64(name string) (v int64, err error) { +func (c *Config) LookupInt64(name string) (int64, error) { var out C.int64_t cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -46,7 +46,7 @@ func (c *Config) LookupInt64(name string) (v int64, err error) { return int64(out), nil } -func (c *Config) LookupString(name string) (v string, err error) { +func (c *Config) LookupString(name string) (string, error) { var ptr *C.char cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -62,7 +62,21 @@ func (c *Config) LookupString(name string) (v string, err error) { return C.GoString(ptr), nil } -func (c *Config) Set(name, value string) (err error) { + +func (c *Config) LookupBool(name string) (bool, error) { + var out C.int + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + ret := C.git_config_get_bool(&out, c.ptr, cname) + if ret < 0 { + return false, LastError() + } + + return out != 0, nil +} + +func (c *Config) SetString(name, value string) (err error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -84,3 +98,70 @@ func (c *Config) Free() { runtime.SetFinalizer(c, nil) C.git_config_free(c.ptr) } + +func (c *Config) SetInt32(name string, value int32) (err error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + ret := C.git_config_set_int32(c.ptr, cname, C.int32_t(value)) + if ret < 0 { + return LastError() + } + + return nil +} + +func (c *Config) SetInt64(name string, value int64) (err error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + ret := C.git_config_set_int64(c.ptr, cname, C.int64_t(value)) + if ret < 0 { + return LastError() + } + + return nil +} + +func (c *Config) SetBool(name string, value bool) (err error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + ret := C.git_config_set_bool(c.ptr, cname, cbool(value)) + if ret < 0 { + return LastError() + } + + return nil +} + +func (c *Config) SetMultivar(name, regexp, value string) (err error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + cregexp := C.CString(regexp) + defer C.free(unsafe.Pointer(cregexp)) + + cvalue := C.CString(value) + defer C.free(unsafe.Pointer(cvalue)) + + ret := C.git_config_set_multivar(c.ptr, cname, cregexp, cvalue) + if ret < 0 { + return LastError() + } + + return nil +} + +func (c *Config) Delete(name string) error { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + ret := C.git_config_delete_entry(c.ptr, cname) + + if ret < 0 { + return LastError() + } + + return nil +} -- cgit v1.2.3 From 129105d410a9fe188d64bab5833d9c13f981101f Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Thu, 12 Sep 2013 01:01:52 +0200 Subject: Add a few more missing config functions --- config.go | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/config.go b/config.go index adaa069..76d25c7 100644 --- a/config.go +++ b/config.go @@ -10,10 +10,61 @@ import ( "unsafe" ) +type ConfigLevel int + +const ( + // System-wide configuration file; /etc/gitconfig on Linux systems + ConfigLevelSystem ConfigLevel = C.GIT_CONFIG_LEVEL_SYSTEM + + // XDG compatible configuration file; typically ~/.config/git/config + ConfigLevelXDG ConfigLevel = C.GIT_CONFIG_LEVEL_XDG + + // User-specific configuration file (also called Global configuration + // file); typically ~/.gitconfig + ConfigLevelGlobal ConfigLevel = C.GIT_CONFIG_LEVEL_GLOBAL + + // Repository specific configuration file; $WORK_DIR/.git/config on + // non-bare repos + ConfigLevelLocal ConfigLevel = C.GIT_CONFIG_LEVEL_LOCAL + + // Application specific configuration file; freely defined by applications + ConfigLevelApp ConfigLevel = C.GIT_CONFIG_LEVEL_APP + + // Represents the highest level available config file (i.e. the most + // specific config file available that actually is loaded) + ConfigLevelHighest ConfigLevel = C.GIT_CONFIG_HIGHEST_LEVEL +) + + type Config struct { ptr *C.git_config } +// NewConfig creates a new empty configuration object +func NewConfig() (*Config, error) { + config := new(Config) + + ret := C.git_config_new(&config.ptr) + if ret < 0 { + return nil, LastError() + } + + return config, nil +} + +// AddFile adds a file-backed backend to the config object at the specified level. +func (c *Config) AddFile(path string, level ConfigLevel, force bool) error { + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + ret := C.git_config_add_file_ondisk(c.ptr, cpath, C.git_config_level_t(level), cbool(force)) + if ret < 0 { + return LastError() + } + + return nil +} + func (c *Config) LookupInt32(name string) (int32, error) { var out C.int32_t cname := C.CString(name) @@ -165,3 +216,38 @@ func (c *Config) Delete(name string) error { return nil } + +// OpenLevel creates a single-level focused config object from a multi-level one +func (c *Config) OpenLevel(parent *Config, level ConfigLevel) (*Config, error) { + config := new(Config) + ret := C.git_config_open_level(&config.ptr, parent.ptr, C.git_config_level_t(level)) + if ret < 0 { + return nil, LastError() + } + + return config, nil +} + +// OpenOndisk creates a new config instance containing a single on-disk file +func OpenOndisk(parent *Config, path string) (*Config, error) { + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + config := new(Config) + ret := C.git_config_open_ondisk(&config.ptr, cpath) + if ret < 0 { + return nil, LastError() + } + + return config, nil +} + +// Refresh refreshes the configuration to reflect any changes made externally e.g. on disk +func (c *Config) Refresh() error { + ret := C.git_config_refresh(c.ptr) + if ret < 0 { + return LastError() + } + + return nil +} -- cgit v1.2.3 From af2446b1da13a86df348e8f167a220a849619b54 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Thu, 12 Sep 2013 01:39:35 +0200 Subject: Add iterators and ConfigEntry --- config.go | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/config.go b/config.go index 76d25c7..f1fafde 100644 --- a/config.go +++ b/config.go @@ -35,6 +35,19 @@ const ( ConfigLevelHighest ConfigLevel = C.GIT_CONFIG_HIGHEST_LEVEL ) +type ConfigEntry struct { + Name string + Value string + Level ConfigLevel +} + +func newConfigEntryFromC(centry *C.git_config_entry) *ConfigEntry { + return &ConfigEntry{ + Name: C.GoString(centry.name), + Value: C.GoString(centry.value), + Level: ConfigLevel(centry.level), + } +} type Config struct { ptr *C.git_config @@ -127,6 +140,55 @@ func (c *Config) LookupBool(name string) (bool, error) { return out != 0, nil } +func (c *Config) NewMultivarIterator(name, regexp string) (*ConfigIterator, error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + var cregexp *C.char + if regexp == "" { + cregexp = nil + } else { + cregexp = C.CString(regexp) + defer C.free(unsafe.Pointer(cregexp)) + } + + iter := new(ConfigIterator) + ret := C.git_config_multivar_iterator_new(&iter.ptr, c.ptr, cname, cregexp) + if ret < 0 { + return nil, LastError() + } + + runtime.SetFinalizer(iter, (*ConfigIterator).Free) + return iter, nil +} + +// NewIterator creates an iterator over each entry in the +// configuration +func (c *Config) NewIterator() (*ConfigIterator, error) { + iter := new(ConfigIterator) + ret := C.git_config_iterator_new(&iter.ptr, c.ptr) + if ret < 0 { + return nil, LastError() + } + + return iter, nil +} + +// 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) + cregexp := C.CString(regexp) + defer C.free(unsafe.Pointer(cregexp)) + + ret := C.git_config_iterator_glob_new(&iter.ptr, c.ptr, cregexp) + if ret < 0 { + return nil, LastError() + } + + return iter, nil +} + func (c *Config) SetString(name, value string) (err error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -251,3 +313,25 @@ func (c *Config) Refresh() error { return nil } + +type ConfigIterator struct { + ptr *C.git_config_iterator +} + +// Next returns the next entry for this iterator +func (iter *ConfigIterator) Next() (*ConfigEntry, error) { + var centry *C.git_config_entry + + ret := C.git_config_next(¢ry, iter.ptr) + if ret < 0 { + return nil, LastError() + } + + return newConfigEntryFromC(centry), nil +} + +func (iter *ConfigIterator) Free() { + runtime.SetFinalizer(iter, nil) + C.free(unsafe.Pointer(iter.ptr)) +} + -- cgit v1.2.3 From fc0a2f56e892d9175289c89c627de66edcb7f778 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Sat, 21 Sep 2013 23:01:37 +0200 Subject: Lock the thread so we can get the error message --- config.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/config.go b/config.go index f1fafde..7665b20 100644 --- a/config.go +++ b/config.go @@ -57,8 +57,10 @@ type Config struct { func NewConfig() (*Config, error) { config := new(Config) - ret := C.git_config_new(&config.ptr) - if ret < 0 { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if ret := C.git_config_new(&config.ptr); ret < 0 { return nil, LastError() } @@ -70,6 +72,10 @@ func (c *Config) AddFile(path string, level ConfigLevel, force bool) error { cpath := C.CString(path) defer C.free(unsafe.Pointer(cpath)) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_config_add_file_ondisk(c.ptr, cpath, C.git_config_level_t(level), cbool(force)) if ret < 0 { return LastError() @@ -118,8 +124,7 @@ func (c *Config) LookupString(name string) (string, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_config_get_string(&ptr, c.ptr, cname) - if ret < 0 { + if ret := C.git_config_get_string(&ptr, c.ptr, cname); ret < 0 { return "", LastError() } @@ -132,6 +137,9 @@ func (c *Config) LookupBool(name string) (bool, error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_config_get_bool(&out, c.ptr, cname) if ret < 0 { return false, LastError() @@ -153,6 +161,10 @@ func (c *Config) NewMultivarIterator(name, regexp string) (*ConfigIterator, erro } iter := new(ConfigIterator) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_config_multivar_iterator_new(&iter.ptr, c.ptr, cname, cregexp) if ret < 0 { return nil, LastError() @@ -166,6 +178,10 @@ func (c *Config) NewMultivarIterator(name, regexp string) (*ConfigIterator, erro // configuration func (c *Config) NewIterator() (*ConfigIterator, error) { iter := new(ConfigIterator) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_config_iterator_new(&iter.ptr, c.ptr) if ret < 0 { return nil, LastError() @@ -181,6 +197,9 @@ func (c *Config) NewIteratorGlob(regexp string) (*ConfigIterator, error) { cregexp := C.CString(regexp) defer C.free(unsafe.Pointer(cregexp)) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_config_iterator_glob_new(&iter.ptr, c.ptr, cregexp) if ret < 0 { return nil, LastError() @@ -228,6 +247,9 @@ func (c *Config) SetInt64(name string, value int64) (err error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_config_set_int64(c.ptr, cname, C.int64_t(value)) if ret < 0 { return LastError() @@ -240,6 +262,9 @@ func (c *Config) SetBool(name string, value bool) (err error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_config_set_bool(c.ptr, cname, cbool(value)) if ret < 0 { return LastError() @@ -258,6 +283,9 @@ func (c *Config) SetMultivar(name, regexp, value string) (err error) { cvalue := C.CString(value) defer C.free(unsafe.Pointer(cvalue)) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_config_set_multivar(c.ptr, cname, cregexp, cvalue) if ret < 0 { return LastError() @@ -270,6 +298,9 @@ func (c *Config) Delete(name string) error { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_config_delete_entry(c.ptr, cname) if ret < 0 { @@ -282,6 +313,10 @@ func (c *Config) Delete(name string) error { // OpenLevel creates a single-level focused config object from a multi-level one func (c *Config) OpenLevel(parent *Config, level ConfigLevel) (*Config, error) { config := new(Config) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_config_open_level(&config.ptr, parent.ptr, C.git_config_level_t(level)) if ret < 0 { return nil, LastError() @@ -296,8 +331,11 @@ func OpenOndisk(parent *Config, path string) (*Config, error) { defer C.free(unsafe.Pointer(cpath)) config := new(Config) - ret := C.git_config_open_ondisk(&config.ptr, cpath) - if ret < 0 { + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if ret := C.git_config_open_ondisk(&config.ptr, cpath); ret < 0 { return nil, LastError() } @@ -306,8 +344,10 @@ func OpenOndisk(parent *Config, path string) (*Config, error) { // Refresh refreshes the configuration to reflect any changes made externally e.g. on disk func (c *Config) Refresh() error { - ret := C.git_config_refresh(c.ptr) - if ret < 0 { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if ret := C.git_config_refresh(c.ptr); ret < 0 { return LastError() } -- cgit v1.2.3 From ca2c3c6db287f469736ff635167cd54f29b8a067 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 26 Feb 2014 14:51:04 +0100 Subject: Add a few reference utility functions --- reference.go | 11 +++++++++++ reference_test.go | 27 +++++++++++++++++++++++++++ repository.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/reference.go b/reference.go index a2f1636..4a839a7 100644 --- a/reference.go +++ b/reference.go @@ -134,6 +134,17 @@ func (v *Reference) Delete() error { return nil } +// Cmp compares both references, retursn 0 on equality, otherwise a +// stable sorting. +func (v *Reference) Cmp(ref2 *Reference) int { + return int(C.git_reference_cmp(v.ptr, ref2.ptr)) +} + +// Shorthand returns a "human-readable" short reference name +func (v *Reference) Shorthand() string { + return C.GoString(C.git_reference_shorthand(v.ptr)) +} + func (v *Reference) Name() string { return C.GoString(C.git_reference_name(v.ptr)) } diff --git a/reference_test.go b/reference_test.go index 156960a..ffa9f35 100644 --- a/reference_test.go +++ b/reference_test.go @@ -159,6 +159,33 @@ func TestIterator(t *testing.T) { compareStringList(t, expected, list) } +func TestUtil(t *testing.T) { + repo := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + + commitId, _ := seedTestRepo(t, repo) + + ref, err := repo.CreateReference("refs/heads/foo", commitId, true, nil, "") + checkFatal(t, err) + + ref2, err := repo.DwimReference("foo") + checkFatal(t, err) + + if ref.Cmp(ref2) != 0 { + t.Fatalf("foo didn't dwim to the right thing") + } + + if ref.Shorthand() != "foo" { + t.Fatalf("refs/heads/foo has no foo shorthand") + } + + hasLog, err := repo.HasLog("refs/heads/foo") + checkFatal(t, err) + if !hasLog { + t.Fatalf("branches ahve logs by default") + } +} + func compareStringList(t *testing.T, expected, actual []string) { for i, v := range expected { if actual[i] != v { diff --git a/repository.go b/repository.go index 48c2b46..5f0cd0b 100644 --- a/repository.go +++ b/repository.go @@ -331,3 +331,52 @@ func (v *Repository) RevparseSingle(spec string) (Object, error) { return allocObject(ptr), nil } + +// EnsureLog ensures that there is a reflog for the given reference +// name and creates an empty one if necessary. +func (v *Repository) EnsureLog(name string) error { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if ret := C.git_reference_ensure_log(v.ptr, cname); ret < 0 { + return LastError() + } + + return nil +} + +// HasLog returns whether there is a reflog for the given reference +// name +func (v *Repository) HasLog(name string) (bool, error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_reference_has_log(v.ptr, cname) + if ret < 0 { + return false, LastError() + } + + return ret == 1, nil +} + +// DwimReference looks up a reference by DWIMing its short name +func (v *Repository) DwimReference(name string) (*Reference, error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var ptr *C.git_reference + if ret := C.git_reference_dwim(&ptr, v.ptr, cname); ret < 0 { + return nil, LastError() + } + + return newReferenceFromC(ptr), nil +} -- cgit v1.2.3 From 2c8de242eeff532feb5258d4f150739d307d7e9f Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 26 Feb 2014 15:01:23 +0100 Subject: Allow for a default in reflog messages We don't have a way to represent a NULL string, so if the user passes an empty string, let's pass NULL down so we tell libgit2 to use the default. --- reference.go | 27 +++++++++++++++++++++------ repository.go | 18 ++++++++++++++---- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/reference.go b/reference.go index a2f1636..f7ea190 100644 --- a/reference.go +++ b/reference.go @@ -40,8 +40,13 @@ func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string) csig := sig.toC() defer C.free(unsafe.Pointer(csig)) - cmsg := C.CString(msg) - defer C.free(unsafe.Pointer(cmsg)) + var cmsg *C.char + if msg == "" { + cmsg = nil + } else { + cmsg = C.CString(msg) + defer C.free(unsafe.Pointer(cmsg)) + } ret := C.git_reference_symbolic_set_target(&ptr, v.ptr, ctarget, csig, cmsg) if ret < 0 { @@ -60,8 +65,13 @@ func (v *Reference) SetTarget(target *Oid, sig *Signature, msg string) (*Referen csig := sig.toC() defer C.free(unsafe.Pointer(csig)) - cmsg := C.CString(msg) - defer C.free(unsafe.Pointer(cmsg)) + var cmsg *C.char + if msg == "" { + cmsg = nil + } else { + cmsg = C.CString(msg) + defer C.free(unsafe.Pointer(cmsg)) + } ret := C.git_reference_set_target(&ptr, v.ptr, target.toC(), csig, cmsg) if ret < 0 { @@ -93,8 +103,13 @@ func (v *Reference) Rename(name string, force bool, sig *Signature, msg string) csig := sig.toC() defer C.free(unsafe.Pointer(csig)) - cmsg := C.CString(msg) - defer C.free(unsafe.Pointer(cmsg)) + var cmsg *C.char + if msg == "" { + cmsg = nil + } else { + cmsg = C.CString(msg) + defer C.free(unsafe.Pointer(cmsg)) + } runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/repository.go b/repository.go index 48c2b46..e4eaaed 100644 --- a/repository.go +++ b/repository.go @@ -153,8 +153,13 @@ func (v *Repository) CreateReference(name string, oid *Oid, force bool, sig *Sig csig := sig.toC() defer C.free(unsafe.Pointer(csig)) - cmsg := C.CString(msg) - defer C.free(unsafe.Pointer(cmsg)) + var cmsg *C.char + if msg == "" { + cmsg = nil + } else { + cmsg = C.CString(msg) + defer C.free(unsafe.Pointer(cmsg)) + } var ptr *C.git_reference @@ -179,8 +184,13 @@ func (v *Repository) CreateSymbolicReference(name, target string, force bool, si csig := sig.toC() defer C.free(unsafe.Pointer(csig)) - cmsg := C.CString(msg) - defer C.free(unsafe.Pointer(cmsg)) + var cmsg *C.char + if msg == "" { + cmsg = nil + } else { + cmsg = C.CString(msg) + defer C.free(unsafe.Pointer(cmsg)) + } var ptr *C.git_reference -- cgit v1.2.3 From 1e01cae286652885432c3d65d0693363e1b4a05c Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 26 Feb 2014 15:18:47 +0100 Subject: Remove pointer to git_index_entry We have all the data --- index.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/index.go b/index.go index 90a49de..2bf3d04 100644 --- a/index.go +++ b/index.go @@ -18,7 +18,6 @@ type Index struct { } type IndexEntry struct { - ptr *C.git_index_entry Ctime time.Time Mtime time.Time Mode uint @@ -68,7 +67,6 @@ func (v *Index) EntryCount() uint { func newIndexEntryFromC(entry *C.git_index_entry) *IndexEntry { return &IndexEntry{ - entry, time.Unix(int64(entry.ctime.seconds), int64(entry.ctime.nanoseconds)), time.Unix(int64(entry.mtime.seconds), int64(entry.mtime.nanoseconds)), uint(entry.mode), -- cgit v1.2.3 From 14f902afed482faefc58aa3af005cb8f2a0b050d Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 26 Feb 2014 15:22:48 +0100 Subject: Adjust to oid -> id --- index.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.go b/index.go index 2bf3d04..3ebb605 100644 --- a/index.go +++ b/index.go @@ -24,7 +24,7 @@ type IndexEntry struct { Uid uint Gid uint Size uint - Oid *Oid + Id *Oid Path string } @@ -73,7 +73,7 @@ func newIndexEntryFromC(entry *C.git_index_entry) *IndexEntry { uint(entry.uid), uint(entry.gid), uint(entry.file_size), - newOidFromC(&entry.oid), + newOidFromC(&entry.id), C.GoString(entry.path), } } -- cgit v1.2.3 From 3e5586bd8d532c929aecf778fc094e4f86588d37 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 26 Feb 2014 15:30:16 +0100 Subject: Remove 'oid' as id name Following the cleanup from libgit2, let's not use 'oid' unless we mean the name of the data type. In the other cases, we mean an identifier, hence the name 'id'. --- repository.go | 24 ++++++++++++------------ walk.go | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/repository.go b/repository.go index 48c2b46..1d58d7e 100644 --- a/repository.go +++ b/repository.go @@ -85,13 +85,13 @@ func (v *Repository) Index() (*Index, error) { return newIndexFromC(ptr), nil } -func (v *Repository) lookupType(oid *Oid, t ObjectType) (Object, error) { +func (v *Repository) lookupType(id *Oid, t ObjectType) (Object, error) { var ptr *C.git_object runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_object_lookup(&ptr, v.ptr, oid.toC(), C.git_otype(t)) + ret := C.git_object_lookup(&ptr, v.ptr, id.toC(), C.git_otype(t)) if ret < 0 { return nil, LastError() } @@ -99,12 +99,12 @@ func (v *Repository) lookupType(oid *Oid, t ObjectType) (Object, error) { return allocObject(ptr), nil } -func (v *Repository) Lookup(oid *Oid) (Object, error) { - return v.lookupType(oid, ObjectAny) +func (v *Repository) Lookup(id *Oid) (Object, error) { + return v.lookupType(id, ObjectAny) } -func (v *Repository) LookupTree(oid *Oid) (*Tree, error) { - obj, err := v.lookupType(oid, ObjectTree) +func (v *Repository) LookupTree(id *Oid) (*Tree, error) { + obj, err := v.lookupType(id, ObjectTree) if err != nil { return nil, err } @@ -112,8 +112,8 @@ func (v *Repository) LookupTree(oid *Oid) (*Tree, error) { return obj.(*Tree), nil } -func (v *Repository) LookupCommit(oid *Oid) (*Commit, error) { - obj, err := v.lookupType(oid, ObjectCommit) +func (v *Repository) LookupCommit(id *Oid) (*Commit, error) { + obj, err := v.lookupType(id, ObjectCommit) if err != nil { return nil, err } @@ -121,8 +121,8 @@ func (v *Repository) LookupCommit(oid *Oid) (*Commit, error) { return obj.(*Commit), nil } -func (v *Repository) LookupBlob(oid *Oid) (*Blob, error) { - obj, err := v.lookupType(oid, ObjectBlob) +func (v *Repository) LookupBlob(id *Oid) (*Blob, error) { + obj, err := v.lookupType(id, ObjectBlob) if err != nil { return nil, err } @@ -146,7 +146,7 @@ func (v *Repository) LookupReference(name string) (*Reference, error) { return newReferenceFromC(ptr), nil } -func (v *Repository) CreateReference(name string, oid *Oid, force bool, sig *Signature, msg string) (*Reference, error) { +func (v *Repository) CreateReference(name string, id *Oid, force bool, sig *Signature, msg string) (*Reference, error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -161,7 +161,7 @@ func (v *Repository) CreateReference(name string, oid *Oid, force bool, sig *Sig runtime.LockOSThread() defer runtime.UnlockOSThread() - ecode := C.git_reference_create(&ptr, v.ptr, cname, oid.toC(), cbool(force), csig, cmsg) + ecode := C.git_reference_create(&ptr, v.ptr, cname, id.toC(), cbool(force), csig, cmsg) if ecode < 0 { return nil, LastError() } diff --git a/walk.go b/walk.go index 6979b6b..619188d 100644 --- a/walk.go +++ b/walk.go @@ -46,11 +46,11 @@ func (v *RevWalk) PushHead() (err error) { return } -func (v *RevWalk) Next(oid *Oid) (err error) { +func (v *RevWalk) Next(id *Oid) (err error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_revwalk_next(oid.toC(), v.ptr) + ret := C.git_revwalk_next(id.toC(), v.ptr) switch { case ret == ITEROVER: err = io.EOF -- cgit v1.2.3 From 499f52a3549503604f30663211361e2fbd3cf202 Mon Sep 17 00:00:00 2001 From: Jesper Hansen Date: Sun, 7 Jul 2013 16:43:44 +0200 Subject: Added git error code to the error object. --- checkout.go | 4 ++-- commit.go | 2 +- config.go | 8 ++++---- git.go | 27 ++++++++++++++++++--------- index.go | 4 ++-- odb.go | 4 ++-- packbuilder.go | 10 +++++----- reference.go | 16 ++++++++-------- repository.go | 31 ++++++++++++++++--------------- submodule.go | 26 +++++++++++++------------- tree.go | 6 +++--- walk.go | 4 ++-- 12 files changed, 76 insertions(+), 66 deletions(-) diff --git a/checkout.go b/checkout.go index f4c1d4e..d3cd47b 100644 --- a/checkout.go +++ b/checkout.go @@ -65,7 +65,7 @@ func (v *Repository) Checkout(opts *CheckoutOpts) error { ret := C.git_checkout_head(v.ptr, &copts) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -81,7 +81,7 @@ func (v *Repository) CheckoutIndex(index *Index, opts *CheckoutOpts) error { ret := C.git_checkout_index(v.ptr, index.ptr, &copts) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil diff --git a/commit.go b/commit.go index 0c64c76..0edebb6 100644 --- a/commit.go +++ b/commit.go @@ -31,7 +31,7 @@ func (c Commit) Tree() (*Tree, error) { err := C.git_commit_tree(&ptr, c.ptr) if err < 0 { - return nil, LastError() + return nil, MakeGitError(err) } return allocObject(ptr).(*Tree), nil diff --git a/config.go b/config.go index 7665b20..2234a43 100644 --- a/config.go +++ b/config.go @@ -94,7 +94,7 @@ func (c *Config) LookupInt32(name string) (int32, error) { ret := C.git_config_get_int32(&out, c.ptr, cname) if ret < 0 { - return 0, LastError() + return 0, MakeGitError(ret) } return int32(out), nil @@ -110,7 +110,7 @@ func (c *Config) LookupInt64(name string) (int64, error) { ret := C.git_config_get_int64(&out, c.ptr, cname) if ret < 0 { - return 0, LastError() + return 0, MakeGitError(ret) } return int64(out), nil @@ -125,7 +125,7 @@ func (c *Config) LookupString(name string) (string, error) { defer runtime.UnlockOSThread() if ret := C.git_config_get_string(&ptr, c.ptr, cname); ret < 0 { - return "", LastError() + return "", MakeGitError(ret) } return C.GoString(ptr), nil @@ -220,7 +220,7 @@ func (c *Config) SetString(name, value string) (err error) { ret := C.git_config_set_string(c.ptr, cname, cvalue) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil diff --git a/git.go b/git.go index 72ea33e..7c76c30 100644 --- a/git.go +++ b/git.go @@ -61,8 +61,8 @@ func NewOidFromString(s string) (*Oid, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if C.git_oid_fromstr(o.toC(), cs) < 0 { - return nil, LastError() + if ret := C.git_oid_fromstr(o.toC(), cs); ret < 0 { + return nil, MakeGitError(ret) } return o, nil @@ -123,27 +123,36 @@ func ShortenOids(ids []*Oid, minlen int) (int, error) { buf[40] = 0 ret = C.git_oid_shorten_add(shorten, (*C.char)(unsafe.Pointer(&buf[0]))) if ret < 0 { - return int(ret), LastError() + return int(ret), MakeGitError(ret) } } return int(ret), nil } type GitError struct { - Message string - Code int + Message string + Class int + ErrorCode int } func (e GitError) Error() string { return e.Message } -func LastError() error { +func IsNotExist(err error) bool { + return err.(*GitError).ErrorCode == C.GIT_ENOTFOUND +} + +func IsExist(err error) bool { + return err.(*GitError).ErrorCode == C.GIT_EEXISTS +} + +func MakeGitError(errorCode C.int) error { err := C.giterr_last() if err == nil { - return &GitError{"No message", 0} + return &GitError{"No message", C.GITERR_INVALID, C.GIT_ERROR} } - return &GitError{C.GoString(err.message), int(err.klass)} + return &GitError{C.GoString(err.message), int(err.klass), int(errorCode)} } func cbool(b bool) C.int { @@ -175,7 +184,7 @@ func Discover(start string, across_fs bool, ceiling_dirs []string) (string, erro ret := C.git_repository_discover(&buf, cstart, cbool(across_fs), ceildirs) if ret < 0 { - return "", LastError() + return "", MakeGitError(ret) } return C.GoString(buf.ptr), nil diff --git a/index.go b/index.go index bc11025..cbb28c4 100644 --- a/index.go +++ b/index.go @@ -42,7 +42,7 @@ func (v *Index) AddByPath(path string) error { ret := C.git_index_add_bypath(v.ptr, cstr) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -56,7 +56,7 @@ func (v *Index) WriteTree() (*Oid, error) { ret := C.git_index_write_tree(oid.toC(), v.ptr) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return oid, nil diff --git a/odb.go b/odb.go index 953791c..3daf3a4 100644 --- a/odb.go +++ b/odb.go @@ -32,7 +32,7 @@ func (v *Odb) Write(data []byte, otype ObjectType) (oid *Oid, err error) { ret := C.git_odb_write(oid.toC(), v.ptr, unsafe.Pointer(hdr.Data), C.size_t(hdr.Len), C.git_otype(otype)) if ret < 0 { - err = LastError() + err = MakeGitError(ret) } return @@ -46,7 +46,7 @@ func (v *Odb) Read(oid *Oid) (obj *OdbObject, err error) { ret := C.git_odb_read(&obj.ptr, v.ptr, oid.toC()) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } runtime.SetFinalizer(obj, (*OdbObject).Free) diff --git a/packbuilder.go b/packbuilder.go index 333f183..70c4530 100644 --- a/packbuilder.go +++ b/packbuilder.go @@ -28,7 +28,7 @@ func (repo *Repository) NewPackbuilder() (*Packbuilder, error) { ret := C.git_packbuilder_new(&builder.ptr, repo.ptr) if ret != 0 { - return nil, LastError() + return nil, MakeGitError(ret) } runtime.SetFinalizer(builder, (*Packbuilder).Free) return builder, nil @@ -48,7 +48,7 @@ func (pb *Packbuilder) Insert(id *Oid, name string) error { ret := C.git_packbuilder_insert(pb.ptr, id.toC(), cname) if ret != 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -59,7 +59,7 @@ func (pb *Packbuilder) InsertCommit(id *Oid) error { ret := C.git_packbuilder_insert_commit(pb.ptr, id.toC()) if ret != 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -70,7 +70,7 @@ func (pb *Packbuilder) InsertTree(id *Oid) error { ret := C.git_packbuilder_insert_tree(pb.ptr, id.toC()) if ret != 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -88,7 +88,7 @@ func (pb *Packbuilder) WriteToFile(name string, mode os.FileMode) error { ret := C.git_packbuilder_write(pb.ptr, cname, C.uint(mode.Perm()), nil, nil) if ret != 0 { - return LastError() + return MakeGitError(ret) } return nil } diff --git a/reference.go b/reference.go index a2f1636..39d328e 100644 --- a/reference.go +++ b/reference.go @@ -45,7 +45,7 @@ func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string) ret := C.git_reference_symbolic_set_target(&ptr, v.ptr, ctarget, csig, cmsg) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return newReferenceFromC(ptr), nil @@ -65,7 +65,7 @@ func (v *Reference) SetTarget(target *Oid, sig *Signature, msg string) (*Referen ret := C.git_reference_set_target(&ptr, v.ptr, target.toC(), csig, cmsg) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return newReferenceFromC(ptr), nil @@ -79,7 +79,7 @@ func (v *Reference) Resolve() (*Reference, error) { ret := C.git_reference_resolve(&ptr, v.ptr) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return newReferenceFromC(ptr), nil @@ -102,7 +102,7 @@ func (v *Reference) Rename(name string, force bool, sig *Signature, msg string) ret := C.git_reference_rename(&ptr, v.ptr, cname, cbool(force), csig, cmsg) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return newReferenceFromC(ptr), nil @@ -128,7 +128,7 @@ func (v *Reference) Delete() error { ret := C.git_reference_delete(v.ptr) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -173,7 +173,7 @@ func (repo *Repository) NewReferenceIterator() (*ReferenceIterator, error) { ret := C.git_reference_iterator_new(&ptr, repo.ptr) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } iter := &ReferenceIterator{repo: repo, ptr: ptr} @@ -194,7 +194,7 @@ func (repo *Repository) NewReferenceIteratorGlob(glob string) (*ReferenceIterato ret := C.git_reference_iterator_glob_new(&ptr, repo.ptr, cstr) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } iter := &ReferenceIterator{repo: repo, ptr: ptr} @@ -215,7 +215,7 @@ func (v *ReferenceIterator) NextName() (string, error) { return "", ErrIterOver } if ret < 0 { - return "", LastError() + return "", MakeGitError(ret) } return C.GoString(ptr), nil diff --git a/repository.go b/repository.go index 1d58d7e..e78422e 100644 --- a/repository.go +++ b/repository.go @@ -26,7 +26,7 @@ func OpenRepository(path string) (*Repository, error) { ret := C.git_repository_open(&repo.ptr, cpath) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } runtime.SetFinalizer(repo, (*Repository).Free) @@ -44,7 +44,7 @@ func InitRepository(path string, isbare bool) (*Repository, error) { ret := C.git_repository_init(&repo.ptr, cpath, ucbool(isbare)) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } runtime.SetFinalizer(repo, (*Repository).Free) @@ -64,7 +64,7 @@ func (v *Repository) Config() (*Config, error) { ret := C.git_repository_config(&config.ptr, v.ptr) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } runtime.SetFinalizer(config, (*Config).Free) @@ -79,7 +79,7 @@ func (v *Repository) Index() (*Index, error) { ret := C.git_repository_index(&ptr, v.ptr) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return newIndexFromC(ptr), nil @@ -93,7 +93,7 @@ func (v *Repository) lookupType(id *Oid, t ObjectType) (Object, error) { ret := C.git_object_lookup(&ptr, v.ptr, id.toC(), C.git_otype(t)) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return allocObject(ptr), nil @@ -140,7 +140,7 @@ func (v *Repository) LookupReference(name string) (*Reference, error) { ecode := C.git_reference_lookup(&ptr, v.ptr, cname) if ecode < 0 { - return nil, LastError() + return nil, MakeGitError(ecode) } return newReferenceFromC(ptr), nil @@ -163,7 +163,7 @@ func (v *Repository) CreateReference(name string, id *Oid, force bool, sig *Sign ecode := C.git_reference_create(&ptr, v.ptr, cname, id.toC(), cbool(force), csig, cmsg) if ecode < 0 { - return nil, LastError() + return nil, MakeGitError(ecode) } return newReferenceFromC(ptr), nil @@ -189,7 +189,7 @@ func (v *Repository) CreateSymbolicReference(name, target string, force bool, si ecode := C.git_reference_symbolic_create(&ptr, v.ptr, cname, ctarget, cbool(force), csig, cmsg) if ecode < 0 { - return nil, LastError() + return nil, MakeGitError(ecode) } return newReferenceFromC(ptr), nil @@ -203,7 +203,7 @@ func (v *Repository) Walk() (*RevWalk, error) { ecode := C.git_revwalk_new(&walk.ptr, v.ptr) if ecode < 0 { - return nil, LastError() + return nil, MakeGitError(ecode) } walk.repo = v @@ -250,7 +250,7 @@ func (v *Repository) CreateCommit( nil, cmsg, tree.ptr, C.size_t(nparents), parentsarg) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return oid, nil @@ -268,7 +268,7 @@ func (v *Repository) Odb() (odb *Odb, err error) { defer runtime.UnlockOSThread() if ret := C.git_repository_odb(&odb.ptr, v.ptr); ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } runtime.SetFinalizer(odb, (*Odb).Free) @@ -294,9 +294,10 @@ func (repo *Repository) SetWorkdir(workdir string, updateGitlink bool) error { runtime.LockOSThread() defer runtime.UnlockOSThread() - if C.git_repository_set_workdir(repo.ptr, cstr, cbool(updateGitlink)) < 0 { - return LastError() + if ret := C.git_repository_set_workdir(repo.ptr, cstr, cbool(updateGitlink)); ret < 0 { + return MakeGitError(ret) } + return nil } @@ -307,7 +308,7 @@ func (v *Repository) TreeBuilder() (*TreeBuilder, error) { defer runtime.UnlockOSThread() if ret := C.git_treebuilder_create(&bld.ptr, nil); ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } runtime.SetFinalizer(bld, (*TreeBuilder).Free) @@ -326,7 +327,7 @@ func (v *Repository) RevparseSingle(spec string) (Object, error) { ecode := C.git_revparse_single(&ptr, v.ptr, cspec) if ecode < 0 { - return nil, LastError() + return nil, MakeGitError(ecode) } return allocObject(ptr), nil diff --git a/submodule.go b/submodule.go index 9abf333..8390e36 100644 --- a/submodule.go +++ b/submodule.go @@ -81,7 +81,7 @@ func (repo *Repository) LookupSubmodule(name string) (*Submodule, error) { ret := C.git_submodule_lookup(&sub.ptr, repo.ptr, cname) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return sub, nil @@ -102,7 +102,7 @@ func (repo *Repository) ForeachSubmodule(cbk SubmoduleCbk) error { ret := C._go_git_visit_submodule(repo.ptr, unsafe.Pointer(&cbk)) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -120,7 +120,7 @@ func (repo *Repository) AddSubmodule(url, path string, use_git_link bool) (*Subm ret := C.git_submodule_add_setup(&sub.ptr, repo.ptr, curl, cpath, cbool(use_git_link)) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return sub, nil } @@ -131,7 +131,7 @@ func (sub *Submodule) FinalizeAdd() error { ret := C.git_submodule_add_finalize(sub.ptr) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -142,7 +142,7 @@ func (sub *Submodule) AddToIndex(write_index bool) error { ret := C.git_submodule_add_to_index(sub.ptr, cbool(write_index)) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -153,7 +153,7 @@ func (sub *Submodule) Save() error { ret := C.git_submodule_save(sub.ptr) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -188,7 +188,7 @@ func (sub *Submodule) SetUrl(url string) error { ret := C.git_submodule_set_url(sub.ptr, curl) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -247,7 +247,7 @@ func (sub *Submodule) SetFetchRecurseSubmodules(recurse SubmoduleRecurse) error ret := C.git_submodule_set_fetch_recurse_submodules(sub.ptr, C.git_submodule_recurse_t(recurse)) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -258,7 +258,7 @@ func (sub *Submodule) Init(overwrite bool) error { ret := C.git_submodule_init(sub.ptr, cbool(overwrite)) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -269,7 +269,7 @@ func (sub *Submodule) Sync() error { ret := C.git_submodule_sync(sub.ptr) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -282,7 +282,7 @@ func (sub *Submodule) Open() (*Repository, error) { ret := C.git_submodule_open(&repo.ptr, sub.ptr) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return repo, nil } @@ -293,7 +293,7 @@ func (sub *Submodule) Reload() error { ret := C.git_submodule_reload(sub.ptr) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil } @@ -304,7 +304,7 @@ func (repo *Repository) ReloadAllSubmodules() error { ret := C.git_submodule_reload_all(repo.ptr) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil } diff --git a/tree.go b/tree.go index 8c74e5d..4efb589 100644 --- a/tree.go +++ b/tree.go @@ -109,7 +109,7 @@ func (t Tree) Walk(callback TreeWalkCallback) error { ) if err < 0 { - return LastError() + return MakeGitError(err) } return nil @@ -134,7 +134,7 @@ func (v *TreeBuilder) Insert(filename string, id *Oid, filemode int) (error) { err := C.git_treebuilder_insert(nil, v.ptr, cfilename, id.toC(), C.git_filemode_t(filemode)) if err < 0 { - return LastError() + return MakeGitError(err) } return nil @@ -149,7 +149,7 @@ func (v *TreeBuilder) Write() (*Oid, error) { err := C.git_treebuilder_write(oid.toC(), v.repo.ptr, v.ptr) if err < 0 { - return nil, LastError() + return nil, MakeGitError(err) } return oid, nil diff --git a/walk.go b/walk.go index 619188d..cdc1a20 100644 --- a/walk.go +++ b/walk.go @@ -40,7 +40,7 @@ func (v *RevWalk) PushHead() (err error) { ecode := C.git_revwalk_push_head(v.ptr) if ecode < 0 { - err = LastError() + err = MakeGitError(ecode) } return @@ -55,7 +55,7 @@ func (v *RevWalk) Next(id *Oid) (err error) { case ret == ITEROVER: err = io.EOF case ret < 0: - err = LastError() + err = MakeGitError(ret) } return -- cgit v1.2.3 From 00ea11691b574b8372cb216427d98038e107e358 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 26 Feb 2014 16:14:31 +0100 Subject: Convert the rest of the errors --- config.go | 30 +++++++++++++++--------------- index.go | 2 +- odb.go | 12 ++++++------ reference.go | 2 +- submodule.go | 2 +- tree.go | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/config.go b/config.go index 2234a43..6b1f093 100644 --- a/config.go +++ b/config.go @@ -61,7 +61,7 @@ func NewConfig() (*Config, error) { defer runtime.UnlockOSThread() if ret := C.git_config_new(&config.ptr); ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return config, nil @@ -78,7 +78,7 @@ func (c *Config) AddFile(path string, level ConfigLevel, force bool) error { ret := C.git_config_add_file_ondisk(c.ptr, cpath, C.git_config_level_t(level), cbool(force)) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -142,7 +142,7 @@ func (c *Config) LookupBool(name string) (bool, error) { ret := C.git_config_get_bool(&out, c.ptr, cname) if ret < 0 { - return false, LastError() + return false, MakeGitError(ret) } return out != 0, nil @@ -167,7 +167,7 @@ func (c *Config) NewMultivarIterator(name, regexp string) (*ConfigIterator, erro ret := C.git_config_multivar_iterator_new(&iter.ptr, c.ptr, cname, cregexp) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } runtime.SetFinalizer(iter, (*ConfigIterator).Free) @@ -184,7 +184,7 @@ func (c *Config) NewIterator() (*ConfigIterator, error) { ret := C.git_config_iterator_new(&iter.ptr, c.ptr) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return iter, nil @@ -202,7 +202,7 @@ func (c *Config) NewIteratorGlob(regexp string) (*ConfigIterator, error) { ret := C.git_config_iterator_glob_new(&iter.ptr, c.ptr, cregexp) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return iter, nil @@ -237,7 +237,7 @@ func (c *Config) SetInt32(name string, value int32) (err error) { ret := C.git_config_set_int32(c.ptr, cname, C.int32_t(value)) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -252,7 +252,7 @@ func (c *Config) SetInt64(name string, value int64) (err error) { ret := C.git_config_set_int64(c.ptr, cname, C.int64_t(value)) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -267,7 +267,7 @@ func (c *Config) SetBool(name string, value bool) (err error) { ret := C.git_config_set_bool(c.ptr, cname, cbool(value)) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -288,7 +288,7 @@ func (c *Config) SetMultivar(name, regexp, value string) (err error) { ret := C.git_config_set_multivar(c.ptr, cname, cregexp, cvalue) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -304,7 +304,7 @@ func (c *Config) Delete(name string) error { ret := C.git_config_delete_entry(c.ptr, cname) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -319,7 +319,7 @@ func (c *Config) OpenLevel(parent *Config, level ConfigLevel) (*Config, error) { ret := C.git_config_open_level(&config.ptr, parent.ptr, C.git_config_level_t(level)) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return config, nil @@ -336,7 +336,7 @@ func OpenOndisk(parent *Config, path string) (*Config, error) { defer runtime.UnlockOSThread() if ret := C.git_config_open_ondisk(&config.ptr, cpath); ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return config, nil @@ -348,7 +348,7 @@ func (c *Config) Refresh() error { defer runtime.UnlockOSThread() if ret := C.git_config_refresh(c.ptr); ret < 0 { - return LastError() + return MakeGitError(ret) } return nil @@ -364,7 +364,7 @@ func (iter *ConfigIterator) Next() (*ConfigEntry, error) { ret := C.git_config_next(¢ry, iter.ptr) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return newConfigEntryFromC(centry), nil diff --git a/index.go b/index.go index cbb28c4..6da3c98 100644 --- a/index.go +++ b/index.go @@ -68,7 +68,7 @@ func (v *Index) Write() (error) { ret := C.git_index_write(v.ptr) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil diff --git a/odb.go b/odb.go index 3daf3a4..daf63dd 100644 --- a/odb.go +++ b/odb.go @@ -90,7 +90,7 @@ func (v *Odb) Hash(data []byte, otype ObjectType) (oid *Oid, err error) { ret := C.git_odb_hash(oid.toC(), ptr, C.size_t(header.Len), C.git_otype(otype)); if ret < 0 { - err = LastError() + err = MakeGitError(ret) } return } @@ -101,7 +101,7 @@ func (v *Odb) NewReadStream(id *Oid) (*OdbReadStream, error) { stream := new(OdbReadStream) ret := C.git_odb_open_rstream(&stream.ptr, v.ptr, id.toC()) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } runtime.SetFinalizer(stream, (*OdbReadStream).Free) @@ -115,7 +115,7 @@ func (v *Odb) NewWriteStream(size int, otype ObjectType) (*OdbWriteStream, error stream := new(OdbWriteStream) ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.size_t(size), C.git_otype(otype)) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } runtime.SetFinalizer(stream, (*OdbWriteStream).Free) @@ -164,7 +164,7 @@ func (stream *OdbReadStream) Read(data []byte) (int, error) { size := C.size_t(header.Cap) ret := C.git_odb_stream_read(stream.ptr, ptr, size) if ret < 0 { - return 0, LastError() + return 0, MakeGitError(ret) } header.Len = int(ret) @@ -196,7 +196,7 @@ func (stream *OdbWriteStream) Write(data []byte) (int, error) { ret := C.git_odb_stream_write(stream.ptr, ptr, size) if ret < 0 { - return 0, LastError() + return 0, MakeGitError(ret) } return len(data), nil @@ -207,7 +207,7 @@ func (stream *OdbWriteStream) Write(data []byte) (int, error) { func (stream *OdbWriteStream) Close() error { ret := C.git_odb_stream_finalize_write(stream.Id.toC(), stream.ptr) if ret < 0 { - return LastError() + return MakeGitError(ret) } return nil diff --git a/reference.go b/reference.go index 39d328e..45a3b22 100644 --- a/reference.go +++ b/reference.go @@ -247,7 +247,7 @@ func (v *ReferenceIterator) Next() (*Reference, error) { return nil, ErrIterOver } if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return newReferenceFromC(ptr), nil diff --git a/submodule.go b/submodule.go index 8390e36..dcc4723 100644 --- a/submodule.go +++ b/submodule.go @@ -247,7 +247,7 @@ func (sub *Submodule) SetFetchRecurseSubmodules(recurse SubmoduleRecurse) error ret := C.git_submodule_set_fetch_recurse_submodules(sub.ptr, C.git_submodule_recurse_t(recurse)) if ret < 0 { - return MakeGitError(ret) + return MakeGitError(C.int(ret)) } return nil } diff --git a/tree.go b/tree.go index 4efb589..b3340d6 100644 --- a/tree.go +++ b/tree.go @@ -67,7 +67,7 @@ func (t Tree) EntryByPath(path string) (*TreeEntry, error) { ret := C.git_tree_entry_bypath(&entry, t.ptr, cpath) if ret < 0 { - return nil, LastError() + return nil, MakeGitError(ret) } return newTreeEntry(entry), nil -- cgit v1.2.3 From a728f70358ab58364c643d04c94a66b3ec2cd947 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Wed, 26 Feb 2014 07:33:50 -0800 Subject: cleanup add-branch --- branch.go | 66 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 34 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 { - return "", LastError() - } - - cBuf := (*C.char)(C.malloc(C.size_t(ret))) - defer C.free(unsafe.Pointer(cBuf)) + nameBuf := C.git_buf{} - // Actually obtain the name - ret = C.git_branch_remote_name(cBuf, C.size_t(ret), repo.ptr, cName) - if ret < 0 { + if C.git_branch_remote_name(&nameBuf, repo.ptr, cName) < 0 { return "", LastError() } + C.git_buf_free(&nameBuf) - 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 { - return "", LastError() - } - - cBuf := (*C.char)(C.malloc(C.size_t(ret))) - defer C.free(unsafe.Pointer(cBuf)) + nameBuf := C.git_buf{} - // Actually obtain the name - ret = C.git_branch_upstream_name(cBuf, C.size_t(ret), repo.ptr, cName) - if ret < 0 { + if C.git_branch_upstream_name(&nameBuf, repo.ptr, cName) < 0 { return "", LastError() } - return C.GoString(cBuf), nil + C.git_buf_free(&nameBuf) + + return C.GoStringN(nameBuf.ptr, C.int(nameBuf.size)), nil } -- cgit v1.2.3 From fe509411a5e8bd45a1c5607d1cc212d8ebf45541 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Wed, 26 Feb 2014 08:45:38 -0800 Subject: 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() } -- cgit v1.2.3 From a5df6111003cb032911a793f186aefb8f27243ef Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Wed, 26 Feb 2014 08:50:47 -0800 Subject: 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) -- cgit v1.2.3 From 374e2112dfc298fa5ecb0805624d75b3500cc345 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Thu, 27 Feb 2014 16:36:44 -0800 Subject: add push, refine remotes --- git_test.go | 15 ++++- push.go | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ push_test.go | 56 ++++++++++++++++++ remote.go | 99 ++++++++++++++++---------------- wrapper.c | 12 ++++ 5 files changed, 310 insertions(+), 53 deletions(-) create mode 100644 push.go create mode 100644 push_test.go diff --git a/git_test.go b/git_test.go index 52aea1d..fff3c6c 100644 --- a/git_test.go +++ b/git_test.go @@ -1,8 +1,8 @@ package git import ( - "testing" "io/ioutil" + "testing" "time" ) @@ -14,7 +14,17 @@ func createTestRepo(t *testing.T) *Repository { checkFatal(t, err) tmpfile := "README" - err = ioutil.WriteFile(path + "/" + tmpfile, []byte("foo\n"), 0644) + err = ioutil.WriteFile(path+"/"+tmpfile, []byte("foo\n"), 0644) + checkFatal(t, err) + + return repo +} + +func createBareTestRepo(t *testing.T) *Repository { + // figure out where we can create the test repo + path, err := ioutil.TempDir("", "git2go") + checkFatal(t, err) + repo, err := InitRepository(path, true) checkFatal(t, err) return repo @@ -44,4 +54,3 @@ func seedTestRepo(t *testing.T, repo *Repository) (*Oid, *Oid) { return commitId, treeId } - diff --git a/push.go b/push.go new file mode 100644 index 0000000..0694fe3 --- /dev/null +++ b/push.go @@ -0,0 +1,181 @@ +package git + +/* +#include +#include + +int _go_git_push_status_foreach(git_push *push, void *data); +int _go_git_push_set_callbacks(git_push *push, void *packbuilder_progress_data, void *transfer_progress_data); + +*/ +import "C" +import ( + "runtime" + "unsafe" +) + +type Push struct { + ptr *C.git_push + + packbuilderProgress *PackbuilderProgressCallback + transferProgress *PushTransferProgressCallback +} + +func newPushFromC(cpush *C.git_push) *Push { + p := &Push{ptr: cpush} + runtime.SetFinalizer(p, (*Push).Free) + return p +} + +func (p *Push) Free() { + runtime.SetFinalizer(p, nil) + C.git_push_free(p.ptr) +} + +func (remote *Remote) NewPush() (*Push, error) { + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var cpush *C.git_push + ret := C.git_push_new(&cpush, remote.ptr) + if ret < 0 { + return nil, MakeGitError(ret) + } + return newPushFromC(cpush), nil +} + +func (p *Push) Finish() error { + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_push_finish(p.ptr) + if ret < 0 { + return MakeGitError(ret) + } + return nil +} + +func (p *Push) UnpackOk() bool { + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_push_unpack_ok(p.ptr) + if ret == 0 { + return false + } else { + return true + } + +} + +func (p *Push) UpdateTips(sig *Signature, msg string) error { + + var csig *C.git_signature = nil + if sig != nil { + csig = sig.toC() + defer C.free(unsafe.Pointer(csig)) + } + + cmsg := C.CString(msg) + defer C.free(unsafe.Pointer(cmsg)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_push_update_tips(p.ptr, csig, cmsg) + if ret < 0 { + return MakeGitError(ret) + } + return nil +} + +func (p *Push) AddRefspec(refspec string) error { + + crefspec := C.CString(refspec) + defer C.free(unsafe.Pointer(crefspec)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_push_add_refspec(p.ptr, crefspec) + if ret < 0 { + return MakeGitError(ret) + } + return nil +} + +type PushOptions struct { + Version uint + PbParallelism uint +} + +func (p *Push) SetOptions(opts PushOptions) error { + copts := C.git_push_options{version: C.uint(opts.Version), pb_parallelism: C.uint(opts.PbParallelism)} + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_push_set_options(p.ptr, &copts) + if ret < 0 { + return MakeGitError(ret) + } + return nil +} + +type StatusForeachFunc func(ref string, msg string) int + +//export statusForeach +func statusForeach(_ref *C.char, _msg *C.char, _data unsafe.Pointer) C.int { + ref := C.GoString(_ref) + msg := C.GoString(_msg) + + cb := (*StatusForeachFunc)(_data) + + return C.int((*cb)(ref, msg)) +} + +func (p *Push) StatusForeach(callback StatusForeachFunc) error { + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C._go_git_push_status_foreach(p.ptr, unsafe.Pointer(&callback)) + if ret < 0 { + return MakeGitError(ret) + } + return nil + +} + +type PushCallbacks struct { + PackbuilderProgress *PackbuilderProgressCallback + TransferProgress *PushTransferProgressCallback +} + +type PackbuilderProgressCallback func(stage int, current uint, total uint) int +type PushTransferProgressCallback func(current uint, total uint, bytes uint) int + +//export packbuilderProgress +func packbuilderProgress(stage C.int, current C.uint, total C.uint, data unsafe.Pointer) C.int { + return C.int((*(*PackbuilderProgressCallback)(data))(int(stage), uint(current), uint(total))) +} + +//export pushTransferProgress +func pushTransferProgress(current C.uint, total C.uint, bytes C.size_t, data unsafe.Pointer) C.int { + return C.int((*(*PushTransferProgressCallback)(data))(uint(current), uint(total), uint(bytes))) +} + +func (p *Push) SetCallbacks(callbacks PushCallbacks) { + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + // save callbacks so they don't get GC'd + p.packbuilderProgress = callbacks.PackbuilderProgress + p.transferProgress = callbacks.TransferProgress + + C._go_git_push_set_callbacks(p.ptr, unsafe.Pointer(p.packbuilderProgress), unsafe.Pointer(p.transferProgress)) +} diff --git a/push_test.go b/push_test.go new file mode 100644 index 0000000..dfd4af7 --- /dev/null +++ b/push_test.go @@ -0,0 +1,56 @@ +package git + +import ( + "log" + "testing" + "time" +) + +func Test_Push_ToRemote(t *testing.T) { + repo := createBareTestRepo(t) + repo2 := createTestRepo(t) + + remote, err := repo2.CreateRemote("test_push", repo.Path()) + checkFatal(t, err) + + index, err := repo2.Index() + checkFatal(t, err) + + index.AddByPath("README") + + err = index.Write() + checkFatal(t, err) + + newTreeId, err := index.WriteTree() + checkFatal(t, err) + + tree, err := repo2.LookupTree(newTreeId) + checkFatal(t, err) + + sig := &Signature{Name: "Rand Om Hacker", Email: "random@hacker.com", When: time.Now()} + // this should cause master branch to be created if it does not already exist + _, err = repo2.CreateCommit("HEAD", sig, sig, "message", tree) + checkFatal(t, err) + + push, err := remote.NewPush() + checkFatal(t, err) + + err = push.AddRefspec("refs/heads/master") + checkFatal(t, err) + + err = push.Finish() + checkFatal(t, err) + + err = push.StatusForeach(func(ref string, msg string) int { + log.Printf("%s -> %s", ref, msg) + return 0 + }) + checkFatal(t, err) + + if !push.UnpackOk() { + t.Fatalf("unable to unpack") + } + + defer remote.Free() + defer repo.Free() +} diff --git a/remote.go b/remote.go index 38c1d47..ab2e174 100644 --- a/remote.go +++ b/remote.go @@ -40,27 +40,7 @@ type RemoteCallbacks struct { UpdateTipsCallback } -type Remote interface { - Save() error - Owner() Repository - Name() string - Url() string - PushUrl() string - - SetUrl(url string) error - SetPushUrl(url string) error - - AddFetch(refspec string) error - GetFetchRefspecs() ([]string, error) - SetFetchRefspecs(refspecs []string) error - AddPush(refspec string) error - GetPushRefspecs() ([]string, error) - SetPushRefspecs(refspecs []string) error - ClearRefspecs() - RefspecCount() uint -} - -type gitRemote struct { +type Remote struct { ptr *C.git_remote } @@ -161,13 +141,13 @@ func RemoteIsValidName(name string) bool { return false } -func freeRemote(o *gitRemote) { - C.git_remote_free(o.ptr) +func (r *Remote) Free() { + runtime.SetFinalizer(r, nil) + C.git_remote_free(r.ptr) } -func CreateRemote(repo *Repository, name string, url string) (Remote, error) { - remote := &gitRemote{} - runtime.SetFinalizer(remote, freeRemote) +func (repo *Repository) CreateRemote(name string, url string) (*Remote, error) { + remote := &Remote{} cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -181,12 +161,12 @@ func CreateRemote(repo *Repository, name string, url string) (Remote, error) { if ret < 0 { return nil, MakeGitError(ret) } + runtime.SetFinalizer(remote, (*Remote).Free) return remote, nil } -func CreateRemoteWithFetchspec(repo *Repository, name string, url string, fetch string) (Remote, error) { - remote := &gitRemote{} - runtime.SetFinalizer(remote, freeRemote) +func (repo *Repository) CreateRemoteWithFetchspec(name string, url string, fetch string) (*Remote, error) { + remote := &Remote{} cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -202,12 +182,12 @@ func CreateRemoteWithFetchspec(repo *Repository, name string, url string, fetch if ret < 0 { return nil, MakeGitError(ret) } + runtime.SetFinalizer(remote, (*Remote).Free) return remote, nil } -func CreateRemoteInMemory(repo *Repository, fetch string, url string) (Remote, error) { - remote := &gitRemote{} - runtime.SetFinalizer(remote, freeRemote) +func (repo *Repository) CreateRemoteInMemory(fetch string, url string) (*Remote, error) { + remote := &Remote{} curl := C.CString(url) defer C.free(unsafe.Pointer(curl)) @@ -221,12 +201,12 @@ func CreateRemoteInMemory(repo *Repository, fetch string, url string) (Remote, e if ret < 0 { return nil, MakeGitError(ret) } + runtime.SetFinalizer(remote, (*Remote).Free) return remote, nil } -func LoadRemote(repo *Repository, name string) (Remote, error) { - remote := &gitRemote{} - runtime.SetFinalizer(remote, freeRemote) +func (repo *Repository) LoadRemote(name string) (*Remote, error) { + remote := &Remote{} cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -238,10 +218,11 @@ func LoadRemote(repo *Repository, name string) (Remote, error) { if ret < 0 { return nil, MakeGitError(ret) } + runtime.SetFinalizer(remote, (*Remote).Free) return remote, nil } -func (o *gitRemote) Save() error { +func (o *Remote) Save() error { runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -253,23 +234,23 @@ func (o *gitRemote) Save() error { return nil } -func (o *gitRemote) Owner() Repository { +func (o *Remote) Owner() Repository { return Repository{C.git_remote_owner(o.ptr)} } -func (o *gitRemote) Name() string { +func (o *Remote) Name() string { return C.GoString(C.git_remote_name(o.ptr)) } -func (o *gitRemote) Url() string { +func (o *Remote) Url() string { return C.GoString(C.git_remote_url(o.ptr)) } -func (o *gitRemote) PushUrl() string { +func (o *Remote) PushUrl() string { return C.GoString(C.git_remote_pushurl(o.ptr)) } -func (o *gitRemote) SetUrl(url string) error { +func (o *Remote) SetUrl(url string) error { curl := C.CString(url) defer C.free(unsafe.Pointer(curl)) @@ -283,7 +264,7 @@ func (o *gitRemote) SetUrl(url string) error { return nil } -func (o *gitRemote) SetPushUrl(url string) error { +func (o *Remote) SetPushUrl(url string) error { curl := C.CString(url) defer C.free(unsafe.Pointer(curl)) @@ -297,7 +278,7 @@ func (o *gitRemote) SetPushUrl(url string) error { return nil } -func (o *gitRemote) AddFetch(refspec string) error { +func (o *Remote) AddFetch(refspec string) error { crefspec := C.CString(refspec) defer C.free(unsafe.Pointer(crefspec)) @@ -311,7 +292,7 @@ func (o *gitRemote) AddFetch(refspec string) error { return nil } -func (o *gitRemote) GetFetchRefspecs() ([]string, error) { +func (o *Remote) GetFetchRefspecs() ([]string, error) { crefspecs := C.git_strarray{} runtime.LockOSThread() @@ -330,7 +311,7 @@ func (o *gitRemote) GetFetchRefspecs() ([]string, error) { return refspecs, nil } -func (o *gitRemote) SetFetchRefspecs(refspecs []string) error { +func (o *Remote) SetFetchRefspecs(refspecs []string) error { crefspecs := C.git_strarray{} crefspecs.count = C.size_t(len(refspecs)) crefspecs.strings = (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(crefspecs.count)))) @@ -349,7 +330,7 @@ func (o *gitRemote) SetFetchRefspecs(refspecs []string) error { return nil } -func (o *gitRemote) AddPush(refspec string) error { +func (o *Remote) AddPush(refspec string) error { crefspec := C.CString(refspec) defer C.free(unsafe.Pointer(crefspec)) @@ -363,7 +344,7 @@ func (o *gitRemote) AddPush(refspec string) error { return nil } -func (o *gitRemote) GetPushRefspecs() ([]string, error) { +func (o *Remote) GetPushRefspecs() ([]string, error) { crefspecs := C.git_strarray{} runtime.LockOSThread() @@ -382,7 +363,7 @@ func (o *gitRemote) GetPushRefspecs() ([]string, error) { return refspecs, nil } -func (o *gitRemote) SetPushRefspecs(refspecs []string) error { +func (o *Remote) SetPushRefspecs(refspecs []string) error { crefspecs := C.git_strarray{} crefspecs.count = C.size_t(len(refspecs)) crefspecs.strings = (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(crefspecs.count)))) @@ -401,10 +382,28 @@ func (o *gitRemote) SetPushRefspecs(refspecs []string) error { return nil } -func (o *gitRemote) ClearRefspecs() { +func (o *Remote) ClearRefspecs() { C.git_remote_clear_refspecs(o.ptr) } -func (o *gitRemote) RefspecCount() uint { +func (o *Remote) RefspecCount() uint { return uint(C.git_remote_refspec_count(o.ptr)) } + +func (o *Remote) Fetch(sig *Signature, msg string) error { + + var csig *C.git_signature = nil + if sig != nil { + csig = sig.toC() + defer C.free(unsafe.Pointer(csig)) + } + + cmsg := C.CString(msg) + defer C.free(unsafe.Pointer(cmsg)) + + ret := C.git_remote_fetch(o.ptr, csig, cmsg) + if ret < 0 { + return MakeGitError(ret) + } + return nil +} diff --git a/wrapper.c b/wrapper.c index 7519a96..9e193ca 100644 --- a/wrapper.c +++ b/wrapper.c @@ -51,4 +51,16 @@ char *_go_git_get_strarray_n(git_strarray *array, size_t n) { return array->strings[n]; } +typedef int (*status_foreach_cb)(const char *ref, const char *msg, void *data); + +int _go_git_push_status_foreach(git_push *push, void *data) +{ + return git_push_status_foreach(push, (status_foreach_cb)statusForeach, data); +} + +int _go_git_push_set_callbacks(git_push *push, void *packbuilder_progress_data, void *transfer_progress_data) +{ + return git_push_set_callbacks(push, packbuilderProgress, packbuilder_progress_data, pushTransferProgress, transfer_progress_data); +} + /* EOF */ -- cgit v1.2.3 From 639b66345c2f00f15deb366cf58b22f0dbedf879 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Fri, 28 Feb 2014 14:11:21 +0100 Subject: 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 -- cgit v1.2.3 From f5f8e13744f40300864956fdceb3849c724b9bbb Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Fri, 28 Feb 2014 14:26:03 +0100 Subject: 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" -- cgit v1.2.3 From 2c56324ca5e2513b386a7b1f94b3b62881183769 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 28 Feb 2014 10:46:57 -0800 Subject: 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 } -- cgit v1.2.3 From b404c8b86250b5abdbb02714cfdc08254c67df49 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 28 Feb 2014 10:47:56 -0800 Subject: 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 } -- cgit v1.2.3 From d6332f9526b48e5145db4ee32d8976cdd0f5972c Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 28 Feb 2014 10:54:16 -0800 Subject: 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) } -- cgit v1.2.3 From 9fb7a746e0103ceff2fd8eb9845e782711a87535 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 28 Feb 2014 10:58:53 -0800 Subject: fix handling of msg to treat empty str as nil --- push.go | 9 +++++++-- remote.go | 10 +++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/push.go b/push.go index 0694fe3..d1742e3 100644 --- a/push.go +++ b/push.go @@ -79,8 +79,13 @@ func (p *Push) UpdateTips(sig *Signature, msg string) error { defer C.free(unsafe.Pointer(csig)) } - cmsg := C.CString(msg) - defer C.free(unsafe.Pointer(cmsg)) + var cmsg *C.char + if msg == "" { + cmsg = nil + } else { + cmsg = C.CString(msg) + defer C.free(unsafe.Pointer(cmsg)) + } runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/remote.go b/remote.go index ab2e174..900a314 100644 --- a/remote.go +++ b/remote.go @@ -398,9 +398,13 @@ func (o *Remote) Fetch(sig *Signature, msg string) error { defer C.free(unsafe.Pointer(csig)) } - cmsg := C.CString(msg) - defer C.free(unsafe.Pointer(cmsg)) - + var cmsg *C.char + if msg == "" { + cmsg = nil + } else { + cmsg = C.CString(msg) + defer C.free(unsafe.Pointer(cmsg)) + } ret := C.git_remote_fetch(o.ptr, csig, cmsg) if ret < 0 { return MakeGitError(ret) -- cgit v1.2.3 From 127643eb543cbeac88466956a6394505abc1176e Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 28 Feb 2014 11:08:15 -0800 Subject: 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) } -- cgit v1.2.3 From 5e163fa2e8281642dbb9dbf6229a9a20387130d2 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 7 Mar 2014 16:43:20 -0800 Subject: 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 */ -- cgit v1.2.3 From 42fce02197789a1577ff7130f7f46ce47e584aca Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 11 Mar 2014 03:09:48 +0100 Subject: 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() -- cgit v1.2.3 From b5b0f3f50e151ef67f8cd7b10044c81920093a81 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 11 Mar 2014 03:14:36 +0100 Subject: 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 } -- cgit v1.2.3 From b09c6d8bbe874d6a08e0c91ad3f11bceb74414b2 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 11 Mar 2014 03:27:35 +0100 Subject: 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) } -- cgit v1.2.3 From 263884a908873803cb8a37f80ba89e7b98001f1e Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 11 Mar 2014 03:30:56 +0100 Subject: 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) } -- cgit v1.2.3 From d560b9e9bd7162334f7122dadd02cd0a075e22ab Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Tue, 11 Mar 2014 13:19:12 -0700 Subject: cleanup clone code --- clone.go | 9 +++---- credentials.go | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ push.go | 3 --- remote.go | 52 +++++++++++++++----------------------- transport.go | 79 ---------------------------------------------------------- wrapper.c | 5 ---- 6 files changed, 97 insertions(+), 125 deletions(-) create mode 100644 credentials.go delete mode 100644 transport.go diff --git a/clone.go b/clone.go index 630c343..51dbd65 100644 --- a/clone.go +++ b/clone.go @@ -4,11 +4,6 @@ package git #include #include -static git_clone_options git_clone_options_init() { - git_clone_options ret = GIT_CLONE_OPTIONS_INIT; - return ret; -} - */ import "C" import ( @@ -60,7 +55,9 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error) } func populateCloneOptions(ptr *C.git_clone_options, opts *CloneOptions) { - *ptr = C.git_clone_options_init() + ptr = &C.git_clone_options{} + C.git_clone_init_options(ptr, 1) + if opts == nil { return } diff --git a/credentials.go b/credentials.go new file mode 100644 index 0000000..c5ed055 --- /dev/null +++ b/credentials.go @@ -0,0 +1,74 @@ +package git + +/* +#include +#include +*/ +import "C" +import "unsafe" + +type CredType uint + +const ( + CredTypeUserpassPlaintext CredType = C.GIT_CREDTYPE_USERPASS_PLAINTEXT + CredTypeSshKey = C.GIT_CREDTYPE_SSH_KEY + CredTypeSshCustom = C.GIT_CREDTYPE_SSH_CUSTOM + CredTypeDefault = C.GIT_CREDTYPE_DEFAULT +) + +type Cred struct { + ptr *C.git_cred +} + +func (o *Cred) HasUsername() bool { + if C.git_cred_has_username(o.ptr) == 1 { + return true + } + return false +} + +func (o *Cred) Type() CredType { + return (CredType)(o.ptr.credtype) +} + +func credFromC(ptr *C.git_cred) *Cred { + return &Cred{ptr} +} + +func NewCredUserpassPlaintext(username string, password string) (int, Cred) { + cred := Cred{} + cusername := C.CString(username) + defer C.free(unsafe.Pointer(cusername)) + cpassword := C.CString(password) + defer C.free(unsafe.Pointer(cpassword)) + ret := C.git_cred_userpass_plaintext_new(&cred.ptr, cusername, cpassword) + return int(ret), cred +} + +func NewCredSshKey(username string, publickey string, privatekey string, passphrase string) (int, Cred) { + cred := Cred{} + cusername := C.CString(username) + defer C.free(unsafe.Pointer(cusername)) + cpublickey := C.CString(publickey) + defer C.free(unsafe.Pointer(cpublickey)) + cprivatekey := C.CString(privatekey) + defer C.free(unsafe.Pointer(cprivatekey)) + cpassphrase := C.CString(passphrase) + defer C.free(unsafe.Pointer(cpassphrase)) + ret := C.git_cred_ssh_key_new(&cred.ptr, cusername, cpublickey, cprivatekey, cpassphrase) + return int(ret), cred +} + +func NewCredSshKeyFromAgent(username string) (int, Cred) { + cred := Cred{} + cusername := C.CString(username) + defer C.free(unsafe.Pointer(cusername)) + ret := C.git_cred_ssh_key_from_agent(&cred.ptr, cusername) + return int(ret), cred +} + +func NewCredDefault() (int, Cred) { + cred := Cred{} + ret := C.git_cred_default_new(&cred.ptr) + return int(ret), cred +} diff --git a/push.go b/push.go index d1742e3..8b205c7 100644 --- a/push.go +++ b/push.go @@ -59,9 +59,6 @@ func (p *Push) Finish() error { func (p *Push) UnpackOk() bool { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - ret := C.git_push_unpack_ok(p.ptr) if ret == 0 { return false diff --git a/remote.go b/remote.go index 900a314..3621b5f 100644 --- a/remote.go +++ b/remote.go @@ -5,7 +5,6 @@ package git #include extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks); -extern git_remote_callbacks _go_git_remote_callbacks_init(); extern void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n); extern char *_go_git_get_strarray_n(git_strarray *array, size_t n); @@ -15,7 +14,22 @@ import "unsafe" import "runtime" type TransferProgress struct { - ptr *C.git_transfer_progress + TotalObjects uint + IndexedObjects uint + ReceivedObjects uint + LocalObjects uint + TotalDeltas uint + ReceivedBytes uint +} + +func newTransferProgressFromC(c *C.git_transfer_progress) TransferProgress { + return TransferProgress{ + TotalObjects: uint(c.total_objects), + IndexedObjects: uint(c.indexed_objects), + ReceivedObjects: uint(c.received_objects), + LocalObjects: uint(c.local_objects), + TotalDeltas: uint(c.total_deltas), + ReceivedBytes: uint(c.received_bytes)} } type RemoteCompletion uint @@ -28,7 +42,7 @@ const ( type ProgressCallback func(str string) int type CompletionCallback func(RemoteCompletion) int -type CredentialsCallback func(url string, username_from_url string, allowed_types CredType) (int, Cred) +type CredentialsCallback func(url string, username_from_url string, allowed_types CredType) (int, *Cred) type TransferProgressCallback func(stats TransferProgress) int type UpdateTipsCallback func(refname string, a *Oid, b *Oid) int @@ -45,7 +59,7 @@ type Remote struct { } func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) { - *ptr = C._go_git_remote_callbacks_init() + C.git_remote_init_callbacks(ptr, C.GIT_REMOTE_CALLBACKS_VERSION) if callbacks == nil { return } @@ -81,9 +95,7 @@ func credentialsCallback(_cred **C.git_cred, _url *C.char, _username_from_url *C url := C.GoString(_url) username_from_url := C.GoString(_username_from_url) ret, cred := callbacks.CredentialsCallback(url, username_from_url, (CredType)(allowed_types)) - if gcred, ok := cred.(gitCred); ok { - *_cred = gcred.ptr - } + *_cred = cred.ptr return ret } @@ -93,7 +105,7 @@ func transferProgressCallback(stats *C.git_transfer_progress, data unsafe.Pointe if callbacks.TransferProgressCallback == nil { return 0 } - return callbacks.TransferProgressCallback(TransferProgress{stats}) + return callbacks.TransferProgressCallback(newTransferProgressFromC(stats)) } //export updateTipsCallback @@ -108,30 +120,6 @@ func updateTipsCallback(_refname *C.char, _a *C.git_oid, _b *C.git_oid, data uns return callbacks.UpdateTipsCallback(refname, a, b) } -func (o TransferProgress) TotalObjects() uint { - return uint(o.ptr.total_objects) -} - -func (o TransferProgress) IndexedObjects() uint { - return uint(o.ptr.indexed_objects) -} - -func (o TransferProgress) ReceivedObjects() uint { - return uint(o.ptr.received_objects) -} - -func (o TransferProgress) LocalObjects() uint { - return uint(o.ptr.local_objects) -} - -func (o TransferProgress) TotalDeltas() uint { - return uint(o.ptr.total_deltas) -} - -func (o TransferProgress) ReceivedBytes() uint { - return uint(o.ptr.received_bytes) -} - func RemoteIsValidName(name string) bool { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) diff --git a/transport.go b/transport.go deleted file mode 100644 index e97a70c..0000000 --- a/transport.go +++ /dev/null @@ -1,79 +0,0 @@ -package git - -/* -#include -#include -*/ -import "C" -import "unsafe" - -type CredType uint -const ( - CredTypeUserpassPlaintext CredType = C.GIT_CREDTYPE_USERPASS_PLAINTEXT - CredTypeSshKey = C.GIT_CREDTYPE_SSH_KEY - CredTypeSshCustom = C.GIT_CREDTYPE_SSH_CUSTOM - CredTypeDefault = C.GIT_CREDTYPE_DEFAULT -) - -type Cred interface { - HasUsername() bool - Type() CredType -} - -type gitCred struct { - ptr *C.git_cred -} - -func (o gitCred) HasUsername() bool { - if C.git_cred_has_username(o.ptr) == 1 { - return true - } - return false -} - -func (o gitCred) Type() CredType { - return (CredType)(o.ptr.credtype); -} - -func credFromC(ptr *C.git_cred) Cred { - return gitCred{ptr} -} - -func NewCredUserpassPlaintext(username string, password string) (int, Cred) { - cred := gitCred{} - cusername := C.CString(username) - defer C.free(unsafe.Pointer(cusername)) - cpassword := C.CString(password) - defer C.free(unsafe.Pointer(cpassword)) - ret := C.git_cred_userpass_plaintext_new(&cred.ptr, cusername, cpassword) - return int(ret), cred -} - -func NewCredSshKey(username string, publickey string, privatekey string, passphrase string) (int, Cred) { - cred := gitCred{} - cusername := C.CString(username) - defer C.free(unsafe.Pointer(cusername)) - cpublickey := C.CString(publickey) - defer C.free(unsafe.Pointer(cpublickey)) - cprivatekey := C.CString(privatekey) - defer C.free(unsafe.Pointer(cprivatekey)) - cpassphrase := C.CString(passphrase) - defer C.free(unsafe.Pointer(cpassphrase)) - ret := C.git_cred_ssh_key_new(&cred.ptr, cusername, cpublickey, cprivatekey, cpassphrase) - return int(ret), cred -} - -func NewCredSshKeyFromAgent(username string) (int, Cred) { - cred := gitCred{} - cusername := C.CString(username) - defer C.free(unsafe.Pointer(cusername)) - ret := C.git_cred_ssh_key_from_agent(&cred.ptr, cusername) - return int(ret), cred -} - -func NewCredDefault() (int, Cred) { - cred := gitCred{} - ret := C.git_cred_default_new(&cred.ptr) - return int(ret), cred -} - diff --git a/wrapper.c b/wrapper.c index 8e337df..bc69cd5 100644 --- a/wrapper.c +++ b/wrapper.c @@ -38,11 +38,6 @@ void _go_git_setup_callbacks(git_remote_callbacks *callbacks) { callbacks->update_tips = (update_tips_cb)updateTipsCallback; } -git_remote_callbacks _go_git_remote_callbacks_init() { - git_remote_callbacks ret = GIT_REMOTE_CALLBACKS_INIT; - return ret; -} - void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n) { array->strings[n] = str; } -- cgit v1.2.3 From 2f531968667f96fd573590f2609589cbdb14a480 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Tue, 11 Mar 2014 13:22:00 -0700 Subject: clean up clone code --- clone.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clone.go b/clone.go index 51dbd65..c2abbe5 100644 --- a/clone.go +++ b/clone.go @@ -56,7 +56,7 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error) func populateCloneOptions(ptr *C.git_clone_options, opts *CloneOptions) { ptr = &C.git_clone_options{} - C.git_clone_init_options(ptr, 1) + C.git_clone_init_options(ptr, C.GIT_CLONE_OPTIONS_VERSION) if opts == nil { return -- cgit v1.2.3 From 0a172478dcba23f73f7f1991c6b39c62ee23f172 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Tue, 11 Mar 2014 13:45:27 -0700 Subject: fix return for old go versions / travis --- push.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/push.go b/push.go index 8b205c7..5fb7f07 100644 --- a/push.go +++ b/push.go @@ -62,9 +62,8 @@ func (p *Push) UnpackOk() bool { ret := C.git_push_unpack_ok(p.ptr) if ret == 0 { return false - } else { - return true } + return true } -- cgit v1.2.3 From 51aa76d6f7170bba60ab2252b74a3cab0276996f Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Tue, 11 Mar 2014 16:25:22 -0700 Subject: remove strarray wrappers --- remote.go | 48 +++++++++++++++++++++++++++++------------------- wrapper.c | 8 -------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/remote.go b/remote.go index 3621b5f..da688e7 100644 --- a/remote.go +++ b/remote.go @@ -5,8 +5,6 @@ package git #include extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks); -extern void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n); -extern char *_go_git_get_strarray_n(git_strarray *array, size_t n); */ import "C" @@ -280,6 +278,31 @@ func (o *Remote) AddFetch(refspec string) error { return nil } +func sptr(p uintptr) *C.char { + return *(**C.char)(unsafe.Pointer(p)) +} + +func makeStringsFromCStrings(x **C.char, l int) []string { + s := make([]string, l) + i := 0 + for p := uintptr(unsafe.Pointer(x)); i < l; p += unsafe.Sizeof(uintptr(0)) { + s[i] = C.GoString(sptr(p)) + i++ + } + return s +} + +func makeCStringsFromStrings(s []string) **C.char { + l := len(s) + x := (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(l)))) + i := 0 + for p := uintptr(unsafe.Pointer(x)); i < l; p += unsafe.Sizeof(uintptr(0)) { + *(**C.char)(unsafe.Pointer(p)) = C.CString(s[i]) + i++ + } + return x +} + func (o *Remote) GetFetchRefspecs() ([]string, error) { crefspecs := C.git_strarray{} @@ -291,21 +314,15 @@ func (o *Remote) GetFetchRefspecs() ([]string, error) { return nil, MakeGitError(ret) } defer C.git_strarray_free(&crefspecs) - refspecs := make([]string, crefspecs.count) - for i := 0; i < int(crefspecs.count); i++ { - refspecs[i] = C.GoString(C._go_git_get_strarray_n(&crefspecs, C.size_t(i))) - } + refspecs := makeStringsFromCStrings(crefspecs.strings, int(crefspecs.count)) return refspecs, nil } func (o *Remote) SetFetchRefspecs(refspecs []string) error { crefspecs := C.git_strarray{} crefspecs.count = C.size_t(len(refspecs)) - crefspecs.strings = (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(crefspecs.count)))) - for i, refspec := range refspecs { - C._go_git_set_strarray_n(&crefspecs, C.CString(refspec), C.size_t(i)) - } + crefspecs.strings = makeCStringsFromStrings(refspecs) defer C.git_strarray_free(&crefspecs) runtime.LockOSThread() @@ -343,21 +360,14 @@ func (o *Remote) GetPushRefspecs() ([]string, error) { return nil, MakeGitError(ret) } defer C.git_strarray_free(&crefspecs) - refspecs := make([]string, crefspecs.count) - - for i := 0; i < int(crefspecs.count); i++ { - refspecs[i] = C.GoString(C._go_git_get_strarray_n(&crefspecs, C.size_t(i))) - } + refspecs := makeStringsFromCStrings(crefspecs.strings, int(crefspecs.count)) return refspecs, nil } func (o *Remote) SetPushRefspecs(refspecs []string) error { crefspecs := C.git_strarray{} crefspecs.count = C.size_t(len(refspecs)) - crefspecs.strings = (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(crefspecs.count)))) - for i, refspec := range refspecs { - C._go_git_set_strarray_n(&crefspecs, C.CString(refspec), C.size_t(i)) - } + crefspecs.strings = makeCStringsFromStrings(refspecs) defer C.git_strarray_free(&crefspecs) runtime.LockOSThread() diff --git a/wrapper.c b/wrapper.c index bc69cd5..0fa6c48 100644 --- a/wrapper.c +++ b/wrapper.c @@ -38,14 +38,6 @@ void _go_git_setup_callbacks(git_remote_callbacks *callbacks) { callbacks->update_tips = (update_tips_cb)updateTipsCallback; } -void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n) { - array->strings[n] = str; -} - -char *_go_git_get_strarray_n(git_strarray *array, size_t n) { - return array->strings[n]; -} - typedef int (*status_foreach_cb)(const char *ref, const char *msg, void *data); int _go_git_push_status_foreach(git_push *push, void *data) -- cgit v1.2.3 From 663c2a69c9ad2f88a6c2a06d7fea82a60392f2fe Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Sun, 16 Mar 2014 22:09:12 -0700 Subject: fix chunk create logic --- blob.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/blob.go b/blob.go index ced2cb1..4cee876 100644 --- a/blob.go +++ b/blob.go @@ -55,13 +55,13 @@ 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 + return 0 } else if err != nil { data.Error = err return -1 } - C.memcpy(unsafe.Pointer(buffer), unsafe.Pointer(&goBuf), C.size_t(len(goBuf))) - return 0 + C.memcpy(unsafe.Pointer(buffer), unsafe.Pointer(&goBuf[0]), C.size_t(len(goBuf))) + return len(goBuf) } func (repo *Repository) CreateBlobFromChunks(hintPath string, callback BlobChunkCallback) (*Oid, error) { -- cgit v1.2.3 From d1e7ee53d53d050d5d5be475f98f51e28a88840c Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Tue, 18 Mar 2014 18:23:33 -0700 Subject: fix clone options init --- clone.go | 1 - 1 file changed, 1 deletion(-) diff --git a/clone.go b/clone.go index c2abbe5..1bc3261 100644 --- a/clone.go +++ b/clone.go @@ -55,7 +55,6 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error) } func populateCloneOptions(ptr *C.git_clone_options, opts *CloneOptions) { - ptr = &C.git_clone_options{} C.git_clone_init_options(ptr, C.GIT_CLONE_OPTIONS_VERSION) if opts == nil { -- cgit v1.2.3 From 3d7f737481e02fd8fb787916ade475b3dd6dc78d Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Tue, 18 Mar 2014 18:24:31 -0700 Subject: add simple clone test --- clone_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 clone_test.go diff --git a/clone_test.go b/clone_test.go new file mode 100644 index 0000000..27e824b --- /dev/null +++ b/clone_test.go @@ -0,0 +1,19 @@ +package git + +import ( + "io/ioutil" + "testing" +) + +func Test_Clone(t *testing.T) { + + repo := createTestRepo(t) + seedTestRepo(t, repo) + + path, err := ioutil.TempDir("", "git2go") + checkFatal(t, err) + + _, err = Clone(repo.Path(), path, &CloneOptions{Bare: true}) + + checkFatal(t, err) +} -- cgit v1.2.3 From f1f0fa7335f6ec3285eae32f84d143edffd73ef5 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Tue, 18 Mar 2014 19:38:02 -0700 Subject: fix naming on test --- clone_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clone_test.go b/clone_test.go index 27e824b..6145228 100644 --- a/clone_test.go +++ b/clone_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func Test_Clone(t *testing.T) { +func TestClone(t *testing.T) { repo := createTestRepo(t) seedTestRepo(t, repo) -- cgit v1.2.3 From b6703d47671b3a736e8b93ff0447da45e688865c Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 18 Mar 2014 04:54:40 +0100 Subject: Oid: make the type directly [20]byte There is no need for a struct with a single field. An Oid is 20 bytes which hold the binary representation of the hash, so let's use that directly. Go lets us have methods on this new type just the same. --- git.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/git.go b/git.go index db9522b..8f543b5 100644 --- a/git.go +++ b/git.go @@ -29,9 +29,7 @@ func init() { } // Oid -type Oid struct { - bytes [20]byte -} +type Oid [20]byte func newOidFromC(coid *C.git_oid) *Oid { if coid == nil { @@ -39,18 +37,18 @@ func newOidFromC(coid *C.git_oid) *Oid { } oid := new(Oid) - copy(oid.bytes[0:20], C.GoBytes(unsafe.Pointer(coid), 20)) + copy(oid[0:20], C.GoBytes(unsafe.Pointer(coid), 20)) return oid } func NewOid(b []byte) *Oid { oid := new(Oid) - copy(oid.bytes[0:20], b[0:20]) + copy(oid[0:20], b[0:20]) return oid } func (oid *Oid) toC() *C.git_oid { - return (*C.git_oid)(unsafe.Pointer(&oid.bytes)) + return (*C.git_oid)(unsafe.Pointer(oid)) } func NewOidFromString(s string) (*Oid, error) { @@ -75,25 +73,25 @@ func (oid *Oid) String() string { } func (oid *Oid) Bytes() []byte { - return oid.bytes[0:] + return oid[0:] } func (oid *Oid) Cmp(oid2 *Oid) int { - return bytes.Compare(oid.bytes[:], oid2.bytes[:]) + return bytes.Compare(oid[:], oid2[:]) } func (oid *Oid) Copy() *Oid { ret := new(Oid) - copy(ret.bytes[:], oid.bytes[:]) + copy(ret[:], oid[:]) return ret } func (oid *Oid) Equal(oid2 *Oid) bool { - return bytes.Equal(oid.bytes[:], oid2.bytes[:]) + return bytes.Equal(oid[:], oid2[:]) } func (oid *Oid) IsZero() bool { - for _, a := range oid.bytes { + for _, a := range oid { if a != '0' { return false } @@ -102,7 +100,7 @@ func (oid *Oid) IsZero() bool { } func (oid *Oid) NCmp(oid2 *Oid, n uint) int { - return bytes.Compare(oid.bytes[:n], oid2.bytes[:n]) + return bytes.Compare(oid[:n], oid2[:n]) } func ShortenOids(ids []*Oid, minlen int) (int, error) { -- cgit v1.2.3 From c9c7c1e77942f88955af0dc3bdfb58d5e7d7f121 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 18 Mar 2014 05:04:26 +0100 Subject: Oid: make NewOid take a string This is the most common way of having an id that's not in Oid form, so let's make it the "default" and rename to NewOidFromBytes() the one that takes []byte. --- git.go | 4 ++-- odb_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/git.go b/git.go index 8f543b5..f3fb7e1 100644 --- a/git.go +++ b/git.go @@ -41,7 +41,7 @@ func newOidFromC(coid *C.git_oid) *Oid { return oid } -func NewOid(b []byte) *Oid { +func NewOidFromBytes(b []byte) *Oid { oid := new(Oid) copy(oid[0:20], b[0:20]) return oid @@ -51,7 +51,7 @@ func (oid *Oid) toC() *C.git_oid { return (*C.git_oid)(unsafe.Pointer(oid)) } -func NewOidFromString(s string) (*Oid, error) { +func NewOid(s string) (*Oid, error) { o := new(Oid) cs := C.CString(s) defer C.free(unsafe.Pointer(cs)) diff --git a/odb_test.go b/odb_test.go index a4f8943..17b3ad2 100644 --- a/odb_test.go +++ b/odb_test.go @@ -27,7 +27,7 @@ func TestOdbStream(t *testing.T) { error = stream.Close() checkFatal(t, error) - expectedId, error := NewOidFromString("30f51a3fba5274d53522d0f19748456974647b4f") + expectedId, error := NewOid("30f51a3fba5274d53522d0f19748456974647b4f") checkFatal(t, error) if stream.Id.Cmp(expectedId) != 0 { t.Fatal("Wrong data written") @@ -59,4 +59,4 @@ Initial commit.`; if oid.Cmp(coid) != 0 { t.Fatal("Hash and write Oids are different") } -} \ No newline at end of file +} -- cgit v1.2.3 From c243c31f7d428680579a1dd20273cd3888c730e4 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 19 Mar 2014 03:11:41 +0100 Subject: Oid: remove Bytes() This is not needed. We can do id[:] to get a slice. --- git.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/git.go b/git.go index f3fb7e1..9e1d3e7 100644 --- a/git.go +++ b/git.go @@ -28,7 +28,7 @@ func init() { C.git_threads_init() } -// Oid +// Oid represents the id for a Git object. type Oid [20]byte func newOidFromC(coid *C.git_oid) *Oid { @@ -72,10 +72,6 @@ func (oid *Oid) String() string { return string(buf) } -func (oid *Oid) Bytes() []byte { - return oid[0:] -} - func (oid *Oid) Cmp(oid2 *Oid) int { return bytes.Compare(oid[:], oid2[:]) } -- cgit v1.2.3 From 0bb73e43a8f26be8608cdd304d73cacb05753417 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 19 Mar 2014 03:39:34 +0100 Subject: Oid: use Go's conversion functions Go already has all the necessary pieces for encoding and decoding hex strings. Using them let's us avoid going into C land. Benchmarks show this takes about half the time as using libgit2's functions. --- git.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/git.go b/git.go index 9e1d3e7..e5fe812 100644 --- a/git.go +++ b/git.go @@ -8,6 +8,7 @@ package git import "C" import ( "bytes" + "encoding/hex" "errors" "runtime" "strings" @@ -52,24 +53,23 @@ func (oid *Oid) toC() *C.git_oid { } func NewOid(s string) (*Oid, error) { - o := new(Oid) - cs := C.CString(s) - defer C.free(unsafe.Pointer(cs)) + if len(s) > C.GIT_OID_HEXSZ { + return nil, errors.New("string is too long for oid") + } - runtime.LockOSThread() - defer runtime.UnlockOSThread() + o := new(Oid) - if ret := C.git_oid_fromstr(o.toC(), cs); ret < 0 { - return nil, MakeGitError(ret) + slice, error := hex.DecodeString(s) + if error != nil { + return nil, error } + copy(o[:], slice[:20]) return o, nil } func (oid *Oid) String() string { - buf := make([]byte, 40) - C.git_oid_fmt((*C.char)(unsafe.Pointer(&buf[0])), oid.toC()) - return string(buf) + return hex.EncodeToString(oid[:]) } func (oid *Oid) Cmp(oid2 *Oid) int { -- cgit v1.2.3 From b82a72a9ce4701a4560288c4ebf1511ffb415b80 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 19 Mar 2014 03:51:59 +0100 Subject: Oid: fix IsZero() We need to compare against the number zero, not its ASCII value. --- git.go | 2 +- git_test.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/git.go b/git.go index e5fe812..b20f993 100644 --- a/git.go +++ b/git.go @@ -88,7 +88,7 @@ func (oid *Oid) Equal(oid2 *Oid) bool { func (oid *Oid) IsZero() bool { for _, a := range oid { - if a != '0' { + if a != 0 { return false } } diff --git a/git_test.go b/git_test.go index fff3c6c..6542ca0 100644 --- a/git_test.go +++ b/git_test.go @@ -54,3 +54,11 @@ func seedTestRepo(t *testing.T, repo *Repository) (*Oid, *Oid) { return commitId, treeId } + +func TestOidZero(t *testing.T) { + var zeroId Oid + + if !zeroId.IsZero() { + t.Error("Zero Oid is not zero") + } +} -- cgit v1.2.3 From ad128bdefb58927762798a5b708a63bff43b627e Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 19 Mar 2014 07:54:52 +0100 Subject: Remote: don't mix allocators We cannot ask libgit2 to free the memory we have allocated ourselves, as it cannot know how to do it. Let's free the strarray ourselves. --- remote.go | 17 +++++++++++++++-- remote_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 remote_test.go diff --git a/remote.go b/remote.go index da688e7..3e01ce1 100644 --- a/remote.go +++ b/remote.go @@ -303,6 +303,19 @@ func makeCStringsFromStrings(s []string) **C.char { return x } +func freeStrarray(arr *C.git_strarray) { + count := int(arr.count) + size := unsafe.Sizeof(unsafe.Pointer(nil)) + + i := 0 + for p := uintptr(unsafe.Pointer(arr.strings)); i < count; p += size { + C.free(unsafe.Pointer(sptr(p))) + i++ + } + + C.free(unsafe.Pointer(arr.strings)) +} + func (o *Remote) GetFetchRefspecs() ([]string, error) { crefspecs := C.git_strarray{} @@ -323,7 +336,7 @@ func (o *Remote) SetFetchRefspecs(refspecs []string) error { crefspecs := C.git_strarray{} crefspecs.count = C.size_t(len(refspecs)) crefspecs.strings = makeCStringsFromStrings(refspecs) - defer C.git_strarray_free(&crefspecs) + defer freeStrarray(&crefspecs) runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -368,7 +381,7 @@ func (o *Remote) SetPushRefspecs(refspecs []string) error { crefspecs := C.git_strarray{} crefspecs.count = C.size_t(len(refspecs)) crefspecs.strings = makeCStringsFromStrings(refspecs) - defer C.git_strarray_free(&crefspecs) + defer freeStrarray(&crefspecs) runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/remote_test.go b/remote_test.go new file mode 100644 index 0000000..16675fc --- /dev/null +++ b/remote_test.go @@ -0,0 +1,27 @@ +package git + +import ( + "os" + "testing" +) + +func TestRefspecs(t *testing.T) { + repo := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + + remote, err := repo.CreateRemoteInMemory("refs/heads/*:refs/heads/*", "git://foo/bar") + checkFatal(t, err) + + expected := []string{ + "refs/heads/*:refs/remotes/origin/*", + "refs/pull/*/head:refs/remotes/origin/*", + } + + err = remote.SetFetchRefspecs(expected) + checkFatal(t, err) + + actual, err := remote.GetFetchRefspecs() + checkFatal(t, err) + + compareStringList(t, expected, actual) +} -- cgit v1.2.3 From 3ae9813fca2837601e5a7c801972396a59e1eb59 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 19 Mar 2014 08:03:21 +0100 Subject: Clean up after the tests --- clone_test.go | 4 ++++ push_test.go | 3 +++ 2 files changed, 7 insertions(+) diff --git a/clone_test.go b/clone_test.go index 6145228..97366bf 100644 --- a/clone_test.go +++ b/clone_test.go @@ -2,18 +2,22 @@ package git import ( "io/ioutil" + "os" "testing" ) func TestClone(t *testing.T) { repo := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + seedTestRepo(t, repo) path, err := ioutil.TempDir("", "git2go") checkFatal(t, err) _, err = Clone(repo.Path(), path, &CloneOptions{Bare: true}) + defer os.RemoveAll(path) checkFatal(t, err) } diff --git a/push_test.go b/push_test.go index dfd4af7..c1e6a22 100644 --- a/push_test.go +++ b/push_test.go @@ -2,13 +2,16 @@ package git import ( "log" + "os" "testing" "time" ) func Test_Push_ToRemote(t *testing.T) { repo := createBareTestRepo(t) + defer os.RemoveAll(repo.Path()) repo2 := createTestRepo(t) + defer os.RemoveAll(repo2.Workdir()) remote, err := repo2.CreateRemote("test_push", repo.Path()) checkFatal(t, err) -- cgit v1.2.3 From 574f0dd12da2eae6f26ae35f197b2ec7a9328249 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Thu, 20 Mar 2014 03:29:54 +0100 Subject: Remote: remove Get prefix from refspecs Idiomatic Go is to omit the Get from the getter methods. --- remote.go | 4 ++-- remote_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/remote.go b/remote.go index 3e01ce1..d556f99 100644 --- a/remote.go +++ b/remote.go @@ -316,7 +316,7 @@ func freeStrarray(arr *C.git_strarray) { C.free(unsafe.Pointer(arr.strings)) } -func (o *Remote) GetFetchRefspecs() ([]string, error) { +func (o *Remote) FetchRefspecs() ([]string, error) { crefspecs := C.git_strarray{} runtime.LockOSThread() @@ -362,7 +362,7 @@ func (o *Remote) AddPush(refspec string) error { return nil } -func (o *Remote) GetPushRefspecs() ([]string, error) { +func (o *Remote) PushRefspecs() ([]string, error) { crefspecs := C.git_strarray{} runtime.LockOSThread() diff --git a/remote_test.go b/remote_test.go index 16675fc..04b3a57 100644 --- a/remote_test.go +++ b/remote_test.go @@ -20,7 +20,7 @@ func TestRefspecs(t *testing.T) { err = remote.SetFetchRefspecs(expected) checkFatal(t, err) - actual, err := remote.GetFetchRefspecs() + actual, err := remote.FetchRefspecs() checkFatal(t, err) compareStringList(t, expected, actual) -- cgit v1.2.3 From 99d7f66477aa09915821659087da8b91e593f4eb Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Thu, 20 Mar 2014 02:06:56 -0700 Subject: add remote list --- remote.go | 12 ++++++++++++ remote_test.go | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/remote.go b/remote.go index d556f99..d675ab8 100644 --- a/remote.go +++ b/remote.go @@ -132,6 +132,18 @@ func (r *Remote) Free() { C.git_remote_free(r.ptr) } +func (repo *Repository) ListRemotes() ([]string, error) { + var r C.git_strarray + ecode := C.git_remote_list(&r, repo.ptr) + if ecode < 0 { + return make([]string, 0), MakeGitError(ecode) + } + defer C.git_strarray_free(&r) + + remotes := makeStringsFromCStrings(r.strings, int(r.count)) + return remotes, nil +} + func (repo *Repository) CreateRemote(name string, url string) (*Remote, error) { remote := &Remote{} diff --git a/remote_test.go b/remote_test.go index 04b3a57..90e24ae 100644 --- a/remote_test.go +++ b/remote_test.go @@ -8,6 +8,7 @@ import ( func TestRefspecs(t *testing.T) { repo := createTestRepo(t) defer os.RemoveAll(repo.Workdir()) + defer repo.Free() remote, err := repo.CreateRemoteInMemory("refs/heads/*:refs/heads/*", "git://foo/bar") checkFatal(t, err) @@ -25,3 +26,22 @@ func TestRefspecs(t *testing.T) { compareStringList(t, expected, actual) } + +func TestListRemotes(t *testing.T) { + repo := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + defer repo.Free() + + _, err := repo.CreateRemote("test", "git://foo/bar") + + checkFatal(t, err) + + expected := []string{ + "test", + } + + actual, err := repo.ListRemotes() + checkFatal(t, err) + + compareStringList(t, expected, actual) +} -- cgit v1.2.3 From 5d8db7f9362a314cf56747cf23605aec8640e92e Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Thu, 20 Mar 2014 20:24:29 -0700 Subject: return nil instead of empty array on error --- remote.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/remote.go b/remote.go index d675ab8..66097b8 100644 --- a/remote.go +++ b/remote.go @@ -136,7 +136,7 @@ func (repo *Repository) ListRemotes() ([]string, error) { var r C.git_strarray ecode := C.git_remote_list(&r, repo.ptr) if ecode < 0 { - return make([]string, 0), MakeGitError(ecode) + return nil, MakeGitError(ecode) } defer C.git_strarray_free(&r) -- cgit v1.2.3 From 1f3f8adda8d6df5053faa63487e70cb3f29f2673 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Thu, 20 Mar 2014 20:49:05 -0700 Subject: Add index WriteTreeTo + test --- index.go | 18 ++++++++++++++++-- index_test.go | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/index.go b/index.go index 6da3c98..7336249 100644 --- a/index.go +++ b/index.go @@ -23,7 +23,7 @@ type IndexEntry struct { Uid uint Gid uint Size uint - Id *Oid + Id *Oid Path string } @@ -48,6 +48,20 @@ func (v *Index) AddByPath(path string) error { return nil } +func (v *Index) WriteTreeTo(repo *Repository) (*Oid, error) { + oid := new(Oid) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_index_write_tree_to(oid.toC(), v.ptr, repo.ptr) + if ret < 0 { + return nil, MakeGitError(ret) + } + + return oid, nil +} + func (v *Index) WriteTree() (*Oid, error) { oid := new(Oid) @@ -62,7 +76,7 @@ func (v *Index) WriteTree() (*Oid, error) { return oid, nil } -func (v *Index) Write() (error) { +func (v *Index) Write() error { runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/index_test.go b/index_test.go index 9828d0f..5920b93 100644 --- a/index_test.go +++ b/index_test.go @@ -22,6 +22,25 @@ func TestCreateRepoAndStage(t *testing.T) { } } +func TestIndexWriteTreeTo(t *testing.T) { + repo := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + + repo2 := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + + idx, err := repo.Index() + checkFatal(t, err) + err = idx.AddByPath("README") + checkFatal(t, err) + treeId, err := idx.WriteTreeTo(repo2) + checkFatal(t, err) + + if treeId.String() != "b7119b11e8ef7a1a5a34d3ac87f5b075228ac81e" { + t.Fatalf("%v", treeId.String()) + } +} + func checkFatal(t *testing.T, err error) { if err == nil { return -- cgit v1.2.3 From b2a2a279d96890c9578370ec4db50c1da31f18d7 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 25 Mar 2014 00:12:32 +0100 Subject: Add a settings package This lets us modify the libgit2-wide options/settings. --- .travis.yml | 5 +-- git.go | 4 ++ script/build-libgit2.sh | 4 -- settings/settings.go | 109 ++++++++++++++++++++++++++++++++++++++++++++++ settings/settings_test.go | 66 ++++++++++++++++++++++++++++ 5 files changed, 181 insertions(+), 7 deletions(-) create mode 100644 settings/settings.go create mode 100644 settings/settings_test.go diff --git a/.travis.yml b/.travis.yml index 86f8265..2a03529 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,7 @@ go: - 1.1 - tip -env: - - PKG_CONFIG_PATH=libgit2/install/lib/pkgconfig LD_LIBRARY_PATH=libgit2/install/lib - install: - script/build-libgit2.sh + - export PKG_CONFIG_PATH=$PWD/libgit2/install/lib/pkgconfig + - export LD_LIBRARY_PATH=$PWD/libgit2/install/lib diff --git a/git.go b/git.go index b20f993..8159244 100644 --- a/git.go +++ b/git.go @@ -149,6 +149,10 @@ func MakeGitError(errorCode C.int) error { return &GitError{C.GoString(err.message), int(err.klass), int(errorCode)} } +func MakeGitError2(err int) error { + return MakeGitError(C.int(err)) +} + func cbool(b bool) C.int { if b { return C.int(1) diff --git a/script/build-libgit2.sh b/script/build-libgit2.sh index aa43df5..8376a15 100755 --- a/script/build-libgit2.sh +++ b/script/build-libgit2.sh @@ -11,7 +11,3 @@ cmake -DTHREADSAFE=ON \ . 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" diff --git a/settings/settings.go b/settings/settings.go new file mode 100644 index 0000000..6661c5d --- /dev/null +++ b/settings/settings.go @@ -0,0 +1,109 @@ +package settings + +/* +#cgo pkg-config: libgit2 +#include + +int _go_git_opts_get_search_path(int level, git_buf *buf) +{ + return git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, level, buf); +} + +int _go_git_opts_set_search_path(int level, const char *path) +{ + return git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, level, path); +} + +int _go_git_opts_set_size_t(int opt, size_t val) +{ + return git_libgit2_opts(opt, val); +} + +int _go_git_opts_get_size_t(int opt, size_t *val) +{ + return git_libgit2_opts(opt, val); +} + +*/ +import "C" +import ( + "runtime" + "unsafe" + "github.com/libgit2/git2go" +) + +func MakeGitError(err C.int) error { + return git.MakeGitError2(int(err)) +} + +func SearchPath(level git.ConfigLevel) (string, error) { + var buf C.git_buf + defer C.git_buf_free(&buf) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := C._go_git_opts_get_search_path(C.int(level), &buf) + if err < 0 { + return "", MakeGitError(err) + } + + return C.GoString(buf.ptr), nil +} + +func SetSearchPath(level git.ConfigLevel, path string) error { + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := C._go_git_opts_set_search_path(C.int(level), cpath) + if err < 0 { + return MakeGitError(err) + } + + return nil +} + +func getSizet(opt C.int) (int, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var val C.size_t + err := C._go_git_opts_get_size_t(opt, &val); + if err < 0 { + return 0, MakeGitError(err) + } + + return int(val), nil +} + +func setSizet(opt C.int, val int) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + cval := C.size_t(val) + err := C._go_git_opts_set_size_t(opt, cval); + if err < 0 { + return MakeGitError(err) + } + + return nil +} + +func MwindowSize() (int, error) { + return getSizet(C.GIT_OPT_GET_MWINDOW_SIZE) +} + +func SetMwindowSize(size int) error { + return setSizet(C.GIT_OPT_SET_MWINDOW_SIZE, size) +} + +func MwindowMappedLimit() (int, error) { + return getSizet(C.GIT_OPT_GET_MWINDOW_MAPPED_LIMIT) +} + +func SetMwindowMappedLimit(size int) error { + return setSizet(C.GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, size) +} diff --git a/settings/settings_test.go b/settings/settings_test.go new file mode 100644 index 0000000..55b08c8 --- /dev/null +++ b/settings/settings_test.go @@ -0,0 +1,66 @@ +package settings + +import ( + "testing" + "runtime" + "github.com/libgit2/git2go" +) + +type pathPair struct { + Level git.ConfigLevel + Path string +} + +func TestSearchPath(t *testing.T) { + paths := []pathPair{ + pathPair{git.ConfigLevelSystem, "/tmp/system"}, + pathPair{git.ConfigLevelGlobal, "/tmp/global"}, + pathPair{git.ConfigLevelXDG, "/tmp/xdg"}, + } + + for _, pair := range paths { + err := SetSearchPath(pair.Level, pair.Path) + checkFatal(t, err) + + actual, err := SearchPath(pair.Level) + checkFatal(t, err) + + if pair.Path != actual { + t.Fatal("Search paths don't match") + } + } +} + +func TestMmapSizes(t *testing.T) { + size := 42 * 1024 + + err := SetMwindowSize(size) + checkFatal(t, err) + + actual, err := MwindowSize() + if size != actual { + t.Fatal("Sizes don't match") + } + + err = SetMwindowMappedLimit(size) + checkFatal(t, err) + + actual, err = MwindowMappedLimit() + if size != actual { + t.Fatal("Sizes don't match") + } +} + +func checkFatal(t *testing.T, err error) { + if err == nil { + return + } + + // The failure happens at wherever we were called, not here + _, file, line, ok := runtime.Caller(1) + if !ok { + t.Fatal() + } + + t.Fatalf("Fail at %v:%v; %v", file, line, err) +} -- cgit v1.2.3 From 429408dbe536157c8cd9e384f121c58e52ce9f8e Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Thu, 27 Mar 2014 11:32:22 +0100 Subject: Added force argument for (*Submodule).Reload() and (*Repository).ReloadAllSubmodules() --- submodule.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/submodule.go b/submodule.go index a94afd4..f6ab5e1 100644 --- a/submodule.go +++ b/submodule.go @@ -287,22 +287,22 @@ func (sub *Submodule) Open() (*Repository, error) { return repo, nil } -func (sub *Submodule) Reload() error { +func (sub *Submodule) Reload(force bool) error { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_submodule_reload(sub.ptr) + ret := C.git_submodule_reload(sub.ptr, cbool(force)) if ret < 0 { return MakeGitError(ret) } return nil } -func (repo *Repository) ReloadAllSubmodules() error { +func (repo *Repository) ReloadAllSubmodules(force bool) error { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_submodule_reload_all(repo.ptr) + ret := C.git_submodule_reload_all(repo.ptr, cbool(force)) if ret < 0 { return MakeGitError(ret) } -- cgit v1.2.3 From 552557ba51343076c1f7378fc90f88508cab8b4b Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Sun, 30 Mar 2014 13:23:03 -0700 Subject: add missing walk functions --- walk.go | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 3 deletions(-) diff --git a/walk.go b/walk.go index 71df7bb..f7c147d 100644 --- a/walk.go +++ b/walk.go @@ -9,6 +9,7 @@ import "C" import ( "io" "runtime" + "unsafe" ) // RevWalk @@ -37,8 +38,57 @@ func (v *RevWalk) Reset() { C.git_revwalk_reset(v.ptr) } -func (v *RevWalk) Push(id *Oid) { - C.git_revwalk_push(v.ptr, id.toC()) +func (v *RevWalk) Push(id *Oid) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_revwalk_push(v.ptr, id.toC()) + if ecode < 0 { + return MakeGitError(ecode) + } + return nil +} + +func (v *RevWalk) PushGlob(glob string) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + cstr := C.CString(glob) + defer C.free(unsafe.Pointer(cstr)) + + ecode := C.git_revwalk_push_glob(v.ptr, cstr) + if ecode < 0 { + return MakeGitError(ecode) + } + return nil +} + +func (v *RevWalk) PushRange(r string) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + cstr := C.CString(r) + defer C.free(unsafe.Pointer(cstr)) + + ecode := C.git_revwalk_push_range(v.ptr, cstr) + if ecode < 0 { + return MakeGitError(ecode) + } + return nil +} + +func (v *RevWalk) PushRef(r string) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + cstr := C.CString(r) + defer C.free(unsafe.Pointer(cstr)) + + ecode := C.git_revwalk_push_ref(v.ptr, cstr) + if ecode < 0 { + return MakeGitError(ecode) + } + return nil } func (v *RevWalk) PushHead() (err error) { @@ -49,8 +99,57 @@ func (v *RevWalk) PushHead() (err error) { if ecode < 0 { err = MakeGitError(ecode) } + return nil +} - return +func (v *RevWalk) Hide(id *Oid) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_revwalk_hide(v.ptr, id.toC()) + if ecode < 0 { + return MakeGitError(ecode) + } + return nil +} + +func (v *RevWalk) HideGlob(glob string) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + cstr := C.CString(glob) + defer C.free(unsafe.Pointer(cstr)) + + ecode := C.git_revwalk_hide_glob(v.ptr, cstr) + if ecode < 0 { + return MakeGitError(ecode) + } + return nil +} + +func (v *RevWalk) HideRef(r string) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + cstr := C.CString(r) + defer C.free(unsafe.Pointer(cstr)) + + ecode := C.git_revwalk_hide_ref(v.ptr, cstr) + if ecode < 0 { + return MakeGitError(ecode) + } + return nil +} + +func (v *RevWalk) HideHead() (err error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_revwalk_hide_head(v.ptr) + if ecode < 0 { + err = MakeGitError(ecode) + } + return nil } func (v *RevWalk) Next(id *Oid) (err error) { -- cgit v1.2.3 From dcdf2c355594f62e00966f7b61b360c7cba1d3f3 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Sun, 30 Mar 2014 19:53:07 -0700 Subject: add conflict functions --- index.go | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 175 insertions(+), 13 deletions(-) diff --git a/index.go b/index.go index 7336249..d3178a2 100644 --- a/index.go +++ b/index.go @@ -27,6 +27,39 @@ type IndexEntry struct { Path string } +func newIndexEntryFromC(entry *C.git_index_entry) *IndexEntry { + if entry == nil { + return nil + } + return &IndexEntry{ + time.Unix(int64(entry.ctime.seconds), int64(entry.ctime.nanoseconds)), + time.Unix(int64(entry.mtime.seconds), int64(entry.mtime.nanoseconds)), + uint(entry.mode), + uint(entry.uid), + uint(entry.gid), + uint(entry.file_size), + newOidFromC(&entry.id), + C.GoString(entry.path), + } +} + +func populateCIndexEntry(source *IndexEntry, dest *C.git_index_entry) { + dest.ctime.seconds = C.git_time_t(source.Ctime.Unix()) + dest.ctime.nanoseconds = C.uint(source.Ctime.UnixNano()) + dest.mtime.seconds = C.git_time_t(source.Mtime.Unix()) + dest.mtime.nanoseconds = C.uint(source.Mtime.UnixNano()) + dest.mode = C.uint(source.Mode) + dest.uid = C.uint(source.Uid) + dest.gid = C.uint(source.Gid) + dest.file_size = C.git_off_t(source.Size) + dest.id = *source.Id.toC() + dest.path = C.CString(source.Path) +} + +func freeCIndexEntry(entry *C.git_index_entry) { + C.free(unsafe.Pointer(entry.path)) +} + func newIndexFromC(ptr *C.git_index) *Index { idx := &Index{ptr} runtime.SetFinalizer(idx, (*Index).Free) @@ -97,19 +130,6 @@ func (v *Index) EntryCount() uint { return uint(C.git_index_entrycount(v.ptr)) } -func newIndexEntryFromC(entry *C.git_index_entry) *IndexEntry { - return &IndexEntry{ - time.Unix(int64(entry.ctime.seconds), int64(entry.ctime.nanoseconds)), - time.Unix(int64(entry.mtime.seconds), int64(entry.mtime.nanoseconds)), - uint(entry.mode), - uint(entry.uid), - uint(entry.gid), - uint(entry.file_size), - newOidFromC(&entry.id), - C.GoString(entry.path), - } -} - func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) { centry := C.git_index_get_byindex(v.ptr, C.size_t(index)) if centry == nil { @@ -117,3 +137,145 @@ func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) { } return newIndexEntryFromC(centry), nil } + +func (v *Index) HasConflicts() bool { + return C.git_index_has_conflicts(v.ptr) != 0 +} + +func (v *Index) CleanupConflicts() { + C.git_index_conflict_cleanup(v.ptr) +} + +func (v *Index) AddConflict(ancestor *IndexEntry, our *IndexEntry, their *IndexEntry) error { + + var cancestor *C.git_index_entry + var cour *C.git_index_entry + var ctheir *C.git_index_entry + + if ancestor != nil { + cancestor = &C.git_index_entry{} + populateCIndexEntry(ancestor, cancestor) + defer freeCIndexEntry(cancestor) + } + + if our != nil { + cour = &C.git_index_entry{} + populateCIndexEntry(our, cour) + defer freeCIndexEntry(cour) + } + + if their != nil { + ctheir = &C.git_index_entry{} + populateCIndexEntry(their, ctheir) + defer freeCIndexEntry(ctheir) + } + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_index_conflict_add(v.ptr, cancestor, cour, ctheir) + if ecode < 0 { + return MakeGitError(ecode) + } + return nil +} + +type IndexConflict struct { + Ancestor *IndexEntry + Our *IndexEntry + Their *IndexEntry +} + +func (v *Index) GetConflict(path string) (IndexConflict, error) { + + var cancestor *C.git_index_entry + var cour *C.git_index_entry + var ctheir *C.git_index_entry + + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_index_conflict_get(&cancestor, &cour, &ctheir, v.ptr, cpath) + if ecode < 0 { + return IndexConflict{}, MakeGitError(ecode) + } + return IndexConflict{ + Ancestor: newIndexEntryFromC(cancestor), + Our: newIndexEntryFromC(cour), + Their: newIndexEntryFromC(ctheir), + }, nil +} + +func (v *Index) RemoveConflict(path string) error { + + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_index_conflict_remove(v.ptr, cpath) + if ecode < 0 { + return MakeGitError(ecode) + } + return nil +} + +type IndexConflictIterator struct { + ptr *C.git_index_conflict_iterator + index *Index +} + +func newIndexConflictIteratorFromC(index *Index, ptr *C.git_index_conflict_iterator) *IndexConflictIterator { + i := &IndexConflictIterator{ptr: ptr, index: index} + runtime.SetFinalizer(i, (*IndexConflictIterator).Free) + return i +} + +func (v *IndexConflictIterator) Index() *Index { + return v.index +} + +func (v *IndexConflictIterator) Free() { + runtime.SetFinalizer(v, nil) + C.git_index_conflict_iterator_free(v.ptr) +} + +func (v *Index) ConflictIterator() (*IndexConflictIterator, error) { + var i *C.git_index_conflict_iterator + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_index_conflict_iterator_new(&i, v.ptr) + if ecode < 0 { + return nil, MakeGitError(ecode) + } + return newIndexConflictIteratorFromC(v, i), nil +} + +func (v *IndexConflictIterator) Next() (IndexConflict, error) { + var cancestor *C.git_index_entry + var cour *C.git_index_entry + var ctheir *C.git_index_entry + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_index_conflict_next(&cancestor, &cour, &ctheir, v.ptr) + if ecode == C.GIT_ITEROVER { + return IndexConflict{}, ErrIterOver + } + + if ecode < 0 { + return IndexConflict{}, MakeGitError(ecode) + } + return IndexConflict{ + Ancestor: newIndexEntryFromC(cancestor), + Our: newIndexEntryFromC(cour), + Their: newIndexEntryFromC(ctheir), + }, nil +} -- cgit v1.2.3 From a06f4a030a90129db76e5a741a73bba5b27cda29 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 1 Apr 2014 12:13:37 +0200 Subject: Adjust to Go tip changes It does not like breaking aliasing rules, so let's keep a casted pointer for when libgit2 wants that. --- blob.go | 7 ++++--- branch.go | 2 +- commit.go | 29 +++++++++++++++-------------- object.go | 19 ++++++++++++++----- repository.go | 6 +++--- tree.go | 11 ++++++----- 6 files changed, 43 insertions(+), 31 deletions(-) diff --git a/blob.go b/blob.go index 4cee876..4277127 100644 --- a/blob.go +++ b/blob.go @@ -20,15 +20,16 @@ import ( type Blob struct { gitObject + cast_ptr *C.git_blob } func (v *Blob) Size() int64 { - return int64(C.git_blob_rawsize(v.ptr)) + return int64(C.git_blob_rawsize(v.cast_ptr)) } func (v *Blob) Contents() []byte { - size := C.int(C.git_blob_rawsize(v.ptr)) - buffer := unsafe.Pointer(C.git_blob_rawcontent(v.ptr)) + 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) } diff --git a/branch.go b/branch.go index aee23e4..bd7312b 100644 --- a/branch.go +++ b/branch.go @@ -43,7 +43,7 @@ func (repo *Repository) CreateBranch(branchName string, target *Commit, force bo runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.ptr, cForce, cSignature, cmsg) + ret := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.cast_ptr, cForce, cSignature, cmsg) if ret < 0 { return nil, MakeGitError(ret) } diff --git a/commit.go b/commit.go index 0edebb6..0a5cfce 100644 --- a/commit.go +++ b/commit.go @@ -17,56 +17,57 @@ import ( // Commit type Commit struct { gitObject + cast_ptr *C.git_commit } func (c Commit) Message() string { - return C.GoString(C.git_commit_message(c.ptr)) + return C.GoString(C.git_commit_message(c.cast_ptr)) } func (c Commit) Tree() (*Tree, error) { - var ptr *C.git_object + var ptr *C.git_tree runtime.LockOSThread() defer runtime.UnlockOSThread() - err := C.git_commit_tree(&ptr, c.ptr) + err := C.git_commit_tree(&ptr, c.cast_ptr) if err < 0 { return nil, MakeGitError(err) } - return allocObject(ptr).(*Tree), nil + return allocObject((*C.git_object)(ptr)).(*Tree), nil } func (c Commit) TreeId() *Oid { - return newOidFromC(C.git_commit_tree_id(c.ptr)) + return newOidFromC(C.git_commit_tree_id(c.cast_ptr)) } func (c Commit) Author() *Signature { - ptr := C.git_commit_author(c.ptr) - return newSignatureFromC(ptr) + cast_ptr := C.git_commit_author(c.cast_ptr) + return newSignatureFromC(cast_ptr) } func (c Commit) Committer() *Signature { - ptr := C.git_commit_committer(c.ptr) - return newSignatureFromC(ptr) + cast_ptr := C.git_commit_committer(c.cast_ptr) + return newSignatureFromC(cast_ptr) } func (c *Commit) Parent(n uint) *Commit { - var cobj *C.git_object - ret := C.git_commit_parent(&cobj, c.ptr, C.uint(n)) + var cobj *C.git_commit + ret := C.git_commit_parent(&cobj, c.cast_ptr, C.uint(n)) if ret != 0 { return nil } - return allocObject(cobj).(*Commit) + return allocObject((*C.git_object)(cobj)).(*Commit) } func (c *Commit) ParentId(n uint) *Oid { - return newOidFromC(C.git_commit_parent_id(c.ptr, C.uint(n))) + return newOidFromC(C.git_commit_parent_id(c.cast_ptr, C.uint(n))) } func (c *Commit) ParentCount() uint { - return uint(C.git_commit_parentcount(c.ptr)) + return uint(C.git_commit_parentcount(c.cast_ptr)) } // Signature diff --git a/object.go b/object.go index 090be1f..101d15e 100644 --- a/object.go +++ b/object.go @@ -48,7 +48,7 @@ func (t ObjectType) String() (string) { } func (o gitObject) Id() *Oid { - return newOidFromC(C.git_commit_id(o.ptr)) + return newOidFromC(C.git_object_id(o.ptr)) } func (o gitObject) Type() ObjectType { @@ -57,24 +57,33 @@ func (o gitObject) Type() ObjectType { func (o *gitObject) Free() { runtime.SetFinalizer(o, nil) - C.git_commit_free(o.ptr) + C.git_object_free(o.ptr) } func allocObject(cobj *C.git_object) Object { switch ObjectType(C.git_object_type(cobj)) { case ObjectCommit: - commit := &Commit{gitObject{cobj}} + commit := &Commit{ + gitObject: gitObject{cobj}, + cast_ptr: (*C.git_commit)(cobj), + } runtime.SetFinalizer(commit, (*Commit).Free) return commit case ObjectTree: - tree := &Tree{gitObject{cobj}} + tree := &Tree{ + gitObject: gitObject{cobj}, + cast_ptr: (*C.git_tree)(cobj), + } runtime.SetFinalizer(tree, (*Tree).Free) return tree case ObjectBlob: - blob := &Blob{gitObject{cobj}} + blob := &Blob{ + gitObject: gitObject{cobj}, + cast_ptr: (*C.git_blob)(cobj), + } runtime.SetFinalizer(blob, (*Blob).Free) return blob } diff --git a/repository.go b/repository.go index d6eadc8..d757747 100644 --- a/repository.go +++ b/repository.go @@ -239,7 +239,7 @@ func (v *Repository) CreateCommit( if nparents > 0 { cparents = make([]*C.git_commit, nparents) for i, v := range parents { - cparents[i] = v.ptr + cparents[i] = v.cast_ptr } parentsarg = &cparents[0] } @@ -256,7 +256,7 @@ func (v *Repository) CreateCommit( ret := C.git_commit_create( oid.toC(), v.ptr, cref, authorSig, committerSig, - nil, cmsg, tree.ptr, C.size_t(nparents), parentsarg) + nil, cmsg, tree.cast_ptr, C.size_t(nparents), parentsarg) if ret < 0 { return nil, MakeGitError(ret) @@ -331,7 +331,7 @@ func (v *Repository) TreeBuilderFromTree(tree *Tree) (*TreeBuilder, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if ret := C.git_treebuilder_create(&bld.ptr, tree.ptr); ret < 0 { + if ret := C.git_treebuilder_create(&bld.ptr, tree.cast_ptr); ret < 0 { return nil, MakeGitError(ret) } runtime.SetFinalizer(bld, (*TreeBuilder).Free) diff --git a/tree.go b/tree.go index 7070ac7..8356fba 100644 --- a/tree.go +++ b/tree.go @@ -26,6 +26,7 @@ const ( type Tree struct { gitObject + cast_ptr *C.git_tree } type TreeEntry struct { @@ -48,7 +49,7 @@ func (t Tree) EntryByName(filename string) *TreeEntry { cname := C.CString(filename) defer C.free(unsafe.Pointer(cname)) - entry := C.git_tree_entry_byname(t.ptr, cname) + entry := C.git_tree_entry_byname(t.cast_ptr, cname) if entry == nil { return nil } @@ -66,7 +67,7 @@ func (t Tree) EntryByPath(path string) (*TreeEntry, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_tree_entry_bypath(&entry, t.ptr, cpath) + ret := C.git_tree_entry_bypath(&entry, t.cast_ptr, cpath) if ret < 0 { return nil, MakeGitError(ret) } @@ -75,7 +76,7 @@ func (t Tree) EntryByPath(path string) (*TreeEntry, error) { } func (t Tree) EntryByIndex(index uint64) *TreeEntry { - entry := C.git_tree_entry_byindex(t.ptr, C.size_t(index)) + entry := C.git_tree_entry_byindex(t.cast_ptr, C.size_t(index)) if entry == nil { return nil } @@ -84,7 +85,7 @@ func (t Tree) EntryByIndex(index uint64) *TreeEntry { } func (t Tree) EntryCount() uint64 { - num := C.git_tree_entrycount(t.ptr) + num := C.git_tree_entrycount(t.cast_ptr) return uint64(num) } @@ -104,7 +105,7 @@ func (t Tree) Walk(callback TreeWalkCallback) error { defer runtime.UnlockOSThread() err := C._go_git_treewalk( - t.ptr, + t.cast_ptr, C.GIT_TREEWALK_PRE, unsafe.Pointer(&callback), ) -- cgit v1.2.3 From 9d0d814f19e9d31caeeb68abce84f9eba9659737 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Tue, 1 Apr 2014 11:06:47 -0700 Subject: rename inmemory to anonymous remote --- remote.go | 4 ++-- remote_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/remote.go b/remote.go index 66097b8..da04d2a 100644 --- a/remote.go +++ b/remote.go @@ -184,7 +184,7 @@ func (repo *Repository) CreateRemoteWithFetchspec(name string, url string, fetch return remote, nil } -func (repo *Repository) CreateRemoteInMemory(fetch string, url string) (*Remote, error) { +func (repo *Repository) CreateAnonymousRemote(fetch string, url string) (*Remote, error) { remote := &Remote{} curl := C.CString(url) @@ -195,7 +195,7 @@ func (repo *Repository) CreateRemoteInMemory(fetch string, url string) (*Remote, runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_remote_create_inmemory(&remote.ptr, repo.ptr, cfetch, curl) + ret := C.git_remote_create_anonymous(&remote.ptr, repo.ptr, cfetch, curl) if ret < 0 { return nil, MakeGitError(ret) } diff --git a/remote_test.go b/remote_test.go index 90e24ae..37ed8c3 100644 --- a/remote_test.go +++ b/remote_test.go @@ -10,7 +10,7 @@ func TestRefspecs(t *testing.T) { defer os.RemoveAll(repo.Workdir()) defer repo.Free() - remote, err := repo.CreateRemoteInMemory("refs/heads/*:refs/heads/*", "git://foo/bar") + remote, err := repo.CreateAnonymousRemote("refs/heads/*:refs/heads/*", "git://foo/bar") checkFatal(t, err) expected := []string{ -- cgit v1.2.3 From 9cd1d129bcd567ef65137783a603f8d898d8d933 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 1 Apr 2014 20:10:20 +0200 Subject: Remote: The whole point of the anonymous change Was that it would break and we'd remember that the order changed. Oh well. --- remote.go | 4 ++-- remote_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/remote.go b/remote.go index da04d2a..eb5d7a7 100644 --- a/remote.go +++ b/remote.go @@ -184,7 +184,7 @@ func (repo *Repository) CreateRemoteWithFetchspec(name string, url string, fetch return remote, nil } -func (repo *Repository) CreateAnonymousRemote(fetch string, url string) (*Remote, error) { +func (repo *Repository) CreateAnonymousRemote(url, fetch string) (*Remote, error) { remote := &Remote{} curl := C.CString(url) @@ -195,7 +195,7 @@ func (repo *Repository) CreateAnonymousRemote(fetch string, url string) (*Remote runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_remote_create_anonymous(&remote.ptr, repo.ptr, cfetch, curl) + ret := C.git_remote_create_anonymous(&remote.ptr, repo.ptr, curl, cfetch) if ret < 0 { return nil, MakeGitError(ret) } diff --git a/remote_test.go b/remote_test.go index 37ed8c3..7cef1ec 100644 --- a/remote_test.go +++ b/remote_test.go @@ -10,7 +10,7 @@ func TestRefspecs(t *testing.T) { defer os.RemoveAll(repo.Workdir()) defer repo.Free() - remote, err := repo.CreateAnonymousRemote("refs/heads/*:refs/heads/*", "git://foo/bar") + remote, err := repo.CreateAnonymousRemote("git://foo/bar", "refs/heads/*:refs/heads/*") checkFatal(t, err) expected := []string{ -- cgit v1.2.3