Skip to content

Commit

Permalink
add blob chunk creation, creation of tree builders for specific trees…
Browse files Browse the repository at this point in the history
…, minor API cleanup
  • Loading branch information
Jesse Ezell committed Mar 8, 2014
1 parent f5f8e13 commit 5e163fa
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 24 deletions.
65 changes: 63 additions & 2 deletions blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,84 @@ package git
/*
#include <git2.h>
#include <git2/errors.h>
#include <string.h>
extern int _go_git_blob_create_fromchunks(git_oid *id,
git_repository *repo,
const char *hintpath,
void *payload);
*/
import "C"
import (
"io"
"runtime"
"unsafe"
)

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
}
24 changes: 19 additions & 5 deletions repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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))
Expand Down
38 changes: 27 additions & 11 deletions tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,24 @@ 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 {
gitObject
}

type TreeEntry struct {
Name string
Id *Oid
Type ObjectType
Name string
Id *Oid
Type ObjectType
Filemode int
}

Expand Down Expand Up @@ -116,7 +117,7 @@ func (t Tree) Walk(callback TreeWalkCallback) error {
}

type TreeBuilder struct {
ptr *C.git_treebuilder
ptr *C.git_treebuilder
repo *Repository
}

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

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

Expand Down
21 changes: 15 additions & 6 deletions walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,25 @@ 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 {
ptr *C.git_revwalk
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)
}
Expand Down Expand Up @@ -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)
}
13 changes: 13 additions & 0 deletions wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

0 comments on commit 5e163fa

Please sign in to comment.