Fix the Cred interface #478

Merged
lhchavez merged 1 commits from fix-cred-interface into master 2020-02-23 10:24:07 -06:00
2 changed files with 73 additions and 21 deletions

View File

@ -7,7 +7,10 @@ package git
git_credtype_t _go_git_cred_credtype(git_cred *cred); git_credtype_t _go_git_cred_credtype(git_cred *cred);
*/ */
import "C" import "C"
import "unsafe" import (
"runtime"
"unsafe"
)
type CredType uint type CredType uint
@ -22,6 +25,12 @@ type Cred struct {
ptr *C.git_cred ptr *C.git_cred
} }
func newCred() *Cred {
cred := &Cred{}
runtime.SetFinalizer(cred, (*Cred).Free)
return cred
}
func (o *Cred) HasUsername() bool { func (o *Cred) HasUsername() bool {
if C.git_cred_has_username(o.ptr) == 1 { if C.git_cred_has_username(o.ptr) == 1 {
return true return true
@ -33,24 +42,36 @@ func (o *Cred) Type() CredType {
return (CredType)(C._go_git_cred_credtype(o.ptr)) return (CredType)(C._go_git_cred_credtype(o.ptr))
} }
func credFromC(ptr *C.git_cred) *Cred { func (o *Cred) Free() {
return &Cred{ptr} C.git_cred_free(o.ptr)
runtime.SetFinalizer(o, nil)
o.ptr = nil
} }
func NewCredUserpassPlaintext(username string, password string) (int, Cred) { func NewCredUserpassPlaintext(username string, password string) (*Cred, error) {
cred := Cred{} runtime.LockOSThread()
defer runtime.UnlockOSThread()
cred := newCred()
cusername := C.CString(username) cusername := C.CString(username)
defer C.free(unsafe.Pointer(cusername)) defer C.free(unsafe.Pointer(cusername))
cpassword := C.CString(password) cpassword := C.CString(password)
defer C.free(unsafe.Pointer(cpassword)) defer C.free(unsafe.Pointer(cpassword))
ret := C.git_cred_userpass_plaintext_new(&cred.ptr, cusername, cpassword) ret := C.git_cred_userpass_plaintext_new(&cred.ptr, cusername, cpassword)
return int(ret), cred if ret != 0 {
cred.Free()
return nil, MakeGitError(ret)
}
return cred, nil
} }
// NewCredSshKey creates new ssh credentials reading the public and private keys // NewCredSshKey creates new ssh credentials reading the public and private keys
// from the file system. // from the file system.
func NewCredSshKey(username string, publicKeyPath string, privateKeyPath string, passphrase string) (int, Cred) { func NewCredSshKey(username string, publicKeyPath string, privateKeyPath string, passphrase string) (*Cred, error) {
cred := Cred{} runtime.LockOSThread()
defer runtime.UnlockOSThread()
cred := newCred()
cusername := C.CString(username) cusername := C.CString(username)
defer C.free(unsafe.Pointer(cusername)) defer C.free(unsafe.Pointer(cusername))
cpublickey := C.CString(publicKeyPath) cpublickey := C.CString(publicKeyPath)
@ -60,13 +81,20 @@ func NewCredSshKey(username string, publicKeyPath string, privateKeyPath string,
cpassphrase := C.CString(passphrase) cpassphrase := C.CString(passphrase)
defer C.free(unsafe.Pointer(cpassphrase)) defer C.free(unsafe.Pointer(cpassphrase))
ret := C.git_cred_ssh_key_new(&cred.ptr, cusername, cpublickey, cprivatekey, cpassphrase) ret := C.git_cred_ssh_key_new(&cred.ptr, cusername, cpublickey, cprivatekey, cpassphrase)
return int(ret), cred if ret != 0 {
cred.Free()
return nil, MakeGitError(ret)
}
return cred, nil
} }
// NewCredSshKeyFromMemory creates new ssh credentials using the publicKey and privateKey // NewCredSshKeyFromMemory creates new ssh credentials using the publicKey and privateKey
// arguments as the values for the public and private keys. // arguments as the values for the public and private keys.
func NewCredSshKeyFromMemory(username string, publicKey string, privateKey string, passphrase string) (int, Cred) { func NewCredSshKeyFromMemory(username string, publicKey string, privateKey string, passphrase string) (*Cred, error) {
cred := Cred{} runtime.LockOSThread()
defer runtime.UnlockOSThread()
cred := newCred()
cusername := C.CString(username) cusername := C.CString(username)
defer C.free(unsafe.Pointer(cusername)) defer C.free(unsafe.Pointer(cusername))
cpublickey := C.CString(publicKey) cpublickey := C.CString(publicKey)
@ -76,19 +104,37 @@ func NewCredSshKeyFromMemory(username string, publicKey string, privateKey strin
cpassphrase := C.CString(passphrase) cpassphrase := C.CString(passphrase)
defer C.free(unsafe.Pointer(cpassphrase)) defer C.free(unsafe.Pointer(cpassphrase))
ret := C.git_cred_ssh_key_memory_new(&cred.ptr, cusername, cpublickey, cprivatekey, cpassphrase) ret := C.git_cred_ssh_key_memory_new(&cred.ptr, cusername, cpublickey, cprivatekey, cpassphrase)
return int(ret), cred if ret != 0 {
cred.Free()
return nil, MakeGitError(ret)
}
return cred, nil
} }
func NewCredSshKeyFromAgent(username string) (int, Cred) { func NewCredSshKeyFromAgent(username string) (*Cred, error) {
cred := Cred{} runtime.LockOSThread()
defer runtime.UnlockOSThread()
cred := newCred()
cusername := C.CString(username) cusername := C.CString(username)
defer C.free(unsafe.Pointer(cusername)) defer C.free(unsafe.Pointer(cusername))
ret := C.git_cred_ssh_key_from_agent(&cred.ptr, cusername) ret := C.git_cred_ssh_key_from_agent(&cred.ptr, cusername)
return int(ret), cred if ret != 0 {
cred.Free()
return nil, MakeGitError(ret)
}
return cred, nil
} }
func NewCredDefault() (int, Cred) { func NewCredDefault() (*Cred, error) {
cred := Cred{} runtime.LockOSThread()
defer runtime.UnlockOSThread()
cred := newCred()
ret := C.git_cred_default_new(&cred.ptr) ret := C.git_cred_default_new(&cred.ptr)
return int(ret), cred if ret != 0 {
cred.Free()
return nil, MakeGitError(ret)
}
return cred, nil
} }

View File

@ -51,7 +51,7 @@ const (
type TransportMessageCallback func(str string) ErrorCode type TransportMessageCallback func(str string) ErrorCode
type CompletionCallback func(RemoteCompletion) ErrorCode type CompletionCallback func(RemoteCompletion) ErrorCode
type CredentialsCallback func(url string, username_from_url string, allowed_types CredType) (ErrorCode, *Cred) type CredentialsCallback func(url string, username_from_url string, allowed_types CredType) (*Cred, error)
type TransferProgressCallback func(stats TransferProgress) ErrorCode type TransferProgressCallback func(stats TransferProgress) ErrorCode
type UpdateTipsCallback func(refname string, a *Oid, b *Oid) ErrorCode type UpdateTipsCallback func(refname string, a *Oid, b *Oid) ErrorCode
type CertificateCheckCallback func(cert *Certificate, valid bool, hostname string) ErrorCode type CertificateCheckCallback func(cert *Certificate, valid bool, hostname string) ErrorCode
@ -246,11 +246,17 @@ func credentialsCallback(_cred **C.git_cred, _url *C.char, _username_from_url *C
} }
url := C.GoString(_url) url := C.GoString(_url)
username_from_url := C.GoString(_username_from_url) username_from_url := C.GoString(_username_from_url)
ret, cred := callbacks.CredentialsCallback(url, username_from_url, (CredType)(allowed_types)) cred, err := callbacks.CredentialsCallback(url, username_from_url, (CredType)(allowed_types))
if err != nil {
if gitError, ok := err.(*GitError); ok {
return int(gitError.Code)
}
return C.GIT_EUSER
}
if cred != nil { if cred != nil {
*_cred = cred.ptr *_cred = cred.ptr
} }
return int(ret) return 0
} }
//export transferProgressCallback //export transferProgressCallback