Add support for indexers and alternate odb packfiles
This allows for implementations of git servers written in Go.
This commit is contained in:
parent
a41e2b6644
commit
a2680c63c2
|
@ -0,0 +1,94 @@
|
|||
package git
|
||||
|
||||
/*
|
||||
#include <git2.h>
|
||||
|
||||
extern const git_oid * git_indexer_hash(const git_indexer *idx);
|
||||
extern int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_transfer_progress *stats);
|
||||
extern int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats);
|
||||
extern int _go_git_indexer_new(git_indexer **out, const char *path, unsigned int mode, git_odb *odb, void *progress_cb_payload);
|
||||
extern void git_indexer_free(git_indexer *idx);
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//export indexerTransferProgress
|
||||
func indexerTransferProgress(_stats *C.git_transfer_progress, ptr unsafe.Pointer) C.int {
|
||||
callback, ok := pointerHandles.Get(ptr).(TransferProgressCallback)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return C.int(callback(newTransferProgressFromC(_stats)))
|
||||
}
|
||||
|
||||
type Indexer struct {
|
||||
ptr *C.git_indexer
|
||||
stats C.git_transfer_progress
|
||||
callback unsafe.Pointer
|
||||
}
|
||||
|
||||
func NewIndexer(packfilePath string, odb *Odb, callback TransferProgressCallback) (indexer *Indexer, err error) {
|
||||
indexer = new(Indexer)
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
var odbPtr *C.git_odb = nil
|
||||
if odb != nil {
|
||||
odbPtr = odb.ptr
|
||||
}
|
||||
|
||||
if callback != nil {
|
||||
indexer.callback = pointerHandles.Track(callback)
|
||||
}
|
||||
|
||||
ret := C._go_git_indexer_new(&indexer.ptr, C.CString(packfilePath), 0, odbPtr, indexer.callback)
|
||||
if ret < 0 {
|
||||
if indexer.callback != nil {
|
||||
pointerHandles.Untrack(indexer.callback)
|
||||
}
|
||||
return nil, MakeGitError(ret)
|
||||
}
|
||||
|
||||
runtime.SetFinalizer(indexer, (*Indexer).Free)
|
||||
return indexer, nil
|
||||
}
|
||||
|
||||
func (indexer *Indexer) Write(data []byte) (int, error) {
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
|
||||
ptr := unsafe.Pointer(header.Data)
|
||||
size := C.size_t(header.Len)
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C.git_indexer_append(indexer.ptr, ptr, size, &indexer.stats)
|
||||
if ret < 0 {
|
||||
return 0, MakeGitError(ret)
|
||||
}
|
||||
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func (indexer *Indexer) Commit() (*Oid, error) {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C.git_indexer_commit(indexer.ptr, &indexer.stats)
|
||||
if ret < 0 {
|
||||
return nil, MakeGitError(ret)
|
||||
}
|
||||
|
||||
return newOidFromC(C.git_indexer_hash(indexer.ptr)), nil
|
||||
}
|
||||
|
||||
func (indexer *Indexer) Free() {
|
||||
if indexer.callback != nil {
|
||||
pointerHandles.Untrack(indexer.callback)
|
||||
}
|
||||
C.git_indexer_free(indexer.ptr)
|
||||
}
|
32
odb.go
32
odb.go
|
@ -3,6 +3,7 @@ package git
|
|||
/*
|
||||
#include <git2.h>
|
||||
|
||||
extern int git_odb_backend_one_pack(git_odb_backend **out, const char *index_file);
|
||||
extern int _go_git_odb_foreach(git_odb *db, void *payload);
|
||||
extern void _go_git_odb_backend_free(git_odb_backend *backend);
|
||||
*/
|
||||
|
@ -41,8 +42,19 @@ func NewOdbBackendFromC(ptr *C.git_odb_backend) (backend *OdbBackend) {
|
|||
return backend
|
||||
}
|
||||
|
||||
func (v *Odb) AddBackend(backend *OdbBackend, priority int) (err error) {
|
||||
func (v *Odb) AddAlternate(backend *OdbBackend, priority int) (err error) {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C.git_odb_add_alternate(v.ptr, backend.ptr, C.int(priority))
|
||||
if ret < 0 {
|
||||
backend.Free()
|
||||
return MakeGitError(ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Odb) AddBackend(backend *OdbBackend, priority int) (err error) {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
|
@ -54,12 +66,24 @@ func (v *Odb) AddBackend(backend *OdbBackend, priority int) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func NewOdbBackendOnePack(packfileIndexPath string) (backend *OdbBackend, err error) {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
var odbOnePack *C.git_odb_backend = nil
|
||||
ret := C.git_odb_backend_one_pack(&odbOnePack, C.CString(packfileIndexPath))
|
||||
if ret < 0 {
|
||||
return nil, MakeGitError(ret)
|
||||
}
|
||||
return NewOdbBackendFromC(odbOnePack), nil
|
||||
}
|
||||
|
||||
func (v *Odb) ReadHeader(oid *Oid) (uint64, ObjectType, error) {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
|
||||
var sz C.size_t
|
||||
var cotype C.git_otype
|
||||
var cotype C.git_otype
|
||||
|
||||
ret := C.git_odb_read_header(&sz, &cotype, v.ptr, oid.toC())
|
||||
if ret < 0 {
|
||||
|
@ -68,7 +92,7 @@ func (v *Odb) ReadHeader(oid *Oid) (uint64, ObjectType, error) {
|
|||
|
||||
return uint64(sz), ObjectType(cotype), nil
|
||||
}
|
||||
|
||||
|
||||
func (v *Odb) Exists(oid *Oid) bool {
|
||||
ret := C.git_odb_exists(v.ptr, oid.toC())
|
||||
return ret != 0
|
||||
|
|
|
@ -174,4 +174,9 @@ void _go_git_writestream_free(git_writestream *stream)
|
|||
stream->free(stream);
|
||||
}
|
||||
|
||||
int _go_git_indexer_new(git_indexer **out, const char *path, unsigned int mode, git_odb *odb, void *progress_cb_payload)
|
||||
{
|
||||
return git_indexer_new(out, path, mode, odb, (git_transfer_progress_cb)&indexerTransferProgress, progress_cb_payload);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in New Issue