From e825d66fba2cb4169c7f3b0a43c491cf9e8c0738 Mon Sep 17 00:00:00 2001 From: Jason Toffaletti Date: Sat, 4 Jan 2014 00:40:21 +0000 Subject: work in progress wrapping git_clone --- git.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'git.go') diff --git a/git.go b/git.go index 28196c8..07892e4 100644 --- a/git.go +++ b/git.go @@ -1,7 +1,7 @@ package git /* -#cgo pkg-config: libgit2 +#cgo pkg-config: --static libgit2 #include #include */ -- cgit v1.2.3 From b6703d47671b3a736e8b93ff0447da45e688865c Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 18 Mar 2014 04:54:40 +0100 Subject: Oid: make the type directly [20]byte There is no need for a struct with a single field. An Oid is 20 bytes which hold the binary representation of the hash, so let's use that directly. Go lets us have methods on this new type just the same. --- git.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'git.go') diff --git a/git.go b/git.go index db9522b..8f543b5 100644 --- a/git.go +++ b/git.go @@ -29,9 +29,7 @@ func init() { } // Oid -type Oid struct { - bytes [20]byte -} +type Oid [20]byte func newOidFromC(coid *C.git_oid) *Oid { if coid == nil { @@ -39,18 +37,18 @@ func newOidFromC(coid *C.git_oid) *Oid { } oid := new(Oid) - copy(oid.bytes[0:20], C.GoBytes(unsafe.Pointer(coid), 20)) + copy(oid[0:20], C.GoBytes(unsafe.Pointer(coid), 20)) return oid } func NewOid(b []byte) *Oid { oid := new(Oid) - copy(oid.bytes[0:20], b[0:20]) + copy(oid[0:20], b[0:20]) return oid } func (oid *Oid) toC() *C.git_oid { - return (*C.git_oid)(unsafe.Pointer(&oid.bytes)) + return (*C.git_oid)(unsafe.Pointer(oid)) } func NewOidFromString(s string) (*Oid, error) { @@ -75,25 +73,25 @@ func (oid *Oid) String() string { } func (oid *Oid) Bytes() []byte { - return oid.bytes[0:] + return oid[0:] } func (oid *Oid) Cmp(oid2 *Oid) int { - return bytes.Compare(oid.bytes[:], oid2.bytes[:]) + return bytes.Compare(oid[:], oid2[:]) } func (oid *Oid) Copy() *Oid { ret := new(Oid) - copy(ret.bytes[:], oid.bytes[:]) + copy(ret[:], oid[:]) return ret } func (oid *Oid) Equal(oid2 *Oid) bool { - return bytes.Equal(oid.bytes[:], oid2.bytes[:]) + return bytes.Equal(oid[:], oid2[:]) } func (oid *Oid) IsZero() bool { - for _, a := range oid.bytes { + for _, a := range oid { if a != '0' { return false } @@ -102,7 +100,7 @@ func (oid *Oid) IsZero() bool { } func (oid *Oid) NCmp(oid2 *Oid, n uint) int { - return bytes.Compare(oid.bytes[:n], oid2.bytes[:n]) + return bytes.Compare(oid[:n], oid2[:n]) } func ShortenOids(ids []*Oid, minlen int) (int, error) { -- cgit v1.2.3 From c9c7c1e77942f88955af0dc3bdfb58d5e7d7f121 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 18 Mar 2014 05:04:26 +0100 Subject: Oid: make NewOid take a string This is the most common way of having an id that's not in Oid form, so let's make it the "default" and rename to NewOidFromBytes() the one that takes []byte. --- git.go | 4 ++-- odb_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'git.go') diff --git a/git.go b/git.go index 8f543b5..f3fb7e1 100644 --- a/git.go +++ b/git.go @@ -41,7 +41,7 @@ func newOidFromC(coid *C.git_oid) *Oid { return oid } -func NewOid(b []byte) *Oid { +func NewOidFromBytes(b []byte) *Oid { oid := new(Oid) copy(oid[0:20], b[0:20]) return oid @@ -51,7 +51,7 @@ func (oid *Oid) toC() *C.git_oid { return (*C.git_oid)(unsafe.Pointer(oid)) } -func NewOidFromString(s string) (*Oid, error) { +func NewOid(s string) (*Oid, error) { o := new(Oid) cs := C.CString(s) defer C.free(unsafe.Pointer(cs)) diff --git a/odb_test.go b/odb_test.go index a4f8943..17b3ad2 100644 --- a/odb_test.go +++ b/odb_test.go @@ -27,7 +27,7 @@ func TestOdbStream(t *testing.T) { error = stream.Close() checkFatal(t, error) - expectedId, error := NewOidFromString("30f51a3fba5274d53522d0f19748456974647b4f") + expectedId, error := NewOid("30f51a3fba5274d53522d0f19748456974647b4f") checkFatal(t, error) if stream.Id.Cmp(expectedId) != 0 { t.Fatal("Wrong data written") @@ -59,4 +59,4 @@ Initial commit.`; if oid.Cmp(coid) != 0 { t.Fatal("Hash and write Oids are different") } -} \ No newline at end of file +} -- cgit v1.2.3 From c243c31f7d428680579a1dd20273cd3888c730e4 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 19 Mar 2014 03:11:41 +0100 Subject: Oid: remove Bytes() This is not needed. We can do id[:] to get a slice. --- git.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'git.go') diff --git a/git.go b/git.go index f3fb7e1..9e1d3e7 100644 --- a/git.go +++ b/git.go @@ -28,7 +28,7 @@ func init() { C.git_threads_init() } -// Oid +// Oid represents the id for a Git object. type Oid [20]byte func newOidFromC(coid *C.git_oid) *Oid { @@ -72,10 +72,6 @@ func (oid *Oid) String() string { return string(buf) } -func (oid *Oid) Bytes() []byte { - return oid[0:] -} - func (oid *Oid) Cmp(oid2 *Oid) int { return bytes.Compare(oid[:], oid2[:]) } -- cgit v1.2.3 From 0bb73e43a8f26be8608cdd304d73cacb05753417 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 19 Mar 2014 03:39:34 +0100 Subject: Oid: use Go's conversion functions Go already has all the necessary pieces for encoding and decoding hex strings. Using them let's us avoid going into C land. Benchmarks show this takes about half the time as using libgit2's functions. --- git.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'git.go') diff --git a/git.go b/git.go index 9e1d3e7..e5fe812 100644 --- a/git.go +++ b/git.go @@ -8,6 +8,7 @@ package git import "C" import ( "bytes" + "encoding/hex" "errors" "runtime" "strings" @@ -52,24 +53,23 @@ func (oid *Oid) toC() *C.git_oid { } func NewOid(s string) (*Oid, error) { - o := new(Oid) - cs := C.CString(s) - defer C.free(unsafe.Pointer(cs)) + if len(s) > C.GIT_OID_HEXSZ { + return nil, errors.New("string is too long for oid") + } - runtime.LockOSThread() - defer runtime.UnlockOSThread() + o := new(Oid) - if ret := C.git_oid_fromstr(o.toC(), cs); ret < 0 { - return nil, MakeGitError(ret) + slice, error := hex.DecodeString(s) + if error != nil { + return nil, error } + copy(o[:], slice[:20]) return o, nil } func (oid *Oid) String() string { - buf := make([]byte, 40) - C.git_oid_fmt((*C.char)(unsafe.Pointer(&buf[0])), oid.toC()) - return string(buf) + return hex.EncodeToString(oid[:]) } func (oid *Oid) Cmp(oid2 *Oid) int { -- cgit v1.2.3 From b82a72a9ce4701a4560288c4ebf1511ffb415b80 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Wed, 19 Mar 2014 03:51:59 +0100 Subject: Oid: fix IsZero() We need to compare against the number zero, not its ASCII value. --- git.go | 2 +- git_test.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'git.go') diff --git a/git.go b/git.go index e5fe812..b20f993 100644 --- a/git.go +++ b/git.go @@ -88,7 +88,7 @@ func (oid *Oid) Equal(oid2 *Oid) bool { func (oid *Oid) IsZero() bool { for _, a := range oid { - if a != '0' { + if a != 0 { return false } } diff --git a/git_test.go b/git_test.go index fff3c6c..6542ca0 100644 --- a/git_test.go +++ b/git_test.go @@ -54,3 +54,11 @@ func seedTestRepo(t *testing.T, repo *Repository) (*Oid, *Oid) { return commitId, treeId } + +func TestOidZero(t *testing.T) { + var zeroId Oid + + if !zeroId.IsZero() { + t.Error("Zero Oid is not zero") + } +} -- cgit v1.2.3 From b2a2a279d96890c9578370ec4db50c1da31f18d7 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Tue, 25 Mar 2014 00:12:32 +0100 Subject: Add a settings package This lets us modify the libgit2-wide options/settings. --- .travis.yml | 5 +-- git.go | 4 ++ script/build-libgit2.sh | 4 -- settings/settings.go | 109 ++++++++++++++++++++++++++++++++++++++++++++++ settings/settings_test.go | 66 ++++++++++++++++++++++++++++ 5 files changed, 181 insertions(+), 7 deletions(-) create mode 100644 settings/settings.go create mode 100644 settings/settings_test.go (limited to 'git.go') diff --git a/.travis.yml b/.travis.yml index 86f8265..2a03529 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,7 @@ go: - 1.1 - tip -env: - - PKG_CONFIG_PATH=libgit2/install/lib/pkgconfig LD_LIBRARY_PATH=libgit2/install/lib - install: - script/build-libgit2.sh + - export PKG_CONFIG_PATH=$PWD/libgit2/install/lib/pkgconfig + - export LD_LIBRARY_PATH=$PWD/libgit2/install/lib diff --git a/git.go b/git.go index b20f993..8159244 100644 --- a/git.go +++ b/git.go @@ -149,6 +149,10 @@ func MakeGitError(errorCode C.int) error { return &GitError{C.GoString(err.message), int(err.klass), int(errorCode)} } +func MakeGitError2(err int) error { + return MakeGitError(C.int(err)) +} + func cbool(b bool) C.int { if b { return C.int(1) diff --git a/script/build-libgit2.sh b/script/build-libgit2.sh index aa43df5..8376a15 100755 --- a/script/build-libgit2.sh +++ b/script/build-libgit2.sh @@ -11,7 +11,3 @@ cmake -DTHREADSAFE=ON \ . make install - -# Let the Go build system know where to find libgit2 -export LD_LIBRARY_PATH="$TMPDIR/libgit2/install/lib" -export PKG_CONFIG_PATH="$TMPDIR/libgit2/install/lib/pkgconfig" diff --git a/settings/settings.go b/settings/settings.go new file mode 100644 index 0000000..6661c5d --- /dev/null +++ b/settings/settings.go @@ -0,0 +1,109 @@ +package settings + +/* +#cgo pkg-config: libgit2 +#include + +int _go_git_opts_get_search_path(int level, git_buf *buf) +{ + return git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, level, buf); +} + +int _go_git_opts_set_search_path(int level, const char *path) +{ + return git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, level, path); +} + +int _go_git_opts_set_size_t(int opt, size_t val) +{ + return git_libgit2_opts(opt, val); +} + +int _go_git_opts_get_size_t(int opt, size_t *val) +{ + return git_libgit2_opts(opt, val); +} + +*/ +import "C" +import ( + "runtime" + "unsafe" + "github.com/libgit2/git2go" +) + +func MakeGitError(err C.int) error { + return git.MakeGitError2(int(err)) +} + +func SearchPath(level git.ConfigLevel) (string, error) { + var buf C.git_buf + defer C.git_buf_free(&buf) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := C._go_git_opts_get_search_path(C.int(level), &buf) + if err < 0 { + return "", MakeGitError(err) + } + + return C.GoString(buf.ptr), nil +} + +func SetSearchPath(level git.ConfigLevel, path string) error { + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := C._go_git_opts_set_search_path(C.int(level), cpath) + if err < 0 { + return MakeGitError(err) + } + + return nil +} + +func getSizet(opt C.int) (int, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var val C.size_t + err := C._go_git_opts_get_size_t(opt, &val); + if err < 0 { + return 0, MakeGitError(err) + } + + return int(val), nil +} + +func setSizet(opt C.int, val int) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + cval := C.size_t(val) + err := C._go_git_opts_set_size_t(opt, cval); + if err < 0 { + return MakeGitError(err) + } + + return nil +} + +func MwindowSize() (int, error) { + return getSizet(C.GIT_OPT_GET_MWINDOW_SIZE) +} + +func SetMwindowSize(size int) error { + return setSizet(C.GIT_OPT_SET_MWINDOW_SIZE, size) +} + +func MwindowMappedLimit() (int, error) { + return getSizet(C.GIT_OPT_GET_MWINDOW_MAPPED_LIMIT) +} + +func SetMwindowMappedLimit(size int) error { + return setSizet(C.GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, size) +} diff --git a/settings/settings_test.go b/settings/settings_test.go new file mode 100644 index 0000000..55b08c8 --- /dev/null +++ b/settings/settings_test.go @@ -0,0 +1,66 @@ +package settings + +import ( + "testing" + "runtime" + "github.com/libgit2/git2go" +) + +type pathPair struct { + Level git.ConfigLevel + Path string +} + +func TestSearchPath(t *testing.T) { + paths := []pathPair{ + pathPair{git.ConfigLevelSystem, "/tmp/system"}, + pathPair{git.ConfigLevelGlobal, "/tmp/global"}, + pathPair{git.ConfigLevelXDG, "/tmp/xdg"}, + } + + for _, pair := range paths { + err := SetSearchPath(pair.Level, pair.Path) + checkFatal(t, err) + + actual, err := SearchPath(pair.Level) + checkFatal(t, err) + + if pair.Path != actual { + t.Fatal("Search paths don't match") + } + } +} + +func TestMmapSizes(t *testing.T) { + size := 42 * 1024 + + err := SetMwindowSize(size) + checkFatal(t, err) + + actual, err := MwindowSize() + if size != actual { + t.Fatal("Sizes don't match") + } + + err = SetMwindowMappedLimit(size) + checkFatal(t, err) + + actual, err = MwindowMappedLimit() + if size != actual { + t.Fatal("Sizes don't match") + } +} + +func checkFatal(t *testing.T, err error) { + if err == nil { + return + } + + // The failure happens at wherever we were called, not here + _, file, line, ok := runtime.Caller(1) + if !ok { + t.Fatal() + } + + t.Fatalf("Fail at %v:%v; %v", file, line, err) +} -- cgit v1.2.3