From 79fe156d307a9c7b294aa92c741dc0c2759a1894 Mon Sep 17 00:00:00 2001 From: Vadzim Ramanenka Date: Mon, 17 Jul 2017 13:12:43 +0300 Subject: [PATCH 01/68] Add binding for `git_index_add_frombuffer` --- index.go | 26 +++++++++++++++++++++++++- index_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/index.go b/index.go index 5106516..d7a1e5f 100644 --- a/index.go +++ b/index.go @@ -90,7 +90,9 @@ func populateCIndexEntry(source *IndexEntry, dest *C.git_index_entry) { dest.uid = C.uint32_t(source.Uid) dest.gid = C.uint32_t(source.Gid) dest.file_size = C.uint32_t(source.Size) - dest.id = *source.Id.toC() + if source.Id != nil { + dest.id = *source.Id.toC() + } dest.path = C.CString(source.Path) } @@ -181,6 +183,28 @@ func (v *Index) AddByPath(path string) error { return nil } +// AddFromBuffer adds or replaces an index entry from a buffer in memory +func (v *Index) AddFromBuffer(entry *IndexEntry, buffer []byte) error { + var centry C.git_index_entry + + populateCIndexEntry(entry, ¢ry) + defer freeCIndexEntry(¢ry) + + var cbuffer unsafe.Pointer + if len(buffer) > 0 { + cbuffer = unsafe.Pointer(&buffer[0]) + } + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if err := C.git_index_add_frombuffer(v.ptr, ¢ry, cbuffer, C.size_t(len(buffer))); err < 0 { + return MakeGitError(err) + } + + return nil +} + func (v *Index) AddAll(pathspecs []string, flags IndexAddOpts, callback IndexMatchedPathCallback) error { cpathspecs := C.git_strarray{} cpathspecs.count = C.size_t(len(pathspecs)) diff --git a/index_test.go b/index_test.go index f47dace..d882809 100644 --- a/index_test.go +++ b/index_test.go @@ -149,6 +149,30 @@ func TestIndexRemoveDirectory(t *testing.T) { } } +func TestIndexAddFromBuffer(t *testing.T) { + t.Parallel() + repo := createTestRepo(t) + defer cleanupTestRepo(t, repo) + + idx, err := repo.Index() + checkFatal(t, err) + + entry := IndexEntry{ + Path: "README", + Mode: FilemodeBlob, + } + + err = idx.AddFromBuffer(&entry, []byte("foo\n")) + checkFatal(t, err) + + treeId, err := idx.WriteTreeTo(repo) + checkFatal(t, err) + + if treeId.String() != "b7119b11e8ef7a1a5a34d3ac87f5b075228ac81e" { + t.Fatalf("%v", treeId.String()) + } +} + func TestIndexAddAllNoCallback(t *testing.T) { t.Parallel() repo := createTestRepo(t) From 21fd4ad5f6ee67580fcf831917e54e18b074b5ed Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Sun, 21 Jan 2018 13:46:08 -0800 Subject: [PATCH 02/68] rebase: add RebaseOperationReword --- rebase.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rebase.go b/rebase.go index 5206fca..4517dde 100644 --- a/rebase.go +++ b/rebase.go @@ -16,6 +16,8 @@ type RebaseOperationType uint const ( // RebaseOperationPick The given commit is to be cherry-picked. The client should commit the changes and continue if there are no conflicts. RebaseOperationPick RebaseOperationType = C.GIT_REBASE_OPERATION_PICK + // RebaseOperationReword The given commit is to be cherry-picked, but the client should prompt the user to provide an updated commit message. + RebaseOperationReword RebaseOperationType = C.GIT_REBASE_OPERATION_REWORD // RebaseOperationEdit The given commit is to be cherry-picked, but the client should stop to allow the user to edit the changes before committing them. RebaseOperationEdit RebaseOperationType = C.GIT_REBASE_OPERATION_EDIT // RebaseOperationSquash The given commit is to be squashed into the previous commit. The commit message will be merged with the previous message. From 9b850d084e13e0376f3fe8cfb556d2e7b51f398f Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Sun, 21 Jan 2018 13:46:54 -0800 Subject: [PATCH 03/68] rebase: make RebaseOperationType a fmt.Stringer Helps with debugging. --- rebase.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/rebase.go b/rebase.go index 4517dde..d29e183 100644 --- a/rebase.go +++ b/rebase.go @@ -6,6 +6,7 @@ package git import "C" import ( "errors" + "fmt" "runtime" "unsafe" ) @@ -28,6 +29,24 @@ const ( RebaseOperationExec RebaseOperationType = C.GIT_REBASE_OPERATION_EXEC ) +func (t RebaseOperationType) String() string { + switch t { + case RebaseOperationPick: + return "pick" + case RebaseOperationReword: + return "reword" + case RebaseOperationEdit: + return "edit" + case RebaseOperationSquash: + return "squash" + case RebaseOperationFixup: + return "fixup" + case RebaseOperationExec: + return "exec" + } + return fmt.Sprintf("RebaseOperationType(%d)", t) +} + // Special value indicating that there is no currently active operation var RebaseNoOperation uint = ^uint(0) From cf2379295a47097438e272e1df11458a82d6d00a Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 25 Jan 2018 15:59:00 -0800 Subject: [PATCH 04/68] signature: improve Signature.Offset docs Use standard godoc style; be more precise. --- signature.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/signature.go b/signature.go index 16964d2..220fe57 100644 --- a/signature.go +++ b/signature.go @@ -26,7 +26,7 @@ func newSignatureFromC(sig *C.git_signature) *Signature { } } -// the offset in mintes, which is what git wants +// Offset returns the time zone offset of v.When in minutes, which is what git wants. func (v *Signature) Offset() int { _, offset := v.When.Zone() return offset / 60 From 03339f731aba66baacab3fd67e7b2d185cdacb33 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 25 Jan 2018 16:00:39 -0800 Subject: [PATCH 05/68] merge: add two missing AnnotatedCommit methods --- merge.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/merge.go b/merge.go index bfbf9a3..cdf7f75 100644 --- a/merge.go +++ b/merge.go @@ -27,6 +27,15 @@ func newAnnotatedCommitFromC(ptr *C.git_annotated_commit, r *Repository) *Annota return mh } +func (mh *AnnotatedCommit) Id() *Oid { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := newOidFromC(C.git_annotated_commit_id(mh.ptr)) + runtime.KeepAlive(mh) + return ret +} + func (mh *AnnotatedCommit) Free() { runtime.SetFinalizer(mh, nil) C.git_annotated_commit_free(mh.ptr) @@ -79,6 +88,22 @@ func (r *Repository) AnnotatedCommitFromRef(ref *Reference) (*AnnotatedCommit, e return newAnnotatedCommitFromC(ptr, r), nil } +func (r *Repository) AnnotatedCommitFromRevspec(spec string) (*AnnotatedCommit, error) { + crevspec := C.CString(spec) + defer C.free(unsafe.Pointer(crevspec)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var ptr *C.git_annotated_commit + ret := C.git_annotated_commit_from_revspec(&ptr, r.ptr, crevspec) + runtime.KeepAlive(r) + if ret < 0 { + return nil, MakeGitError(ret) + } + return newAnnotatedCommitFromC(ptr, r), nil +} + type MergeTreeFlag int const ( From 9de57cc90ef4e3d778613ad9eec35dfb9b6b21b2 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 25 Jan 2018 16:43:27 -0800 Subject: [PATCH 06/68] merge: add missing MergeFileFlag constants While we're here, pull in comments as well. While one can pop back and forth between godoc and libgit2 refs, it's much nicer to have it in one place. Note that MergeFileStyleSimplifyAlnum probably should have been called merely MergeFileSimplifyAlnum (no "Style"). It's probably not worth breaking backwards compatibility to fix it, but we avoid the mistake going forwards. --- merge.go | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/merge.go b/merge.go index bfbf9a3..abe1426 100644 --- a/merge.go +++ b/merge.go @@ -344,9 +344,29 @@ type MergeFileFlags int const ( MergeFileDefault MergeFileFlags = C.GIT_MERGE_FILE_DEFAULT - MergeFileStyleMerge MergeFileFlags = C.GIT_MERGE_FILE_STYLE_MERGE - MergeFileStyleDiff MergeFileFlags = C.GIT_MERGE_FILE_STYLE_DIFF3 + // Create standard conflicted merge files + MergeFileStyleMerge MergeFileFlags = C.GIT_MERGE_FILE_STYLE_MERGE + + // Create diff3-style files + MergeFileStyleDiff MergeFileFlags = C.GIT_MERGE_FILE_STYLE_DIFF3 + + // Condense non-alphanumeric regions for simplified diff file MergeFileStyleSimplifyAlnum MergeFileFlags = C.GIT_MERGE_FILE_SIMPLIFY_ALNUM + + // Ignore all whitespace + MergeFileIgnoreWhitespace MergeFileFlags = C.GIT_MERGE_FILE_IGNORE_WHITESPACE + + // Ignore changes in amount of whitespace + MergeFileIgnoreWhitespaceChange MergeFileFlags = C.GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE + + // Ignore whitespace at end of line + MergeFileIgnoreWhitespaceEOL MergeFileFlags = C.GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL + + // Use the "patience diff" algorithm + MergeFileDiffPatience MergeFileFlags = C.GIT_MERGE_FILE_DIFF_PATIENCE + + // Take extra time to find minimal diff + MergeFileDiffMinimal MergeFileFlags = C.GIT_MERGE_FILE_DIFF_MINIMAL ) type MergeFileOptions struct { From fcb86e6f8ec787d7ae1fd8978445da2d33ecef72 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Fri, 9 Feb 2018 07:52:16 +0000 Subject: [PATCH 07/68] tree: keep tree receiver alive as long as dependent entry is used Signed-off-by: Steffen Prohaska --- tree.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tree.go b/tree.go index ee14ec5..02507d2 100644 --- a/tree.go +++ b/tree.go @@ -52,12 +52,13 @@ func (t Tree) EntryByName(filename string) *TreeEntry { defer C.free(unsafe.Pointer(cname)) entry := C.git_tree_entry_byname(t.cast_ptr, cname) - runtime.KeepAlive(t) if entry == nil { return nil } - return newTreeEntry(entry) + goEntry := newTreeEntry(entry) + runtime.KeepAlive(t) + return goEntry } // EntryById performs a lookup for a tree entry with the given SHA value. @@ -71,13 +72,14 @@ func (t Tree) EntryById(id *Oid) *TreeEntry { defer runtime.UnlockOSThread() entry := C.git_tree_entry_byid(t.cast_ptr, id.toC()) - runtime.KeepAlive(t) runtime.KeepAlive(id) if entry == nil { return nil } - return newTreeEntry(entry) + goEntry := newTreeEntry(entry) + runtime.KeepAlive(t) + return goEntry } // EntryByPath looks up an entry by its full path, recursing into @@ -102,12 +104,13 @@ func (t Tree) EntryByPath(path string) (*TreeEntry, error) { func (t Tree) EntryByIndex(index uint64) *TreeEntry { entry := C.git_tree_entry_byindex(t.cast_ptr, C.size_t(index)) - runtime.KeepAlive(t) if entry == nil { return nil } - return newTreeEntry(entry) + goEntry := newTreeEntry(entry) + runtime.KeepAlive(t) + return goEntry } func (t Tree) EntryCount() uint64 { From 589ec2bc28232fc93a404d680a46eb0f7270dcdf Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 15 Feb 2018 09:39:26 -0800 Subject: [PATCH 08/68] reference: minor doc improvements --- reference.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/reference.go b/reference.go index e10c9b2..294c2f3 100644 --- a/reference.go +++ b/reference.go @@ -301,7 +301,7 @@ func (v *Reference) Owner() *Repository { } } -// Cmp compares both references, retursn 0 on equality, otherwise a +// Cmp compares v to ref2. It returns 0 on equality, otherwise a // stable sorting. func (v *Reference) Cmp(ref2 *Reference) int { ret := int(C.git_reference_cmp(v.ptr, ref2.ptr)) @@ -310,13 +310,14 @@ func (v *Reference) Cmp(ref2 *Reference) int { return ret } -// Shorthand ret :=s a "human-readable" short reference name +// Shorthand returns a "human-readable" short reference name. func (v *Reference) Shorthand() string { ret := C.GoString(C.git_reference_shorthand(v.ptr)) runtime.KeepAlive(v) return ret } +// Name returns the full name of v. func (v *Reference) Name() string { ret := C.GoString(C.git_reference_name(v.ptr)) runtime.KeepAlive(v) From b7ca4a96f55c8f5d601ca3a3e55678fca467c641 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 15 Feb 2018 10:01:14 -0800 Subject: [PATCH 09/68] git: simplify some Oid methods --- git.go | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/git.go b/git.go index 0925e45..897d261 100644 --- a/git.go +++ b/git.go @@ -189,22 +189,16 @@ func (oid *Oid) Cmp(oid2 *Oid) int { } func (oid *Oid) Copy() *Oid { - ret := new(Oid) - copy(ret[:], oid[:]) - return ret + ret := *oid + return &ret } func (oid *Oid) Equal(oid2 *Oid) bool { - return bytes.Equal(oid[:], oid2[:]) + return *oid == *oid2 } func (oid *Oid) IsZero() bool { - for _, a := range oid { - if a != 0 { - return false - } - } - return true + return *oid == Oid{} } func (oid *Oid) NCmp(oid2 *Oid, n uint) int { From ec429ccdfc54141e30dd829020fc8fa2927e690c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 22 Feb 2018 09:07:57 +0100 Subject: [PATCH 10/68] vendor: bump libgit2 to 809b0ca6b (v0.27.0-rc1) --- vendor/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libgit2 b/vendor/libgit2 index f1323d9..809b0ca 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit f1323d9c161aeeada190fd9615a8b5a9fb8a7f3e +Subproject commit 809b0ca6b9b6a5648b8e802a9f0c6a0821257595 From b52e13f37dfb80a47b78ca6f95e06b4b27220767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 22 Feb 2018 09:28:49 +0100 Subject: [PATCH 11/68] Switch over the version contraints to v0.27 --- git_dynamic.go | 4 ++-- git_static.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/git_dynamic.go b/git_dynamic.go index 00828a5..0a977e8 100644 --- a/git_dynamic.go +++ b/git_dynamic.go @@ -6,8 +6,8 @@ package git #include #cgo pkg-config: libgit2 -#if LIBGIT2_VER_MAJOR != 0 || LIBGIT2_VER_MINOR != 26 -# error "Invalid libgit2 version; this git2go supports libgit2 v0.26" +#if LIBGIT2_VER_MAJOR != 0 || LIBGIT2_VER_MINOR != 27 +# error "Invalid libgit2 version; this git2go supports libgit2 v0.27" #endif */ diff --git a/git_static.go b/git_static.go index b42d49f..6303734 100644 --- a/git_static.go +++ b/git_static.go @@ -9,8 +9,8 @@ package git #cgo !windows pkg-config: --static ${SRCDIR}/vendor/libgit2/build/libgit2.pc #include -#if LIBGIT2_VER_MAJOR != 0 || LIBGIT2_VER_MINOR != 26 -# error "Invalid libgit2 version; this git2go supports libgit2 v0.26" +#if LIBGIT2_VER_MAJOR != 0 || LIBGIT2_VER_MINOR != 27 +# error "Invalid libgit2 version; this git2go supports libgit2 v0.27" #endif */ From cff71166ec65cee1a070f04ac5c4d10fe3b009d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 22 Feb 2018 09:28:58 +0100 Subject: [PATCH 12/68] Adjust to the change in the git_odb_open_rstream signature --- odb.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/odb.go b/odb.go index 64c5415..f236fc4 100644 --- a/odb.go +++ b/odb.go @@ -182,17 +182,21 @@ func (v *Odb) Hash(data []byte, otype ObjectType) (oid *Oid, err error) { // contents of the object. func (v *Odb) NewReadStream(id *Oid) (*OdbReadStream, error) { stream := new(OdbReadStream) + var ctype C.git_otype + var csize C.size_t runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_odb_open_rstream(&stream.ptr, v.ptr, id.toC()) + ret := C.git_odb_open_rstream(&stream.ptr, &csize, &ctype, v.ptr, id.toC()) runtime.KeepAlive(v) runtime.KeepAlive(id) if ret < 0 { return nil, MakeGitError(ret) } + stream.Size = uint64(csize) + stream.Type = ObjectType(ctype) runtime.SetFinalizer(stream, (*OdbReadStream).Free) return stream, nil } @@ -264,7 +268,9 @@ func (object *OdbObject) Data() (data []byte) { } type OdbReadStream struct { - ptr *C.git_odb_stream + ptr *C.git_odb_stream + Size uint64 + Type ObjectType } // Read reads from the stream From 661e1a6f1b70a3f4837c4aec6a3006dcc5689bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 22 Feb 2018 09:46:42 +0100 Subject: [PATCH 13/68] merge: expose the conflict marker size option --- merge.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/merge.go b/merge.go index bfbf9a3..adc521a 100644 --- a/merge.go +++ b/merge.go @@ -355,6 +355,7 @@ type MergeFileOptions struct { TheirLabel string Favor MergeFileFavor Flags MergeFileFlags + MarkerSize uint16 } func mergeFileOptionsFromC(c C.git_merge_file_options) MergeFileOptions { @@ -364,6 +365,7 @@ func mergeFileOptionsFromC(c C.git_merge_file_options) MergeFileOptions { TheirLabel: C.GoString(c.their_label), Favor: MergeFileFavor(c.favor), Flags: MergeFileFlags(c.flags), + MarkerSize: uint16(c.marker_size), } } @@ -373,6 +375,7 @@ func populateCMergeFileOptions(c *C.git_merge_file_options, options MergeFileOpt c.their_label = C.CString(options.TheirLabel) c.favor = C.git_merge_file_favor_t(options.Favor) c.flags = C.git_merge_file_flag_t(options.Flags) + c.marker_size = C.ushort(options.MarkerSize) } func freeCMergeFileOptions(c *C.git_merge_file_options) { From 304d67b0fb5042f0df73e1868be543c9ecab1026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 26 Mar 2018 12:21:20 +0200 Subject: [PATCH 14/68] vendor: update libgit2 to v0.27.0 --- vendor/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libgit2 b/vendor/libgit2 index 809b0ca..6311e88 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit 809b0ca6b9b6a5648b8e802a9f0c6a0821257595 +Subproject commit 6311e886d8b5377c6037cd9937ccf66a71f3361d From bcb303ad1798b687267f4a2cdfa82b5bb3048d8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 26 Mar 2018 12:35:03 +0200 Subject: [PATCH 15/68] travis: build against Go 1.10 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index dd9f97a..e99fb2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ go: - 1.7 - 1.8 - 1.9 + - 1.10 - tip script: make test-static From 1381380f3450f91b66c7951ad0e40c31acb784a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 26 Mar 2018 12:58:53 +0200 Subject: [PATCH 16/68] travis: let yaml know these strings are strings --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e99fb2b..f611cc3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ go: - 1.7 - 1.8 - 1.9 - - 1.10 + - "1.10" - tip script: make test-static From 925932a54fb021a972c68d6f4b43d31684c1ffb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 29 May 2018 21:09:45 +0200 Subject: [PATCH 17/68] vendor: bump libgit2 to 7f6c1ce9760c6 --- vendor/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libgit2 b/vendor/libgit2 index 6311e88..7f6c1ce 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit 6311e886d8b5377c6037cd9937ccf66a71f3361d +Subproject commit 7f6c1ce9760c6c397e94d4eba506faeb95452702 From a2de5abababeb291f269fe254fc0341e5323af3f Mon Sep 17 00:00:00 2001 From: Michel Lespinasse Date: Wed, 30 May 2018 14:15:59 -0700 Subject: [PATCH 18/68] git2go: fix reference iterator leak This fixes a leak that was apparently introduced in commit 55a109614151. --- reference.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/reference.go b/reference.go index 294c2f3..12ecb74 100644 --- a/reference.go +++ b/reference.go @@ -456,10 +456,12 @@ func (v *ReferenceIterator) Next() (*Reference, error) { } func newReferenceIteratorFromC(ptr *C.git_reference_iterator, r *Repository) *ReferenceIterator { - return &ReferenceIterator{ + iter := &ReferenceIterator{ ptr: ptr, repo: r, } + runtime.SetFinalizer(iter, (*ReferenceIterator).Free) + return iter } // Free the reference iterator From bdca40d27558337f2aa84856b0dd8c6b1b6bb5c8 Mon Sep 17 00:00:00 2001 From: Michel Lespinasse Date: Tue, 3 Jul 2018 16:43:07 -0700 Subject: [PATCH 19/68] git2go: small fixes to odb module - Fix couple cgo issues in odb.Write() and odb.Hash(). This is the same issue - and same solution - as repo.CreateBlobFromBuffer() used to have. - Add test for odb.Read() --- odb.go | 26 ++++++++++++++++++-------- odb_test.go | 33 +++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/odb.go b/odb.go index f236fc4..fa6779f 100644 --- a/odb.go +++ b/odb.go @@ -80,15 +80,19 @@ func (v *Odb) Exists(oid *Oid) bool { func (v *Odb) Write(data []byte, otype ObjectType) (oid *Oid, err error) { oid = new(Oid) - var cptr unsafe.Pointer - if len(data) > 0 { - cptr = unsafe.Pointer(&data[0]) - } runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_odb_write(oid.toC(), v.ptr, cptr, C.size_t(len(data)), C.git_otype(otype)) + var size C.size_t + if len(data) > 0 { + size = C.size_t(len(data)) + } else { + data = []byte{0} + size = C.size_t(0) + } + + ret := C.git_odb_write(oid.toC(), v.ptr, unsafe.Pointer(&data[0]), size, C.git_otype(otype)) runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) @@ -164,13 +168,19 @@ func (v *Odb) ForEach(callback OdbForEachCallback) error { // Hash determines the object-ID (sha1) of a data buffer. func (v *Odb) Hash(data []byte, otype ObjectType) (oid *Oid, err error) { oid = new(Oid) - header := (*reflect.SliceHeader)(unsafe.Pointer(&data)) - ptr := unsafe.Pointer(header.Data) runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_odb_hash(oid.toC(), ptr, C.size_t(header.Len), C.git_otype(otype)) + var size C.size_t + if len(data) > 0 { + size = C.size_t(len(data)) + } else { + data = []byte{0} + size = C.size_t(0) + } + + ret := C.git_odb_hash(oid.toC(), unsafe.Pointer(&data[0]), size, C.git_otype(otype)) runtime.KeepAlive(data) if ret < 0 { return nil, MakeGitError(ret) diff --git a/odb_test.go b/odb_test.go index 3d22fc9..8502c36 100644 --- a/odb_test.go +++ b/odb_test.go @@ -1,12 +1,13 @@ package git import ( + "bytes" "errors" "io" "testing" ) -func TestOdbReadHeader(t *testing.T) { +func TestOdbRead(t *testing.T) { t.Parallel() repo := createTestRepo(t) defer cleanupTestRepo(t, repo) @@ -26,13 +27,27 @@ func TestOdbReadHeader(t *testing.T) { 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) } + + obj, err := odb.Read(id) + if err != nil { + t.Fatalf("Read: %v", err) + } + if !bytes.Equal(obj.Data(), data) { + t.Errorf("Read got wrong data") + } + if sz := obj.Len(); sz != uint64(len(data)) { + t.Errorf("Read got size %d, want %d", sz, len(data)) + } + if typ := obj.Type(); typ != ObjectBlob { + t.Errorf("Read got object type %s", typ) + } } func TestOdbStream(t *testing.T) { @@ -82,14 +97,16 @@ committer John Doe 1390682018 +0000 Initial commit.` - oid, error := odb.Hash([]byte(str), ObjectCommit) - checkFatal(t, error) + for _, data := range [][]byte{[]byte(str), doublePointerBytes()} { + oid, error := odb.Hash(data, ObjectCommit) + checkFatal(t, error) - coid, error := odb.Write([]byte(str), ObjectCommit) - checkFatal(t, error) + coid, error := odb.Write(data, ObjectCommit) + checkFatal(t, error) - if oid.Cmp(coid) != 0 { - t.Fatal("Hash and write Oids are different") + if oid.Cmp(coid) != 0 { + t.Fatal("Hash and write Oids are different") + } } } From d7fd15b1e0fda55c7237609bbdc8caddff49d032 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Thu, 5 Jul 2018 03:50:10 +0000 Subject: [PATCH 20/68] Add support for mempack This allows the creation of git packfiles without needing to write them to the filesystem. --- mempack.go | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 mempack.go diff --git a/mempack.go b/mempack.go new file mode 100644 index 0000000..0b82cd4 --- /dev/null +++ b/mempack.go @@ -0,0 +1,97 @@ +package git + +/* +#include +#include + +extern int git_mempack_new(git_odb_backend **out); +extern int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *backend); +extern void git_mempack_reset(git_odb_backend *backend); +extern void _go_git_odb_backend_free(git_odb_backend *backend); +*/ +import "C" + +import ( + "runtime" + "unsafe" +) + +// Mempack is a custom ODB backend that permits packing object in-memory. +type Mempack struct { + ptr *C.git_odb_backend +} + +// NewMempack creates a new mempack instance and registers it to the ODB. +func NewMempack(odb *Odb) (mempack *Mempack, err error) { + mempack = new(Mempack) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_mempack_new(&mempack.ptr) + if ret < 0 { + return nil, MakeGitError(ret) + } + runtime.SetFinalizer(mempack, (*Mempack).Free) + + ret = C.git_odb_add_backend(odb.ptr, mempack.ptr, C.int(999)) + if ret < 0 { + // Since git_odb_add_alternate() takes ownership of the ODB backend, the + // only case in which we free the mempack's memory is if it fails to be + // added to the ODB. Mempack.Free() is actually just a no-op. + C._go_git_odb_backend_free(mempack.ptr) + mempack.Free() + return nil, MakeGitError(ret) + } + + return mempack, nil +} + +// Dump dumps all the queued in-memory writes to a packfile. +// +// It is the caller's responsibility to ensure that the generated packfile is +// available to the repository (e.g. by writing it to disk, or doing something +// crazy like distributing it across several copies of the repository over a +// network). +// +// Once the generated packfile is available to the repository, call +// Mempack.Reset to cleanup the memory store. +// +// Calling Mempack.Reset before the packfile has been written to disk will +// result in an inconsistent repository (the objects in the memory store won't +// be accessible). +func (mempack *Mempack) Dump(repository *Repository) ([]byte, error) { + buf := C.git_buf{} + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var repoPtr *C.git_repository + if repository != nil { + repoPtr = repository.ptr + } + + ret := C.git_mempack_dump(&buf, repoPtr, mempack.ptr) + if ret < 0 { + return nil, MakeGitError(ret) + } + defer C.git_buf_free(&buf) + + return C.GoBytes(unsafe.Pointer(buf.ptr), C.int(buf.size)), nil +} + +// Reset resets the memory packer by clearing all the queued objects. +// +// This assumes that Mempack.Dump has been called before to store all the +// queued objects into a single packfile. +func (mempack *Mempack) Reset() { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + C.git_mempack_reset(mempack.ptr) +} + +// Free frees the mempack and its resources. +func (mempack *Mempack) Free() { + runtime.SetFinalizer(mempack, nil) +} From 973938cbb5539c7ee7eec3b9895a66f502b16604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 8 Aug 2018 11:45:48 +0200 Subject: [PATCH 21/68] Bump vendored libgit2 to 9275d84c583 --- vendor/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libgit2 b/vendor/libgit2 index 7f6c1ce..9275d84 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit 7f6c1ce9760c6c397e94d4eba506faeb95452702 +Subproject commit 9275d84c583a030e759edbfafacf99c42a83c543 From 538a05d55c6051371dd1749af75a7b2e2d623d53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 8 Aug 2018 11:51:51 +0200 Subject: [PATCH 22/68] Remove uses of deprecated git_buf_free --- branch.go | 4 ++-- commit.go | 4 ++-- config.go | 10 +++++----- describe.go | 2 +- diff.go | 2 +- git.go | 2 +- note.go | 2 +- object.go | 2 +- patch.go | 2 +- settings.go | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/branch.go b/branch.go index d6e7a53..6f79825 100644 --- a/branch.go +++ b/branch.go @@ -208,7 +208,7 @@ func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) { if ret < 0 { return "", MakeGitError(ret) } - defer C.git_buf_free(&nameBuf) + defer C.git_buf_dispose(&nameBuf) return C.GoString(nameBuf.ptr), nil } @@ -256,7 +256,7 @@ func (repo *Repository) UpstreamName(canonicalBranchName string) (string, error) if ret < 0 { return "", MakeGitError(ret) } - defer C.git_buf_free(&nameBuf) + defer C.git_buf_dispose(&nameBuf) return C.GoString(nameBuf.ptr), nil } diff --git a/commit.go b/commit.go index 223b093..0ab720d 100644 --- a/commit.go +++ b/commit.go @@ -37,10 +37,10 @@ func (c *Commit) RawMessage() string { func (c *Commit) ExtractSignature() (string, string, error) { var c_signed C.git_buf - defer C.git_buf_free(&c_signed) + defer C.git_buf_dispose(&c_signed) var c_signature C.git_buf - defer C.git_buf_free(&c_signature) + defer C.git_buf_dispose(&c_signature) oid := c.Id() repo := C.git_commit_owner(c.cast_ptr) diff --git a/config.go b/config.go index ab9af38..8dfe0af 100644 --- a/config.go +++ b/config.go @@ -134,7 +134,7 @@ func (c *Config) LookupString(name string) (string, error) { if ret < 0 { return "", MakeGitError(ret) } - defer C.git_buf_free(&valBuf) + defer C.git_buf_dispose(&valBuf) return C.GoString(valBuf.ptr), nil } @@ -390,7 +390,7 @@ func (iter *ConfigIterator) Free() { func ConfigFindGlobal() (string, error) { var buf C.git_buf - defer C.git_buf_free(&buf) + defer C.git_buf_dispose(&buf) runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -405,7 +405,7 @@ func ConfigFindGlobal() (string, error) { func ConfigFindSystem() (string, error) { var buf C.git_buf - defer C.git_buf_free(&buf) + defer C.git_buf_dispose(&buf) runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -420,7 +420,7 @@ func ConfigFindSystem() (string, error) { func ConfigFindXDG() (string, error) { var buf C.git_buf - defer C.git_buf_free(&buf) + defer C.git_buf_dispose(&buf) runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -438,7 +438,7 @@ func ConfigFindXDG() (string, error) { // Look for the file in %PROGRAMDATA%\Git\config used by portable git. func ConfigFindProgramdata() (string, error) { var buf C.git_buf - defer C.git_buf_free(&buf) + defer C.git_buf_dispose(&buf) runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/describe.go b/describe.go index 0b75076..f7036df 100644 --- a/describe.go +++ b/describe.go @@ -212,7 +212,7 @@ func (result *DescribeResult) Format(opts *DescribeFormatOptions) (string, error if ecode < 0 { return "", MakeGitError(ecode) } - defer C.git_buf_free(&resultBuf) + defer C.git_buf_dispose(&resultBuf) return C.GoString(resultBuf.ptr), nil } diff --git a/diff.go b/diff.go index 3088320..20eb9e8 100644 --- a/diff.go +++ b/diff.go @@ -246,7 +246,7 @@ const ( func (stats *DiffStats) String(format DiffStatsFormat, width uint) (string, error) { buf := C.git_buf{} - defer C.git_buf_free(&buf) + defer C.git_buf_dispose(&buf) runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/git.go b/git.go index 0925e45..a1c07f6 100644 --- a/git.go +++ b/git.go @@ -309,7 +309,7 @@ func Discover(start string, across_fs bool, ceiling_dirs []string) (string, erro defer C.free(unsafe.Pointer(cstart)) var buf C.git_buf - defer C.git_buf_free(&buf) + defer C.git_buf_dispose(&buf) runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/note.go b/note.go index 21bed57..9df1b9d 100644 --- a/note.go +++ b/note.go @@ -132,7 +132,7 @@ func (c *NoteCollection) DefaultRef() (string, error) { } ret := C.GoString(buf.ptr) - C.git_buf_free(&buf) + C.git_buf_dispose(&buf) return ret, nil } diff --git a/object.go b/object.go index 5505e35..66a4618 100644 --- a/object.go +++ b/object.go @@ -67,7 +67,7 @@ func (o *Object) ShortId() (string, error) { if ecode < 0 { return "", MakeGitError(ecode) } - defer C.git_buf_free(&resultBuf) + defer C.git_buf_dispose(&resultBuf) return C.GoString(resultBuf.ptr), nil } diff --git a/patch.go b/patch.go index 7e6f71d..6a16b5f 100644 --- a/patch.go +++ b/patch.go @@ -51,7 +51,7 @@ func (patch *Patch) String() (string, error) { if ecode < 0 { return "", MakeGitError(ecode) } - defer C.git_buf_free(&buf) + defer C.git_buf_dispose(&buf) return C.GoString(buf.ptr), nil } diff --git a/settings.go b/settings.go index c7f1850..b9bc216 100644 --- a/settings.go +++ b/settings.go @@ -31,7 +31,7 @@ import ( func SearchPath(level ConfigLevel) (string, error) { var buf C.git_buf - defer C.git_buf_free(&buf) + defer C.git_buf_dispose(&buf) runtime.LockOSThread() defer runtime.UnlockOSThread() From b3256d9058aa93176190cb69f73afb72f0730100 Mon Sep 17 00:00:00 2001 From: Ryan Graham Date: Tue, 8 May 2018 15:47:34 -0700 Subject: [PATCH 23/68] static: use pkg-config exclusively when using it When using the static linking option on platforms that use pkg-config, use ONLY pkg-config to get the CFLAGS and LDFLAGS. This prevents pulling in dependencies and flags for any non-vendored version that may be present on the host. The main practical effect of this is that if someone doesn't need/want any sort of remote access support at all they can completely disable libcurl, libssh2, libssl, etc and produce a smaller/simpler binary and greatly simplify their build-time dependencies. When done properly, the generated pkg-config file will tell cgo everything it needs to know. This also prevents confusion if there is a system copy of libgit2 that is being given priority over the vendored build. Signed-off-by: Ryan Graham --- git_static.go | 5 ++--- script/build-libgit2-static.sh | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/git_static.go b/git_static.go index 6303734..243669f 100644 --- a/git_static.go +++ b/git_static.go @@ -3,9 +3,8 @@ package git /* -#cgo CFLAGS: -I${SRCDIR}/vendor/libgit2/include -#cgo LDFLAGS: -L${SRCDIR}/vendor/libgit2/build/ -lgit2 -#cgo windows LDFLAGS: -lwinhttp +#cgo windows CFLAGS: -I${SRCDIR}/vendor/libgit2/include +#cgo windows LDFLAGS: -L${SRCDIR}/vendor/libgit2/build/ -lgit2 -lwinhttp #cgo !windows pkg-config: --static ${SRCDIR}/vendor/libgit2/build/libgit2.pc #include diff --git a/script/build-libgit2-static.sh b/script/build-libgit2-static.sh index 5723721..1568ece 100755 --- a/script/build-libgit2-static.sh +++ b/script/build-libgit2-static.sh @@ -16,4 +16,4 @@ cmake -DTHREADSAFE=ON \ -DCMAKE_INSTALL_PREFIX=../install \ .. && -cmake --build . +cmake --build . --target install From 92501bd663509b4fd3c4796ff99d056eb8818fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 7 Oct 2018 18:50:25 +0200 Subject: [PATCH 24/68] Update vendored libgit2 to 838a2f291 --- vendor/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libgit2 b/vendor/libgit2 index 9275d84..838a2f2 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit 9275d84c583a030e759edbfafacf99c42a83c543 +Subproject commit 838a2f2918b6d9fad8768d2498575ff5d75c35f0 From dd973b99ad050eae73c3cc3deac162e797c6f530 Mon Sep 17 00:00:00 2001 From: Melvin Date: Thu, 25 Oct 2018 15:13:32 -0700 Subject: [PATCH 25/68] Add index.Clear() to clear the index object --- index.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/index.go b/index.go index 5106516..dd13460 100644 --- a/index.go +++ b/index.go @@ -145,6 +145,20 @@ func (v *Index) Path() string { return ret } +// Clear clears the index object in memory; changes must be explicitly +// written to disk for them to take effect persistently +func (v *Index) Clear() error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := C.git_index_clear(v.ptr) + runtime.KeepAlive(v) + if err < 0 { + return MakeGitError(err) + } + return nil +} + // Add adds or replaces the given entry to the index, making a copy of // the data func (v *Index) Add(entry *IndexEntry) error { From 8ff5e4371117994a7d9061128837f8c73317c527 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sat, 18 Aug 2018 00:46:30 +0000 Subject: [PATCH 26/68] Add support for CreateCommitFromIds This change adds support for CreateCommitFromIds from libgit2. --- repository.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/repository.go b/repository.go index d8de97a..a430751 100644 --- a/repository.go +++ b/repository.go @@ -3,6 +3,8 @@ package git /* #include #include +#include +#include */ import "C" import ( @@ -389,6 +391,66 @@ func (v *Repository) CreateCommit( return oid, nil } +func (v *Repository) CreateCommitFromIds( + refname string, author, committer *Signature, + message string, tree *Oid, parents ...*Oid) (*Oid, error) { + + oid := new(Oid) + + var cref *C.char + if refname == "" { + cref = nil + } else { + cref = C.CString(refname) + defer C.free(unsafe.Pointer(cref)) + } + + cmsg := C.CString(message) + defer C.free(unsafe.Pointer(cmsg)) + + var parentsarg **C.git_oid = nil + + nparents := len(parents) + if nparents > 0 { + parentsarg = (**C.git_oid)(C.malloc(C.size_t(unsafe.Sizeof(uintptr(0)) * uintptr(nparents)))) + defer C.free(unsafe.Pointer(parentsarg)) + parentsptr := uintptr(unsafe.Pointer(parentsarg)) + for _, v := range parents { + *(**C.git_oid)(unsafe.Pointer(parentsptr)) = v.toC() + parentsptr += unsafe.Sizeof(uintptr(0)) + } + } + + authorSig, err := author.toC() + if err != nil { + return nil, err + } + defer C.git_signature_free(authorSig) + + committerSig, err := committer.toC() + if err != nil { + return nil, err + } + defer C.git_signature_free(committerSig) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_commit_create_from_ids( + oid.toC(), v.ptr, cref, + authorSig, committerSig, + nil, cmsg, tree.toC(), C.size_t(nparents), parentsarg) + + runtime.KeepAlive(v) + runtime.KeepAlive(oid) + runtime.KeepAlive(parents) + if ret < 0 { + return nil, MakeGitError(ret) + } + + return oid, nil +} + func (v *Odb) Free() { runtime.SetFinalizer(v, nil) C.git_odb_free(v.ptr) From 8d27336e8a158dccc55c966f57ff7e90acce1614 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Thu, 15 Nov 2018 02:27:03 +0000 Subject: [PATCH 27/68] Add support for Packbuilder.InsertFromWalk() This change adds support for Packbuilder.InsertFromWalk() from libgit2. --- packbuilder.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packbuilder.go b/packbuilder.go index 0e04bbf..576e5ca 100644 --- a/packbuilder.go +++ b/packbuilder.go @@ -85,6 +85,19 @@ func (pb *Packbuilder) InsertTree(id *Oid) error { return nil } +func (pb *Packbuilder) InsertWalk(walk *RevWalk) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_packbuilder_insert_walk(pb.ptr, walk.ptr) + runtime.KeepAlive(pb) + runtime.KeepAlive(walk) + if ret != 0 { + return MakeGitError(ret) + } + return nil +} + func (pb *Packbuilder) ObjectCount() uint32 { ret := uint32(C.git_packbuilder_object_count(pb.ptr)) runtime.KeepAlive(pb) From a2ac1b9ed115b7576b59a3f54abe3a93ce24d44e Mon Sep 17 00:00:00 2001 From: Will Medlar <5326769+wmedlar@users.noreply.github.com> Date: Mon, 17 Dec 2018 01:56:37 -0600 Subject: [PATCH 28/68] Fix typo in constant name --- checkout.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkout.go b/checkout.go index db3118f..2b12058 100644 --- a/checkout.go +++ b/checkout.go @@ -35,7 +35,7 @@ const ( CheckoutDontUpdateIndex CheckoutStrategy = C.GIT_CHECKOUT_DONT_UPDATE_INDEX // Normally checkout updates index entries as it goes; this stops that CheckoutNoRefresh CheckoutStrategy = C.GIT_CHECKOUT_NO_REFRESH // Don't refresh index/config/etc before doing checkout CheckoutSkipUnmerged CheckoutStrategy = C.GIT_CHECKOUT_SKIP_UNMERGED // Allow checkout to skip unmerged files - CheckoutUserOurs CheckoutStrategy = C.GIT_CHECKOUT_USE_OURS // For unmerged files, checkout stage 2 from index + CheckoutUseOurs CheckoutStrategy = C.GIT_CHECKOUT_USE_OURS // For unmerged files, checkout stage 2 from index CheckoutUseTheirs CheckoutStrategy = C.GIT_CHECKOUT_USE_THEIRS // For unmerged files, checkout stage 3 from index CheckoutDisablePathspecMatch CheckoutStrategy = C.GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH // Treat pathspec as simple list of exact match file paths CheckoutSkipLockedDirectories CheckoutStrategy = C.GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES // Ignore directories in use, they will be left empty From 92ebf4515c770993205757f98e3e7d4fa6f69166 Mon Sep 17 00:00:00 2001 From: praveen Date: Tue, 25 Dec 2018 08:27:32 +0530 Subject: [PATCH 29/68] Remove unused parameter in OpenOndisk --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index 8dfe0af..7260089 100644 --- a/config.go +++ b/config.go @@ -344,7 +344,7 @@ func (c *Config) OpenLevel(parent *Config, level ConfigLevel) (*Config, error) { } // OpenOndisk creates a new config instance containing a single on-disk file -func OpenOndisk(parent *Config, path string) (*Config, error) { +func OpenOndisk(path string) (*Config, error) { cpath := C.CString(path) defer C.free(unsafe.Pointer(cpath)) From e0ad45065e7ae240cba5fa0a3cbe5c2ee1df85f7 Mon Sep 17 00:00:00 2001 From: praveen Date: Tue, 25 Dec 2018 08:44:01 +0530 Subject: [PATCH 30/68] Fixed issues with tests --- config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_test.go b/config_test.go index 196d4ad..398236e 100644 --- a/config_test.go +++ b/config_test.go @@ -13,7 +13,7 @@ func setupConfig() (*Config, error) { err error ) - c, err = OpenOndisk(nil, tempConfig) + c, err = OpenOndisk(tempConfig) if err != nil { return nil, err } From 344dc33faef98cb383ec0858e33b1aea695cbc1e Mon Sep 17 00:00:00 2001 From: lhchavez Date: Fri, 28 Dec 2018 04:29:20 +0000 Subject: [PATCH 31/68] Return io.EOF on OdbReadStream.Read() This change makes OdbReadStream.Read() comply with the usual io.Reader semantics. --- odb.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/odb.go b/odb.go index f236fc4..fd27363 100644 --- a/odb.go +++ b/odb.go @@ -8,6 +8,7 @@ extern void _go_git_odb_backend_free(git_odb_backend *backend); */ import "C" import ( + "io" "reflect" "runtime" "unsafe" @@ -287,6 +288,9 @@ func (stream *OdbReadStream) Read(data []byte) (int, error) { if ret < 0 { return 0, MakeGitError(ret) } + if ret == 0 { + return 0, io.EOF + } header.Len = int(ret) From ab3470030be17e024c96b7f00c757f8343ca70f5 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Fri, 28 Dec 2018 04:42:09 +0000 Subject: [PATCH 32/68] Add some tests This should prevent regressions in the future. --- odb_test.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/odb_test.go b/odb_test.go index 3d22fc9..090bdf6 100644 --- a/odb_test.go +++ b/odb_test.go @@ -3,6 +3,7 @@ package git import ( "errors" "io" + "io/ioutil" "testing" ) @@ -26,7 +27,7 @@ func TestOdbReadHeader(t *testing.T) { if err != nil { t.Fatalf("ReadHeader: %v", err) } - + if sz != uint64(len(data)) { t.Errorf("ReadHeader got size %d, want %d", sz, len(data)) } @@ -47,22 +48,29 @@ func TestOdbStream(t *testing.T) { str := "hello, world!" - stream, error := odb.NewWriteStream(int64(len(str)), ObjectBlob) + writeStream, error := odb.NewWriteStream(int64(len(str)), ObjectBlob) checkFatal(t, error) - n, error := io.WriteString(stream, str) + n, error := io.WriteString(writeStream, str) checkFatal(t, error) if n != len(str) { t.Fatalf("Bad write length %v != %v", n, len(str)) } - error = stream.Close() + error = writeStream.Close() checkFatal(t, error) expectedId, error := NewOid("30f51a3fba5274d53522d0f19748456974647b4f") checkFatal(t, error) - if stream.Id.Cmp(expectedId) != 0 { + if writeStream.Id.Cmp(expectedId) != 0 { t.Fatal("Wrong data written") } + + readStream, error := odb.NewReadStream(&writeStream.Id) + checkFatal(t, error) + data, error := ioutil.ReadAll(readStream) + if str != string(data) { + t.Fatalf("Wrong data read %v != %v", str, string(data)) + } } func TestOdbHash(t *testing.T) { From f969cc900dde4ba92c814823bc004bd1870079a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 4 Jan 2019 13:18:54 +0000 Subject: [PATCH 33/68] Bump vendored libgit2 to fba70a9d5f This includes updating the `Index.WriteTreeTo` test as it was abusing an oversight of the object creation safety checks and creating a tree referencing a non-existent blob. Instead we update it to the primary purpose of this method which is to write into a repository from an unattached index. --- index_test.go | 26 +++++++++++++++++++++----- vendor/libgit2 | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/index_test.go b/index_test.go index f47dace..43644fa 100644 --- a/index_test.go +++ b/index_test.go @@ -3,6 +3,7 @@ package git import ( "io/ioutil" "os" + "path" "runtime" "testing" ) @@ -59,14 +60,29 @@ func TestIndexWriteTreeTo(t *testing.T) { repo := createTestRepo(t) defer cleanupTestRepo(t, repo) - repo2 := createTestRepo(t) - defer cleanupTestRepo(t, repo2) + idx, err := NewIndex() + checkFatal(t, err) - idx, err := repo.Index() + odb, err := repo.Odb() checkFatal(t, err) - err = idx.AddByPath("README") + + content, err := ioutil.ReadFile(path.Join(repo.Workdir(), "README")) checkFatal(t, err) - treeId, err := idx.WriteTreeTo(repo2) + + id, err := odb.Write(content, ObjectBlob) + checkFatal(t, err) + + err = idx.Add(&IndexEntry{ + Mode: FilemodeBlob, + Uid: 0, + Gid: 0, + Size: uint32(len(content)), + Id: id, + Path: "README", + }) + checkFatal(t, err) + + treeId, err := idx.WriteTreeTo(repo) checkFatal(t, err) if treeId.String() != "b7119b11e8ef7a1a5a34d3ac87f5b075228ac81e" { diff --git a/vendor/libgit2 b/vendor/libgit2 index 838a2f2..fba70a9 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit 838a2f2918b6d9fad8768d2498575ff5d75c35f0 +Subproject commit fba70a9d5f1fa433968a3dfd51e3153c8eebe834 From ee6dff2f8e3b130dee5e888f18cae0f74c35e8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 5 Jan 2019 10:45:30 +0000 Subject: [PATCH 34/68] Use git_object_t instead of deprecated git_otype --- object.go | 14 +++++++------- odb.go | 12 ++++++------ reference.go | 2 +- repository.go | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/object.go b/object.go index 66a4618..40ab2bf 100644 --- a/object.go +++ b/object.go @@ -13,12 +13,12 @@ import ( type ObjectType int const ( - ObjectAny ObjectType = C.GIT_OBJ_ANY - ObjectBad ObjectType = C.GIT_OBJ_BAD - ObjectCommit ObjectType = C.GIT_OBJ_COMMIT - ObjectTree ObjectType = C.GIT_OBJ_TREE - ObjectBlob ObjectType = C.GIT_OBJ_BLOB - ObjectTag ObjectType = C.GIT_OBJ_TAG + ObjectAny ObjectType = C.GIT_OBJECT_ANY + ObjectBad ObjectType = C.GIT_OBJECT_BAD + ObjectCommit ObjectType = C.GIT_OBJECT_COMMIT + ObjectTree ObjectType = C.GIT_OBJECT_TREE + ObjectBlob ObjectType = C.GIT_OBJECT_BLOB + ObjectTag ObjectType = C.GIT_OBJECT_TAG ) type Object struct { @@ -217,7 +217,7 @@ func (o *Object) Peel(t ObjectType) (*Object, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - err := C.git_object_peel(&cobj, o.ptr, C.git_otype(t)) + err := C.git_object_peel(&cobj, o.ptr, C.git_object_t(t)) runtime.KeepAlive(o) if err < 0 { return nil, MakeGitError(err) diff --git a/odb.go b/odb.go index 7ae108a..5768cf4 100644 --- a/odb.go +++ b/odb.go @@ -61,12 +61,12 @@ func (v *Odb) ReadHeader(oid *Oid) (uint64, ObjectType, error) { defer runtime.UnlockOSThread() var sz C.size_t - var cotype C.git_otype + var cotype C.git_object_t ret := C.git_odb_read_header(&sz, &cotype, v.ptr, oid.toC()) runtime.KeepAlive(v) if ret < 0 { - return 0, C.GIT_OBJ_BAD, MakeGitError(ret) + return 0, ObjectBad, MakeGitError(ret) } return uint64(sz), ObjectType(cotype), nil @@ -93,7 +93,7 @@ func (v *Odb) Write(data []byte, otype ObjectType) (oid *Oid, err error) { size = C.size_t(0) } - ret := C.git_odb_write(oid.toC(), v.ptr, unsafe.Pointer(&data[0]), size, C.git_otype(otype)) + ret := C.git_odb_write(oid.toC(), v.ptr, unsafe.Pointer(&data[0]), size, C.git_object_t(otype)) runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) @@ -181,7 +181,7 @@ func (v *Odb) Hash(data []byte, otype ObjectType) (oid *Oid, err error) { size = C.size_t(0) } - ret := C.git_odb_hash(oid.toC(), unsafe.Pointer(&data[0]), size, C.git_otype(otype)) + ret := C.git_odb_hash(oid.toC(), unsafe.Pointer(&data[0]), size, C.git_object_t(otype)) runtime.KeepAlive(data) if ret < 0 { return nil, MakeGitError(ret) @@ -193,7 +193,7 @@ func (v *Odb) Hash(data []byte, otype ObjectType) (oid *Oid, err error) { // contents of the object. func (v *Odb) NewReadStream(id *Oid) (*OdbReadStream, error) { stream := new(OdbReadStream) - var ctype C.git_otype + var ctype C.git_object_t var csize C.size_t runtime.LockOSThread() @@ -221,7 +221,7 @@ func (v *Odb) NewWriteStream(size int64, otype ObjectType) (*OdbWriteStream, err runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.git_off_t(size), C.git_otype(otype)) + ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.git_off_t(size), C.git_object_t(otype)) runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) diff --git a/reference.go b/reference.go index 12ecb74..b5f5e47 100644 --- a/reference.go +++ b/reference.go @@ -284,7 +284,7 @@ func (v *Reference) Peel(t ObjectType) (*Object, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - err := C.git_reference_peel(&cobj, v.ptr, C.git_otype(t)) + err := C.git_reference_peel(&cobj, v.ptr, C.git_object_t(t)) runtime.KeepAlive(v) if err < 0 { return nil, MakeGitError(err) diff --git a/repository.go b/repository.go index d8de97a..74924b7 100644 --- a/repository.go +++ b/repository.go @@ -174,7 +174,7 @@ func (v *Repository) lookupType(id *Oid, t ObjectType) (*Object, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_object_lookup(&ptr, v.ptr, id.toC(), C.git_otype(t)) + ret := C.git_object_lookup(&ptr, v.ptr, id.toC(), C.git_object_t(t)) runtime.KeepAlive(id) if ret < 0 { return nil, MakeGitError(ret) From f3c487966d53ad78e25d2e6750414009f5606dbb Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sat, 5 Jan 2019 20:13:01 +0000 Subject: [PATCH 35/68] Improve the static build script This change: * Uses the installed version of both the library and the pkgconfig file, which fixes path resolution on Ubuntu Xenial. * Uses quoting liberally so that paths with spaces in them are correctly handled. * Moves the build+install directories to static-build/ in the git2go repository to avoid having a dirty vendor/libgit2 checkout. --- .gitignore | 1 + git_static.go | 6 +++--- script/build-libgit2-static.sh | 15 ++++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..edc18d5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/static-build/ diff --git a/git_static.go b/git_static.go index 243669f..547ae8a 100644 --- a/git_static.go +++ b/git_static.go @@ -3,9 +3,9 @@ package git /* -#cgo windows CFLAGS: -I${SRCDIR}/vendor/libgit2/include -#cgo windows LDFLAGS: -L${SRCDIR}/vendor/libgit2/build/ -lgit2 -lwinhttp -#cgo !windows pkg-config: --static ${SRCDIR}/vendor/libgit2/build/libgit2.pc +#cgo windows CFLAGS: -I${SRCDIR}/static-build/install/include/ +#cgo windows LDFLAGS: -L${SRCDIR}/static-build/install/lib/ -lgit2 -lwinhttp +#cgo !windows pkg-config: --static ${SRCDIR}/static-build/install/lib/pkgconfig/libgit2.pc #include #if LIBGIT2_VER_MAJOR != 0 || LIBGIT2_VER_MINOR != 27 diff --git a/script/build-libgit2-static.sh b/script/build-libgit2-static.sh index 1568ece..680dd93 100755 --- a/script/build-libgit2-static.sh +++ b/script/build-libgit2-static.sh @@ -2,18 +2,19 @@ set -ex -VENDORED_PATH=vendor/libgit2 +ROOT="$(cd "$0/../.." && echo "${PWD}")" +BUILD_PATH="${ROOT}/static-build" +VENDORED_PATH="${ROOT}/vendor/libgit2" -cd $VENDORED_PATH && -mkdir -p install/lib && -mkdir -p build && -cd build && +mkdir -p "${BUILD_PATH}/build" "${BUILD_PATH}/install/lib" + +cd "${BUILD_PATH}/build" && cmake -DTHREADSAFE=ON \ -DBUILD_CLAR=OFF \ -DBUILD_SHARED_LIBS=OFF \ -DCMAKE_C_FLAGS=-fPIC \ -DCMAKE_BUILD_TYPE="RelWithDebInfo" \ - -DCMAKE_INSTALL_PREFIX=../install \ - .. && + -DCMAKE_INSTALL_PREFIX="${BUILD_PATH}/install" \ + "${VENDORED_PATH}" && cmake --build . --target install From e9856f2c38b4cf74341dd9706bff79d95ff9cb21 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sat, 5 Jan 2019 21:42:49 +0000 Subject: [PATCH 36/68] Clean up one leaked temporary directory A `defer cleanupTestRepo()` was missing. --- reset_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/reset_test.go b/reset_test.go index 45777e4..89ebc49 100644 --- a/reset_test.go +++ b/reset_test.go @@ -8,6 +8,8 @@ import ( func TestResetToCommit(t *testing.T) { t.Parallel() repo := createTestRepo(t) + defer cleanupTestRepo(t, repo) + seedTestRepo(t, repo) // create commit to reset to commitId, _ := updateReadme(t, repo, "testing reset") From 30c57ff09ef08b4019701320f328b3587e326df0 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sun, 6 Jan 2019 07:34:50 -0800 Subject: [PATCH 37/68] Add support for Go 1.11 modules This change adds a `go.mod` file. An empty file is sufficient since this project has no external dependencies. For people that want to use the static version of libgit2, this module can be vendored and the following can be added to their `go.mod` file: replace github.com/libgit2/git2go => ./vendor/github.com/libgit2/git2go --- go.mod | 1 + 1 file changed, 1 insertion(+) create mode 100644 go.mod diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..688b8e3 --- /dev/null +++ b/go.mod @@ -0,0 +1 @@ +module github.com/libgit2/git2go From a2c93a0bcf63c88f9324333f7f3f6a204a817617 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Tue, 8 Jan 2019 02:45:04 +0000 Subject: [PATCH 38/68] Addressed review feedback and added a test --- mempack.go | 22 ++++-------------- mempack_test.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 mempack_test.go diff --git a/mempack.go b/mempack.go index 0b82cd4..72a3df5 100644 --- a/mempack.go +++ b/mempack.go @@ -32,15 +32,13 @@ func NewMempack(odb *Odb) (mempack *Mempack, err error) { if ret < 0 { return nil, MakeGitError(ret) } - runtime.SetFinalizer(mempack, (*Mempack).Free) ret = C.git_odb_add_backend(odb.ptr, mempack.ptr, C.int(999)) if ret < 0 { // Since git_odb_add_alternate() takes ownership of the ODB backend, the // only case in which we free the mempack's memory is if it fails to be - // added to the ODB. Mempack.Free() is actually just a no-op. + // added to the ODB. C._go_git_odb_backend_free(mempack.ptr) - mempack.Free() return nil, MakeGitError(ret) } @@ -66,16 +64,12 @@ func (mempack *Mempack) Dump(repository *Repository) ([]byte, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - var repoPtr *C.git_repository - if repository != nil { - repoPtr = repository.ptr - } - - ret := C.git_mempack_dump(&buf, repoPtr, mempack.ptr) + ret := C.git_mempack_dump(&buf, repository.ptr, mempack.ptr) + runtime.KeepAlive(repository) if ret < 0 { return nil, MakeGitError(ret) } - defer C.git_buf_free(&buf) + defer C.git_buf_dispose(&buf) return C.GoBytes(unsafe.Pointer(buf.ptr), C.int(buf.size)), nil } @@ -85,13 +79,5 @@ func (mempack *Mempack) Dump(repository *Repository) ([]byte, error) { // This assumes that Mempack.Dump has been called before to store all the // queued objects into a single packfile. func (mempack *Mempack) Reset() { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - C.git_mempack_reset(mempack.ptr) } - -// Free frees the mempack and its resources. -func (mempack *Mempack) Free() { - runtime.SetFinalizer(mempack, nil) -} diff --git a/mempack_test.go b/mempack_test.go new file mode 100644 index 0000000..3e31dcf --- /dev/null +++ b/mempack_test.go @@ -0,0 +1,60 @@ +package git + +import ( + "bytes" + "testing" +) + +func TestMempack(t *testing.T) { + t.Parallel() + + odb, err := NewOdb() + checkFatal(t, err) + + repo, err := NewRepositoryWrapOdb(odb) + checkFatal(t, err) + + mempack, err := NewMempack(odb) + checkFatal(t, err) + + id, err := odb.Write([]byte("hello, world!"), ObjectBlob) + checkFatal(t, err) + + expectedId, err := NewOid("30f51a3fba5274d53522d0f19748456974647b4f") + checkFatal(t, err) + if !expectedId.Equal(id) { + t.Errorf("mismatched id. expected %v, got %v", expectedId.String(), id.String()) + } + + // The object should be available from the odb. + { + obj, err := odb.Read(expectedId) + checkFatal(t, err) + defer obj.Free() + } + + data, err := mempack.Dump(repo) + checkFatal(t, err) + + expectedData := []byte{ + 0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x9d, 0x08, 0x82, 0x3b, 0xd8, 0xa8, 0xea, 0xb5, 0x10, 0xad, 0x6a, + 0xc7, 0x5c, 0x82, 0x3c, 0xfd, 0x3e, 0xd3, 0x1e, + } + if !bytes.Equal(expectedData, data) { + t.Errorf("mismatched mempack data. expected %v, got %v", expectedData, data) + } + + mempack.Reset() + + // After the reset, the object should now be unavailable. + { + obj, err := odb.Read(expectedId) + if err == nil { + t.Errorf("object %s unexpectedly found", obj.Id().String()) + obj.Free() + } else if !IsErrorCode(err, ErrNotFound) { + t.Errorf("unexpected error %v", err) + } + } +} From f505e39c9eac64264d6341cc925c5fa7f67b56cf Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sat, 5 Jan 2019 20:13:01 +0000 Subject: [PATCH 39/68] Add a test and some comments as to the ugly pointer arithmetic --- repository.go | 11 +++++++++-- repository_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 repository_test.go diff --git a/repository.go b/repository.go index a430751..30673a7 100644 --- a/repository.go +++ b/repository.go @@ -412,12 +412,19 @@ func (v *Repository) CreateCommitFromIds( nparents := len(parents) if nparents > 0 { - parentsarg = (**C.git_oid)(C.malloc(C.size_t(unsafe.Sizeof(uintptr(0)) * uintptr(nparents)))) + // All this awful pointer arithmetic is needed to avoid passing a Go + // pointer to Go pointer into C. Other methods (like CreateCommits) are + // fine without this workaround because they are just passing Go pointers + // to C pointers, but arrays-of-pointers-to-git_oid are a bit special since + // both the array and the objects are allocated from Go. + var emptyOidPtr *C.git_oid + sizeofOidPtr := unsafe.Sizeof(emptyOidPtr) + parentsarg = (**C.git_oid)(C.calloc(C.size_t(uintptr(nparents)), C.size_t(sizeofOidPtr))) defer C.free(unsafe.Pointer(parentsarg)) parentsptr := uintptr(unsafe.Pointer(parentsarg)) for _, v := range parents { *(**C.git_oid)(unsafe.Pointer(parentsptr)) = v.toC() - parentsptr += unsafe.Sizeof(uintptr(0)) + parentsptr += sizeofOidPtr } } diff --git a/repository_test.go b/repository_test.go new file mode 100644 index 0000000..1950c69 --- /dev/null +++ b/repository_test.go @@ -0,0 +1,42 @@ +package git + +import ( + "testing" + "time" +) + +func TestCreateCommitFromIds(t *testing.T) { + t.Parallel() + repo := createTestRepo(t) + defer cleanupTestRepo(t, repo) + + loc, err := time.LoadLocation("Europe/Berlin") + checkFatal(t, err) + sig := &Signature{ + Name: "Rand Om Hacker", + Email: "random@hacker.com", + When: time.Date(2013, 03, 06, 14, 30, 0, 0, loc), + } + + idx, err := repo.Index() + checkFatal(t, err) + err = idx.AddByPath("README") + checkFatal(t, err) + err = idx.Write() + checkFatal(t, err) + treeId, err := idx.WriteTree() + checkFatal(t, err) + + message := "This is a commit\n" + tree, err := repo.LookupTree(treeId) + checkFatal(t, err) + expectedCommitId, err := repo.CreateCommit("HEAD", sig, sig, message, tree) + checkFatal(t, err) + + commitId, err := repo.CreateCommitFromIds("", sig, sig, message, treeId) + checkFatal(t, err) + + if !expectedCommitId.Equal(commitId) { + t.Errorf("mismatched commit ids, expected %v, got %v", expectedCommitId.String(), commitId.String()) + } +} From 35518c78df9ae727651212512bfaa1a8dae02585 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Tue, 8 Jan 2019 02:50:42 +0000 Subject: [PATCH 40/68] Keeping the tree alive --- repository.go | 1 + 1 file changed, 1 insertion(+) diff --git a/repository.go b/repository.go index 30673a7..2a4e9c8 100644 --- a/repository.go +++ b/repository.go @@ -450,6 +450,7 @@ func (v *Repository) CreateCommitFromIds( runtime.KeepAlive(v) runtime.KeepAlive(oid) + runtime.KeepAlive(tree) runtime.KeepAlive(parents) if ret < 0 { return nil, MakeGitError(ret) From f4ea2a561da9868efc670467061129ac6e53825d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 15 Jan 2019 20:28:36 +0100 Subject: [PATCH 41/68] Keep odb alive when adding mempack --- mempack.go | 1 + 1 file changed, 1 insertion(+) diff --git a/mempack.go b/mempack.go index 72a3df5..337e67d 100644 --- a/mempack.go +++ b/mempack.go @@ -34,6 +34,7 @@ func NewMempack(odb *Odb) (mempack *Mempack, err error) { } ret = C.git_odb_add_backend(odb.ptr, mempack.ptr, C.int(999)) + runtime.KeepAlive(odb) if ret < 0 { // Since git_odb_add_alternate() takes ownership of the ODB backend, the // only case in which we free the mempack's memory is if it fails to be From 5fda6dd90191b1c51a1785ad7cabd2fd5b05e802 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sat, 12 Jan 2019 21:21:20 +0000 Subject: [PATCH 42/68] Uprev vendored libgit2 to v0.28 New version is here! --- git_static.go | 4 ++-- object.go | 16 ++++++++-------- odb.go | 2 +- vendor/libgit2 | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/git_static.go b/git_static.go index 547ae8a..d7c2295 100644 --- a/git_static.go +++ b/git_static.go @@ -8,8 +8,8 @@ package git #cgo !windows pkg-config: --static ${SRCDIR}/static-build/install/lib/pkgconfig/libgit2.pc #include -#if LIBGIT2_VER_MAJOR != 0 || LIBGIT2_VER_MINOR != 27 -# error "Invalid libgit2 version; this git2go supports libgit2 v0.27" +#if LIBGIT2_VER_MAJOR != 0 || LIBGIT2_VER_MINOR != 28 +# error "Invalid libgit2 version; this git2go supports libgit2 v0.28" #endif */ diff --git a/object.go b/object.go index 40ab2bf..2d75b06 100644 --- a/object.go +++ b/object.go @@ -13,12 +13,12 @@ import ( type ObjectType int const ( - ObjectAny ObjectType = C.GIT_OBJECT_ANY - ObjectBad ObjectType = C.GIT_OBJECT_BAD - ObjectCommit ObjectType = C.GIT_OBJECT_COMMIT - ObjectTree ObjectType = C.GIT_OBJECT_TREE - ObjectBlob ObjectType = C.GIT_OBJECT_BLOB - ObjectTag ObjectType = C.GIT_OBJECT_TAG + ObjectAny ObjectType = C.GIT_OBJECT_ANY + ObjectInvalid ObjectType = C.GIT_OBJECT_INVALID + ObjectCommit ObjectType = C.GIT_OBJECT_COMMIT + ObjectTree ObjectType = C.GIT_OBJECT_TREE + ObjectBlob ObjectType = C.GIT_OBJECT_BLOB + ObjectTag ObjectType = C.GIT_OBJECT_TAG ) type Object struct { @@ -35,8 +35,8 @@ func (t ObjectType) String() string { switch t { case ObjectAny: return "Any" - case ObjectBad: - return "Bad" + case ObjectInvalid: + return "Invalid" case ObjectCommit: return "Commit" case ObjectTree: diff --git a/odb.go b/odb.go index 5768cf4..fec0eb9 100644 --- a/odb.go +++ b/odb.go @@ -66,7 +66,7 @@ func (v *Odb) ReadHeader(oid *Oid) (uint64, ObjectType, error) { ret := C.git_odb_read_header(&sz, &cotype, v.ptr, oid.toC()) runtime.KeepAlive(v) if ret < 0 { - return 0, ObjectBad, MakeGitError(ret) + return 0, ObjectInvalid, MakeGitError(ret) } return uint64(sz), ObjectType(cotype), nil diff --git a/vendor/libgit2 b/vendor/libgit2 index fba70a9..1a107fa 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit fba70a9d5f1fa433968a3dfd51e3153c8eebe834 +Subproject commit 1a107fac0fc88a4d74b64ffc9ae2fd178ba631c0 From 13090d85b44a9ff5f5781f28ef1807fbc6ecb864 Mon Sep 17 00:00:00 2001 From: Jon Miller Date: Tue, 7 May 2019 11:36:34 -0400 Subject: [PATCH 43/68] script/build-libgit2-static.sh: correctly set ROOT The ROOT variable is not being set correctly. Need to use dirname against $0 as well as only go up one directory instead of two. --- script/build-libgit2-static.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/build-libgit2-static.sh b/script/build-libgit2-static.sh index 680dd93..4d89fba 100755 --- a/script/build-libgit2-static.sh +++ b/script/build-libgit2-static.sh @@ -2,7 +2,7 @@ set -ex -ROOT="$(cd "$0/../.." && echo "${PWD}")" +ROOT="$(cd "$(dirname "$0")/.." && echo "${PWD}")" BUILD_PATH="${ROOT}/static-build" VENDORED_PATH="${ROOT}/vendor/libgit2" From fe0f562cc03d300ec351beca53b5eed7fe4b29e4 Mon Sep 17 00:00:00 2001 From: Takuji Shimokawa Date: Fri, 10 May 2019 20:31:01 +0900 Subject: [PATCH 44/68] Add Commit.MessageEncoding() method. --- commit.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/commit.go b/commit.go index 0ab720d..4262060 100644 --- a/commit.go +++ b/commit.go @@ -28,6 +28,12 @@ func (c *Commit) Message() string { return ret } +func (c *Commit) MessageEncoding() string { + ret := C.GoString(C.git_commit_message_encoding(c.cast_ptr)) + runtime.KeepAlive(c) + return ret +} + func (c *Commit) RawMessage() string { ret := C.GoString(C.git_commit_message_raw(c.cast_ptr)) runtime.KeepAlive(c) From ad02c37e6d57dddf25d9c72a788a447dd7d5de12 Mon Sep 17 00:00:00 2001 From: Segev Finer Date: Wed, 29 May 2019 17:55:37 +0300 Subject: [PATCH 45/68] Add Diff.ToBuf wrapping git_diff_to_buf --- diff.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/diff.go b/diff.go index 20eb9e8..b025edd 100644 --- a/diff.go +++ b/diff.go @@ -405,6 +405,36 @@ func (diff *Diff) Patch(deltaIndex int) (*Patch, error) { return newPatchFromC(patchPtr), nil } +type DiffFormat int + +const ( + DiffFormatPatch DiffFormat = C.GIT_DIFF_FORMAT_PATCH + DiffFormatPatchHeader DiffFormat = C.GIT_DIFF_FORMAT_PATCH_HEADER + DiffFormatRaw DiffFormat = C.GIT_DIFF_FORMAT_RAW + DiffFormatNameOnly DiffFormat = C.GIT_DIFF_FORMAT_NAME_ONLY + DiffFormatNameStatus DiffFormat = C.GIT_DIFF_FORMAT_NAME_STATUS +) + +func (diff *Diff) ToBuf(format DiffFormat) ([]byte, error) { + if diff.ptr == nil { + return nil, ErrInvalid + } + + diffBuf := C.git_buf{} + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_diff_to_buf(&diffBuf, diff.ptr, C.git_diff_format_t(format)) + runtime.KeepAlive(diff) + if ecode < 0 { + return nil, MakeGitError(ecode) + } + defer C.git_buf_free(&diffBuf) + + return C.GoBytes(unsafe.Pointer(diffBuf.ptr), C.int(diffBuf.size)), nil +} + type DiffOptionsFlag int const ( From 5cdcbf16079661b7c1f8274e07d9f1a7c9d4488d Mon Sep 17 00:00:00 2001 From: Melvin Date: Wed, 19 Jun 2019 10:48:37 -0700 Subject: [PATCH 46/68] fix invalid guard forcing v27 instead of v28 --- git_dynamic.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git_dynamic.go b/git_dynamic.go index 0a977e8..06deeeb 100644 --- a/git_dynamic.go +++ b/git_dynamic.go @@ -6,8 +6,8 @@ package git #include #cgo pkg-config: libgit2 -#if LIBGIT2_VER_MAJOR != 0 || LIBGIT2_VER_MINOR != 27 -# error "Invalid libgit2 version; this git2go supports libgit2 v0.27" +#if LIBGIT2_VER_MAJOR != 0 || LIBGIT2_VER_MINOR != 28 +# error "Invalid libgit2 version; this git2go supports libgit2 v0.28" #endif */ From b7eeb4f405c194fbff145eb8c5f19ec6157c38d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 13 Aug 2019 19:30:16 +0200 Subject: [PATCH 47/68] Update vendored libgit2 to 08cfa43d0e1a921 --- vendor/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libgit2 b/vendor/libgit2 index 1a107fa..08cfa43 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit 1a107fac0fc88a4d74b64ffc9ae2fd178ba631c0 +Subproject commit 08cfa43d0e1a9214a2f1239593686078e75e5636 From 57ab6bc351f96caabdeb58a5092c9dda51962603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 13 Aug 2019 20:15:01 +0200 Subject: [PATCH 48/68] script: tell libgit2 to use the builtin regex backend --- script/build-libgit2-static.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/script/build-libgit2-static.sh b/script/build-libgit2-static.sh index 680dd93..096c5c6 100755 --- a/script/build-libgit2-static.sh +++ b/script/build-libgit2-static.sh @@ -12,6 +12,7 @@ cd "${BUILD_PATH}/build" && cmake -DTHREADSAFE=ON \ -DBUILD_CLAR=OFF \ -DBUILD_SHARED_LIBS=OFF \ + -DREGEX_BACKEND=builtin \ -DCMAKE_C_FLAGS=-fPIC \ -DCMAKE_BUILD_TYPE="RelWithDebInfo" \ -DCMAKE_INSTALL_PREFIX="${BUILD_PATH}/install" \ From 26c983c3a25cfb449e0e55d73871605c4d5667fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 15 Aug 2019 09:38:02 +0200 Subject: [PATCH 49/68] Setup CI via Actions --- .github/workflows/ci.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..34eed3b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: git2go CI +on: + pull_request: + push: + branches: + - master + - v* + +jobs: + + build: + strategy: + fail-fast: false + matrix: + go: [ '1.9', '1.10', '1.11', '1.12' ] + name: Go ${{ matrix.go }} + + runs-on: ubuntu-18.04 + + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: ${{ matrix.go }} + id: go + - name: Check out code into the Go module directory + uses: actions/checkout@v1 + - name: Build + run: make test-static From a5b3de11aec347d2431372afffd7bacb224d8ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 15 Aug 2019 09:42:58 +0200 Subject: [PATCH 50/68] submodule --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34eed3b..ab7a9da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,4 +26,6 @@ jobs: - name: Check out code into the Go module directory uses: actions/checkout@v1 - name: Build - run: make test-static + run: | + git submodule update --init + make test-static From 3849c7f52a4d923013685d6b7303daae9132fafe Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 27 Aug 2019 10:02:12 -0700 Subject: [PATCH 51/68] make Delta and DiffLineType stringers --- delta_string.go | 33 +++++++++++++++++++++++++ diff.go | 4 +++ difflinetype_string.go | 56 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 delta_string.go create mode 100644 difflinetype_string.go diff --git a/delta_string.go b/delta_string.go new file mode 100644 index 0000000..53e02bd --- /dev/null +++ b/delta_string.go @@ -0,0 +1,33 @@ +// Code generated by "stringer -type Delta -trimprefix Delta -tags static"; DO NOT EDIT. + +package git + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[DeltaUnmodified-0] + _ = x[DeltaAdded-1] + _ = x[DeltaDeleted-2] + _ = x[DeltaModified-3] + _ = x[DeltaRenamed-4] + _ = x[DeltaCopied-5] + _ = x[DeltaIgnored-6] + _ = x[DeltaUntracked-7] + _ = x[DeltaTypeChange-8] + _ = x[DeltaUnreadable-9] + _ = x[DeltaConflicted-10] +} + +const _Delta_name = "UnmodifiedAddedDeletedModifiedRenamedCopiedIgnoredUntrackedTypeChangeUnreadableConflicted" + +var _Delta_index = [...]uint8{0, 10, 15, 22, 30, 37, 43, 50, 59, 69, 79, 89} + +func (i Delta) String() string { + if i < 0 || i >= Delta(len(_Delta_index)-1) { + return "Delta(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Delta_name[_Delta_index[i]:_Delta_index[i+1]] +} diff --git a/diff.go b/diff.go index b025edd..1756217 100644 --- a/diff.go +++ b/diff.go @@ -39,6 +39,8 @@ const ( DeltaConflicted Delta = C.GIT_DELTA_CONFLICTED ) +//go:generate stringer -type Delta -trimprefix Delta -tags static + type DiffLineType int const ( @@ -54,6 +56,8 @@ const ( DiffLineBinary DiffLineType = C.GIT_DIFF_LINE_BINARY ) +//go:generate stringer -type DiffLineType -trimprefix DiffLine -tags static + type DiffFile struct { Path string Oid *Oid diff --git a/difflinetype_string.go b/difflinetype_string.go new file mode 100644 index 0000000..3c1ad58 --- /dev/null +++ b/difflinetype_string.go @@ -0,0 +1,56 @@ +// Code generated by "stringer -type DiffLineType -trimprefix DiffLine -tags static"; DO NOT EDIT. + +package git + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[DiffLineContext-32] + _ = x[DiffLineAddition-43] + _ = x[DiffLineDeletion-45] + _ = x[DiffLineContextEOFNL-61] + _ = x[DiffLineAddEOFNL-62] + _ = x[DiffLineDelEOFNL-60] + _ = x[DiffLineFileHdr-70] + _ = x[DiffLineHunkHdr-72] + _ = x[DiffLineBinary-66] +} + +const ( + _DiffLineType_name_0 = "Context" + _DiffLineType_name_1 = "Addition" + _DiffLineType_name_2 = "Deletion" + _DiffLineType_name_3 = "DelEOFNLContextEOFNLAddEOFNL" + _DiffLineType_name_4 = "Binary" + _DiffLineType_name_5 = "FileHdr" + _DiffLineType_name_6 = "HunkHdr" +) + +var ( + _DiffLineType_index_3 = [...]uint8{0, 8, 20, 28} +) + +func (i DiffLineType) String() string { + switch { + case i == 32: + return _DiffLineType_name_0 + case i == 43: + return _DiffLineType_name_1 + case i == 45: + return _DiffLineType_name_2 + case 60 <= i && i <= 62: + i -= 60 + return _DiffLineType_name_3[_DiffLineType_index_3[i]:_DiffLineType_index_3[i+1]] + case i == 66: + return _DiffLineType_name_4 + case i == 70: + return _DiffLineType_name_5 + case i == 72: + return _DiffLineType_name_6 + default: + return "DiffLineType(" + strconv.FormatInt(int64(i), 10) + ")" + } +} From 79b2cb6ca1aae4a9f442291fd88e37ef9b52ff2a Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 27 Aug 2019 10:23:37 -0700 Subject: [PATCH 52/68] provide param names in DiffForEachFileCallback Without a parameter name, the float64 param is pretty inscrutable. --- diff.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diff.go b/diff.go index b025edd..a5d1a61 100644 --- a/diff.go +++ b/diff.go @@ -284,7 +284,7 @@ type diffForEachData struct { Error error } -type DiffForEachFileCallback func(DiffDelta, float64) (DiffForEachHunkCallback, error) +type DiffForEachFileCallback func(delta DiffDelta, progress float64) (DiffForEachHunkCallback, error) type DiffDetail int From bf289c8b3645158a552161825326347e346f314a Mon Sep 17 00:00:00 2001 From: Dinesh Bolkensteyn Date: Sun, 17 Nov 2019 09:19:36 +0100 Subject: [PATCH 53/68] Fixes #513 - Segfault during tree walk --- tree.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tree.go b/tree.go index 02507d2..b309193 100644 --- a/tree.go +++ b/tree.go @@ -47,7 +47,7 @@ func newTreeEntry(entry *C.git_tree_entry) *TreeEntry { } } -func (t Tree) EntryByName(filename string) *TreeEntry { +func (t *Tree) EntryByName(filename string) *TreeEntry { cname := C.CString(filename) defer C.free(unsafe.Pointer(cname)) @@ -67,7 +67,7 @@ func (t Tree) EntryByName(filename string) *TreeEntry { // 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 { +func (t *Tree) EntryById(id *Oid) *TreeEntry { runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -84,7 +84,7 @@ func (t Tree) EntryById(id *Oid) *TreeEntry { // 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) { +func (t *Tree) EntryByPath(path string) (*TreeEntry, error) { cpath := C.CString(path) defer C.free(unsafe.Pointer(cpath)) var entry *C.git_tree_entry @@ -102,7 +102,7 @@ func (t Tree) EntryByPath(path string) (*TreeEntry, error) { return newTreeEntry(entry), nil } -func (t Tree) EntryByIndex(index uint64) *TreeEntry { +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 @@ -113,7 +113,7 @@ func (t Tree) EntryByIndex(index uint64) *TreeEntry { return goEntry } -func (t Tree) EntryCount() uint64 { +func (t *Tree) EntryCount() uint64 { num := C.git_tree_entrycount(t.cast_ptr) runtime.KeepAlive(t) return uint64(num) @@ -122,9 +122,8 @@ func (t Tree) EntryCount() uint64 { type TreeWalkCallback func(string, *TreeEntry) int //export CallbackGitTreeWalk -func CallbackGitTreeWalk(_root *C.char, _entry unsafe.Pointer, ptr unsafe.Pointer) C.int { +func CallbackGitTreeWalk(_root *C.char, entry *C.git_tree_entry, 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))) @@ -133,7 +132,7 @@ func CallbackGitTreeWalk(_root *C.char, _entry unsafe.Pointer, ptr unsafe.Pointe } } -func (t Tree) Walk(callback TreeWalkCallback) error { +func (t *Tree) Walk(callback TreeWalkCallback) error { runtime.LockOSThread() defer runtime.UnlockOSThread() From 5c796836853b5651aaa141224cbde03646e78696 Mon Sep 17 00:00:00 2001 From: Dinesh Bolkensteyn Date: Sun, 17 Nov 2019 17:41:43 +0100 Subject: [PATCH 54/68] Similar to #513 Fix potential segfault on Tag objects --- tag.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tag.go b/tag.go index 4debdb7..1bea2b7 100644 --- a/tag.go +++ b/tag.go @@ -21,26 +21,26 @@ func (t *Tag) AsObject() *Object { return &t.Object } -func (t Tag) Message() string { +func (t *Tag) Message() string { ret := C.GoString(C.git_tag_message(t.cast_ptr)) runtime.KeepAlive(t) return ret } -func (t Tag) Name() string { +func (t *Tag) Name() string { ret := C.GoString(C.git_tag_name(t.cast_ptr)) runtime.KeepAlive(t) return ret } -func (t Tag) Tagger() *Signature { +func (t *Tag) Tagger() *Signature { cast_ptr := C.git_tag_tagger(t.cast_ptr) ret := newSignatureFromC(cast_ptr) runtime.KeepAlive(t) return ret } -func (t Tag) Target() *Object { +func (t *Tag) Target() *Object { var ptr *C.git_object ret := C.git_tag_target(&ptr, t.cast_ptr) runtime.KeepAlive(t) @@ -51,13 +51,13 @@ func (t Tag) Target() *Object { return allocObject(ptr, t.repo) } -func (t Tag) TargetId() *Oid { +func (t *Tag) TargetId() *Oid { ret := newOidFromC(C.git_tag_target_id(t.cast_ptr)) runtime.KeepAlive(t) return ret } -func (t Tag) TargetType() ObjectType { +func (t *Tag) TargetType() ObjectType { ret := ObjectType(C.git_tag_target_type(t.cast_ptr)) runtime.KeepAlive(t) return ret From 93a1ee401f5b924a23a43d1499b0516ce455e59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 10 Dec 2019 21:28:24 +0000 Subject: [PATCH 55/68] Bump libgit2 to 6777db8e83 --- vendor/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libgit2 b/vendor/libgit2 index 08cfa43..6777db8 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit 08cfa43d0e1a9214a2f1239593686078e75e5636 +Subproject commit 6777db8e8343014d57c41b335e0c60af44d4e9f2 From 790b3d2ac014385a76e858bc21549be50c3ef7c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 10 Dec 2019 22:15:09 +0000 Subject: [PATCH 56/68] Makefile: disable test caching This does not work well when you're changing C stuff underneath. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index cf00cef..4dffce0 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ default: test test: build-libgit2 go run script/check-MakeGitError-thread-lock.go - go test ./... + go test --count=1 ./... install: build-libgit2 go install ./... @@ -15,4 +15,4 @@ install-static: build-libgit2 test-static: build-libgit2 go run script/check-MakeGitError-thread-lock.go - go test --tags "static" ./... + go test --count=1 --tags "static" ./... From 97e6392d3ab67bbf3e3e59b86a0bc9ebf7430e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 10 Dec 2019 22:15:32 +0000 Subject: [PATCH 57/68] Adjust to libgit2 changes --- credentials.go | 1 + go.mod | 2 ++ merge.go | 4 ++-- odb.go | 2 +- stash.go | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/credentials.go b/credentials.go index 4e42b6e..766619c 100644 --- a/credentials.go +++ b/credentials.go @@ -2,6 +2,7 @@ package git /* #include +#include */ import "C" import "unsafe" diff --git a/go.mod b/go.mod index 688b8e3..7a68658 100644 --- a/go.mod +++ b/go.mod @@ -1 +1,3 @@ module github.com/libgit2/git2go + +go 1.13 diff --git a/merge.go b/merge.go index bc672ce..955289a 100644 --- a/merge.go +++ b/merge.go @@ -132,7 +132,7 @@ func (mo *MergeOptions) toC() *C.git_merge_options { } return &C.git_merge_options{ version: C.uint(mo.Version), - flags: C.git_merge_flag_t(mo.TreeFlags), + flags: C.uint32_t(mo.TreeFlags), rename_threshold: C.uint(mo.RenameThreshold), target_limit: C.uint(mo.TargetLimit), file_favor: C.git_merge_file_favor_t(mo.FileFavor), @@ -394,7 +394,7 @@ func populateCMergeFileOptions(c *C.git_merge_file_options, options MergeFileOpt c.our_label = C.CString(options.OurLabel) c.their_label = C.CString(options.TheirLabel) c.favor = C.git_merge_file_favor_t(options.Favor) - c.flags = C.git_merge_file_flag_t(options.Flags) + c.flags = C.uint32_t(options.Flags) c.marker_size = C.ushort(options.MarkerSize) } diff --git a/odb.go b/odb.go index fec0eb9..6489653 100644 --- a/odb.go +++ b/odb.go @@ -221,7 +221,7 @@ func (v *Odb) NewWriteStream(size int64, otype ObjectType) (*OdbWriteStream, err runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.git_off_t(size), C.git_object_t(otype)) + ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.git_object_size_t(size), C.git_object_t(otype)) runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) diff --git a/stash.go b/stash.go index 8743da8..6624bce 100644 --- a/stash.go +++ b/stash.go @@ -171,7 +171,7 @@ func (opts *StashApplyOptions) toC() ( optsC = &C.git_stash_apply_options{ version: C.GIT_STASH_APPLY_OPTIONS_VERSION, - flags: C.git_stash_apply_flags(opts.Flags), + flags: C.uint32_t(opts.Flags), } populateCheckoutOpts(&optsC.checkout_options, &opts.CheckoutOptions) if opts.ProgressCallback != nil { From ce19fa064f3cb3ef6c4b360076ffc17556b2cc3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 10 Dec 2019 22:20:20 +0000 Subject: [PATCH 58/68] travis: update versions of Go to be tested --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index f611cc3..7d53122 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,9 @@ language: go go: - - 1.7 - - 1.8 - - 1.9 - - "1.10" + - "1.11" + - "1.12" + - "1.13" - tip script: make test-static From c5159e624e55cb14c56a3e5f36200be409fba9d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 10 Dec 2019 22:33:00 +0000 Subject: [PATCH 59/68] credentials: unconfuse Go about the type For some reason cgo thinks the `credtype` field does not exist in `git_cred` so let's put it into the C code. --- credentials.go | 4 +++- wrapper.c | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/credentials.go b/credentials.go index 766619c..038313b 100644 --- a/credentials.go +++ b/credentials.go @@ -3,6 +3,8 @@ package git /* #include #include + +git_credtype_t _go_git_cred_credtype(git_cred *cred); */ import "C" import "unsafe" @@ -28,7 +30,7 @@ func (o *Cred) HasUsername() bool { } func (o *Cred) Type() CredType { - return (CredType)(o.ptr.credtype) + return (CredType)(C._go_git_cred_credtype(o.ptr)) } func credFromC(ptr *C.git_cred) *Cred { diff --git a/wrapper.c b/wrapper.c index 11c2f32..3656773 100644 --- a/wrapper.c +++ b/wrapper.c @@ -2,6 +2,7 @@ #include #include #include +#include typedef int (*gogit_submodule_cbk)(git_submodule *sm, const char *name, void *payload); @@ -180,4 +181,8 @@ void _go_git_writestream_free(git_writestream *stream) stream->free(stream); } +git_credtype_t _go_git_cred_credtype(git_cred *cred) { + return cred->credtype; +} + /* EOF */ From b201c503ab5788b2ce5511fa75792127e27e254c Mon Sep 17 00:00:00 2001 From: lhchavez Date: Wed, 12 Feb 2020 17:07:17 -0800 Subject: [PATCH 60/68] Update .github/workflows/ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab7a9da..d058ec6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - go: [ '1.9', '1.10', '1.11', '1.12' ] + go: [ '1.9', '1.10', '1.11', '1.12' , '1.13'] name: Go ${{ matrix.go }} runs-on: ubuntu-18.04 From 22d400832bced5456a0495111d6e9eea432bc5e6 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Thu, 13 Feb 2020 02:52:50 +0000 Subject: [PATCH 61/68] Fix build for go 1.9 This change makes the #includes between credentials.go and remote.go consistent to avoid a build error in go 1.9. --- remote.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/remote.go b/remote.go index b4b1dd7..43ffd33 100644 --- a/remote.go +++ b/remote.go @@ -1,9 +1,11 @@ package git /* -#include #include +#include +#include + extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks); */ From 419bac9075cd0967b09f4e0f9884a1d87298c2e3 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Thu, 13 Feb 2020 03:06:01 +0000 Subject: [PATCH 62/68] Uprev libgit2 This uprevs libgit2 to the latest and greatest. Notably, * Fixes the interface of `git_mempack_reset`, since it now returns an `int` instead of being `void`. Fixes: #533 --- mempack.go | 13 ++++++++++--- vendor/libgit2 | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/mempack.go b/mempack.go index 337e67d..bdea224 100644 --- a/mempack.go +++ b/mempack.go @@ -6,7 +6,7 @@ package git extern int git_mempack_new(git_odb_backend **out); extern int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *backend); -extern void git_mempack_reset(git_odb_backend *backend); +extern int git_mempack_reset(git_odb_backend *backend); extern void _go_git_odb_backend_free(git_odb_backend *backend); */ import "C" @@ -79,6 +79,13 @@ func (mempack *Mempack) Dump(repository *Repository) ([]byte, error) { // // This assumes that Mempack.Dump has been called before to store all the // queued objects into a single packfile. -func (mempack *Mempack) Reset() { - C.git_mempack_reset(mempack.ptr) +func (mempack *Mempack) Reset() error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_mempack_reset(mempack.ptr) + if ret < 0 { + return MakeGitError(ret) + } + return nil } diff --git a/vendor/libgit2 b/vendor/libgit2 index 6777db8..ee3307a 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit 6777db8e8343014d57c41b335e0c60af44d4e9f2 +Subproject commit ee3307a183e39d602b25fa94831c6fc09e7c1b61 From 26edffd5f57618d2927926fde4c4ac1fcba5d84a Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sat, 22 Feb 2020 23:07:08 +0000 Subject: [PATCH 63/68] Update CI configuration This change: * Updates the GitHub actions so that they run different commands for the dynamic and static flavors of libgit2. * Updates the .travis.yml file so that it does roughly the same as the GitHub actions. * Adds the release-* branches to the CI configurations. --- .github/workflows/ci.yml | 64 +++++++++++++++++++++++++++++++-- .gitignore | 1 + .travis.yml | 16 +++++---- Makefile | 47 ++++++++++++++++++++---- script/build-libgit2-dynamic.sh | 5 +++ script/build-libgit2-static.sh | 20 ++--------- script/build-libgit2.sh | 46 ++++++++++++++++++++++++ 7 files changed, 166 insertions(+), 33 deletions(-) create mode 100755 script/build-libgit2-dynamic.sh create mode 100755 script/build-libgit2.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d058ec6..931cc09 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,15 +4,49 @@ on: push: branches: - master + - release-* - v* jobs: - build: + build-legacy: strategy: fail-fast: false matrix: - go: [ '1.9', '1.10', '1.11', '1.12' , '1.13'] + go: [ '1.9', '1.10' ] + name: Go ${{ matrix.go }} + + runs-on: ubuntu-18.04 + + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: ${{ matrix.go }} + id: go + - name: Check out code into the GOPATH + uses: actions/checkout@v1 + with: + fetch-depth: 1 + path: src/github.com/${{ github.repository }} + - name: Build + env: + GOPATH: /home/runner/work/git2go + run: | + git submodule update --init + make build-libgit2-static + go get --tags "static" github.com/${{ github.repository }}/... + go build --tags "static" github.com/${{ github.repository }}/... + - name: Test + env: + GOPATH: /home/runner/work/git2go + run: make test-static + + build-static: + strategy: + fail-fast: false + matrix: + go: [ '1.11', '1.12', '1.13' ] name: Go ${{ matrix.go }} runs-on: ubuntu-18.04 @@ -28,4 +62,28 @@ jobs: - name: Build run: | git submodule update --init - make test-static + make build-libgit2-static + - name: Test + run: make test-static + + build-dynamic: + strategy: + fail-fast: false + name: Go (dynamic) + + runs-on: ubuntu-18.04 + + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: '1.13' + id: go + - name: Check out code into the Go module directory + uses: actions/checkout@v1 + - name: Build + run: | + git submodule update --init + make build-libgit2-dynamic + - name: Test + run: make test-dynamic diff --git a/.gitignore b/.gitignore index edc18d5..713781b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /static-build/ +/dynamic-build/ diff --git a/.travis.yml b/.travis.yml index 7d53122..b25a052 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,29 @@ language: go go: + - "1.9" + - "1.10" - "1.11" - "1.12" - "1.13" - tip -script: make test-static +install: + - make build-libgit2-static + - go get --tags "static" ./... + +script: + - make test-static matrix: allow_failures: - go: tip git: - submodules: false - -before_install: - - git submodule update --init + submodules: true branches: only: - master - /v\d+/ - - next + - /release-.*/ diff --git a/Makefile b/Makefile index 4dffce0..182c53e 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,53 @@ default: test -test: build-libgit2 +# System library +# ============== +# This uses whatever version of libgit2 can be found in the system. +test: go run script/check-MakeGitError-thread-lock.go go test --count=1 ./... -install: build-libgit2 +install: go install ./... -build-libgit2: +# Bundled dynamic library +# ======================= +# In order to avoid having to manipulate `git_dynamic.go`, which would prevent +# the system-wide libgit2.so from being used in a sort of ergonomic way, this +# instead moves the complexity of overriding the paths so that the built +# libraries can be found by the build and tests. +.PHONY: build-libgit2-dynamic +build-libgit2-dynamic: + ./script/build-libgit2-dynamic.sh + +dynamic-build/install/lib/libgit2.so: + ./script/build-libgit2-dynamic.sh + +test-dynamic: dynamic-build/install/lib/libgit2.so + PKG_CONFIG_PATH=dynamic-build/install/lib/pkgconfig \ + go run script/check-MakeGitError-thread-lock.go + PKG_CONFIG_PATH=dynamic-build/install/lib/pkgconfig \ + LD_LIBRARY_PATH=dynamic-build/install/lib \ + go test --count=1 ./... + +install-dynamic: dynamic-build/install/lib/libgit2.so + PKG_CONFIG_PATH=dynamic-build/install/lib/pkgconfig \ + go install ./... + +# Bundled static library +# ====================== +# This is mostly used in tests, but can also be used to provide a +# statically-linked library with the bundled version of libgit2. +.PHONY: build-libgit2-static +build-libgit2-static: ./script/build-libgit2-static.sh -install-static: build-libgit2 - go install --tags "static" ./... +static-build/install/lib/libgit2.a: + ./script/build-libgit2-static.sh -test-static: build-libgit2 +test-static: static-build/install/lib/libgit2.a go run script/check-MakeGitError-thread-lock.go go test --count=1 --tags "static" ./... + +install-static: static-build/install/lib/libgit2.a + go install --tags "static" ./... diff --git a/script/build-libgit2-dynamic.sh b/script/build-libgit2-dynamic.sh new file mode 100755 index 0000000..af037f3 --- /dev/null +++ b/script/build-libgit2-dynamic.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +exec "$(dirname "$0")/build-libgit2.sh" --dynamic diff --git a/script/build-libgit2-static.sh b/script/build-libgit2-static.sh index 26efc8e..1d28898 100755 --- a/script/build-libgit2-static.sh +++ b/script/build-libgit2-static.sh @@ -1,21 +1,5 @@ #!/bin/sh -set -ex +set -e -ROOT="$(cd "$(dirname "$0")/.." && echo "${PWD}")" -BUILD_PATH="${ROOT}/static-build" -VENDORED_PATH="${ROOT}/vendor/libgit2" - -mkdir -p "${BUILD_PATH}/build" "${BUILD_PATH}/install/lib" - -cd "${BUILD_PATH}/build" && -cmake -DTHREADSAFE=ON \ - -DBUILD_CLAR=OFF \ - -DBUILD_SHARED_LIBS=OFF \ - -DREGEX_BACKEND=builtin \ - -DCMAKE_C_FLAGS=-fPIC \ - -DCMAKE_BUILD_TYPE="RelWithDebInfo" \ - -DCMAKE_INSTALL_PREFIX="${BUILD_PATH}/install" \ - "${VENDORED_PATH}" && - -cmake --build . --target install +exec "$(dirname "$0")/build-libgit2.sh" --static diff --git a/script/build-libgit2.sh b/script/build-libgit2.sh new file mode 100755 index 0000000..acbc84a --- /dev/null +++ b/script/build-libgit2.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +# Since CMake cannot build the static and dynamic libraries in the same +# directory, this script helps build both static and dynamic versions of it and +# have the common flags in one place instead of split between two places. + +set -e + +if [ "$#" -eq "0" ]; then + echo "Usage: $0 <--dynamic|--static>">&2 + exit 1 +fi + +ROOT="$(cd "$(dirname "$0")/.." && echo "${PWD}")" +VENDORED_PATH="${ROOT}/vendor/libgit2" + +case "$1" in + --static) + BUILD_PATH="${ROOT}/static-build" + BUILD_SHARED_LIBS=OFF + ;; + + --dynamic) + BUILD_PATH="${ROOT}/dynamic-build" + BUILD_SHARED_LIBS=ON + ;; + + *) + echo "Usage: $0 <--dynamic|--static>">&2 + exit 1 + ;; +esac + +mkdir -p "${BUILD_PATH}/build" "${BUILD_PATH}/install/lib" + +cd "${BUILD_PATH}/build" && +cmake -DTHREADSAFE=ON \ + -DBUILD_CLAR=OFF \ + -DBUILD_SHARED_LIBS"=${BUILD_SHARED_LIBS}" \ + -DREGEX_BACKEND=builtin \ + -DCMAKE_C_FLAGS=-fPIC \ + -DCMAKE_BUILD_TYPE="RelWithDebInfo" \ + -DCMAKE_INSTALL_PREFIX="${BUILD_PATH}/install" \ + "${VENDORED_PATH}" && + +exec cmake --build . --target install From 2bb5930733a50b441c4a591dee931af00cf293f2 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sat, 16 Feb 2019 17:14:39 +0000 Subject: [PATCH 64/68] Free() the copies of repository.LookupXxx() `repository.LookupXxx()` allocate new go `Object`s that have a reference to a `C.git_object`. Those are then duplicated with `git_object_dup()`, so the original `Object`s linger unnecessarily until the Go GC kicks in. This change explicitly calls `Free()` on the originals to avoid unnecessary accumulation of garbage. --- repository.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/repository.go b/repository.go index 3e0d20f..07b2605 100644 --- a/repository.go +++ b/repository.go @@ -194,6 +194,7 @@ func (v *Repository) LookupTree(id *Oid) (*Tree, error) { if err != nil { return nil, err } + defer obj.Free() return obj.AsTree() } @@ -203,6 +204,7 @@ func (v *Repository) LookupCommit(id *Oid) (*Commit, error) { if err != nil { return nil, err } + defer obj.Free() return obj.AsCommit() } @@ -212,6 +214,7 @@ func (v *Repository) LookupBlob(id *Oid) (*Blob, error) { if err != nil { return nil, err } + defer obj.Free() return obj.AsBlob() } @@ -221,6 +224,7 @@ func (v *Repository) LookupTag(id *Oid) (*Tag, error) { if err != nil { return nil, err } + defer obj.Free() return obj.AsTag() } From 30c3d0ffe2118376ccbf3ff5ea1676bd7442440d Mon Sep 17 00:00:00 2001 From: Richard Burke Date: Tue, 3 Jul 2018 22:05:05 +0100 Subject: [PATCH 65/68] Add revert functionality Closes #436 --- revert.go | 103 +++++++++++++++++++++++++++++++++++++++++++++++++ revert_test.go | 76 ++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 revert.go create mode 100644 revert_test.go diff --git a/revert.go b/revert.go new file mode 100644 index 0000000..8e8bb29 --- /dev/null +++ b/revert.go @@ -0,0 +1,103 @@ +package git + +/* +#include +*/ +import "C" +import ( + "runtime" +) + +// RevertOptions contains options for performing a revert +type RevertOptions struct { + Version uint + Mainline uint + MergeOpts MergeOptions + CheckoutOpts CheckoutOpts +} + +func (opts *RevertOptions) toC() *C.git_revert_options { + return &C.git_revert_options{ + version: C.uint(opts.Version), + mainline: C.uint(opts.Mainline), + merge_opts: *opts.MergeOpts.toC(), + checkout_opts: *opts.CheckoutOpts.toC(), + } +} + +func revertOptionsFromC(opts *C.git_revert_options) RevertOptions { + return RevertOptions{ + Version: uint(opts.version), + Mainline: uint(opts.mainline), + MergeOpts: mergeOptionsFromC(&opts.merge_opts), + CheckoutOpts: checkoutOptionsFromC(&opts.checkout_opts), + } +} + +func freeRevertOptions(opts *C.git_revert_options) { + freeCheckoutOpts(&opts.checkout_opts) +} + +// DefaultRevertOptions initialises a RevertOptions struct with default values +func DefaultRevertOptions() (RevertOptions, error) { + opts := C.git_revert_options{} + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_revert_init_options(&opts, C.GIT_REVERT_OPTIONS_VERSION) + if ecode < 0 { + return RevertOptions{}, MakeGitError(ecode) + } + + defer freeRevertOptions(&opts) + return revertOptionsFromC(&opts), nil +} + +// Revert the provided commit leaving the index updated with the results of the revert +func (r *Repository) Revert(commit *Commit, revertOptions *RevertOptions) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var cOpts *C.git_revert_options + + if revertOptions != nil { + cOpts = revertOptions.toC() + defer freeRevertOptions(cOpts) + } + + ecode := C.git_revert(r.ptr, commit.cast_ptr, cOpts) + runtime.KeepAlive(r) + runtime.KeepAlive(commit) + + if ecode < 0 { + return MakeGitError(ecode) + } + + return nil +} + +// RevertCommit reverts the provided commit against "ourCommit" +// The returned index contains the result of the revert and should be freed +func (r *Repository) RevertCommit(revertCommit *Commit, ourCommit *Commit, mainline uint, mergeOptions *MergeOptions) (*Index, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var cOpts *C.git_merge_options + + if mergeOptions != nil { + cOpts = mergeOptions.toC() + } + + var index *C.git_index + + ecode := C.git_revert_commit(&index, r.ptr, revertCommit.cast_ptr, ourCommit.cast_ptr, C.uint(mainline), cOpts) + runtime.KeepAlive(revertCommit) + runtime.KeepAlive(ourCommit) + + if ecode < 0 { + return nil, MakeGitError(ecode) + } + + return newIndexFromC(index, r), nil +} diff --git a/revert_test.go b/revert_test.go new file mode 100644 index 0000000..fcf8e43 --- /dev/null +++ b/revert_test.go @@ -0,0 +1,76 @@ +package git + +import ( + "testing" +) + +const ( + expectedRevertedReadmeContents = "foo\n" +) + +func TestRevert(t *testing.T) { + t.Parallel() + repo := createTestRepo(t) + defer cleanupTestRepo(t, repo) + + seedTestRepo(t, repo) + commitID, _ := updateReadme(t, repo, content) + + commit, err := repo.LookupCommit(commitID) + checkFatal(t, err) + + revertOptions, err := DefaultRevertOptions() + checkFatal(t, err) + + err = repo.Revert(commit, &revertOptions) + checkFatal(t, err) + + actualReadmeContents := readReadme(t, repo) + + if actualReadmeContents != expectedRevertedReadmeContents { + t.Fatalf(`README has incorrect contents after revert. Expected: "%v", Actual: "%v"`, + expectedRevertedReadmeContents, actualReadmeContents) + } + + state := repo.State() + if state != RepositoryStateRevert { + t.Fatalf("Incorrect repository state. Expected: %v, Actual: %v", RepositoryStateRevert, state) + } + + err = repo.StateCleanup() + checkFatal(t, err) + + state = repo.State() + if state != RepositoryStateNone { + t.Fatalf("Incorrect repository state. Expected: %v, Actual: %v", RepositoryStateNone, state) + } +} + +func TestRevertCommit(t *testing.T) { + t.Parallel() + repo := createTestRepo(t) + defer cleanupTestRepo(t, repo) + + seedTestRepo(t, repo) + commitID, _ := updateReadme(t, repo, content) + + commit, err := repo.LookupCommit(commitID) + checkFatal(t, err) + + revertOptions, err := DefaultRevertOptions() + checkFatal(t, err) + + index, err := repo.RevertCommit(commit, commit, 0, &revertOptions.MergeOpts) + checkFatal(t, err) + defer index.Free() + + err = repo.CheckoutIndex(index, &revertOptions.CheckoutOpts) + checkFatal(t, err) + + actualReadmeContents := readReadme(t, repo) + + if actualReadmeContents != expectedRevertedReadmeContents { + t.Fatalf(`README has incorrect contents after revert. Expected: "%v", Actual: "%v"`, + expectedRevertedReadmeContents, actualReadmeContents) + } +} From 4bca045e5aa98b0b791fb467705de0692fe3514f Mon Sep 17 00:00:00 2001 From: Richard Burke Date: Tue, 15 Jan 2019 21:29:45 +0000 Subject: [PATCH 66/68] Remove Version from RevertOptions Version is defaulted to GIT_REVERT_OPTIONS_VERSION --- revert.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/revert.go b/revert.go index 8e8bb29..e745f11 100644 --- a/revert.go +++ b/revert.go @@ -10,7 +10,6 @@ import ( // RevertOptions contains options for performing a revert type RevertOptions struct { - Version uint Mainline uint MergeOpts MergeOptions CheckoutOpts CheckoutOpts @@ -18,7 +17,7 @@ type RevertOptions struct { func (opts *RevertOptions) toC() *C.git_revert_options { return &C.git_revert_options{ - version: C.uint(opts.Version), + version: C.GIT_REVERT_OPTIONS_VERSION, mainline: C.uint(opts.Mainline), merge_opts: *opts.MergeOpts.toC(), checkout_opts: *opts.CheckoutOpts.toC(), @@ -27,7 +26,6 @@ func (opts *RevertOptions) toC() *C.git_revert_options { func revertOptionsFromC(opts *C.git_revert_options) RevertOptions { return RevertOptions{ - Version: uint(opts.version), Mainline: uint(opts.mainline), MergeOpts: mergeOptionsFromC(&opts.merge_opts), CheckoutOpts: checkoutOptionsFromC(&opts.checkout_opts), From 00374b39aad728f34eeadbb575ac607acbfa205a Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sun, 23 Feb 2020 14:38:10 +0000 Subject: [PATCH 67/68] Update the method name --- index.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.go b/index.go index 32acd14..50538bd 100644 --- a/index.go +++ b/index.go @@ -212,7 +212,7 @@ func (v *Index) AddFromBuffer(entry *IndexEntry, buffer []byte) error { runtime.LockOSThread() defer runtime.UnlockOSThread() - if err := C.git_index_add_frombuffer(v.ptr, ¢ry, cbuffer, C.size_t(len(buffer))); err < 0 { + if err := C.git_index_add_from_buffer(v.ptr, ¢ry, cbuffer, C.size_t(len(buffer))); err < 0 { return MakeGitError(err) } From a140f2310f56eb06d37454514e67647a8a49d197 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sun, 23 Feb 2020 14:58:21 +0000 Subject: [PATCH 68/68] Add test and runtime.KeepAlive() --- merge.go | 19 +++++++++++++++---- merge_test.go | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/merge.go b/merge.go index ab30fb2..06e98a0 100644 --- a/merge.go +++ b/merge.go @@ -58,7 +58,9 @@ func (r *Repository) AnnotatedCommitFromFetchHead(branchName string, remoteURL s return nil, MakeGitError(ret) } - return newAnnotatedCommitFromC(ptr, r), nil + annotatedCommit := newAnnotatedCommitFromC(ptr, r) + runtime.KeepAlive(r) + return annotatedCommit, nil } func (r *Repository) LookupAnnotatedCommit(oid *Oid) (*AnnotatedCommit, error) { @@ -71,7 +73,10 @@ func (r *Repository) LookupAnnotatedCommit(oid *Oid) (*AnnotatedCommit, error) { if ret < 0 { return nil, MakeGitError(ret) } - return newAnnotatedCommitFromC(ptr, r), nil + + annotatedCommit := newAnnotatedCommitFromC(ptr, r) + runtime.KeepAlive(r) + return annotatedCommit, nil } func (r *Repository) AnnotatedCommitFromRef(ref *Reference) (*AnnotatedCommit, error) { @@ -85,7 +90,10 @@ func (r *Repository) AnnotatedCommitFromRef(ref *Reference) (*AnnotatedCommit, e if ret < 0 { return nil, MakeGitError(ret) } - return newAnnotatedCommitFromC(ptr, r), nil + + annotatedCommit := newAnnotatedCommitFromC(ptr, r) + runtime.KeepAlive(r) + return annotatedCommit, nil } func (r *Repository) AnnotatedCommitFromRevspec(spec string) (*AnnotatedCommit, error) { @@ -101,7 +109,10 @@ func (r *Repository) AnnotatedCommitFromRevspec(spec string) (*AnnotatedCommit, if ret < 0 { return nil, MakeGitError(ret) } - return newAnnotatedCommitFromC(ptr, r), nil + + annotatedCommit := newAnnotatedCommitFromC(ptr, r) + runtime.KeepAlive(r) + return annotatedCommit, nil } type MergeTreeFlag int diff --git a/merge_test.go b/merge_test.go index f2c84bc..7cf034f 100644 --- a/merge_test.go +++ b/merge_test.go @@ -5,6 +5,22 @@ import ( "time" ) +func TestAnnotatedCommitFromRevspec(t *testing.T) { + t.Parallel() + repo := createTestRepo(t) + defer cleanupTestRepo(t, repo) + + seedTestRepo(t, repo) + + mergeHead, err := repo.AnnotatedCommitFromRevspec("refs/heads/master") + checkFatal(t, err) + + expectedId := "473bf778b67b6d53e2ab289e0f1a2e8addef2fc2" + if mergeHead.Id().String() != expectedId { + t.Errorf("mergeHead.Id() = %v, want %v", mergeHead.Id(), expectedId) + } +} + func TestMergeWithSelf(t *testing.T) { t.Parallel() repo := createTestRepo(t) @@ -18,6 +34,11 @@ func TestMergeWithSelf(t *testing.T) { mergeHead, err := repo.AnnotatedCommitFromRef(master) checkFatal(t, err) + expectedId := "473bf778b67b6d53e2ab289e0f1a2e8addef2fc2" + if mergeHead.Id().String() != expectedId { + t.Errorf("mergeHead.Id() = %v, want %v", mergeHead.Id(), expectedId) + } + mergeHeads := make([]*AnnotatedCommit, 1) mergeHeads[0] = mergeHead err = repo.Merge(mergeHeads, nil, nil)