Initial commit

This commit is contained in:
Vicent Marti 2013-03-05 20:53:04 +01:00
commit b1d50b70ea
10 changed files with 624 additions and 0 deletions

21
LICENSE Normal file
View File

@ -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.

16
README.md Normal file
View File

@ -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)

26
blob.go Normal file
View File

@ -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)
}

52
commit.go Normal file
View File

@ -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}
}
*/

69
config.go Normal file
View File

@ -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
}

92
git.go Normal file
View File

@ -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)
}

71
odb.go Normal file
View File

@ -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))
}

141
repository.go Normal file
View File

@ -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
}

127
tree.go Normal file
View File

@ -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
}

9
wrapper.c Normal file
View File

@ -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 */