diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8eb5872 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vendor/libgit2"] + path = vendor/libgit2 + url = https://github.com/libgit2/libgit2 diff --git a/.travis.yml b/.travis.yml index e833a32..f84d07e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,5 @@ language: go -install: - - cd "${HOME}" - - wget -O libgit2-0.22.1.tar.gz https://github.com/libgit2/libgit2/archive/v0.22.1.tar.gz - - tar -xzvf libgit2-0.22.1.tar.gz - - cd libgit2-0.22.1 && mkdir build && cd build - - cmake -DTHREADSAFE=ON -DBUILD_CLAR=OFF -DCMAKE_C_FLAGS=-fPIC -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DCMAKE_INSTALL_PREFIX=/usr/local .. && make && sudo make install - - sudo ldconfig - - cd "${TRAVIS_BUILD_DIR}" - go: - 1.1 - 1.2 diff --git a/Makefile b/Makefile index 9c42283..3040857 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,11 @@ default: test -test: - go run script/check-MakeGitError-thread-lock.go - go test ./... +build-libgit2: + ./script/build-libgit2-static.sh -install: - go install ./... +test: build-libgit2 + go run script/check-MakeGitError-thread-lock.go + ./script/with-static.sh go test ./... + +install: build-libgit2 + ./script/with-static.sh go install ./... diff --git a/README.md b/README.md index 386ff83..faeb5f5 100644 --- a/README.md +++ b/README.md @@ -3,34 +3,27 @@ git2go [![GoDoc](https://godoc.org/github.com/libgit2/git2go?status.svg)](http://godoc.org/github.com/libgit2/git2go) [![Build Status](https://travis-ci.org/libgit2/git2go.svg?branch=master)](https://travis-ci.org/libgit2/git2go) -Go bindings for [libgit2](http://libgit2.github.com/). The `master` branch follows the latest libgit2 release. The versioned branches indicate which libgit2 version they work against. +Go bindings for [libgit2](http://libgit2.github.com/). The master branch follows the latest libgit2 release. The versioned branches indicate which libgit2 version they work against. Installing ---------- -This project wraps the functionality provided by libgit2. If you're using a stable version, install it to your system via your system's package manger and then install git2go as usual. - -Otherwise (`next` which tracks an unstable version), we need to build libgit2 as well. In order to build it, you need `cmake`, `pkg-config` and a C compiler. You will also need the development packages for OpenSSL and LibSSH2 installed if you want libgit2 to support HTTPS and SSH respectively. +This project needs libgit2, which is written in C so we need to build that as well. In order to build libgit2, you need `cmake`, `pkg-config` and a C compiler. You will also need the development packages for OpenSSL and LibSSH2 installed if you want libgit2 to support HTTPS and SSH respectively. ### Stable version -git2go has `master` which tracks the latest release of libgit2, and versioned branches which indicate which version of libgit2 they work against. Install the development package it on your system via your favourite package manager or from source and you can use a service like gopkg.in to use the appropriate version. For the libgit2 v0.22 case, you can use +git2go has versioned branches which indicate which version of libgit2 they work against. Install the development package it on your system via your favourite package manager or from source and you can use a service like gopkg.in to use the appropriate version. For the libgit2 v0.22 case, you can use import "gopkg.in/libgit2/git2go.v22" -to use a version of git2go which will work against libgit2 v0.22 and dynamically link to the library. You can use +to use a version of git2go which will work against libgit2 v0.22 and dynamically link to the library. - import "github.com/libgit2/git2go" +### From master -to use the version which works against the latest release. - -### From `next` - -The `next` branch follows libgit2's master branch, which means there is no stable API or ABI to link against. git2go can statically link against a vendored version of libgit2. +The master branch follows libgit2's master branch, which means there is no stable API or ABI to link against. git2go can statically link against a vendored version of libgit2. Run `go get -d github.com/libgit2/git2go` to download the code and go to your `$GOPATH/src/github.com/libgit2/git2go` dir. From there, we need to build the C code and put it into the resulting go binary. - git checkout next git submodule update --init # get libgit2 make install @@ -44,7 +37,7 @@ libgit2 uses OpenSSL and LibSSH2 for performing encrypted network connections. F Running the tests ----------------- -For the stable version, `go test` will work as usual. For the `next` branch, similarly to installing, running the tests requires linking against the local libgit2 library, so the Makefile provides a wrapper +For the stable version, `go test` will work as usual. For the master branch, similarly to installing, running the tests requires linking against the local libgit2 library, so the Makefile provides a wrapper make test diff --git a/branch.go b/branch.go index 22b767e..54b01fb 100644 --- a/branch.go +++ b/branch.go @@ -96,10 +96,7 @@ func (repo *Repository) CreateBranch(branchName string, target *Commit, force bo cBranchName := C.CString(branchName) cForce := cbool(force) - cSignature, err := signature.toC() - if err != nil { - return nil, err - } + cSignature := signature.toC() defer C.git_signature_free(cSignature) var cmsg *C.char @@ -136,10 +133,7 @@ func (b *Branch) Move(newBranchName string, force bool, signature *Signature, ms cNewBranchName := C.CString(newBranchName) cForce := cbool(force) - cSignature, err := signature.toC() - if err != nil { - return nil, err - } + cSignature := signature.toC() defer C.git_signature_free(cSignature) var cmsg *C.char diff --git a/checkout.go b/checkout.go index 6eb6098..c507172 100644 --- a/checkout.go +++ b/checkout.go @@ -20,10 +20,10 @@ const ( CheckoutAllowConflicts CheckoutStrategy = C.GIT_CHECKOUT_ALLOW_CONFLICTS // Allow checkout to make safe updates even if conflicts are found CheckoutRemoveUntracked CheckoutStrategy = C.GIT_CHECKOUT_REMOVE_UNTRACKED // Remove untracked files not in index (that are not ignored) CheckoutRemoveIgnored CheckoutStrategy = C.GIT_CHECKOUT_REMOVE_IGNORED // Remove ignored files not in index - CheckoutUpdateOnly CheckoutStrategy = C.GIT_CHECKOUT_UPDATE_ONLY // Only update existing files, don't create new ones + CheckotUpdateOnly CheckoutStrategy = C.GIT_CHECKOUT_UPDATE_ONLY // Only update existing files, don't create new ones 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 - CheckoutDisablePathspecMatch CheckoutStrategy = C.GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH // Treat pathspec as simple list of exact match file paths + CheckooutDisablePathspecMatch CheckoutStrategy = C.GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH // Treat pathspec as simple list of exact match file paths CheckoutSkipUnmerged CheckoutStrategy = C.GIT_CHECKOUT_SKIP_UNMERGED // Allow checkout to skip unmerged files (NOT IMPLEMENTED) CheckoutUserOurs CheckoutStrategy = C.GIT_CHECKOUT_USE_OURS // For unmerged files, checkout stage 2 from index (NOT IMPLEMENTED) CheckoutUseTheirs CheckoutStrategy = C.GIT_CHECKOUT_USE_THEIRS // For unmerged files, checkout stage 3 from index (NOT IMPLEMENTED) @@ -38,19 +38,7 @@ type CheckoutOpts struct { FileMode os.FileMode // Default is 0644 or 0755 as dictated by blob FileOpenFlags int // Default is O_CREAT | O_TRUNC | O_WRONLY TargetDirectory string // Alternative checkout path to workdir -} - -func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts { - opts := CheckoutOpts{} - opts.Strategy = CheckoutStrategy(c.checkout_strategy) - opts.DisableFilters = c.disable_filters != 0 - opts.DirMode = os.FileMode(c.dir_mode) - opts.FileMode = os.FileMode(c.file_mode) - opts.FileOpenFlags = int(c.file_open_flags) - if c.target_directory != nil { - opts.TargetDirectory = C.GoString(c.target_directory) - } - return opts + Paths []string } func (opts *CheckoutOpts) toC() *C.git_checkout_options { @@ -78,6 +66,11 @@ func populateCheckoutOpts(ptr *C.git_checkout_options, opts *CheckoutOpts) *C.gi if opts.TargetDirectory != "" { ptr.target_directory = C.CString(opts.TargetDirectory) } + if len(opts.Paths) > 0 { + ptr.paths.strings = makeCStringsFromStrings(opts.Paths) + ptr.paths.count = C.size_t(len(opts.Paths)) + } + return ptr } @@ -86,6 +79,9 @@ func freeCheckoutOpts(ptr *C.git_checkout_options) { return } C.free(unsafe.Pointer(ptr.target_directory)) + if ptr.paths.count > 0 { + freeStrarray(&ptr.paths) + } } // Updates files in the index and the working tree to match the content of @@ -141,4 +137,4 @@ func (v *Repository) CheckoutTree(tree *Tree, opts *CheckoutOpts) error { } return nil -} +} \ No newline at end of file diff --git a/cherrypick.go b/cherrypick.go deleted file mode 100644 index afc1b7e..0000000 --- a/cherrypick.go +++ /dev/null @@ -1,73 +0,0 @@ -package git - -/* -#include -*/ -import "C" -import ( - "runtime" -) - -type CherrypickOptions struct { - Version uint - Mainline uint - MergeOpts MergeOptions - CheckoutOpts CheckoutOpts -} - -func cherrypickOptionsFromC(c *C.git_cherrypick_options) CherrypickOptions { - opts := CherrypickOptions{ - Version: uint(c.version), - Mainline: uint(c.mainline), - MergeOpts: mergeOptionsFromC(&c.merge_opts), - CheckoutOpts: checkoutOptionsFromC(&c.checkout_opts), - } - return opts -} - -func (opts *CherrypickOptions) toC() *C.git_cherrypick_options { - if opts == nil { - return nil - } - c := C.git_cherrypick_options{} - c.version = C.uint(opts.Version) - c.mainline = C.uint(opts.Mainline) - c.merge_opts = *opts.MergeOpts.toC() - c.checkout_opts = *opts.CheckoutOpts.toC() - return &c -} - -func freeCherrypickOpts(ptr *C.git_cherrypick_options) { - if ptr == nil { - return - } - freeCheckoutOpts(&ptr.checkout_opts) -} - -func DefaultCherrypickOptions() (CherrypickOptions, error) { - c := C.git_cherrypick_options{} - - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - ecode := C.git_cherrypick_init_options(&c, C.GIT_CHERRYPICK_OPTIONS_VERSION) - if ecode < 0 { - return CherrypickOptions{}, MakeGitError(ecode) - } - defer freeCherrypickOpts(&c) - return cherrypickOptionsFromC(&c), nil -} - -func (v *Repository) Cherrypick(commit *Commit, opts CherrypickOptions) error { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - cOpts := opts.toC() - defer freeCherrypickOpts(cOpts) - - ecode := C.git_cherrypick(v.ptr, commit.cast_ptr, cOpts) - if ecode < 0 { - return MakeGitError(ecode) - } - return nil -} diff --git a/cherrypick_test.go b/cherrypick_test.go deleted file mode 100644 index f06dbdd..0000000 --- a/cherrypick_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package git - -import ( - "io/ioutil" - "testing" -) - -func checkout(t *testing.T, repo *Repository, commit *Commit) { - tree, err := commit.Tree() - if err != nil { - t.Fatal(err) - } - - err = repo.CheckoutTree(tree, &CheckoutOpts{Strategy: CheckoutSafe}) - if err != nil { - t.Fatal(err) - } - - err = repo.SetHeadDetached(commit.Id(), commit.Author(), "checkout") - if err != nil { - t.Fatal(err) - } -} - -const content = "Herro, Worrd!" - -func readReadme(t *testing.T, repo *Repository) string { - bytes, err := ioutil.ReadFile(pathInRepo(repo, "README")) - if err != nil { - t.Fatal(err) - } - return string(bytes) -} - -func TestCherrypick(t *testing.T) { - repo := createTestRepo(t) - c1, _ := seedTestRepo(t, repo) - c2, _ := updateReadme(t, repo, content) - - commit1, err := repo.LookupCommit(c1) - if err != nil { - t.Fatal(err) - } - commit2, err := repo.LookupCommit(c2) - if err != nil { - t.Fatal(err) - } - - checkout(t, repo, commit1) - - if readReadme(t, repo) == content { - t.Fatalf("README has wrong content after checking out initial commit") - } - - opts, err := DefaultCherrypickOptions() - if err != nil { - t.Fatal(err) - } - - err = repo.Cherrypick(commit2, opts) - if err != nil { - t.Fatal(err) - } - - if readReadme(t, repo) != content { - t.Fatalf("README has wrong contents after cherry-picking") - } - - state := repo.State() - if state != RepositoryStateCherrypick { - t.Fatal("Incorrect repository state: ", state) - } - - err = repo.StateCleanup() - if err != nil { - t.Fatal(err) - } - - state = repo.State() - if state != RepositoryStateNone { - t.Fatal("Incorrect repository state: ", state) - } -} diff --git a/commit.go b/commit.go index 57e1a77..559a1bd 100644 --- a/commit.go +++ b/commit.go @@ -9,6 +9,8 @@ import "C" import ( "runtime" + "time" + "unsafe" ) // Commit @@ -21,10 +23,6 @@ func (c Commit) Message() string { return C.GoString(C.git_commit_message(c.cast_ptr)) } -func (c Commit) Summary() string { - return C.GoString(C.git_commit_summary(c.cast_ptr)) -} - func (c Commit) Tree() (*Tree, error) { var ptr *C.git_tree @@ -70,3 +68,49 @@ func (c *Commit) ParentId(n uint) *Oid { func (c *Commit) ParentCount() uint { return uint(C.git_commit_parentcount(c.cast_ptr)) } + +// Signature + +type Signature struct { + Name string + Email string + When time.Time +} + +func newSignatureFromC(sig *C.git_signature) *Signature { + // git stores minutes, go wants seconds + loc := time.FixedZone("", int(sig.when.offset)*60) + return &Signature{ + C.GoString(sig.name), + C.GoString(sig.email), + time.Unix(int64(sig.when.time), 0).In(loc), + } +} + +// the offset in mintes, which is what git wants +func (v *Signature) Offset() int { + _, offset := v.When.Zone() + return offset / 60 +} + +func (sig *Signature) toC() *C.git_signature { + + if sig == nil { + return nil + } + + var out *C.git_signature + + name := C.CString(sig.Name) + defer C.free(unsafe.Pointer(name)) + + email := C.CString(sig.Email) + defer C.free(unsafe.Pointer(email)) + + ret := C.git_signature_new(&out, name, email, C.git_time_t(sig.When.Unix()), C.int(sig.Offset())) + if ret < 0 { + return nil + } + + return out +} diff --git a/git.go b/git.go index 9496d2d..8e78710 100644 --- a/git.go +++ b/git.go @@ -3,7 +3,6 @@ package git /* #include #include -#cgo pkg-config: libgit2 */ import "C" import ( diff --git a/git_test.go b/git_test.go index b9cf0a9..56adeed 100644 --- a/git_test.go +++ b/git_test.go @@ -57,10 +57,6 @@ func seedTestRepo(t *testing.T, repo *Repository) (*Oid, *Oid) { return commitId, treeId } -func pathInRepo(repo *Repository, name string) string { - return path.Join(path.Dir(path.Dir(repo.Path())), name) -} - func updateReadme(t *testing.T, repo *Repository, content string) (*Oid, *Oid) { loc, err := time.LoadLocation("Europe/Berlin") checkFatal(t, err) @@ -71,7 +67,7 @@ func updateReadme(t *testing.T, repo *Repository, content string) (*Oid, *Oid) { } tmpfile := "README" - err = ioutil.WriteFile(pathInRepo(repo, tmpfile), []byte(content), 0644) + err = ioutil.WriteFile(path.Join(path.Dir(path.Dir(repo.Path())), tmpfile), []byte(content), 0644) checkFatal(t, err) idx, err := repo.Index() diff --git a/object.go b/object.go index 20cee85..7428e0f 100644 --- a/object.go +++ b/object.go @@ -25,12 +25,12 @@ type Object interface { } type gitObject struct { - ptr *C.git_object + ptr *C.git_object repo *Repository } -func (t ObjectType) String() string { - switch t { +func (t ObjectType) String() (string) { + switch (t) { case ObjectAny: return "Any" case ObjectBad: @@ -71,7 +71,7 @@ func (o *gitObject) Free() { func allocObject(cobj *C.git_object, repo *Repository) Object { obj := gitObject{ - ptr: cobj, + ptr: cobj, repo: repo, } diff --git a/odb.go b/odb.go index ba03860..19bb71c 100644 --- a/odb.go +++ b/odb.go @@ -94,7 +94,7 @@ type OdbForEachCallback func(id *Oid) error type foreachData struct { callback OdbForEachCallback - err error + err error } //export odbForEachCb @@ -111,9 +111,9 @@ func odbForEachCb(id *C.git_oid, payload unsafe.Pointer) int { } func (v *Odb) ForEach(callback OdbForEachCallback) error { - data := foreachData{ + data := foreachData { callback: callback, - err: nil, + err: nil, } runtime.LockOSThread() @@ -138,7 +138,7 @@ func (v *Odb) Hash(data []byte, otype ObjectType) (oid *Oid, err error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_odb_hash(oid.toC(), ptr, C.size_t(header.Len), C.git_otype(otype)) + ret := C.git_odb_hash(oid.toC(), ptr, C.size_t(header.Len), C.git_otype(otype)); if ret < 0 { return nil, MakeGitError(ret) } diff --git a/odb_test.go b/odb_test.go index 5e6b7ff..14a3658 100644 --- a/odb_test.go +++ b/odb_test.go @@ -1,9 +1,9 @@ package git import ( - "errors" "io" "os" + "errors" "testing" ) @@ -37,7 +37,7 @@ func TestOdbStream(t *testing.T) { func TestOdbHash(t *testing.T) { - repo := createTestRepo(t) + repo := createTestRepo(t) defer os.RemoveAll(repo.Workdir()) _, _ = seedTestRepo(t, repo) diff --git a/packbuilder.go b/packbuilder.go index 54a8390..7c94926 100644 --- a/packbuilder.go +++ b/packbuilder.go @@ -128,7 +128,7 @@ func packbuilderForEachCb(buf unsafe.Pointer, size C.size_t, payload unsafe.Poin func (pb *Packbuilder) ForEach(callback PackbuilderForeachCallback) error { data := packbuilderCbData{ callback: callback, - err: nil, + err: nil, } runtime.LockOSThread() diff --git a/reference.go b/reference.go index ef12d0b..46436a6 100644 --- a/reference.go +++ b/reference.go @@ -36,10 +36,7 @@ func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string) runtime.LockOSThread() defer runtime.UnlockOSThread() - csig, err := sig.toC() - if err != nil { - return nil, err - } + csig := sig.toC() defer C.free(unsafe.Pointer(csig)) var cmsg *C.char @@ -64,10 +61,7 @@ func (v *Reference) SetTarget(target *Oid, sig *Signature, msg string) (*Referen runtime.LockOSThread() defer runtime.UnlockOSThread() - csig, err := sig.toC() - if err != nil { - return nil, err - } + csig := sig.toC() defer C.free(unsafe.Pointer(csig)) var cmsg *C.char @@ -105,10 +99,7 @@ func (v *Reference) Rename(name string, force bool, sig *Signature, msg string) cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) - csig, err := sig.toC() - if err != nil { - return nil, err - } + csig := sig.toC() defer C.free(unsafe.Pointer(csig)) var cmsg *C.char diff --git a/remote.go b/remote.go index 84750d3..2684c20 100644 --- a/remote.go +++ b/remote.go @@ -604,10 +604,7 @@ func (o *Remote) Fetch(refspecs []string, sig *Signature, msg string) error { var csig *C.git_signature = nil if sig != nil { - csig, err := sig.toC() - if err != nil { - return err - } + csig = sig.toC() defer C.free(unsafe.Pointer(csig)) } @@ -699,10 +696,7 @@ func (o *Remote) Ls(filterRefs ...string) ([]RemoteHead, error) { func (o *Remote) Push(refspecs []string, opts *PushOptions, sig *Signature, msg string) error { var csig *C.git_signature = nil if sig != nil { - csig, err := sig.toC() - if err != nil { - return err - } + csig = sig.toC() defer C.free(unsafe.Pointer(csig)) } diff --git a/repository.go b/repository.go index 7fac277..7760c3a 100644 --- a/repository.go +++ b/repository.go @@ -210,10 +210,7 @@ func (v *Repository) SetHead(refname string, sig *Signature, msg string) error { cname := C.CString(refname) defer C.free(unsafe.Pointer(cname)) - csig, err := sig.toC() - if err != nil { - return err - } + csig := sig.toC() defer C.free(unsafe.Pointer(csig)) var cmsg *C.char @@ -233,10 +230,7 @@ func (v *Repository) SetHead(refname string, sig *Signature, msg string) error { } func (v *Repository) SetHeadDetached(id *Oid, sig *Signature, msg string) error { - csig, err := sig.toC() - if err != nil { - return err - } + csig := sig.toC() defer C.free(unsafe.Pointer(csig)) var cmsg *C.char @@ -259,10 +253,7 @@ func (v *Repository) CreateReference(name string, id *Oid, force bool, sig *Sign cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) - csig, err := sig.toC() - if err != nil { - return nil, err - } + csig := sig.toC() defer C.free(unsafe.Pointer(csig)) var cmsg *C.char @@ -293,10 +284,7 @@ func (v *Repository) CreateSymbolicReference(name, target string, force bool, si ctarget := C.CString(target) defer C.free(unsafe.Pointer(ctarget)) - csig, err := sig.toC() - if err != nil { - return nil, err - } + csig := sig.toC() defer C.free(unsafe.Pointer(csig)) var cmsg *C.char @@ -364,16 +352,10 @@ func (v *Repository) CreateCommit( parentsarg = &cparents[0] } - authorSig, err := author.toC() - if err != nil { - return nil, err - } + authorSig := author.toC() defer C.git_signature_free(authorSig) - committerSig, err := committer.toC() - if err != nil { - return nil, err - } + committerSig := committer.toC() defer C.git_signature_free(committerSig) runtime.LockOSThread() @@ -402,10 +384,7 @@ func (v *Repository) CreateTag( cmessage := C.CString(message) defer C.free(unsafe.Pointer(cmessage)) - taggerSig, err := tagger.toC() - if err != nil { - return nil, err - } + taggerSig := tagger.toC() defer C.git_signature_free(taggerSig) ctarget := commit.gitObject.ptr @@ -567,16 +546,10 @@ func (v *Repository) CreateNote( defer C.free(unsafe.Pointer(cref)) } - authorSig, err := author.toC() - if err != nil { - return nil, err - } + authorSig := author.toC() defer C.git_signature_free(authorSig) - committerSig, err := committer.toC() - if err != nil { - return nil, err - } + committerSig := committer.toC() defer C.git_signature_free(committerSig) cnote := C.CString(note) @@ -628,16 +601,10 @@ func (v *Repository) RemoveNote(ref string, author, committer *Signature, id *Oi defer C.free(unsafe.Pointer(cref)) } - authorSig, err := author.toC() - if err != nil { - return err - } + authorSig := author.toC() defer C.git_signature_free(authorSig) - committerSig, err := committer.toC() - if err != nil { - return err - } + committerSig := committer.toC() defer C.git_signature_free(committerSig) runtime.LockOSThread() @@ -663,36 +630,3 @@ func (v *Repository) DefaultNoteRef() (string, error) { return C.GoString(ptr), nil } - -type RepositoryState int - -const ( - RepositoryStateNone RepositoryState = C.GIT_REPOSITORY_STATE_NONE - RepositoryStateMerge RepositoryState = C.GIT_REPOSITORY_STATE_MERGE - RepositoryStateRevert RepositoryState = C.GIT_REPOSITORY_STATE_REVERT - RepositoryStateCherrypick RepositoryState = C.GIT_REPOSITORY_STATE_CHERRYPICK - RepositoryStateBisect RepositoryState = C.GIT_REPOSITORY_STATE_BISECT - RepositoryStateRebase RepositoryState = C.GIT_REPOSITORY_STATE_REBASE - RepositoryStateRebaseInteractive RepositoryState = C.GIT_REPOSITORY_STATE_REBASE_INTERACTIVE - RepositoryStateRebaseMerge RepositoryState = C.GIT_REPOSITORY_STATE_REBASE_MERGE - RepositoryStateApplyMailbox RepositoryState = C.GIT_REPOSITORY_STATE_APPLY_MAILBOX - RepositoryStateApplyMailboxOrRebase RepositoryState = C.GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE -) - -func (r *Repository) State() RepositoryState { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - return RepositoryState(C.git_repository_state(r.ptr)) -} - -func (r *Repository) StateCleanup() error { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - cErr := C.git_repository_state_cleanup(r.ptr) - if cErr < 0 { - return MakeGitError(cErr) - } - return nil -} diff --git a/script/build-libgit2-static.sh b/script/build-libgit2-static.sh new file mode 100755 index 0000000..5723721 --- /dev/null +++ b/script/build-libgit2-static.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +set -ex + +VENDORED_PATH=vendor/libgit2 + +cd $VENDORED_PATH && +mkdir -p install/lib && +mkdir -p build && +cd build && +cmake -DTHREADSAFE=ON \ + -DBUILD_CLAR=OFF \ + -DBUILD_SHARED_LIBS=OFF \ + -DCMAKE_C_FLAGS=-fPIC \ + -DCMAKE_BUILD_TYPE="RelWithDebInfo" \ + -DCMAKE_INSTALL_PREFIX=../install \ + .. && + +cmake --build . diff --git a/script/with-static.sh b/script/with-static.sh new file mode 100755 index 0000000..3f60e31 --- /dev/null +++ b/script/with-static.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +set -ex + +export BUILD="$PWD/vendor/libgit2/build" +export PCFILE="$BUILD/libgit2.pc" + +FLAGS=$(pkg-config --static --libs $PCFILE) || exit 1 +export CGO_LDFLAGS="$BUILD/libgit2.a -L$BUILD ${FLAGS}" +export CGO_CFLAGS="-I$PWD/vendor/libgit2/include" + +$@ diff --git a/signature.go b/signature.go deleted file mode 100644 index 0518387..0000000 --- a/signature.go +++ /dev/null @@ -1,73 +0,0 @@ -package git - -/* -#include -*/ -import "C" -import ( - "runtime" - "time" - "unsafe" -) - -type Signature struct { - Name string - Email string - When time.Time -} - -func newSignatureFromC(sig *C.git_signature) *Signature { - // git stores minutes, go wants seconds - loc := time.FixedZone("", int(sig.when.offset)*60) - return &Signature{ - C.GoString(sig.name), - C.GoString(sig.email), - time.Unix(int64(sig.when.time), 0).In(loc), - } -} - -// the offset in mintes, which is what git wants -func (v *Signature) Offset() int { - _, offset := v.When.Zone() - return offset / 60 -} - -func (sig *Signature) toC() (*C.git_signature, error) { - if sig == nil { - return nil, nil - } - - var out *C.git_signature - - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - name := C.CString(sig.Name) - defer C.free(unsafe.Pointer(name)) - - email := C.CString(sig.Email) - defer C.free(unsafe.Pointer(email)) - - ret := C.git_signature_new(&out, name, email, C.git_time_t(sig.When.Unix()), C.int(sig.Offset())) - if ret < 0 { - return nil, MakeGitError(ret) - } - - return out, nil -} - -func (repo *Repository) DefaultSignature() (*Signature, error) { - var out *C.git_signature - - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - cErr := C.git_signature_default(&out, repo.ptr) - if cErr < 0 { - return nil, MakeGitError(cErr) - } - - defer C.git_signature_free(out) - - return newSignatureFromC(out), nil -} diff --git a/status.go b/status.go index 3f5a06d..c849aca 100644 --- a/status.go +++ b/status.go @@ -45,7 +45,7 @@ func statusEntryFromC(statusEntry *C.git_status_entry) StatusEntry { indexToWorkdir = diffDeltaFromC(statusEntry.index_to_workdir) } - return StatusEntry{ + return StatusEntry { Status: Status(statusEntry.status), HeadToIndex: headToIndex, IndexToWorkdir: indexToWorkdir, @@ -96,20 +96,20 @@ func (statusList *StatusList) EntryCount() (int, error) { type StatusOpt int const ( - StatusOptIncludeUntracked StatusOpt = C.GIT_STATUS_OPT_INCLUDE_UNTRACKED - StatusOptIncludeIgnored StatusOpt = C.GIT_STATUS_OPT_INCLUDE_IGNORED - StatusOptIncludeUnmodified StatusOpt = C.GIT_STATUS_OPT_INCLUDE_UNMODIFIED - StatusOptExcludeSubmodules StatusOpt = C.GIT_STATUS_OPT_EXCLUDE_SUBMODULES - StatusOptRecurseUntrackedDirs StatusOpt = C.GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS - StatusOptDisablePathspecMatch StatusOpt = C.GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH - StatusOptRecurseIgnoredDirs StatusOpt = C.GIT_STATUS_OPT_RECURSE_IGNORED_DIRS - StatusOptRenamesHeadToIndex StatusOpt = C.GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX - StatusOptRenamesIndexToWorkdir StatusOpt = C.GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR - StatusOptSortCaseSensitively StatusOpt = C.GIT_STATUS_OPT_SORT_CASE_SENSITIVELY - StatusOptSortCaseInsensitively StatusOpt = C.GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY - StatusOptRenamesFromRewrites StatusOpt = C.GIT_STATUS_OPT_RENAMES_FROM_REWRITES - StatusOptNoRefresh StatusOpt = C.GIT_STATUS_OPT_NO_REFRESH - StatusOptUpdateIndex StatusOpt = C.GIT_STATUS_OPT_UPDATE_INDEX + StatusOptIncludeUntracked StatusOpt = C.GIT_STATUS_OPT_INCLUDE_UNTRACKED + StatusOptIncludeIgnored StatusOpt = C.GIT_STATUS_OPT_INCLUDE_IGNORED + StatusOptIncludeUnmodified StatusOpt = C.GIT_STATUS_OPT_INCLUDE_UNMODIFIED + StatusOptExcludeSubmodules StatusOpt = C.GIT_STATUS_OPT_EXCLUDE_SUBMODULES + StatusOptRecurseUntrackedDirs StatusOpt = C.GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS + StatusOptDisablePathspecMatch StatusOpt = C.GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH + StatusOptRecurseIgnoredDirs StatusOpt = C.GIT_STATUS_OPT_RECURSE_IGNORED_DIRS + StatusOptRenamesHeadToIndex StatusOpt = C.GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX + StatusOptRenamesIndexToWorkdir StatusOpt = C.GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR + StatusOptSortCaseSensitively StatusOpt = C.GIT_STATUS_OPT_SORT_CASE_SENSITIVELY + StatusOptSortCaseInsensitively StatusOpt = C.GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY + StatusOptRenamesFromRewrites StatusOpt = C.GIT_STATUS_OPT_RENAMES_FROM_REWRITES + StatusOptNoRefresh StatusOpt = C.GIT_STATUS_OPT_NO_REFRESH + StatusOptUpdateIndex StatusOpt = C.GIT_STATUS_OPT_UPDATE_INDEX ) type StatusShow int @@ -173,6 +173,7 @@ func (v *Repository) StatusList(opts *StatusOptions) (*StatusList, error) { return newStatusListFromC(ptr), nil } + func (v *Repository) StatusFile(path string) (Status, error) { var statusFlags C.uint cPath := C.CString(path) diff --git a/status_test.go b/status_test.go index d18fca1..4be4824 100644 --- a/status_test.go +++ b/status_test.go @@ -12,11 +12,6 @@ func TestStatusFile(t *testing.T) { defer repo.Free() defer os.RemoveAll(repo.Workdir()) - state := repo.State() - if state != RepositoryStateNone { - t.Fatal("Incorrect repository state: ", state) - } - err := ioutil.WriteFile(path.Join(path.Dir(repo.Workdir()), "hello.txt"), []byte("Hello, World"), 0644) checkFatal(t, err) diff --git a/submodule.go b/submodule.go index 7c6c922..6923c61 100644 --- a/submodule.go +++ b/submodule.go @@ -318,10 +318,7 @@ func (repo *Repository) ReloadAllSubmodules(force bool) error { func (sub *Submodule) Update(init bool, opts *SubmoduleUpdateOptions) error { var copts C.git_submodule_update_options - err := populateSubmoduleUpdateOptions(&copts, opts) - if err != nil { - return err - } + populateSubmoduleUpdateOptions(&copts, opts) runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -334,22 +331,15 @@ func (sub *Submodule) Update(init bool, opts *SubmoduleUpdateOptions) error { return nil } -func populateSubmoduleUpdateOptions(ptr *C.git_submodule_update_options, opts *SubmoduleUpdateOptions) error { +func populateSubmoduleUpdateOptions(ptr *C.git_submodule_update_options, opts *SubmoduleUpdateOptions) { C.git_submodule_update_init_options(ptr, C.GIT_SUBMODULE_UPDATE_OPTIONS_VERSION) if opts == nil { - return nil + return } populateCheckoutOpts(&ptr.checkout_opts, opts.CheckoutOpts) populateRemoteCallbacks(&ptr.remote_callbacks, opts.RemoteCallbacks) ptr.clone_checkout_strategy = C.uint(opts.CloneCheckoutStrategy) - - sig, err := opts.Signature.toC() - if err != nil { - return err - } - ptr.signature = sig - - return nil + ptr.signature = opts.Signature.toC() } diff --git a/tag_test.go b/tag_test.go index 126cf6e..5ebd53d 100644 --- a/tag_test.go +++ b/tag_test.go @@ -2,8 +2,8 @@ package git import ( "os" - "testing" "time" + "testing" ) func TestCreateTag(t *testing.T) { diff --git a/vendor/libgit2 b/vendor/libgit2 new file mode 160000 index 0000000..04bdd97 --- /dev/null +++ b/vendor/libgit2 @@ -0,0 +1 @@ +Subproject commit 04bdd97f2b63793a8720fd19007911e946ba3c55