commit
d300110b85
10
branch.go
10
branch.go
|
@ -96,7 +96,10 @@ func (repo *Repository) CreateBranch(branchName string, target *Commit, force bo
|
|||
cBranchName := C.CString(branchName)
|
||||
cForce := cbool(force)
|
||||
|
||||
cSignature := signature.toC()
|
||||
cSignature, err := signature.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.git_signature_free(cSignature)
|
||||
|
||||
var cmsg *C.char
|
||||
|
@ -133,7 +136,10 @@ func (b *Branch) Move(newBranchName string, force bool, signature *Signature, ms
|
|||
cNewBranchName := C.CString(newBranchName)
|
||||
cForce := cbool(force)
|
||||
|
||||
cSignature := signature.toC()
|
||||
cSignature, err := signature.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.git_signature_free(cSignature)
|
||||
|
||||
var cmsg *C.char
|
||||
|
|
17
checkout.go
17
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
|
||||
CheckotUpdateOnly CheckoutStrategy = C.GIT_CHECKOUT_UPDATE_ONLY // Only update existing files, don't create new ones
|
||||
CheckoutUpdateOnly 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
|
||||
CheckooutDisablePathspecMatch CheckoutStrategy = C.GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH // Treat pathspec as simple list of exact match file paths
|
||||
CheckoutDisablePathspecMatch 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)
|
||||
|
@ -40,6 +40,19 @@ type CheckoutOpts struct {
|
|||
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
|
||||
}
|
||||
|
||||
func (opts *CheckoutOpts) toC() *C.git_checkout_options {
|
||||
if opts == nil {
|
||||
return nil
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package git
|
||||
|
||||
/*
|
||||
#include <git2.h>
|
||||
*/
|
||||
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
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
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)
|
||||
}
|
||||
}
|
52
commit.go
52
commit.go
|
@ -9,8 +9,6 @@ import "C"
|
|||
|
||||
import (
|
||||
"runtime"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Commit
|
||||
|
@ -23,6 +21,10 @@ 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
|
||||
|
||||
|
@ -68,49 +70,3 @@ 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
|
||||
}
|
||||
|
|
|
@ -57,6 +57,10 @@ 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)
|
||||
|
@ -67,7 +71,7 @@ func updateReadme(t *testing.T, repo *Repository, content string) (*Oid, *Oid) {
|
|||
}
|
||||
|
||||
tmpfile := "README"
|
||||
err = ioutil.WriteFile(path.Join(path.Dir(path.Dir(repo.Path())), tmpfile), []byte(content), 0644)
|
||||
err = ioutil.WriteFile(pathInRepo(repo, tmpfile), []byte(content), 0644)
|
||||
checkFatal(t, err)
|
||||
|
||||
idx, err := repo.Index()
|
||||
|
|
|
@ -29,8 +29,8 @@ type gitObject struct {
|
|||
repo *Repository
|
||||
}
|
||||
|
||||
func (t ObjectType) String() (string) {
|
||||
switch (t) {
|
||||
func (t ObjectType) String() string {
|
||||
switch t {
|
||||
case ObjectAny:
|
||||
return "Any"
|
||||
case ObjectBad:
|
||||
|
|
4
odb.go
4
odb.go
|
@ -111,7 +111,7 @@ 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,
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
15
reference.go
15
reference.go
|
@ -36,7 +36,10 @@ func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string)
|
|||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
csig := sig.toC()
|
||||
csig, err := sig.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.free(unsafe.Pointer(csig))
|
||||
|
||||
var cmsg *C.char
|
||||
|
@ -61,7 +64,10 @@ func (v *Reference) SetTarget(target *Oid, sig *Signature, msg string) (*Referen
|
|||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
csig := sig.toC()
|
||||
csig, err := sig.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.free(unsafe.Pointer(csig))
|
||||
|
||||
var cmsg *C.char
|
||||
|
@ -99,7 +105,10 @@ func (v *Reference) Rename(name string, force bool, sig *Signature, msg string)
|
|||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
|
||||
csig := sig.toC()
|
||||
csig, err := sig.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.free(unsafe.Pointer(csig))
|
||||
|
||||
var cmsg *C.char
|
||||
|
|
10
remote.go
10
remote.go
|
@ -604,7 +604,10 @@ func (o *Remote) Fetch(refspecs []string, sig *Signature, msg string) error {
|
|||
|
||||
var csig *C.git_signature = nil
|
||||
if sig != nil {
|
||||
csig = sig.toC()
|
||||
csig, err := sig.toC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer C.free(unsafe.Pointer(csig))
|
||||
}
|
||||
|
||||
|
@ -696,7 +699,10 @@ 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 = sig.toC()
|
||||
csig, err := sig.toC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer C.free(unsafe.Pointer(csig))
|
||||
}
|
||||
|
||||
|
|
|
@ -210,7 +210,10 @@ func (v *Repository) SetHead(refname string, sig *Signature, msg string) error {
|
|||
cname := C.CString(refname)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
|
||||
csig := sig.toC()
|
||||
csig, err := sig.toC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer C.free(unsafe.Pointer(csig))
|
||||
|
||||
var cmsg *C.char
|
||||
|
@ -230,7 +233,10 @@ func (v *Repository) SetHead(refname string, sig *Signature, msg string) error {
|
|||
}
|
||||
|
||||
func (v *Repository) SetHeadDetached(id *Oid, sig *Signature, msg string) error {
|
||||
csig := sig.toC()
|
||||
csig, err := sig.toC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer C.free(unsafe.Pointer(csig))
|
||||
|
||||
var cmsg *C.char
|
||||
|
@ -253,7 +259,10 @@ func (v *Repository) CreateReference(name string, id *Oid, force bool, sig *Sign
|
|||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
|
||||
csig := sig.toC()
|
||||
csig, err := sig.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.free(unsafe.Pointer(csig))
|
||||
|
||||
var cmsg *C.char
|
||||
|
@ -284,7 +293,10 @@ func (v *Repository) CreateSymbolicReference(name, target string, force bool, si
|
|||
ctarget := C.CString(target)
|
||||
defer C.free(unsafe.Pointer(ctarget))
|
||||
|
||||
csig := sig.toC()
|
||||
csig, err := sig.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.free(unsafe.Pointer(csig))
|
||||
|
||||
var cmsg *C.char
|
||||
|
@ -352,10 +364,16 @@ func (v *Repository) CreateCommit(
|
|||
parentsarg = &cparents[0]
|
||||
}
|
||||
|
||||
authorSig := author.toC()
|
||||
authorSig, err := author.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.git_signature_free(authorSig)
|
||||
|
||||
committerSig := committer.toC()
|
||||
committerSig, err := committer.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.git_signature_free(committerSig)
|
||||
|
||||
runtime.LockOSThread()
|
||||
|
@ -384,7 +402,10 @@ func (v *Repository) CreateTag(
|
|||
cmessage := C.CString(message)
|
||||
defer C.free(unsafe.Pointer(cmessage))
|
||||
|
||||
taggerSig := tagger.toC()
|
||||
taggerSig, err := tagger.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.git_signature_free(taggerSig)
|
||||
|
||||
ctarget := commit.gitObject.ptr
|
||||
|
@ -546,10 +567,16 @@ func (v *Repository) CreateNote(
|
|||
defer C.free(unsafe.Pointer(cref))
|
||||
}
|
||||
|
||||
authorSig := author.toC()
|
||||
authorSig, err := author.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.git_signature_free(authorSig)
|
||||
|
||||
committerSig := committer.toC()
|
||||
committerSig, err := committer.toC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.git_signature_free(committerSig)
|
||||
|
||||
cnote := C.CString(note)
|
||||
|
@ -601,10 +628,16 @@ func (v *Repository) RemoveNote(ref string, author, committer *Signature, id *Oi
|
|||
defer C.free(unsafe.Pointer(cref))
|
||||
}
|
||||
|
||||
authorSig := author.toC()
|
||||
authorSig, err := author.toC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer C.git_signature_free(authorSig)
|
||||
|
||||
committerSig := committer.toC()
|
||||
committerSig, err := committer.toC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer C.git_signature_free(committerSig)
|
||||
|
||||
runtime.LockOSThread()
|
||||
|
@ -630,3 +663,36 @@ 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
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package git
|
||||
|
||||
/*
|
||||
#include <git2.h>
|
||||
*/
|
||||
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
|
||||
}
|
|
@ -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,
|
||||
|
@ -173,7 +173,6 @@ 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)
|
||||
|
|
|
@ -12,6 +12,11 @@ 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)
|
||||
|
||||
|
|
18
submodule.go
18
submodule.go
|
@ -318,7 +318,10 @@ func (repo *Repository) ReloadAllSubmodules(force bool) error {
|
|||
|
||||
func (sub *Submodule) Update(init bool, opts *SubmoduleUpdateOptions) error {
|
||||
var copts C.git_submodule_update_options
|
||||
populateSubmoduleUpdateOptions(&copts, opts)
|
||||
err := populateSubmoduleUpdateOptions(&copts, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
@ -331,15 +334,22 @@ func (sub *Submodule) Update(init bool, opts *SubmoduleUpdateOptions) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func populateSubmoduleUpdateOptions(ptr *C.git_submodule_update_options, opts *SubmoduleUpdateOptions) {
|
||||
func populateSubmoduleUpdateOptions(ptr *C.git_submodule_update_options, opts *SubmoduleUpdateOptions) error {
|
||||
C.git_submodule_update_init_options(ptr, C.GIT_SUBMODULE_UPDATE_OPTIONS_VERSION)
|
||||
|
||||
if opts == nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
populateCheckoutOpts(&ptr.checkout_opts, opts.CheckoutOpts)
|
||||
populateRemoteCallbacks(&ptr.remote_callbacks, opts.RemoteCallbacks)
|
||||
ptr.clone_checkout_strategy = C.uint(opts.CloneCheckoutStrategy)
|
||||
ptr.signature = opts.Signature.toC()
|
||||
|
||||
sig, err := opts.Signature.toC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.signature = sig
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ package git
|
|||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCreateTag(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue