M api/graph/model/blob.go => api/graph/model/blob.go +3 -4
@@ 5,7 5,6 @@ import (
"io/ioutil"
"unicode/utf8"
- "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
)
@@ 18,7 17,7 @@ type BinaryBlob struct {
Base64 string `json:"base64"`
blob *object.Blob
- repo *git.Repository
+ repo *RepoWrapper
}
func (BinaryBlob) IsObject() {}
@@ 33,13 32,13 @@ type TextBlob struct {
Text string `json:"text"`
blob *object.Blob
- repo *git.Repository
+ repo *RepoWrapper
}
func (TextBlob) IsObject() {}
func (TextBlob) IsBlob() {}
-func BlobFromObject(repo *git.Repository, obj *object.Blob) Object {
+func BlobFromObject(repo *RepoWrapper, obj *object.Blob) Object {
reader, err := obj.Reader()
if err != nil {
panic(err)
M api/graph/model/commit.go => api/graph/model/commit.go +2 -3
@@ 3,7 3,6 @@ package model
import (
"context"
- "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
)
@@ 14,7 13,7 @@ type Commit struct {
Raw string `json:"raw"`
commit *object.Commit
- repo *git.Repository
+ repo *RepoWrapper
}
func (Commit) IsObject() {}
@@ 70,7 69,7 @@ func (c *Commit) Parents() []*Commit {
return parents
}
-func CommitFromObject(repo *git.Repository, obj *object.Commit) *Commit {
+func CommitFromObject(repo *RepoWrapper, obj *object.Commit) *Commit {
return &Commit{
Type: ObjectTypeCommit,
ID: obj.ID().String(),
M api/graph/model/object.go => api/graph/model/object.go +3 -2
@@ 3,7 3,6 @@ package model
import (
"fmt"
- "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
@@ 12,8 11,10 @@ type Object interface {
IsObject()
}
-func LookupObject(repo *git.Repository, hash plumbing.Hash) (Object, error) {
+func LookupObject(repo *RepoWrapper, hash plumbing.Hash) (Object, error) {
+ repo.Lock()
obj, err := repo.Object(plumbing.AnyObject, hash)
+ repo.Unlock()
if err != nil {
return nil, fmt.Errorf("lookup object %s: %w", hash.String(), err)
}
M api/graph/model/reference.go => api/graph/model/reference.go +5 -2
@@ 10,11 10,14 @@ type Reference struct {
}
func (r *Reference) Follow() Object {
- ref, err := r.Repo.Repo().Reference(r.Ref.Name(), true)
+ repo := r.Repo.Repo()
+ repo.Lock()
+ ref, err := repo.Reference(r.Ref.Name(), true)
+ repo.Unlock()
if err != nil {
panic(err)
}
- obj, err := LookupObject(r.Repo.Repo(), ref.Hash())
+ obj, err := LookupObject(repo, ref.Hash())
if err != nil {
println(err)
panic(err)
M api/graph/model/repository.go => api/graph/model/repository.go +6 -4
@@ 27,23 27,25 @@ type Repository struct {
OwnerID int
alias string
- repo *git.Repository
+ repo *RepoWrapper
}
-func (r *Repository) Repo() *git.Repository {
+func (r *Repository) Repo() *RepoWrapper {
if r.repo != nil {
return r.repo
}
- var err error
- r.repo, err = git.PlainOpen(r.Path)
+ repo, err := git.PlainOpen(r.Path)
if err != nil {
panic(err)
}
+ r.repo = WrapRepo(repo)
return r.repo
}
func (r *Repository) Head() *Reference {
+ r.Repo().Lock()
ref, err := r.Repo().Head()
+ r.repo.Unlock()
if err != nil {
if err == plumbing.ErrReferenceNotFound {
return nil
A api/graph/model/repowrapper.go => api/graph/model/repowrapper.go +16 -0
@@ 0,0 1,16 @@
+package model
+
+import (
+ "sync"
+
+ "github.com/go-git/go-git/v5"
+)
+
+type RepoWrapper struct {
+ *git.Repository
+ sync.Mutex
+}
+
+func WrapRepo(repo *git.Repository) *RepoWrapper {
+ return &RepoWrapper{repo, sync.Mutex{}}
+}
M api/graph/model/tree.go => api/graph/model/tree.go +3 -4
@@ 3,7 3,6 @@ package model
import (
"sort"
- "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
@@ 15,7 14,7 @@ type Tree struct {
Raw string `json:"raw"`
tree *object.Tree
- repo *git.Repository
+ repo *RepoWrapper
}
func (Tree) IsObject() {}
@@ 25,7 24,7 @@ type TreeEntry struct {
Mode int `json:"mode"`
hash plumbing.Hash
- repo *git.Repository
+ repo *RepoWrapper
}
func (ent *TreeEntry) ID() string {
@@ 72,7 71,7 @@ func (tree *Tree) GetEntries() []*TreeEntry {
return qlents
}
-func TreeFromObject(repo *git.Repository, obj *object.Tree) *Tree {
+func TreeFromObject(repo *RepoWrapper, obj *object.Tree) *Tree {
return &Tree{
Type: ObjectTypeTree,
ID: obj.ID().String(),
M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +30 -11
@@ 172,11 172,14 @@ func (r *referenceResolver) Artifacts(ctx context.Context, obj *model.Reference,
cursor = gqlmodel.NewCursor(nil)
}
- ref, err := obj.Repo.Repo().Reference(obj.Ref.Name(), true)
+ repo := obj.Repo.Repo()
+ repo.Lock()
+ defer repo.Unlock()
+ ref, err := repo.Reference(obj.Ref.Name(), true)
if err != nil {
return nil, err
}
- o, err := obj.Repo.Repo().Object(plumbing.TagObject, ref.Hash())
+ o, err := repo.Object(plumbing.TagObject, ref.Hash())
if err == plumbing.ErrObjectNotFound {
return &model.ArtifactCursor{nil, cursor}, nil
} else if err != nil {
@@ 233,7 236,10 @@ func (r *repositoryResolver) Objects(ctx context.Context, obj *model.Repository,
}
func (r *repositoryResolver) References(ctx context.Context, obj *model.Repository, cursor *gqlmodel.Cursor) (*model.ReferenceCursor, error) {
- iter, err := obj.Repo().References()
+ repo := obj.Repo()
+ repo.Lock()
+ defer repo.Unlock()
+ iter, err := repo.References()
if err != nil {
return nil, err
}
@@ 286,11 292,14 @@ func (r *repositoryResolver) Log(ctx context.Context, obj *model.Repository, cur
}
}
+ repo := obj.Repo()
opts := &git.LogOptions{
Order: git.LogOrderCommitterTime,
}
if cursor.Next != "" {
- rev, err := obj.Repo().ResolveRevision(plumbing.Revision(cursor.Next))
+ repo.Lock()
+ rev, err := repo.ResolveRevision(plumbing.Revision(cursor.Next))
+ repo.Unlock()
if err != nil {
return nil, err
}
@@ 300,14 309,16 @@ func (r *repositoryResolver) Log(ctx context.Context, obj *model.Repository, cur
opts.From = *rev
}
- log, err := obj.Repo().Log(opts)
+ repo.Lock()
+ log, err := repo.Log(opts)
+ repo.Unlock()
if err != nil {
return nil, err
}
var commits []*model.Commit
log.ForEach(func(c *object.Commit) error {
- commits = append(commits, model.CommitFromObject(obj.Repo(), c))
+ commits = append(commits, model.CommitFromObject(repo, c))
if len(commits) == cursor.Count+1 {
return storer.ErrStop
}
@@ 333,14 344,19 @@ func (r *repositoryResolver) Path(ctx context.Context, obj *model.Repository, re
if revspec != nil {
rev = plumbing.Revision(*revspec)
}
- hash, err := obj.Repo().ResolveRevision(rev)
+ repo := obj.Repo()
+ repo.Lock()
+ hash, err := repo.ResolveRevision(rev)
+ repo.Unlock()
if err != nil {
return nil, err
}
if hash == nil {
return nil, fmt.Errorf("No such object")
}
- o, err := obj.Repo().Object(plumbing.CommitObject, *hash)
+ repo.Lock()
+ o, err := repo.Object(plumbing.CommitObject, *hash)
+ repo.Unlock()
if err != nil {
return nil, err
}
@@ 352,21 368,24 @@ func (r *repositoryResolver) Path(ctx context.Context, obj *model.Repository, re
if treeObj, err := commit.Tree(); err != nil {
panic(err)
} else {
- tree = model.TreeFromObject(obj.Repo(), treeObj)
+ tree = model.TreeFromObject(repo, treeObj)
}
return tree.Entry(path), nil
}
func (r *repositoryResolver) RevparseSingle(ctx context.Context, obj *model.Repository, revspec string) (*model.Commit, error) {
rev := plumbing.Revision(revspec)
- hash, err := obj.Repo().ResolveRevision(rev)
+ repo := obj.Repo()
+ repo.Lock()
+ hash, err := repo.ResolveRevision(rev)
+ repo.Unlock()
if err != nil {
return nil, err
}
if hash == nil {
return nil, fmt.Errorf("No such object")
}
- o, err := model.LookupObject(obj.Repo(), *hash)
+ o, err := model.LookupObject(repo, *hash)
if err != nil {
return nil, err
}