diff options
Diffstat (limited to 'vendor/github.com/libgit2/git2go/tree.go')
-rw-r--r-- | vendor/github.com/libgit2/git2go/tree.go | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/vendor/github.com/libgit2/git2go/tree.go b/vendor/github.com/libgit2/git2go/tree.go new file mode 100644 index 000000000..02507d2c9 --- /dev/null +++ b/vendor/github.com/libgit2/git2go/tree.go @@ -0,0 +1,212 @@ +package git + +/* +#include <git2.h> + +extern int _go_git_treewalk(git_tree *tree, git_treewalk_mode mode, void *ptr); +*/ +import "C" + +import ( + "runtime" + "unsafe" +) + +type Filemode int + +const ( + FilemodeTree Filemode = C.GIT_FILEMODE_TREE + FilemodeBlob Filemode = C.GIT_FILEMODE_BLOB + FilemodeBlobExecutable Filemode = C.GIT_FILEMODE_BLOB_EXECUTABLE + FilemodeLink Filemode = C.GIT_FILEMODE_LINK + FilemodeCommit Filemode = C.GIT_FILEMODE_COMMIT +) + +type Tree struct { + Object + cast_ptr *C.git_tree +} + +func (t *Tree) AsObject() *Object { + return &t.Object +} + +type TreeEntry struct { + Name string + Id *Oid + Type ObjectType + Filemode Filemode +} + +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)), + ObjectType(C.git_tree_entry_type(entry)), + Filemode(C.git_tree_entry_filemode(entry)), + } +} + +func (t Tree) EntryByName(filename string) *TreeEntry { + cname := C.CString(filename) + defer C.free(unsafe.Pointer(cname)) + + entry := C.git_tree_entry_byname(t.cast_ptr, cname) + if entry == nil { + return nil + } + + goEntry := newTreeEntry(entry) + runtime.KeepAlive(t) + return goEntry +} + +// EntryById performs a lookup for a tree entry with the given SHA value. +// +// It returns a *TreeEntry that is owned by the Tree. You don't have to +// free it, but you must not use it after the Tree is freed. +// +// Warning: this must examine every entry in the tree, so it is not fast. +func (t Tree) EntryById(id *Oid) *TreeEntry { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + entry := C.git_tree_entry_byid(t.cast_ptr, id.toC()) + runtime.KeepAlive(id) + if entry == nil { + return nil + } + + goEntry := newTreeEntry(entry) + runtime.KeepAlive(t) + return goEntry +} + +// EntryByPath looks up an entry by its full path, recursing into +// deeper trees if necessary (i.e. if there are slashes in the path) +func (t Tree) EntryByPath(path string) (*TreeEntry, error) { + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + var entry *C.git_tree_entry + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_tree_entry_bypath(&entry, t.cast_ptr, cpath) + runtime.KeepAlive(t) + if ret < 0 { + return nil, MakeGitError(ret) + } + defer C.git_tree_entry_free(entry) + + return newTreeEntry(entry), nil +} + +func (t Tree) EntryByIndex(index uint64) *TreeEntry { + entry := C.git_tree_entry_byindex(t.cast_ptr, C.size_t(index)) + if entry == nil { + return nil + } + + goEntry := newTreeEntry(entry) + runtime.KeepAlive(t) + return goEntry +} + +func (t Tree) EntryCount() uint64 { + num := C.git_tree_entrycount(t.cast_ptr) + runtime.KeepAlive(t) + return uint64(num) +} + +type TreeWalkCallback func(string, *TreeEntry) int + +//export CallbackGitTreeWalk +func CallbackGitTreeWalk(_root *C.char, _entry unsafe.Pointer, ptr unsafe.Pointer) C.int { + root := C.GoString(_root) + entry := (*C.git_tree_entry)(_entry) + + if callback, ok := pointerHandles.Get(ptr).(TreeWalkCallback); ok { + return C.int(callback(root, newTreeEntry(entry))) + } else { + panic("invalid treewalk callback") + } +} + +func (t Tree) Walk(callback TreeWalkCallback) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ptr := pointerHandles.Track(callback) + defer pointerHandles.Untrack(ptr) + + err := C._go_git_treewalk( + t.cast_ptr, + C.GIT_TREEWALK_PRE, + ptr, + ) + runtime.KeepAlive(t) + if err < 0 { + return MakeGitError(err) + } + + return nil +} + +type TreeBuilder struct { + ptr *C.git_treebuilder + repo *Repository +} + +func (v *TreeBuilder) Free() { + runtime.SetFinalizer(v, nil) + C.git_treebuilder_free(v.ptr) +} + +func (v *TreeBuilder) Insert(filename string, id *Oid, filemode Filemode) error { + cfilename := C.CString(filename) + defer C.free(unsafe.Pointer(cfilename)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := C.git_treebuilder_insert(nil, v.ptr, cfilename, id.toC(), C.git_filemode_t(filemode)) + runtime.KeepAlive(v) + runtime.KeepAlive(id) + if err < 0 { + return MakeGitError(err) + } + + 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) + runtime.KeepAlive(v) + if err < 0 { + return MakeGitError(err) + } + + return nil +} + +func (v *TreeBuilder) Write() (*Oid, error) { + oid := new(Oid) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := C.git_treebuilder_write(oid.toC(), v.ptr) + runtime.KeepAlive(v) + if err < 0 { + return nil, MakeGitError(err) + } + + return oid, nil +} |