git2go/index.go

326 lines
6.8 KiB
Go
Raw Normal View History

2013-03-06 06:10:53 -06:00
package git
/*
#include <git2.h>
#include <git2/errors.h>
*/
import "C"
import (
2013-05-22 07:41:42 -05:00
"fmt"
2013-03-06 06:10:53 -06:00
"runtime"
2013-05-22 07:41:42 -05:00
"time"
2013-03-06 06:10:53 -06:00
"unsafe"
)
type Index struct {
ptr *C.git_index
}
2013-05-22 07:41:42 -05:00
type IndexEntry struct {
Ctime time.Time
Mtime time.Time
Mode uint
Uid uint
Gid uint
Size uint
2014-03-20 22:49:05 -05:00
Id *Oid
2013-05-22 07:41:42 -05:00
Path string
}
2014-03-30 21:53:07 -05:00
func newIndexEntryFromC(entry *C.git_index_entry) *IndexEntry {
if entry == nil {
return nil
}
return &IndexEntry{
time.Unix(int64(entry.ctime.seconds), int64(entry.ctime.nanoseconds)),
time.Unix(int64(entry.mtime.seconds), int64(entry.mtime.nanoseconds)),
uint(entry.mode),
uint(entry.uid),
uint(entry.gid),
uint(entry.file_size),
newOidFromC(&entry.id),
C.GoString(entry.path),
}
}
func populateCIndexEntry(source *IndexEntry, dest *C.git_index_entry) {
dest.ctime.seconds = C.git_time_t(source.Ctime.Unix())
dest.ctime.nanoseconds = C.uint(source.Ctime.UnixNano())
dest.mtime.seconds = C.git_time_t(source.Mtime.Unix())
dest.mtime.nanoseconds = C.uint(source.Mtime.UnixNano())
dest.mode = C.uint(source.Mode)
dest.uid = C.uint(source.Uid)
dest.gid = C.uint(source.Gid)
dest.file_size = C.git_off_t(source.Size)
dest.id = *source.Id.toC()
dest.path = C.CString(source.Path)
}
func freeCIndexEntry(entry *C.git_index_entry) {
C.free(unsafe.Pointer(entry.path))
}
2013-03-06 06:10:53 -06:00
func newIndexFromC(ptr *C.git_index) *Index {
idx := &Index{ptr}
runtime.SetFinalizer(idx, (*Index).Free)
return idx
}
// NewIndex allocates a new index. It won't be associated with any
// file on the filesystem or repository
func NewIndex() (*Index, error) {
var ptr *C.git_index
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if err := C.git_index_new(&ptr); err < 0 {
return nil, MakeGitError(err)
}
return &Index{ptr: ptr}, nil
}
// Add adds or replaces the given entry to the index, making a copy of
// the data
func (v *Index) Add(entry *IndexEntry) error {
var centry C.git_index_entry
populateCIndexEntry(entry, &centry)
defer freeCIndexEntry(&centry)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if err := C.git_index_add(v.ptr, &centry); err < 0 {
return MakeGitError(err)
}
return nil
}
2013-03-06 06:10:53 -06:00
func (v *Index) AddByPath(path string) error {
cstr := C.CString(path)
defer C.free(unsafe.Pointer(cstr))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
2013-03-06 06:10:53 -06:00
ret := C.git_index_add_bypath(v.ptr, cstr)
if ret < 0 {
return MakeGitError(ret)
2013-03-06 06:10:53 -06:00
}
return nil
}
2014-08-23 09:55:36 -05:00
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
}
2014-03-20 22:49:05 -05:00
func (v *Index) WriteTreeTo(repo *Repository) (*Oid, error) {
oid := new(Oid)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_index_write_tree_to(oid.toC(), v.ptr, repo.ptr)
if ret < 0 {
return nil, MakeGitError(ret)
}
return oid, nil
}
2013-03-06 06:10:53 -06:00
func (v *Index) WriteTree() (*Oid, error) {
oid := new(Oid)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
2013-03-06 06:10:53 -06:00
ret := C.git_index_write_tree(oid.toC(), v.ptr)
if ret < 0 {
return nil, MakeGitError(ret)
2013-03-06 06:10:53 -06:00
}
return oid, nil
}
2014-03-20 22:49:05 -05:00
func (v *Index) Write() error {
2014-01-23 19:10:23 -06:00
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_index_write(v.ptr)
if ret < 0 {
2014-02-26 09:14:31 -06:00
return MakeGitError(ret)
2014-01-23 19:10:23 -06:00
}
return nil
}
2013-03-06 06:10:53 -06:00
func (v *Index) Free() {
runtime.SetFinalizer(v, nil)
C.git_index_free(v.ptr)
}
2013-05-22 07:41:42 -05:00
func (v *Index) EntryCount() uint {
return uint(C.git_index_entrycount(v.ptr))
}
func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) {
centry := C.git_index_get_byindex(v.ptr, C.size_t(index))
if centry == nil {
return nil, fmt.Errorf("Index out of Bounds")
}
return newIndexEntryFromC(centry), nil
}
2014-03-30 21:53:07 -05:00
func (v *Index) HasConflicts() bool {
return C.git_index_has_conflicts(v.ptr) != 0
}
func (v *Index) CleanupConflicts() {
C.git_index_conflict_cleanup(v.ptr)
}
func (v *Index) AddConflict(ancestor *IndexEntry, our *IndexEntry, their *IndexEntry) error {
var cancestor *C.git_index_entry
var cour *C.git_index_entry
var ctheir *C.git_index_entry
if ancestor != nil {
cancestor = &C.git_index_entry{}
populateCIndexEntry(ancestor, cancestor)
defer freeCIndexEntry(cancestor)
}
if our != nil {
cour = &C.git_index_entry{}
populateCIndexEntry(our, cour)
defer freeCIndexEntry(cour)
}
if their != nil {
ctheir = &C.git_index_entry{}
populateCIndexEntry(their, ctheir)
defer freeCIndexEntry(ctheir)
}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_index_conflict_add(v.ptr, cancestor, cour, ctheir)
if ecode < 0 {
return MakeGitError(ecode)
}
return nil
}
type IndexConflict struct {
Ancestor *IndexEntry
Our *IndexEntry
Their *IndexEntry
}
func (v *Index) GetConflict(path string) (IndexConflict, error) {
var cancestor *C.git_index_entry
var cour *C.git_index_entry
var ctheir *C.git_index_entry
cpath := C.CString(path)
defer C.free(unsafe.Pointer(cpath))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_index_conflict_get(&cancestor, &cour, &ctheir, v.ptr, cpath)
if ecode < 0 {
return IndexConflict{}, MakeGitError(ecode)
}
return IndexConflict{
Ancestor: newIndexEntryFromC(cancestor),
Our: newIndexEntryFromC(cour),
Their: newIndexEntryFromC(ctheir),
}, nil
}
func (v *Index) RemoveConflict(path string) error {
cpath := C.CString(path)
defer C.free(unsafe.Pointer(cpath))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_index_conflict_remove(v.ptr, cpath)
if ecode < 0 {
return MakeGitError(ecode)
}
return nil
}
type IndexConflictIterator struct {
ptr *C.git_index_conflict_iterator
index *Index
}
func newIndexConflictIteratorFromC(index *Index, ptr *C.git_index_conflict_iterator) *IndexConflictIterator {
i := &IndexConflictIterator{ptr: ptr, index: index}
runtime.SetFinalizer(i, (*IndexConflictIterator).Free)
return i
}
func (v *IndexConflictIterator) Index() *Index {
return v.index
}
func (v *IndexConflictIterator) Free() {
runtime.SetFinalizer(v, nil)
C.git_index_conflict_iterator_free(v.ptr)
}
func (v *Index) ConflictIterator() (*IndexConflictIterator, error) {
var i *C.git_index_conflict_iterator
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_index_conflict_iterator_new(&i, v.ptr)
if ecode < 0 {
return nil, MakeGitError(ecode)
}
return newIndexConflictIteratorFromC(v, i), nil
}
func (v *IndexConflictIterator) Next() (IndexConflict, error) {
var cancestor *C.git_index_entry
var cour *C.git_index_entry
var ctheir *C.git_index_entry
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_index_conflict_next(&cancestor, &cour, &ctheir, v.ptr)
if ecode < 0 {
return IndexConflict{}, MakeGitError(ecode)
}
return IndexConflict{
Ancestor: newIndexEntryFromC(cancestor),
Our: newIndexEntryFromC(cour),
Their: newIndexEntryFromC(ctheir),
}, nil
}