From 9397af0854575913f72b10a7ebf474ef023e2e69 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Wed, 16 Sep 2015 16:08:37 -0400 Subject: [PATCH 01/13] Expose baseline field in CheckoutOptions --- checkout.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/checkout.go b/checkout.go index e0c067e..a2e312b 100644 --- a/checkout.go +++ b/checkout.go @@ -44,7 +44,8 @@ type CheckoutOpts struct { FileMode os.FileMode // Default is 0644 or 0755 as dictated by blob FileOpenFlags int // Default is O_CREAT | O_TRUNC | O_WRONLY TargetDirectory string // Alternative checkout path to workdir - Paths []string + Paths []string + Baseline *Tree } func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts { @@ -90,6 +91,10 @@ func populateCheckoutOpts(ptr *C.git_checkout_options, opts *CheckoutOpts) *C.gi ptr.paths.count = C.size_t(len(opts.Paths)) } + if opts.Baseline != nil { + ptr.baseline = opts.Baseline.cast_ptr + } + return ptr } @@ -156,4 +161,4 @@ func (v *Repository) CheckoutTree(tree *Tree, opts *CheckoutOpts) error { } return nil -} \ No newline at end of file +} From b1d97c1ebd3c66e7311c11c02575d66f41bab953 Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Tue, 6 Oct 2015 15:12:49 -0500 Subject: [PATCH 02/13] Fix typo in README: manaager -> manager --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a5e6100..315032f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Go bindings for [libgit2](http://libgit2.github.com/). The `master` branch follo 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. From 80cf533fe4e48ddfab3015d9570f2833951c1dea Mon Sep 17 00:00:00 2001 From: David Pierce Date: Sat, 26 Sep 2015 15:37:48 -0700 Subject: [PATCH 03/13] Config#LookupString uses git_buf to load value --- config.go | 8 ++++--- config_test.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 config_test.go diff --git a/config.go b/config.go index 9d25e35..c4c4028 100644 --- a/config.go +++ b/config.go @@ -115,18 +115,20 @@ func (c *Config) LookupInt64(name string) (int64, error) { } 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..e4a2c1f --- /dev/null +++ b/config_test.go @@ -0,0 +1,58 @@ +package git + +import ( + "os" + "testing" +) + +func setupConfig() (*Config, error) { + var ( + c *Config + err error + p string + ) + + p, err = ConfigFindGlobal() + if err != nil { + return nil, err + } + + c, err = OpenOndisk(nil, p) + if err != nil { + return nil, err + } + + c.SetString("foo.bar", "baz") + + return c, err +} + +func cleanupConfig() { + os.Remove(tempConfig) +} + +func TestConfigLookupString(t *testing.T) { + var ( + err error + val string + c *Config + ) + + c, err = setupConfig() + defer cleanupConfig() + if err != nil { + t.Errorf("Setup error: '%v'. Expected none\n", err) + t.FailNow() + } + defer c.Free() + + val, err = c.LookupString("foo.bar") + if err != nil { + t.Errorf("Got error: '%v', expected none\n", err) + t.FailNow() + } + + if val != "baz" { + t.Errorf("Got '%s', expected 'bar'\n", val) + } +} From 81e0b16d9fbbfa916b34d0fa38967a14f8796f49 Mon Sep 17 00:00:00 2001 From: David Pierce Date: Sat, 26 Sep 2015 16:11:49 -0700 Subject: [PATCH 04/13] Tests config lookup methods --- config_test.go | 73 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 18 deletions(-) diff --git a/config_test.go b/config_test.go index e4a2c1f..8c2decc 100644 --- a/config_test.go +++ b/config_test.go @@ -5,24 +5,23 @@ import ( "testing" ) +var tempConfig = "./temp.gitconfig" + func setupConfig() (*Config, error) { var ( c *Config err error - p string ) - p, err = ConfigFindGlobal() - if err != nil { - return nil, err - } - - c, err = OpenOndisk(nil, p) + c, err = OpenOndisk(nil, tempConfig) if err != nil { return nil, err } c.SetString("foo.bar", "baz") + c.SetBool("foo.bool", true) + c.SetInt32("foo.int32", 32) + c.SetInt64("foo.int64", 64) return c, err } @@ -31,28 +30,66 @@ func cleanupConfig() { os.Remove(tempConfig) } -func TestConfigLookupString(t *testing.T) { +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 - val string c *Config ) c, err = setupConfig() defer cleanupConfig() + if err != nil { t.Errorf("Setup error: '%v'. Expected none\n", err) - t.FailNow() } defer c.Free() - val, err = c.LookupString("foo.bar") - if err != nil { - t.Errorf("Got error: '%v', expected none\n", err) - t.FailNow() - } - - if val != "baz" { - t.Errorf("Got '%s', expected 'bar'\n", val) + for _, test := range tests { + test(c, t) } } From 22495763b73d1560c5c8b8182ee8b723adee1bcd Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Tue, 13 Oct 2015 11:31:00 -0400 Subject: [PATCH 05/13] Expose AddGitIgnoreRules and ClearGitIgnoreRules funcs --- repository.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/repository.go b/repository.go index 62fde6d..12638e1 100644 --- a/repository.go +++ b/repository.go @@ -433,3 +433,24 @@ func (r *Repository) StateCleanup() error { } 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 +} From 3b5633de219eec2908723a8e557758cc055d84d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 26 Oct 2015 21:22:22 +0100 Subject: [PATCH 06/13] Mention that MergeAnalysis is a bitmask --- merge.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/merge.go b/merge.go index bab53e0..272bf6a 100644 --- a/merge.go +++ b/merge.go @@ -178,6 +178,9 @@ const ( 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() From ae107d5f56a0cb2b9703ad3733143e0f6acc01de Mon Sep 17 00:00:00 2001 From: FUJII Ryota Date: Tue, 27 Oct 2015 15:20:50 +0900 Subject: [PATCH 07/13] Fix memory leaks in NewIndex() and OpenIndex() --- index.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.go b/index.go index 0174dc1..1eb5e9d 100644 --- a/index.go +++ b/index.go @@ -97,7 +97,7 @@ func NewIndex() (*Index, error) { 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 @@ -115,7 +115,7 @@ func OpenIndex(path string) (*Index, error) { 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 From f18ea412dc8d3a43930bb7f9143dcc2e01d60158 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 2 Nov 2015 15:47:59 -0500 Subject: [PATCH 08/13] config_test: properly detect failed config writes This patch fixes the setup stage of the config tests to notice when the writes fail (eg $PWD is a read-only filesystem) and to correctly skip the entire test function as a result. --- config_test.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/config_test.go b/config_test.go index 8c2decc..fea8d8a 100644 --- a/config_test.go +++ b/config_test.go @@ -18,10 +18,22 @@ func setupConfig() (*Config, error) { return nil, err } - c.SetString("foo.bar", "baz") - c.SetBool("foo.bool", true) - c.SetInt32("foo.int32", 32) - c.SetInt64("foo.int64", 64) + 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 } @@ -86,6 +98,7 @@ func TestConfigLookups(t *testing.T) { if err != nil { t.Errorf("Setup error: '%v'. Expected none\n", err) + return } defer c.Free() From 714cd56c715d22e9759413783c9c4be0018193e0 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 2 Nov 2015 15:51:03 -0500 Subject: [PATCH 09/13] odb: remove debug fmt.Printlns These appear to be left over debug statements, and they also look like they were intended to be fmt.Printf calls anyway. --- odb.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/odb.go b/odb.go index be0870e..b15851f 100644 --- a/odb.go +++ b/odb.go @@ -11,7 +11,6 @@ import ( "reflect" "runtime" "unsafe" - "fmt" ) type Odb struct { @@ -107,9 +106,7 @@ func odbForEachCb(id *C.git_oid, handle unsafe.Pointer) int { } 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 +127,6 @@ func (v *Odb) ForEach(callback OdbForEachCallback) error { 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 { From 92d736d12c5263826662ad26a152b7f027aa1efa Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Thu, 12 Nov 2015 21:15:24 -0500 Subject: [PATCH 10/13] Fix Fetch/Push memory allocation problems The Fetch/Push operations didn't allocate the git_*_options structure and this causes a memory problem in the libgit2 code. Following the example of Clone operation, the Fetch/Push functions allocates the options structure before calling the C. --- remote.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/remote.go b/remote.go index b2fb96f..330f202 100644 --- a/remote.go +++ b/remote.go @@ -623,14 +623,16 @@ func (o *Remote) Fetch(refspecs []string, opts *FetchOptions, msg string) error 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) 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) } @@ -710,14 +712,16 @@ func (o *Remote) Push(refspecs []string, opts *PushOptions) error { 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) 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) } From 51d3ead30d58d523cef5aaea1666c8e28a94dc42 Mon Sep 17 00:00:00 2001 From: Michael Gehring Date: Mon, 4 Jan 2016 15:02:21 +0100 Subject: [PATCH 11/13] Don't drop CreateBlobFromChunks hintPath argument --- blob.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blob.go b/blob.go index b1fc78a..382bb9e 100644 --- a/blob.go +++ b/blob.go @@ -84,7 +84,7 @@ func (repo *Repository) CreateBlobFromChunks(hintPath string, callback BlobChunk 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{} From 773ac24a16da6261e0f31b9354a9c890b1002422 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 2 Feb 2016 19:02:15 +0100 Subject: [PATCH 12/13] Expose git_odb_read_header as Odb.ReadHeader. This function is much faster for discovering sizes for a given OID. --- odb.go | 15 +++++++++++++++ odb_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/odb.go b/odb.go index b15851f..d881f63 100644 --- a/odb.go +++ b/odb.go @@ -54,6 +54,21 @@ func (v *Odb) AddBackend(backend *OdbBackend, priority int) (err error) { 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 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 @@ import ( "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) From b876e836fa76747b34832f42c354934854601f7d Mon Sep 17 00:00:00 2001 From: Orivej Desh Date: Sun, 7 Feb 2016 03:12:35 +0000 Subject: [PATCH 13/13] Add RevWalk.SimplifyFirstParent() --- walk.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/walk.go b/walk.go index c314f60..60e618d 100644 --- a/walk.go +++ b/walk.go @@ -194,6 +194,10 @@ func (v *RevWalk) Iterate(fun RevWalkIterator) (err error) { 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)) }