diff options
| -rw-r--r-- | .travis.yml | 1 | ||||
| -rw-r--r-- | branch.go | 4 | ||||
| -rw-r--r-- | checkout.go | 2 | ||||
| -rw-r--r-- | commit.go | 4 | ||||
| -rw-r--r-- | config.go | 12 | ||||
| -rw-r--r-- | config_test.go | 2 | ||||
| -rw-r--r-- | describe.go | 2 | ||||
| -rw-r--r-- | diff.go | 2 | ||||
| -rw-r--r-- | git.go | 2 | ||||
| -rw-r--r-- | git_dynamic.go | 4 | ||||
| -rw-r--r-- | git_static.go | 4 | ||||
| -rw-r--r-- | merge.go | 27 | ||||
| -rw-r--r-- | note.go | 2 | ||||
| -rw-r--r-- | object.go | 2 | ||||
| -rw-r--r-- | odb.go | 40 | ||||
| -rw-r--r-- | odb_test.go | 49 | ||||
| -rw-r--r-- | patch.go | 2 | ||||
| -rw-r--r-- | reference.go | 9 | ||||
| -rw-r--r-- | settings.go | 2 | ||||
| -rw-r--r-- | signature.go | 2 | ||||
| -rw-r--r-- | tree.go | 15 | ||||
| m--------- | vendor/libgit2 | 0 |
22 files changed, 132 insertions, 57 deletions
diff --git a/.travis.yml b/.travis.yml index dd9f97a..f611cc3 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 @@ -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/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 @@ -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) @@ -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 } @@ -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)) @@ -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/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 } 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 } @@ -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() @@ -303,7 +303,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/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 <git2.h> #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 <git2.h> -#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 */ @@ -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 { @@ -355,6 +375,7 @@ type MergeFileOptions struct { TheirLabel string Favor MergeFileFavor Flags MergeFileFlags + MarkerSize uint16 } func mergeFileOptionsFromC(c C.git_merge_file_options) MergeFileOptions { @@ -364,6 +385,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 +395,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) { @@ -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 } @@ -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 } @@ -8,6 +8,7 @@ extern void _go_git_odb_backend_free(git_odb_backend *backend); */ import "C" import ( + "io" "reflect" "runtime" "unsafe" @@ -80,15 +81,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 +169,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) @@ -182,17 +193,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 +279,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 @@ -281,6 +298,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) diff --git a/odb_test.go b/odb_test.go index 3d22fc9..46acdba 100644 --- a/odb_test.go +++ b/odb_test.go @@ -1,12 +1,14 @@ package git import ( + "bytes" "errors" "io" + "io/ioutil" "testing" ) -func TestOdbReadHeader(t *testing.T) { +func TestOdbRead(t *testing.T) { t.Parallel() repo := createTestRepo(t) defer cleanupTestRepo(t, repo) @@ -26,13 +28,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) { @@ -47,22 +63,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) { @@ -82,14 +105,16 @@ committer John Doe <[email protected]> 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") + } } } @@ -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/reference.go b/reference.go index e10c9b2..12ecb74 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) @@ -455,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 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() 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 @@ -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 { diff --git a/vendor/libgit2 b/vendor/libgit2 -Subproject f1323d9c161aeeada190fd9615a8b5a9fb8a7f3 +Subproject 838a2f2918b6d9fad8768d2498575ff5d75c35f |
