summaryrefslogtreecommitdiff
path: root/tree.go
blob: 3bc89999d489980ebefa7ce2962422aecdfe9301 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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 (
	"runtime"
	"unsafe"
)

type Tree struct {
	gitObject
}

type TreeEntry struct {
	Name string
	Id  *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) 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 (v *TreeBuilder) Free() {
	runtime.SetFinalizer(v, nil)
	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
}