summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <[email protected]>2013-03-05 20:53:04 +0100
committerVicent Marti <[email protected]>2013-03-05 20:53:04 +0100
commitb1d50b70ea8c4be9c19fe91768d6653736660c4c (patch)
tree56670245aa3f3379bc2cfd9baec097c9f8231b94
Initial commit
-rw-r--r--LICENSE21
-rw-r--r--README.md16
-rw-r--r--blob.go26
-rw-r--r--commit.go52
-rw-r--r--config.go69
-rw-r--r--git.go92
-rw-r--r--odb.go71
-rw-r--r--repository.go141
-rw-r--r--tree.go127
-rw-r--r--wrapper.c9
10 files changed, 624 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..46a7407
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2013 The git2go contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..94aedea
--- /dev/null
+++ b/README.md
@@ -0,0 +1,16 @@
+git2go
+======
+
+Go bindings for [libgit2](http://libgit2.github.com/). Pre-release, things may or may not work. Operator get me Beijing-jing-jing-jing!
+
+License
+-------
+
+M to the I to the T.
+
+Authors
+-------
+
+- Carlos Martín (@cmn)
+- Vicent Martí (@vmg)
+
diff --git a/blob.go b/blob.go
new file mode 100644
index 0000000..91064b1
--- /dev/null
+++ b/blob.go
@@ -0,0 +1,26 @@
+package git
+
+/*
+#cgo pkg-config: libgit2
+#include <git2.h>
+#include <git2/errors.h>
+*/
+import "C"
+import (
+ "unsafe"
+)
+
+type Blob struct {
+ ptr *C.git_object
+}
+
+func freeBlob(blob *Blob) {
+ C.git_object_free(blob.ptr)
+}
+
+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)
+}
+
diff --git a/commit.go b/commit.go
new file mode 100644
index 0000000..bba02e8
--- /dev/null
+++ b/commit.go
@@ -0,0 +1,52 @@
+package git
+
+/*
+#include <git2.h>
+#include <git2/errors.h>
+
+extern int _go_git_treewalk(git_tree *tree, git_treewalk_mode mode, void *ptr);
+*/
+import "C"
+
+import (
+)
+
+// Commit
+type Commit struct {
+ ptr *C.git_commit
+}
+
+func (c *Commit) Id() *Oid {
+ return newOidFromC(C.git_commit_id(c.ptr))
+}
+
+func (c *Commit) Message() string {
+ return C.GoString(C.git_commit_message(c.ptr))
+}
+
+func (c *Commit) Tree() (*Tree, error) {
+ tree := new(Tree)
+
+ err := C.git_commit_tree(&tree.ptr, c.ptr)
+ if err < 0 {
+ return nil, LastError()
+ }
+ return tree, nil
+}
+
+func (c *Commit) TreeId() *Oid {
+ return newOidFromC(C.git_commit_tree_id(c.ptr))
+}
+
+/* TODO */
+/*
+func (c *Commit) Author() *Signature {
+ ptr := C.git_commit_author(c.ptr)
+ return &Signature{ptr}
+}
+
+func (c *Commit) Committer() *Signature {
+ ptr := C.git_commit_committer(c.ptr)
+ return &Signature{ptr}
+}
+*/
diff --git a/config.go b/config.go
new file mode 100644
index 0000000..ec8b8d0
--- /dev/null
+++ b/config.go
@@ -0,0 +1,69 @@
+package git
+
+/*
+#cgo pkg-config: libgit2
+#include <git2.h>
+#include <git2/errors.h>
+*/
+import "C"
+import (
+ "unsafe"
+)
+
+type Config struct {
+ ptr *C.git_config
+}
+
+func (c *Config) LookupInt32(name string) (v int32, err error) {
+ var out C.int32_t
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ ret := C.git_config_get_int32(&out, c.ptr, cname)
+ if ret < 0 {
+ return 0, LastError()
+ }
+
+ return int32(out), nil
+}
+
+func (c *Config) LookupInt64(name string) (v int64, err error) {
+ var out C.int64_t
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ ret := C.git_config_get_int64(&out, c.ptr, cname)
+ if ret < 0 {
+ return 0, LastError()
+ }
+
+ return int64(out), nil
+}
+
+func (c *Config) LookupString(name string) (v string, err error) {
+ var ptr *C.char
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ ret := C.git_config_get_string(&ptr, c.ptr, cname)
+ if ret < 0 {
+ return "", LastError()
+ }
+
+ return C.GoString(ptr), nil
+}
+
+func (c *Config) Set(name, value string) (err error) {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ cvalue := C.CString(value)
+ defer C.free(unsafe.Pointer(cvalue))
+
+ ret := C.git_config_set_string(c.ptr, cname, cvalue)
+ if ret < 0 {
+ return LastError()
+ }
+
+ return nil
+}
diff --git a/git.go b/git.go
new file mode 100644
index 0000000..84716e3
--- /dev/null
+++ b/git.go
@@ -0,0 +1,92 @@
+package git
+
+/*
+#cgo pkg-config: libgit2
+#include <git2.h>
+#include <git2/errors.h>
+*/
+import "C"
+import (
+ "unsafe"
+)
+
+const (
+ ITEROVER = C.GIT_ITEROVER
+ EEXISTS = C.GIT_EEXISTS
+ ENOTFOUND = C.GIT_ENOTFOUND
+)
+
+func init() {
+ C.git_threads_init()
+}
+
+// Oid
+type Oid struct {
+ bytes [20]byte
+}
+
+func newOidFromC(coid *C.git_oid) *Oid {
+ oid := new(Oid)
+ copy(oid.bytes[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])
+ return oid
+}
+
+func (oid *Oid) toC() *C.git_oid {
+ return (*C.git_oid)(unsafe.Pointer(&oid.bytes))
+}
+
+func NewOidFromString(s string) (*Oid, error) {
+ o := new(Oid)
+ cs := C.CString(s)
+ defer C.free(unsafe.Pointer(cs))
+
+ if C.git_oid_fromstr(o.toC(), cs) < 0 {
+ return nil, LastError()
+ }
+
+ 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)
+}
+
+func (oid *Oid) Bytes() []byte {
+ return oid.bytes[0:]
+}
+
+type GitError struct {
+ Message string
+ Code int
+}
+
+func (e GitError) Error() string{
+ return e.Message
+}
+
+func LastError() error {
+ err := C.giterr_last()
+ return &GitError{C.GoString(err.message), int(err.klass)}
+}
+
+func cbool(b bool) C.int {
+ if (b) {
+ return C.int(1)
+ }
+ return C.int(0)
+}
+
+func ucbool(b bool) C.uint {
+ if (b) {
+ return C.uint(1)
+ }
+ return C.uint(0)
+}
diff --git a/odb.go b/odb.go
new file mode 100644
index 0000000..5688080
--- /dev/null
+++ b/odb.go
@@ -0,0 +1,71 @@
+package git
+
+/*
+#cgo pkg-config: libgit2
+#include <git2.h>
+#include <git2/errors.h>
+*/
+import "C"
+import (
+ "unsafe"
+ "reflect"
+ "runtime"
+)
+
+var (
+ OBJ_ANY = C.GIT_OBJ_ANY
+ OBJ_BAD = C.GIT_OBJ_BAD
+ OBJ_COMMIT = C.GIT_OBJ_COMMIT
+ OBJ_TREE = C.GIT_OBJ_TREE
+ OBJ_BLOB = C.GIT_OBJ_BLOB
+ OBJ_TAG = C.GIT_OBJ_TAG
+)
+
+type Odb struct {
+ ptr *C.git_odb
+}
+
+func (v *Odb) Exists(oid *Oid) bool {
+ ret := C.git_odb_exists(v.ptr, oid.toC())
+ return ret != 0
+}
+
+func (v *Odb) Write(data []byte, otype int) (oid *Oid, err error) {
+ oid = new(Oid)
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&data))
+ 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()
+ }
+
+ return
+}
+
+func (v *Odb) Read(oid *Oid) (obj *OdbObject, err error) {
+ obj = new(OdbObject)
+ ret := C.git_odb_read(&obj.ptr, v.ptr, oid.toC())
+ if ret < 0 {
+ return nil, LastError()
+ }
+
+ runtime.SetFinalizer(obj, freeOdbObject)
+ return
+}
+
+type OdbObject struct {
+ ptr *C.git_odb_object
+}
+
+func freeOdbObject(obj *OdbObject) {
+ C.git_odb_object_free(obj.ptr)
+}
+
+func (v *OdbObject) Type() int {
+ return int(C.git_odb_object_type(v.ptr))
+}
+
+func (v *OdbObject) Size() int64 {
+ return int64(C.git_odb_object_size(v.ptr))
+}
+
diff --git a/repository.go b/repository.go
new file mode 100644
index 0000000..3b845e7
--- /dev/null
+++ b/repository.go
@@ -0,0 +1,141 @@
+package git
+
+/*
+#cgo pkg-config: libgit2
+#include <git2.h>
+#include <git2/errors.h>
+*/
+import "C"
+import (
+ "unsafe"
+ "runtime"
+)
+
+// Repository
+type Repository struct {
+ ptr *C.git_repository
+}
+
+func Open(path string) (*Repository, error) {
+ repo := new(Repository)
+
+ cpath := C.CString(path)
+ defer C.free(unsafe.Pointer(cpath))
+
+ ret := C.git_repository_open(&repo.ptr, cpath)
+ if ret < 0 {
+ return nil, LastError()
+ }
+
+ runtime.SetFinalizer(repo, freeRepository)
+ return repo, nil
+}
+
+func Init(path string, isbare bool) (*Repository, error) {
+ repo := new(Repository)
+
+ cpath := C.CString(path)
+ defer C.free(unsafe.Pointer(cpath))
+
+ ret := C.git_repository_init(&repo.ptr, cpath, ucbool(isbare))
+ if ret < 0 {
+ return nil, LastError()
+ }
+
+ runtime.SetFinalizer(repo, freeRepository)
+ return repo, nil
+}
+
+func freeRepository(repo *Repository) {
+ C.git_repository_free(repo.ptr)
+}
+
+func (v *Repository) Config() (*Config, error) {
+ config := new(Config)
+
+ ret := C.git_repository_config(&config.ptr, v.ptr)
+ if ret < 0 {
+ return nil, LastError()
+ }
+
+ return config, nil
+}
+
+func (v *Repository) LookupTree(oid *Oid) (*Tree, error) {
+ tree := new(Tree)
+ ret := C.git_tree_lookup(&tree.ptr, v.ptr, oid.toC())
+ if ret < 0 {
+ return nil, LastError()
+ }
+
+ return tree, nil
+}
+
+func (v *Repository) LookupCommit(o *Oid) (*Commit, error) {
+ commit := new(Commit)
+ ecode := C.git_commit_lookup(&commit.ptr, v.ptr, o.toC())
+ if ecode < 0 {
+ return nil, LastError()
+ }
+
+ return commit, nil
+}
+
+/* TODO
+func (v *Repository) Commit(
+ refname string, author, committer *Signature,
+ message string, tree *Tree, parents ...*Commit) (*Oid, error) {
+
+ oid := new(Oid)
+ cref := C.CString(refname)
+ defer C.free(unsafe.Pointer(cref))
+ cmsg := C.CString(message)
+ defer C.free(unsafe.Pointer(cmsg))
+ nparents := len(parents)
+ var cparents []*C.git_commit = nil
+ var parentsarg **C.git_commit = nil
+ if nparents > 0 {
+ cparents = make([]*C.git_commit, nparents)
+ for i, v := range parents {
+ cparents[i] = v.ptr
+ }
+ parentsarg = &cparents[0]
+ }
+
+ ret := C.git_commit_create(
+ oid.toC(), v.ptr, cref,
+ author.git_signature, committer.git_signature,
+ nil, cmsg, tree.ptr, C.int(nparents), parentsarg)
+
+ if ret < GIT_SUCCESS {
+ return nil, LastError()
+ }
+
+ return oid, nil
+}
+*/
+
+func freeOdb(odb *Odb) {
+ C.git_odb_free(odb.ptr)
+}
+
+func (v *Repository) Odb() (odb *Odb, err error) {
+ odb = new(Odb)
+ if ret := C.git_repository_odb(&odb.ptr, v.ptr); ret < 0 {
+ return nil, LastError()
+ }
+
+ runtime.SetFinalizer(odb, freeOdb)
+ return
+}
+
+func (v *Repository) TreeBuilder() (*TreeBuilder, error) {
+ bld := new(TreeBuilder)
+ if ret := C.git_treebuilder_create(&bld.ptr, nil); ret < 0 {
+ return nil, LastError()
+ }
+
+ bld.repo = v
+ return bld, nil
+}
+
diff --git a/tree.go b/tree.go
new file mode 100644
index 0000000..324fc1f
--- /dev/null
+++ b/tree.go
@@ -0,0 +1,127 @@
+package git
+
+/*
+#include <git2.h>
+#include <git2/errors.h>
+
+extern int _go_git_treewalk(git_tree *tree, git_treewalk_mode mode, void *ptr);
+*/
+import "C"
+
+import (
+ "unsafe"
+)
+
+type Tree struct {
+ ptr *C.git_tree
+}
+
+type TreeEntry struct {
+ Name string
+ Oid *Oid
+ Type int
+}
+
+func newTreeEntry(entry *C.git_tree_entry) *TreeEntry {
+ return &TreeEntry{
+ C.GoString(C.git_tree_entry_name(entry)),
+ newOidFromC(C.git_tree_entry_id(entry)),
+ int(C.git_tree_entry_type(entry)),
+ }
+}
+
+func (t *Tree) Free() {
+ C.git_tree_free(t.ptr)
+}
+
+func TreeLookup(repo *Repository, oid *Oid) (*Tree, error) {
+ tree := new(Tree)
+ err := C.git_tree_lookup(&tree.ptr, repo.ptr, oid.toC())
+ if err < 0 {
+ return nil, LastError()
+ }
+ return tree, nil
+}
+
+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)
+ if entry == nil {
+ return nil
+ }
+
+ return newTreeEntry(entry)
+}
+
+func (t *Tree) EntryByIndex(index uint64) *TreeEntry {
+ entry := C.git_tree_entry_byindex(t.ptr, C.size_t(index))
+ if entry == nil {
+ return nil
+ }
+
+ return newTreeEntry(entry)
+}
+
+func (t *Tree) EntryCount() uint64 {
+ num := C.git_tree_entrycount(t.ptr)
+ return uint64(num)
+}
+
+type TreeWalkCallback func(string, *TreeEntry) int
+
+//export CallbackGitTreeWalk
+func CallbackGitTreeWalk(_root unsafe.Pointer, _entry unsafe.Pointer, ptr unsafe.Pointer) C.int {
+ root := C.GoString((*C.char)(_root))
+ entry := (*C.git_tree_entry)(_entry)
+ callback := *(*TreeWalkCallback)(ptr)
+
+ return C.int(callback(root, newTreeEntry(entry)))
+}
+
+func (t *Tree) Walk(callback TreeWalkCallback) error {
+ err := C._go_git_treewalk(
+ t.ptr,
+ C.GIT_TREEWALK_PRE,
+ unsafe.Pointer(&callback),
+ )
+
+ if err < 0 {
+ return LastError()
+ }
+
+ return nil
+}
+
+type TreeBuilder struct {
+ ptr *C.git_treebuilder
+ repo *Repository
+}
+
+func freeTreeBuilder(v *TreeBuilder) {
+ C.git_treebuilder_free(v.ptr)
+}
+
+func (v *TreeBuilder) Insert(filename string, id *Oid, filemode int) (error) {
+ cfilename := C.CString(filename)
+ defer C.free(unsafe.Pointer(cfilename))
+
+ err := C.git_treebuilder_insert(nil, v.ptr, cfilename, id.toC(), C.git_filemode_t(filemode))
+ if err < 0 {
+ return LastError()
+ }
+
+ return nil
+}
+
+func (v *TreeBuilder) Write() (*Oid, error) {
+ oid := new(Oid)
+ err := C.git_treebuilder_write(oid.toC(), v.repo.ptr, v.ptr)
+
+ if err < 0 {
+ return nil, LastError()
+ }
+
+ return oid, nil
+}
diff --git a/wrapper.c b/wrapper.c
new file mode 100644
index 0000000..4e1304e
--- /dev/null
+++ b/wrapper.c
@@ -0,0 +1,9 @@
+#include "_cgo_export.h"
+#include "git2.h"
+
+int _go_git_treewalk(git_tree *tree, git_treewalk_mode mode, void *ptr)
+{
+ return git_tree_walk(tree, mode, (git_treewalk_cb)&CallbackGitTreeWalk, ptr);
+}
+
+/* EOF */