Merge remote-tracking branch 'upstream/master' into next
diff --git a/README.md b/README.md
index a5e6100..315032f 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
Installing
----------
-This project wraps the functionality provided by libgit2. If you're using a stable version, install it to your system via your system's package manaager and then install git2go as usual.
+This project wraps the functionality provided by libgit2. If you're using a stable version, install it to your system via your system's package manager and then install git2go as usual.
Otherwise (`next` which tracks an unstable version), we need to build libgit2 as well. In order to build it, you need `cmake`, `pkg-config` and a C compiler. You will also need the development packages for OpenSSL and LibSSH2 installed if you want libgit2 to support HTTPS and SSH respectively.
diff --git a/blob.go b/blob.go
index 16ec183..1a86e60 100644
--- a/blob.go
+++ b/blob.go
@@ -84,7 +84,7 @@
var chintPath *C.char = nil
if len(hintPath) > 0 {
- C.CString(hintPath)
+ chintPath = C.CString(hintPath)
defer C.free(unsafe.Pointer(chintPath))
}
oid := C.git_oid{}
diff --git a/checkout.go b/checkout.go
index ce2f469..a2e312b 100644
--- a/checkout.go
+++ b/checkout.go
@@ -45,6 +45,7 @@
FileOpenFlags int // Default is O_CREAT | O_TRUNC | O_WRONLY
TargetDirectory string // Alternative checkout path to workdir
Paths []string
+ Baseline *Tree
}
func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts {
@@ -90,6 +91,10 @@
ptr.paths.count = C.size_t(len(opts.Paths))
}
+ if opts.Baseline != nil {
+ ptr.baseline = opts.Baseline.cast_ptr
+ }
+
return ptr
}
diff --git a/config.go b/config.go
index 73365c8..7408fbc 100644
--- a/config.go
+++ b/config.go
@@ -118,18 +118,20 @@
}
func (c *Config) LookupString(name string) (string, error) {
- var ptr *C.char
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
+ valBuf := C.git_buf{}
+
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- if ret := C.git_config_get_string(&ptr, c.ptr, cname); ret < 0 {
+ if ret := C.git_config_get_string_buf(&valBuf, c.ptr, cname); ret < 0 {
return "", MakeGitError(ret)
}
+ defer C.git_buf_free(&valBuf)
- return C.GoString(ptr), nil
+ return C.GoString(valBuf.ptr), nil
}
func (c *Config) LookupBool(name string) (bool, error) {
diff --git a/config_test.go b/config_test.go
new file mode 100644
index 0000000..fea8d8a
--- /dev/null
+++ b/config_test.go
@@ -0,0 +1,108 @@
+package git
+
+import (
+ "os"
+ "testing"
+)
+
+var tempConfig = "./temp.gitconfig"
+
+func setupConfig() (*Config, error) {
+ var (
+ c *Config
+ err error
+ )
+
+ c, err = OpenOndisk(nil, tempConfig)
+ if err != nil {
+ return nil, err
+ }
+
+ err = c.SetString("foo.bar", "baz")
+ if err != nil {
+ return nil, err
+ }
+ err = c.SetBool("foo.bool", true)
+ if err != nil {
+ return nil, err
+ }
+ err = c.SetInt32("foo.int32", 32)
+ if err != nil {
+ return nil, err
+ }
+ err = c.SetInt64("foo.int64", 64)
+ if err != nil {
+ return nil, err
+ }
+
+ return c, err
+}
+
+func cleanupConfig() {
+ os.Remove(tempConfig)
+}
+
+type TestRunner func(*Config, *testing.T)
+
+var tests = []TestRunner{
+ // LookupString
+ func(c *Config, t *testing.T) {
+ val, err := c.LookupString("foo.bar")
+ if err != nil {
+ t.Errorf("Got LookupString error: '%v', expected none\n", err)
+ }
+ if val != "baz" {
+ t.Errorf("Got '%s' from LookupString, expected 'bar'\n", val)
+ }
+ },
+ // LookupBool
+ func(c *Config, t *testing.T) {
+ val, err := c.LookupBool("foo.bool")
+ if err != nil {
+ t.Errorf("Got LookupBool error: '%v', expected none\n", err)
+ }
+ if !val {
+ t.Errorf("Got %b from LookupBool, expected 'false'\n", val)
+ }
+ },
+ // LookupInt32
+ func(c *Config, t *testing.T) {
+ val, err := c.LookupInt32("foo.int32")
+ if err != nil {
+ t.Errorf("Got LookupInt32 error: '%v', expected none\n", err)
+ }
+ if val != 32 {
+ t.Errorf("Got %v, expected 32\n", val)
+ }
+ },
+ // LookupInt64
+ func(c *Config, t *testing.T) {
+ val, err := c.LookupInt64("foo.int64")
+ if err != nil {
+ t.Errorf("Got LookupInt64 error: '%v', expected none\n", err)
+ }
+ if val != 64 {
+ t.Errorf("Got %v, expected 64\n", val)
+ }
+ },
+}
+
+func TestConfigLookups(t *testing.T) {
+ var (
+ err error
+ c *Config
+ )
+
+ c, err = setupConfig()
+ defer cleanupConfig()
+
+ if err != nil {
+ t.Errorf("Setup error: '%v'. Expected none\n", err)
+ return
+ }
+ defer c.Free()
+
+ for _, test := range tests {
+ test(c, t)
+ }
+}
diff --git a/index.go b/index.go
index 16e63a1..ae94864 100644
--- a/index.go
+++ b/index.go
@@ -115,7 +115,7 @@
return nil, MakeGitError(err)
}
- return &Index{ptr: ptr}, nil
+ return newIndexFromC(ptr), nil
}
// OpenIndex creates a new index at the given path. If the file does
@@ -133,7 +133,7 @@
return nil, MakeGitError(err)
}
- return &Index{ptr: ptr}, nil
+ return newIndexFromC(ptr), nil
}
// Path returns the index' path on disk or an empty string if it
diff --git a/merge.go b/merge.go
index 53d5a72..0b0a8f1 100644
--- a/merge.go
+++ b/merge.go
@@ -185,6 +185,9 @@
MergePreferenceFastForwardOnly MergePreference = C.GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY
)
+// MergeAnalysis returns the possible actions which could be taken by
+// a 'git-merge' command. There may be multiple answers, so the first
+// return value is a bitmask of MergeAnalysis values.
func (r *Repository) MergeAnalysis(theirHeads []*AnnotatedCommit) (MergeAnalysis, MergePreference, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
diff --git a/odb.go b/odb.go
index ff8b739..d881f63 100644
--- a/odb.go
+++ b/odb.go
@@ -8,7 +8,6 @@
*/
import "C"
import (
- "fmt"
"reflect"
"runtime"
"unsafe"
@@ -55,6 +54,21 @@
return 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
+
+ ret := C.git_odb_read_header(&sz, &cotype, v.ptr, oid.toC())
+ if ret < 0 {
+ return 0, C.GIT_OBJ_BAD, MakeGitError(ret)
+ }
+
+ 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
@@ -107,9 +121,7 @@
}
err := data.callback(newOidFromC(id))
- fmt.Println("err %v", err)
if err != nil {
- fmt.Println("returning EUSER")
data.err = err
return C.GIT_EUSER
}
@@ -130,7 +142,6 @@
defer pointerHandles.Untrack(handle)
ret := C._go_git_odb_foreach(v.ptr, handle)
- fmt.Println("ret %v", ret)
if ret == C.GIT_EUSER {
return data.err
} else if ret < 0 {
diff --git a/odb_test.go b/odb_test.go
index 0d765b9..dfd2ad0 100644
--- a/odb_test.go
+++ b/odb_test.go
@@ -6,6 +6,34 @@
"testing"
)
+func TestOdbReadHeader(t *testing.T) {
+ repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
+ _, _ = seedTestRepo(t, repo)
+ odb, err := repo.Odb()
+ if err != nil {
+ t.Fatalf("Odb: %v", err)
+ }
+ data := []byte("hello")
+ id, err := odb.Write(data, ObjectBlob)
+ if err != nil {
+ t.Fatalf("odb.Write: %v", err)
+ }
+
+ sz, typ, err := odb.ReadHeader(id)
+ if err != nil {
+ t.Fatalf("ReadHeader: %v", err)
+ }
+
+ if sz != uint64(len(data)) {
+ t.Errorf("ReadHeader got size %d, want %d", sz, len(data))
+ }
+ if typ != ObjectBlob {
+ t.Errorf("ReadHeader got object type %s", typ)
+ }
+}
+
func TestOdbStream(t *testing.T) {
repo := createTestRepo(t)
defer cleanupTestRepo(t, repo)
diff --git a/remote.go b/remote.go
index a216513..8a57280 100644
--- a/remote.go
+++ b/remote.go
@@ -637,15 +637,17 @@
crefspecs.strings = makeCStringsFromStrings(refspecs)
defer freeStrarray(&crefspecs)
- var coptions C.git_fetch_options
- populateFetchOptions(&coptions, opts)
+ coptions := (*C.git_fetch_options)(C.calloc(1, C.size_t(unsafe.Sizeof(C.git_fetch_options{}))))
+ defer C.free(unsafe.Pointer(coptions))
+
+ populateFetchOptions(coptions, opts)
defer untrackCalbacksPayload(&coptions.callbacks)
defer freeStrarray(&coptions.custom_headers)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_fetch(o.ptr, &crefspecs, &coptions, cmsg)
+ ret := C.git_remote_fetch(o.ptr, &crefspecs, coptions, cmsg)
if ret < 0 {
return MakeGitError(ret)
}
@@ -737,15 +739,17 @@
crefspecs.strings = makeCStringsFromStrings(refspecs)
defer freeStrarray(&crefspecs)
- var coptions C.git_push_options
- populatePushOptions(&coptions, opts)
+ coptions := (*C.git_push_options)(C.calloc(1, C.size_t(unsafe.Sizeof(C.git_push_options{}))))
+ defer C.free(unsafe.Pointer(coptions))
+
+ populatePushOptions(coptions, opts)
defer untrackCalbacksPayload(&coptions.callbacks)
defer freeStrarray(&coptions.custom_headers)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_push(o.ptr, &crefspecs, &coptions)
+ ret := C.git_remote_push(o.ptr, &crefspecs, coptions)
if ret < 0 {
return MakeGitError(ret)
}
diff --git a/repository.go b/repository.go
index 398f91a..77e9f9c 100644
--- a/repository.go
+++ b/repository.go
@@ -447,3 +447,24 @@
}
return nil
}
+func (r *Repository) AddGitIgnoreRules(rules string) error {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ crules := C.CString(rules)
+ defer C.free(unsafe.Pointer(crules))
+ if ret := C.git_ignore_add_rule(r.ptr, crules); ret < 0 {
+ return MakeGitError(ret)
+ }
+ return nil
+}
+
+func (r *Repository) ClearGitIgnoreRules() error {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ if ret := C.git_ignore_clear_internal_rules(r.ptr); ret < 0 {
+ return MakeGitError(ret)
+ }
+ return nil
+}
diff --git a/walk.go b/walk.go
index c314f60..60e618d 100644
--- a/walk.go
+++ b/walk.go
@@ -194,6 +194,10 @@
return nil
}
+func (v *RevWalk) SimplifyFirstParent() {
+ C.git_revwalk_simplify_first_parent(v.ptr)
+}
+
func (v *RevWalk) Sorting(sm SortType) {
C.git_revwalk_sorting(v.ptr, C.uint(sm))
}