diff options
| -rw-r--r-- | blob.go | 15 | ||||
| -rw-r--r-- | checkout.go | 23 | ||||
| -rw-r--r-- | clone.go | 27 | ||||
| -rw-r--r-- | index.go | 15 | ||||
| -rw-r--r-- | repository.go | 26 | ||||
| -rw-r--r-- | revparse.go | 114 | ||||
| -rw-r--r-- | revparse_test.go | 58 | ||||
| -rwxr-xr-x | script/build-libgit2-static.sh | 1 | ||||
| -rwxr-xr-x | script/with-static.sh | 3 | ||||
| -rw-r--r-- | tree.go | 3 | ||||
| m--------- | vendor/libgit2 | 0 |
11 files changed, 237 insertions, 48 deletions
@@ -36,12 +36,21 @@ func (v *Blob) Contents() []byte { 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))) + + var id C.git_oid + var ptr unsafe.Pointer + + if len(data) > 0 { + ptr = unsafe.Pointer(&data[0]) + } else { + ptr = unsafe.Pointer(nil) + } + + ecode := C.git_blob_create_frombuffer(&id, repo.ptr, ptr, C.size_t(len(data))) if ecode < 0 { return nil, MakeGitError(ecode) } - return newOidFromC(&oid), nil + return newOidFromC(&id), nil } type BlobChunkCallback func(maxLen int) ([]byte, error) diff --git a/checkout.go b/checkout.go index 8974a8c..633303d 100644 --- a/checkout.go +++ b/checkout.go @@ -67,14 +67,10 @@ func populateCheckoutOpts(ptr *C.git_checkout_options, opts *CheckoutOpts) *C.gi // Updates files in the index and the working tree to match the content of // the commit pointed at by HEAD. opts may be nil. func (v *Repository) CheckoutHead(opts *CheckoutOpts) error { - var copts C.git_checkout_options - - ptr := populateCheckoutOpts(&copts, opts) - runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_checkout_head(v.ptr, ptr) + ret := C.git_checkout_head(v.ptr, opts.toC()) if ret < 0 { return MakeGitError(ret) } @@ -86,9 +82,6 @@ func (v *Repository) CheckoutHead(opts *CheckoutOpts) error { // 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 @@ -97,7 +90,19 @@ func (v *Repository) CheckoutIndex(index *Index, opts *CheckoutOpts) error { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_checkout_index(v.ptr, iptr, ptr) + ret := C.git_checkout_index(v.ptr, iptr, opts.toC()) + if ret < 0 { + return MakeGitError(ret) + } + + return nil +} + +func (v *Repository) CheckoutTree(tree *Tree, opts *CheckoutOpts) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_checkout_tree(v.ptr, tree.ptr, opts.toC()) if ret < 0 { return MakeGitError(ret) } @@ -14,10 +14,10 @@ import ( type CloneOptions struct { *CheckoutOpts *RemoteCallbacks - Bare bool - IgnoreCertErrors bool - RemoteName string - CheckoutBranch string + Bare bool + CheckoutBranch string + RemoteCreateCallback C.git_remote_create_cb + RemoteCreatePayload unsafe.Pointer } func Clone(url string, path string, options *CloneOptions) (*Repository, error) { @@ -32,12 +32,6 @@ 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)) @@ -67,9 +61,14 @@ func populateCloneOptions(ptr *C.git_clone_options, opts *CloneOptions) { } else { ptr.bare = 0 } - if opts.IgnoreCertErrors { - ptr.ignore_cert_errors = 1 - } else { - ptr.ignore_cert_errors = 0 + + if opts.RemoteCreateCallback != nil { + ptr.remote_cb = opts.RemoteCreateCallback + defer C.free(unsafe.Pointer(opts.RemoteCreateCallback)) + + if opts.RemoteCreatePayload != nil { + ptr.remote_cb_payload = opts.RemoteCreatePayload + defer C.free(opts.RemoteCreatePayload) + } } } @@ -114,6 +114,21 @@ func (v *Index) AddByPath(path string) error { return nil } +func (v *Index) RemoveByPath(path string) error { + cstr := C.CString(path) + defer C.free(unsafe.Pointer(cstr)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_index_remove_bypath(v.ptr, cstr) + if ret < 0 { + return MakeGitError(ret) + } + + return nil +} + func (v *Index) WriteTreeTo(repo *Repository) (*Oid, error) { oid := new(Oid) diff --git a/repository.go b/repository.go index 8cc966c..09f5fef 100644 --- a/repository.go +++ b/repository.go @@ -326,8 +326,13 @@ func (v *Repository) CreateCommit( oid := new(Oid) - cref := C.CString(refname) - defer C.free(unsafe.Pointer(cref)) + var cref *C.char + if refname == "" { + cref = nil + } else { + cref = C.CString(refname) + defer C.free(unsafe.Pointer(cref)) + } cmsg := C.CString(message) defer C.free(unsafe.Pointer(cmsg)) @@ -469,23 +474,6 @@ func (v *Repository) TreeBuilderFromTree(tree *Tree) (*TreeBuilder, error) { return bld, nil } -func (v *Repository) RevparseSingle(spec string) (Object, error) { - cspec := C.CString(spec) - defer C.free(unsafe.Pointer(cspec)) - - var ptr *C.git_object - - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - ecode := C.git_revparse_single(&ptr, v.ptr, cspec) - if ecode < 0 { - return nil, MakeGitError(ecode) - } - - return allocObject(ptr, v), 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 { diff --git a/revparse.go b/revparse.go new file mode 100644 index 0000000..9e0070e --- /dev/null +++ b/revparse.go @@ -0,0 +1,114 @@ +package git + +/* +#include <git2.h> +#include <git2/errors.h> + +extern void _go_git_revspec_free(git_revspec *revspec); +*/ +import "C" +import ( + "runtime" + "unsafe" +) + +type RevparseFlag int + +const ( + RevparseSingle RevparseFlag = C.GIT_REVPARSE_SINGLE + RevparseRange = C.GIT_REVPARSE_RANGE + RevparseMergeBase = C.GIT_REVPARSE_MERGE_BASE +) + +type Revspec struct { + to Object + from Object + flags RevparseFlag +} + +func (rs *Revspec) To() Object { + return rs.to +} + +func (rs *Revspec) From() Object { + return rs.from +} + +func (rs *Revspec) Flags() RevparseFlag { + return rs.flags +} + +func newRevspecFromC(ptr *C.git_revspec, repo *Repository) *Revspec { + var to Object + var from Object + + if ptr.to != nil { + to = allocObject(ptr.to, repo) + } + + if ptr.from != nil { + from = allocObject(ptr.from, repo) + } + + return &Revspec{ + to: to, + from: from, + flags: RevparseFlag(ptr.flags), + } +} + +func (r *Repository) Revparse(spec string) (*Revspec, error) { + cspec := C.CString(spec) + defer C.free(unsafe.Pointer(cspec)) + + var crevspec C.git_revspec + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_revparse(&crevspec, r.ptr, cspec) + if ecode != 0 { + return nil, MakeGitError(ecode) + } + + return newRevspecFromC(&crevspec, r), nil +} + +func (v *Repository) RevparseSingle(spec string) (Object, error) { + cspec := C.CString(spec) + defer C.free(unsafe.Pointer(cspec)) + + var ptr *C.git_object + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_revparse_single(&ptr, v.ptr, cspec) + if ecode < 0 { + return nil, MakeGitError(ecode) + } + + return allocObject(ptr, v), nil +} + +func (r *Repository) RevparseExt(spec string) (Object, *Reference, error) { + cspec := C.CString(spec) + defer C.free(unsafe.Pointer(cspec)) + + var obj *C.git_object + var ref *C.git_reference + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_revparse_ext(&obj, &ref, r.ptr, cspec) + if ecode != 0 { + return nil, nil, MakeGitError(ecode) + } + + if ref == nil { + return allocObject(obj, r), nil, nil + } + + return allocObject(obj, r), newReferenceFromC(ref, r), nil +} diff --git a/revparse_test.go b/revparse_test.go new file mode 100644 index 0000000..c046a20 --- /dev/null +++ b/revparse_test.go @@ -0,0 +1,58 @@ +package git + +import ( + "os" + "testing" +) + +func TestRevparse(t *testing.T) { + repo := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + + commitId, _ := seedTestRepo(t, repo) + + revSpec, err := repo.Revparse("HEAD") + checkFatal(t, err) + + checkObject(t, revSpec.From(), commitId) +} + +func TestRevparseSingle(t *testing.T) { + repo := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + + commitId, _ := seedTestRepo(t, repo) + + obj, err := repo.RevparseSingle("HEAD") + checkFatal(t, err) + + checkObject(t, obj, commitId) +} + +func TestRevparseExt(t *testing.T) { + repo := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + + _, treeId := seedTestRepo(t, repo) + + ref, err := repo.CreateReference("refs/heads/master", treeId, true, nil, "") + checkFatal(t, err) + + obj, ref, err := repo.RevparseExt("master") + checkFatal(t, err) + + checkObject(t, obj, treeId) + if ref == nil { + t.Fatalf("bad reference") + } +} + +func checkObject(t *testing.T, obj Object, id *Oid) { + if obj == nil { + t.Fatalf("bad object") + } + + if !obj.Id().Equal(id) { + t.Fatalf("bad object, expected %s, got %s", id.String(), obj.Id().String()) + } +} diff --git a/script/build-libgit2-static.sh b/script/build-libgit2-static.sh index b4d4241..5723721 100755 --- a/script/build-libgit2-static.sh +++ b/script/build-libgit2-static.sh @@ -5,6 +5,7 @@ set -ex VENDORED_PATH=vendor/libgit2 cd $VENDORED_PATH && +mkdir -p install/lib && mkdir -p build && cd build && cmake -DTHREADSAFE=ON \ diff --git a/script/with-static.sh b/script/with-static.sh index 0caed5e..3f60e31 100755 --- a/script/with-static.sh +++ b/script/with-static.sh @@ -5,7 +5,8 @@ set -ex export BUILD="$PWD/vendor/libgit2/build" export PCFILE="$BUILD/libgit2.pc" -export CGO_LDFLAGS="$BUILD/libgit2.a -L$BUILD $(pkg-config --static --libs $PCFILE)" +FLAGS=$(pkg-config --static --libs $PCFILE) || exit 1 +export CGO_LDFLAGS="$BUILD/libgit2.a -L$BUILD ${FLAGS}" export CGO_CFLAGS="-I$PWD/vendor/libgit2/include" $@ @@ -16,8 +16,7 @@ import ( type Filemode int const ( - FilemodeNew Filemode = C.GIT_FILEMODE_NEW - FilemodeTree = C.GIT_FILEMODE_TREE + FilemodeTree Filemode = C.GIT_FILEMODE_TREE FilemodeBlob = C.GIT_FILEMODE_BLOB FilemodeBlobExecutable = C.GIT_FILEMODE_BLOB_EXECUTABLE FilemodeLink = C.GIT_FILEMODE_LINK diff --git a/vendor/libgit2 b/vendor/libgit2 -Subproject 28f087c8642ff9c8dd6964e101e6d8539db6281 +Subproject 89e05e2ab19ac452e84e0eaa2dfb8e07ac6839b |
