Update Go-Git to take advantage of LargeObjectThreshold (#16316)
Following the merging of https://github.com/go-git/go-git/pull/330 we can now add a setting to avoid go-git reading and caching large objects. Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
+79
@@ -0,0 +1,79 @@
|
||||
package dotgit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/format/objfile"
|
||||
"github.com/go-git/go-git/v5/utils/ioutil"
|
||||
)
|
||||
|
||||
var _ (plumbing.EncodedObject) = &EncodedObject{}
|
||||
|
||||
type EncodedObject struct {
|
||||
dir *DotGit
|
||||
h plumbing.Hash
|
||||
t plumbing.ObjectType
|
||||
sz int64
|
||||
}
|
||||
|
||||
func (e *EncodedObject) Hash() plumbing.Hash {
|
||||
return e.h
|
||||
}
|
||||
|
||||
func (e *EncodedObject) Reader() (io.ReadCloser, error) {
|
||||
f, err := e.dir.Object(e.h)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, plumbing.ErrObjectNotFound
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
r, err := objfile.NewReader(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, size, err := r.Header()
|
||||
if err != nil {
|
||||
_ = r.Close()
|
||||
return nil, err
|
||||
}
|
||||
if t != e.t {
|
||||
_ = r.Close()
|
||||
return nil, objfile.ErrHeader
|
||||
}
|
||||
if size != e.sz {
|
||||
_ = r.Close()
|
||||
return nil, objfile.ErrHeader
|
||||
}
|
||||
return ioutil.NewReadCloserWithCloser(r, f.Close), nil
|
||||
}
|
||||
|
||||
func (e *EncodedObject) SetType(plumbing.ObjectType) {}
|
||||
|
||||
func (e *EncodedObject) Type() plumbing.ObjectType {
|
||||
return e.t
|
||||
}
|
||||
|
||||
func (e *EncodedObject) Size() int64 {
|
||||
return e.sz
|
||||
}
|
||||
|
||||
func (e *EncodedObject) SetSize(int64) {}
|
||||
|
||||
func (e *EncodedObject) Writer() (io.WriteCloser, error) {
|
||||
return nil, fmt.Errorf("Not supported")
|
||||
}
|
||||
|
||||
func NewEncodedObject(dir *DotGit, h plumbing.Hash, t plumbing.ObjectType, size int64) *EncodedObject {
|
||||
return &EncodedObject{
|
||||
dir: dir,
|
||||
h: h,
|
||||
t: t,
|
||||
sz: size,
|
||||
}
|
||||
}
|
||||
+15
-6
@@ -204,9 +204,9 @@ func (s *ObjectStorage) packfile(idx idxfile.Index, pack plumbing.Hash) (*packfi
|
||||
|
||||
var p *packfile.Packfile
|
||||
if s.objectCache != nil {
|
||||
p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.objectCache)
|
||||
p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.objectCache, s.options.LargeObjectThreshold)
|
||||
} else {
|
||||
p = packfile.NewPackfile(idx, s.dir.Fs(), f)
|
||||
p = packfile.NewPackfile(idx, s.dir.Fs(), f, s.options.LargeObjectThreshold)
|
||||
}
|
||||
|
||||
return p, s.storePackfileInCache(pack, p)
|
||||
@@ -389,7 +389,6 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb
|
||||
return cacheObj, nil
|
||||
}
|
||||
|
||||
obj = s.NewEncodedObject()
|
||||
r, err := objfile.NewReader(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -402,6 +401,13 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if s.options.LargeObjectThreshold > 0 && size > s.options.LargeObjectThreshold {
|
||||
obj = dotgit.NewEncodedObject(s.dir, h, t, size)
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
obj = s.NewEncodedObject()
|
||||
|
||||
obj.SetType(t)
|
||||
obj.SetSize(size)
|
||||
w, err := obj.Writer()
|
||||
@@ -595,6 +601,7 @@ func (s *ObjectStorage) buildPackfileIters(
|
||||
return newPackfileIter(
|
||||
s.dir.Fs(), pack, t, seen, s.index[h],
|
||||
s.objectCache, s.options.KeepDescriptors,
|
||||
s.options.LargeObjectThreshold,
|
||||
)
|
||||
},
|
||||
}, nil
|
||||
@@ -684,6 +691,7 @@ func NewPackfileIter(
|
||||
idxFile billy.File,
|
||||
t plumbing.ObjectType,
|
||||
keepPack bool,
|
||||
largeObjectThreshold int64,
|
||||
) (storer.EncodedObjectIter, error) {
|
||||
idx := idxfile.NewMemoryIndex()
|
||||
if err := idxfile.NewDecoder(idxFile).Decode(idx); err != nil {
|
||||
@@ -695,7 +703,7 @@ func NewPackfileIter(
|
||||
}
|
||||
|
||||
seen := make(map[plumbing.Hash]struct{})
|
||||
return newPackfileIter(fs, f, t, seen, idx, nil, keepPack)
|
||||
return newPackfileIter(fs, f, t, seen, idx, nil, keepPack, largeObjectThreshold)
|
||||
}
|
||||
|
||||
func newPackfileIter(
|
||||
@@ -706,12 +714,13 @@ func newPackfileIter(
|
||||
index idxfile.Index,
|
||||
cache cache.Object,
|
||||
keepPack bool,
|
||||
largeObjectThreshold int64,
|
||||
) (storer.EncodedObjectIter, error) {
|
||||
var p *packfile.Packfile
|
||||
if cache != nil {
|
||||
p = packfile.NewPackfileWithCache(index, fs, f, cache)
|
||||
p = packfile.NewPackfileWithCache(index, fs, f, cache, largeObjectThreshold)
|
||||
} else {
|
||||
p = packfile.NewPackfile(index, fs, f)
|
||||
p = packfile.NewPackfile(index, fs, f, largeObjectThreshold)
|
||||
}
|
||||
|
||||
iter, err := p.GetByType(t)
|
||||
|
||||
+3
@@ -34,6 +34,9 @@ type Options struct {
|
||||
// MaxOpenDescriptors is the max number of file descriptors to keep
|
||||
// open. If KeepDescriptors is true, all file descriptors will remain open.
|
||||
MaxOpenDescriptors int
|
||||
// LargeObjectThreshold maximum object size (in bytes) that will be read in to memory.
|
||||
// If left unset or set to 0 there is no limit
|
||||
LargeObjectThreshold int64
|
||||
}
|
||||
|
||||
// NewStorage returns a new Storage backed by a given `fs.Filesystem` and cache.
|
||||
|
||||
Reference in New Issue
Block a user