summaryrefslogtreecommitdiff
path: root/remote.go
diff options
context:
space:
mode:
authorlhchavez <[email protected]>2021-09-05 15:44:18 -0700
committerGitHub <[email protected]>2021-09-05 15:44:18 -0700
commitf1fa96c7b7f548389c7560d3a1a0bce83be56c9f (patch)
treed78a98f00e1d1e1419ca14223784f15db2de2b18 /remote.go
parentdbe032c347b1a1308a4b880e7c5a06d8dfb4d507 (diff)
Add support for custom smart transports (#806)
This change adds support for git smart transports. This will be then used to implement http, https, and ssh transports that don't rely on the libgit2 library.
Diffstat (limited to 'remote.go')
-rw-r--r--remote.go114
1 files changed, 106 insertions, 8 deletions
diff --git a/remote.go b/remote.go
index c8076d5..fb70f55 100644
--- a/remote.go
+++ b/remote.go
@@ -15,6 +15,7 @@ import (
"reflect"
"runtime"
"strings"
+ "sync"
"unsafe"
)
@@ -174,6 +175,64 @@ type Remote struct {
repo *Repository
}
+type remotePointerList struct {
+ sync.RWMutex
+ // stores the Go pointers
+ pointers map[*C.git_remote]*Remote
+}
+
+func newRemotePointerList() *remotePointerList {
+ return &remotePointerList{
+ pointers: make(map[*C.git_remote]*Remote),
+ }
+}
+
+// track adds the given pointer to the list of pointers to track and
+// returns a pointer value which can be passed to C as an opaque
+// pointer.
+func (v *remotePointerList) track(remote *Remote) {
+ v.Lock()
+ v.pointers[remote.ptr] = remote
+ v.Unlock()
+
+ runtime.SetFinalizer(remote, (*Remote).Free)
+}
+
+// untrack stops tracking the git_remote pointer.
+func (v *remotePointerList) untrack(remote *Remote) {
+ v.Lock()
+ delete(v.pointers, remote.ptr)
+ v.Unlock()
+}
+
+// clear stops tracking all the git_remote pointers.
+func (v *remotePointerList) clear() {
+ v.Lock()
+ var remotes []*Remote
+ for remotePtr, remote := range v.pointers {
+ remotes = append(remotes, remote)
+ delete(v.pointers, remotePtr)
+ }
+ v.Unlock()
+
+ for _, remote := range remotes {
+ remote.free()
+ }
+}
+
+// get retrieves the pointer from the given *git_remote.
+func (v *remotePointerList) get(ptr *C.git_remote) (*Remote, bool) {
+ v.RLock()
+ defer v.RUnlock()
+
+ r, ok := v.pointers[ptr]
+ if !ok {
+ return nil, false
+ }
+
+ return r, true
+}
+
type CertificateKind uint
const (
@@ -509,17 +568,42 @@ func RemoteIsValidName(name string) bool {
return C.git_remote_is_valid_name(cname) == 1
}
-// Free releases the resources of the Remote.
-func (r *Remote) Free() {
+// free releases the resources of the Remote.
+func (r *Remote) free() {
runtime.SetFinalizer(r, nil)
C.git_remote_free(r.ptr)
r.ptr = nil
r.repo = nil
}
+// Free releases the resources of the Remote.
+func (r *Remote) Free() {
+ r.repo.Remotes.untrackRemote(r)
+ r.free()
+}
+
type RemoteCollection struct {
doNotCompare
repo *Repository
+
+ sync.RWMutex
+ remotes map[*C.git_remote]*Remote
+}
+
+func (c *RemoteCollection) trackRemote(r *Remote) {
+ c.Lock()
+ c.remotes[r.ptr] = r
+ c.Unlock()
+
+ remotePointers.track(r)
+}
+
+func (c *RemoteCollection) untrackRemote(r *Remote) {
+ c.Lock()
+ delete(c.remotes, r.ptr)
+ c.Unlock()
+
+ remotePointers.untrack(r)
}
func (c *RemoteCollection) List() ([]string, error) {
@@ -554,7 +638,7 @@ func (c *RemoteCollection) Create(name string, url string) (*Remote, error) {
if ret < 0 {
return nil, MakeGitError(ret)
}
- runtime.SetFinalizer(remote, (*Remote).Free)
+ c.trackRemote(remote)
return remote, nil
}
@@ -570,13 +654,13 @@ func (c *RemoteCollection) CreateWithOptions(url string, option *RemoteCreateOpt
copts := populateRemoteCreateOptions(&C.git_remote_create_options{}, option, c.repo)
defer freeRemoteCreateOptions(copts)
+
ret := C.git_remote_create_with_opts(&remote.ptr, curl, copts)
runtime.KeepAlive(c.repo)
if ret < 0 {
return nil, MakeGitError(ret)
}
-
- runtime.SetFinalizer(remote, (*Remote).Free)
+ c.trackRemote(remote)
return remote, nil
}
@@ -612,7 +696,7 @@ func (c *RemoteCollection) CreateWithFetchspec(name string, url string, fetch st
if ret < 0 {
return nil, MakeGitError(ret)
}
- runtime.SetFinalizer(remote, (*Remote).Free)
+ c.trackRemote(remote)
return remote, nil
}
@@ -629,7 +713,7 @@ func (c *RemoteCollection) CreateAnonymous(url string) (*Remote, error) {
if ret < 0 {
return nil, MakeGitError(ret)
}
- runtime.SetFinalizer(remote, (*Remote).Free)
+ c.trackRemote(remote)
return remote, nil
}
@@ -646,10 +730,24 @@ func (c *RemoteCollection) Lookup(name string) (*Remote, error) {
if ret < 0 {
return nil, MakeGitError(ret)
}
- runtime.SetFinalizer(remote, (*Remote).Free)
+ c.trackRemote(remote)
return remote, nil
}
+func (c *RemoteCollection) Free() {
+ var remotes []*Remote
+ c.Lock()
+ for remotePtr, remote := range c.remotes {
+ remotes = append(remotes, remote)
+ delete(c.remotes, remotePtr)
+ }
+ c.Unlock()
+
+ for _, remote := range remotes {
+ remotePointers.untrack(remote)
+ }
+}
+
func (o *Remote) Name() string {
s := C.git_remote_name(o.ptr)
runtime.KeepAlive(o)