mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-28 16:02:01 +03:00
Bump go-git
This commit is contained in:
236
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/dotgit/dotgit.go
generated
vendored
236
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/dotgit/dotgit.go
generated
vendored
@ -7,19 +7,22 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
stdioutil "io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
"github.com/jesseduffield/go-git/v5/plumbing"
|
||||
"github.com/jesseduffield/go-git/v5/plumbing/hash"
|
||||
"github.com/jesseduffield/go-git/v5/storage"
|
||||
"github.com/jesseduffield/go-git/v5/utils/ioutil"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/go-git/go-billy/v5/helper/chroot"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -38,6 +41,7 @@ const (
|
||||
remotesPath = "remotes"
|
||||
logsPath = "logs"
|
||||
worktreesPath = "worktrees"
|
||||
alternatesPath = "alternates"
|
||||
|
||||
tmpPackedRefsPrefix = "._packed-refs"
|
||||
|
||||
@ -68,6 +72,9 @@ var (
|
||||
// ErrIsDir is returned when a reference file is attempting to be read,
|
||||
// but the path specified is a directory.
|
||||
ErrIsDir = errors.New("reference path is a directory")
|
||||
// ErrEmptyRefFile is returned when a reference file is attempted to be read,
|
||||
// but the file is empty
|
||||
ErrEmptyRefFile = errors.New("ref file is empty")
|
||||
)
|
||||
|
||||
// Options holds configuration for the storage.
|
||||
@ -78,6 +85,10 @@ type Options struct {
|
||||
// KeepDescriptors makes the file descriptors to be reused but they will
|
||||
// need to be manually closed calling Close().
|
||||
KeepDescriptors bool
|
||||
// AlternatesFS provides the billy filesystem to be used for Git Alternates.
|
||||
// If none is provided, it falls back to using the underlying instance used for
|
||||
// DotGit.
|
||||
AlternatesFS billy.Filesystem
|
||||
}
|
||||
|
||||
// The DotGit type represents a local git repository on disk. This
|
||||
@ -241,7 +252,7 @@ func (d *DotGit) objectPacks() ([]plumbing.Hash, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
h := plumbing.NewHash(n[5 : len(n)-5]) //pack-(hash).pack
|
||||
h := plumbing.NewHash(n[5 : len(n)-5]) // pack-(hash).pack
|
||||
if h.IsZero() {
|
||||
// Ignore files with badly-formatted names.
|
||||
continue
|
||||
@ -552,8 +563,8 @@ func (d *DotGit) hasPack(h plumbing.Hash) error {
|
||||
}
|
||||
|
||||
func (d *DotGit) objectPath(h plumbing.Hash) string {
|
||||
hash := h.String()
|
||||
return d.fs.Join(objectsPath, hash[0:2], hash[2:40])
|
||||
hex := h.String()
|
||||
return d.fs.Join(objectsPath, hex[0:2], hex[2:hash.HexSize])
|
||||
}
|
||||
|
||||
// incomingObjectPath is intended to add support for a git pre-receive hook
|
||||
@ -563,15 +574,16 @@ func (d *DotGit) objectPath(h plumbing.Hash) string {
|
||||
//
|
||||
// More on git hooks found here : https://git-scm.com/docs/githooks
|
||||
// More on 'quarantine'/incoming directory here:
|
||||
// https://git-scm.com/docs/git-receive-pack
|
||||
//
|
||||
// https://git-scm.com/docs/git-receive-pack
|
||||
func (d *DotGit) incomingObjectPath(h plumbing.Hash) string {
|
||||
hString := h.String()
|
||||
|
||||
if d.incomingDirName == "" {
|
||||
return d.fs.Join(objectsPath, hString[0:2], hString[2:40])
|
||||
return d.fs.Join(objectsPath, hString[0:2], hString[2:hash.HexSize])
|
||||
}
|
||||
|
||||
return d.fs.Join(objectsPath, d.incomingDirName, hString[0:2], hString[2:40])
|
||||
return d.fs.Join(objectsPath, d.incomingDirName, hString[0:2], hString[2:hash.HexSize])
|
||||
}
|
||||
|
||||
// hasIncomingObjects searches for an incoming directory and keeps its name
|
||||
@ -581,7 +593,9 @@ func (d *DotGit) hasIncomingObjects() bool {
|
||||
directoryContents, err := d.fs.ReadDir(objectsPath)
|
||||
if err == nil {
|
||||
for _, file := range directoryContents {
|
||||
if strings.HasPrefix(file.Name(), "incoming-") && file.IsDir() {
|
||||
if file.IsDir() && (strings.HasPrefix(file.Name(), "tmp_objdir-incoming-") ||
|
||||
// Before Git 2.35 incoming commits directory had another prefix
|
||||
strings.HasPrefix(file.Name(), "incoming-")) {
|
||||
d.incomingDirName = file.Name()
|
||||
}
|
||||
}
|
||||
@ -645,23 +659,38 @@ func (d *DotGit) ObjectDelete(h plumbing.Hash) error {
|
||||
}
|
||||
|
||||
func (d *DotGit) readReferenceFrom(rd io.Reader, name string) (ref *plumbing.Reference, err error) {
|
||||
b, err := stdioutil.ReadAll(rd)
|
||||
b, err := io.ReadAll(rd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(b) == 0 {
|
||||
return nil, ErrEmptyRefFile
|
||||
}
|
||||
|
||||
line := strings.TrimSpace(string(b))
|
||||
return plumbing.NewReferenceFromStrings(name, line), nil
|
||||
}
|
||||
|
||||
// checkReferenceAndTruncate reads the reference from the given file, or the `pack-refs` file if
|
||||
// the file was empty. Then it checks that the old reference matches the stored reference and
|
||||
// truncates the file.
|
||||
func (d *DotGit) checkReferenceAndTruncate(f billy.File, old *plumbing.Reference) error {
|
||||
if old == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ref, err := d.readReferenceFrom(f, old.Name().String())
|
||||
if errors.Is(err, ErrEmptyRefFile) {
|
||||
// This may happen if the reference is being read from a newly created file.
|
||||
// In that case, try getting the reference from the packed refs file.
|
||||
ref, err = d.packedRef(old.Name())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ref.Hash() != old.Hash() {
|
||||
return storage.ErrReferenceHasChanged
|
||||
}
|
||||
@ -690,7 +719,11 @@ func (d *DotGit) SetRef(r, old *plumbing.Reference) error {
|
||||
// Symbolic references are resolved and included in the output.
|
||||
func (d *DotGit) Refs() ([]*plumbing.Reference, error) {
|
||||
var refs []*plumbing.Reference
|
||||
var seen = make(map[plumbing.ReferenceName]bool)
|
||||
seen := make(map[plumbing.ReferenceName]bool)
|
||||
if err := d.addRefFromHEAD(&refs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -699,10 +732,6 @@ func (d *DotGit) Refs() ([]*plumbing.Reference, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := d.addRefFromHEAD(&refs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
@ -716,48 +745,56 @@ func (d *DotGit) Ref(name plumbing.ReferenceName) (*plumbing.Reference, error) {
|
||||
return d.packedRef(name)
|
||||
}
|
||||
|
||||
func (d *DotGit) findPackedRefsInFile(f billy.File) ([]*plumbing.Reference, error) {
|
||||
func (d *DotGit) findPackedRefsInFile(f billy.File, recv refsRecv) error {
|
||||
s := bufio.NewScanner(f)
|
||||
var refs []*plumbing.Reference
|
||||
for s.Scan() {
|
||||
ref, err := d.processLine(s.Text())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
if ref != nil {
|
||||
refs = append(refs, ref)
|
||||
if !recv(ref) {
|
||||
// skip parse
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return refs, s.Err()
|
||||
if err := s.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DotGit) findPackedRefs() (r []*plumbing.Reference, err error) {
|
||||
// refsRecv: returning true means that the reference continues to be resolved, otherwise it is stopped, which will speed up the lookup of a single reference.
|
||||
type refsRecv func(*plumbing.Reference) bool
|
||||
|
||||
func (d *DotGit) findPackedRefs(recv refsRecv) error {
|
||||
f, err := d.fs.Open(packedRefsPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(f, &err)
|
||||
return d.findPackedRefsInFile(f)
|
||||
return d.findPackedRefsInFile(f, recv)
|
||||
}
|
||||
|
||||
func (d *DotGit) packedRef(name plumbing.ReferenceName) (*plumbing.Reference, error) {
|
||||
refs, err := d.findPackedRefs()
|
||||
if err != nil {
|
||||
var ref *plumbing.Reference
|
||||
if err := d.findPackedRefs(func(r *plumbing.Reference) bool {
|
||||
if r != nil && r.Name() == name {
|
||||
ref = r
|
||||
// ref found
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, ref := range refs {
|
||||
if ref.Name() == name {
|
||||
return ref, nil
|
||||
}
|
||||
if ref != nil {
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
return nil, plumbing.ErrReferenceNotFound
|
||||
}
|
||||
|
||||
@ -777,38 +814,27 @@ func (d *DotGit) RemoveRef(name plumbing.ReferenceName) error {
|
||||
return d.rewritePackedRefsWithoutRef(name)
|
||||
}
|
||||
|
||||
func (d *DotGit) addRefsFromPackedRefs(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) (err error) {
|
||||
packedRefs, err := d.findPackedRefs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ref := range packedRefs {
|
||||
if !seen[ref.Name()] {
|
||||
*refs = append(*refs, ref)
|
||||
seen[ref.Name()] = true
|
||||
func refsRecvFunc(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) refsRecv {
|
||||
return func(r *plumbing.Reference) bool {
|
||||
if r != nil && !seen[r.Name()] {
|
||||
*refs = append(*refs, r)
|
||||
seen[r.Name()] = true
|
||||
}
|
||||
return true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DotGit) addRefsFromPackedRefs(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) (err error) {
|
||||
return d.findPackedRefs(refsRecvFunc(refs, seen))
|
||||
}
|
||||
|
||||
func (d *DotGit) addRefsFromPackedRefsFile(refs *[]*plumbing.Reference, f billy.File, seen map[plumbing.ReferenceName]bool) (err error) {
|
||||
packedRefs, err := d.findPackedRefsInFile(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ref := range packedRefs {
|
||||
if !seen[ref.Name()] {
|
||||
*refs = append(*refs, ref)
|
||||
seen[ref.Name()] = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return d.findPackedRefsInFile(f, refsRecvFunc(refs, seen))
|
||||
}
|
||||
|
||||
func (d *DotGit) openAndLockPackedRefs(doCreate bool) (
|
||||
pr billy.File, err error) {
|
||||
pr billy.File, err error,
|
||||
) {
|
||||
var f billy.File
|
||||
defer func() {
|
||||
if err != nil && f != nil {
|
||||
@ -943,6 +969,7 @@ func (d *DotGit) walkReferencesTree(refs *[]*plumbing.Reference, relPath []strin
|
||||
files, err := d.fs.ReadDir(d.fs.Join(relPath...))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// a race happened, and our directory is gone now
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -960,6 +987,10 @@ func (d *DotGit) walkReferencesTree(refs *[]*plumbing.Reference, relPath []strin
|
||||
}
|
||||
|
||||
ref, err := d.readReferenceFile(".", strings.Join(newRelPath, "/"))
|
||||
if os.IsNotExist(err) {
|
||||
// a race happened, and our file is gone now
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1008,7 +1039,7 @@ func (d *DotGit) readReferenceFile(path, name string) (ref *plumbing.Reference,
|
||||
|
||||
func (d *DotGit) CountLooseRefs() (int, error) {
|
||||
var refs []*plumbing.Reference
|
||||
var seen = make(map[plumbing.ReferenceName]bool)
|
||||
seen := make(map[plumbing.ReferenceName]bool)
|
||||
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -1101,38 +1132,93 @@ func (d *DotGit) Module(name string) (billy.Filesystem, error) {
|
||||
return d.fs.Chroot(d.fs.Join(modulePath, name))
|
||||
}
|
||||
|
||||
func (d *DotGit) AddAlternate(remote string) error {
|
||||
altpath := d.fs.Join(objectsPath, infoPath, alternatesPath)
|
||||
|
||||
f, err := d.fs.OpenFile(altpath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0640)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot open file: %w", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// locking in windows throws an error, based on comments
|
||||
// https://github.com/go-git/go-git/pull/860#issuecomment-1751823044
|
||||
// do not lock on windows platform.
|
||||
if runtime.GOOS != "windows" {
|
||||
if err = f.Lock(); err != nil {
|
||||
return fmt.Errorf("cannot lock file: %w", err)
|
||||
}
|
||||
defer f.Unlock()
|
||||
}
|
||||
|
||||
line := path.Join(remote, objectsPath) + "\n"
|
||||
_, err = io.WriteString(f, line)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing 'alternates' file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Alternates returns DotGit(s) based off paths in objects/info/alternates if
|
||||
// available. This can be used to checks if it's a shared repository.
|
||||
func (d *DotGit) Alternates() ([]*DotGit, error) {
|
||||
altpath := d.fs.Join("objects", "info", "alternates")
|
||||
altpath := d.fs.Join(objectsPath, infoPath, alternatesPath)
|
||||
f, err := d.fs.Open(altpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fs := d.options.AlternatesFS
|
||||
if fs == nil {
|
||||
fs = d.fs
|
||||
}
|
||||
|
||||
var alternates []*DotGit
|
||||
seen := make(map[string]struct{})
|
||||
|
||||
// Read alternate paths line-by-line and create DotGit objects.
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
path := scanner.Text()
|
||||
if !filepath.IsAbs(path) {
|
||||
// For relative paths, we can perform an internal conversion to
|
||||
// slash so that they work cross-platform.
|
||||
slashPath := filepath.ToSlash(path)
|
||||
// If the path is not absolute, it must be relative to object
|
||||
// database (.git/objects/info).
|
||||
// https://www.kernel.org/pub/software/scm/git/docs/gitrepository-layout.html
|
||||
// Hence, derive a path relative to DotGit's root.
|
||||
// "../../../reponame/.git/" -> "../../reponame/.git"
|
||||
// Remove the first ../
|
||||
relpath := filepath.Join(strings.Split(slashPath, "/")[1:]...)
|
||||
normalPath := filepath.FromSlash(relpath)
|
||||
path = filepath.Join(d.fs.Root(), normalPath)
|
||||
|
||||
// Avoid creating multiple dotgits for the same alternative path.
|
||||
if _, ok := seen[path]; ok {
|
||||
continue
|
||||
}
|
||||
fs := osfs.New(filepath.Dir(path))
|
||||
alternates = append(alternates, New(fs))
|
||||
|
||||
seen[path] = struct{}{}
|
||||
|
||||
if filepath.IsAbs(path) {
|
||||
// Handling absolute paths should be straight-forward. However, the default osfs (Chroot)
|
||||
// tries to concatenate an abs path with the root path in some operations (e.g. Stat),
|
||||
// which leads to unexpected errors. Therefore, make the path relative to the current FS instead.
|
||||
if reflect.TypeOf(fs) == reflect.TypeOf(&chroot.ChrootHelper{}) {
|
||||
path, err = filepath.Rel(fs.Root(), path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot make path %q relative: %w", path, err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// By Git conventions, relative paths should be based on the object database (.git/objects/info)
|
||||
// location as per: https://www.kernel.org/pub/software/scm/git/docs/gitrepository-layout.html
|
||||
// However, due to the nature of go-git and its filesystem handling via Billy, paths cannot
|
||||
// cross its "chroot boundaries". Therefore, ignore any "../" and treat the path from the
|
||||
// fs root. If this is not correct based on the dotgit fs, set a different one via AlternatesFS.
|
||||
abs := filepath.Join(string(filepath.Separator), filepath.ToSlash(path))
|
||||
path = filepath.FromSlash(abs)
|
||||
}
|
||||
|
||||
// Aligns with upstream behavior: exit if target path is not a valid directory.
|
||||
if fi, err := fs.Stat(path); err != nil || !fi.IsDir() {
|
||||
return nil, fmt.Errorf("invalid object directory %q: %w", path, err)
|
||||
}
|
||||
afs, err := fs.Chroot(filepath.Dir(path))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot chroot %q: %w", path, err)
|
||||
}
|
||||
alternates = append(alternates, New(afs))
|
||||
}
|
||||
|
||||
if err = scanner.Err(); err != nil {
|
||||
|
79
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/dotgit/reader.go
generated
vendored
Normal file
79
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/dotgit/reader.go
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
package dotgit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/jesseduffield/go-git/v5/plumbing"
|
||||
"github.com/jesseduffield/go-git/v5/plumbing/format/objfile"
|
||||
"github.com/jesseduffield/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,
|
||||
}
|
||||
}
|
5
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/dotgit/writers.go
generated
vendored
5
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/dotgit/writers.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
||||
"github.com/jesseduffield/go-git/v5/plumbing/format/idxfile"
|
||||
"github.com/jesseduffield/go-git/v5/plumbing/format/objfile"
|
||||
"github.com/jesseduffield/go-git/v5/plumbing/format/packfile"
|
||||
"github.com/jesseduffield/go-git/v5/plumbing/hash"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
)
|
||||
@ -277,8 +278,8 @@ func (w *ObjectWriter) Close() error {
|
||||
}
|
||||
|
||||
func (w *ObjectWriter) save() error {
|
||||
hash := w.Hash().String()
|
||||
file := w.fs.Join(objectsPath, hash[0:2], hash[2:40])
|
||||
hex := w.Hash().String()
|
||||
file := w.fs.Join(objectsPath, hex[0:2], hex[2:hash.HexSize])
|
||||
|
||||
return w.fs.Rename(w.f.Name(), file)
|
||||
}
|
||||
|
2
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/index.go
generated
vendored
2
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/index.go
generated
vendored
@ -48,7 +48,7 @@ func (s *IndexStorage) Index() (i *index.Index, err error) {
|
||||
|
||||
defer ioutil.CheckClose(f, &err)
|
||||
|
||||
d := index.NewDecoder(bufio.NewReader(f))
|
||||
d := index.NewDecoder(f)
|
||||
err = d.Decode(idx)
|
||||
return idx, err
|
||||
}
|
||||
|
58
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/object.go
generated
vendored
58
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/object.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/jesseduffield/go-git/v5/plumbing"
|
||||
@ -145,6 +146,19 @@ func (s *ObjectStorage) SetEncodedObject(o plumbing.EncodedObject) (h plumbing.H
|
||||
return o.Hash(), err
|
||||
}
|
||||
|
||||
// LazyWriter returns a lazy ObjectWriter that is bound to a DotGit file.
|
||||
// It first write the header passing on the object type and size, so
|
||||
// that the object contents can be written later, without the need to
|
||||
// create a MemoryObject and buffering its entire contents into memory.
|
||||
func (s *ObjectStorage) LazyWriter() (w io.WriteCloser, wh func(typ plumbing.ObjectType, sz int64) error, err error) {
|
||||
ow, err := s.dir.NewObject()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return ow, ow.WriteHeader, nil
|
||||
}
|
||||
|
||||
// HasEncodedObject returns nil if the object exists, without actually
|
||||
// reading the object data from storage.
|
||||
func (s *ObjectStorage) HasEncodedObject(h plumbing.Hash) (err error) {
|
||||
@ -204,9 +218,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 +403,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 +415,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()
|
||||
@ -411,12 +431,23 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb
|
||||
|
||||
defer ioutil.CheckClose(w, &err)
|
||||
|
||||
bufp := copyBufferPool.Get().(*[]byte)
|
||||
buf := *bufp
|
||||
_, err = io.CopyBuffer(w, r, buf)
|
||||
copyBufferPool.Put(bufp)
|
||||
|
||||
s.objectCache.Put(obj)
|
||||
|
||||
_, err = io.Copy(w, r)
|
||||
return obj, err
|
||||
}
|
||||
|
||||
var copyBufferPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
b := make([]byte, 32*1024)
|
||||
return &b
|
||||
},
|
||||
}
|
||||
|
||||
// Get returns the object with the given hash, by searching for it in
|
||||
// the packfile.
|
||||
func (s *ObjectStorage) getFromPackfile(h plumbing.Hash, canBeDelta bool) (
|
||||
@ -519,14 +550,21 @@ func (s *ObjectStorage) findObjectInPackfile(h plumbing.Hash) (plumbing.Hash, pl
|
||||
return plumbing.ZeroHash, plumbing.ZeroHash, -1
|
||||
}
|
||||
|
||||
// HashesWithPrefix returns all objects with a hash that starts with a prefix by searching for
|
||||
// them in the packfile and the git object directories.
|
||||
func (s *ObjectStorage) HashesWithPrefix(prefix []byte) ([]plumbing.Hash, error) {
|
||||
hashes, err := s.dir.ObjectsWithPrefix(prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
seen := hashListAsMap(hashes)
|
||||
|
||||
// TODO: This could be faster with some idxfile changes,
|
||||
// or diving into the packfile.
|
||||
if err := s.requireIndex(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, index := range s.index {
|
||||
ei, err := index.Entries()
|
||||
if err != nil {
|
||||
@ -540,6 +578,9 @@ func (s *ObjectStorage) HashesWithPrefix(prefix []byte) ([]plumbing.Hash, error)
|
||||
return nil, err
|
||||
}
|
||||
if bytes.HasPrefix(e.Hash[:], prefix) {
|
||||
if _, ok := seen[e.Hash]; ok {
|
||||
continue
|
||||
}
|
||||
hashes = append(hashes, e.Hash)
|
||||
}
|
||||
}
|
||||
@ -595,6 +636,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 +726,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 +738,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 +749,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)
|
||||
|
2
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/shallow.go
generated
vendored
2
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/shallow.go
generated
vendored
@ -34,7 +34,7 @@ func (s *ShallowStorage) SetShallow(commits []plumbing.Hash) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Shallow return the shallow commits reading from shallo file from .git
|
||||
// Shallow returns the shallow commits reading from shallo file from .git
|
||||
func (s *ShallowStorage) Shallow() ([]plumbing.Hash, error) {
|
||||
f, err := s.dir.Shallow()
|
||||
if f == nil || err != nil {
|
||||
|
12
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/storage.go
generated
vendored
12
vendor/github.com/jesseduffield/go-git/v5/storage/filesystem/storage.go
generated
vendored
@ -34,6 +34,13 @@ 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
|
||||
// AlternatesFS provides the billy filesystem to be used for Git Alternates.
|
||||
// If none is provided, it falls back to using the underlying instance used for
|
||||
// DotGit.
|
||||
AlternatesFS billy.Filesystem
|
||||
}
|
||||
|
||||
// NewStorage returns a new Storage backed by a given `fs.Filesystem` and cache.
|
||||
@ -46,6 +53,7 @@ func NewStorage(fs billy.Filesystem, cache cache.Object) *Storage {
|
||||
func NewStorageWithOptions(fs billy.Filesystem, cache cache.Object, ops Options) *Storage {
|
||||
dirOps := dotgit.Options{
|
||||
ExclusiveAccess: ops.ExclusiveAccess,
|
||||
AlternatesFS: ops.AlternatesFS,
|
||||
}
|
||||
dir := dotgit.NewWithOptions(fs, dirOps)
|
||||
|
||||
@ -71,3 +79,7 @@ func (s *Storage) Filesystem() billy.Filesystem {
|
||||
func (s *Storage) Init() error {
|
||||
return s.dir.Initialize()
|
||||
}
|
||||
|
||||
func (s *Storage) AddAlternate(remote string) error {
|
||||
return s.dir.AddAlternate(remote)
|
||||
}
|
||||
|
6
vendor/github.com/jesseduffield/go-git/v5/storage/memory/storage.go
generated
vendored
6
vendor/github.com/jesseduffield/go-git/v5/storage/memory/storage.go
generated
vendored
@ -193,7 +193,7 @@ func (o *ObjectStorage) DeleteOldObjectPackAndIndex(plumbing.Hash, time.Time) er
|
||||
return nil
|
||||
}
|
||||
|
||||
var errNotSupported = fmt.Errorf("Not supported")
|
||||
var errNotSupported = fmt.Errorf("not supported")
|
||||
|
||||
func (o *ObjectStorage) LooseObjectTime(hash plumbing.Hash) (time.Time, error) {
|
||||
return time.Time{}, errNotSupported
|
||||
@ -202,6 +202,10 @@ func (o *ObjectStorage) DeleteLooseObject(plumbing.Hash) error {
|
||||
return errNotSupported
|
||||
}
|
||||
|
||||
func (o *ObjectStorage) AddAlternate(remote string) error {
|
||||
return errNotSupported
|
||||
}
|
||||
|
||||
type TxObjectStorage struct {
|
||||
Storage *ObjectStorage
|
||||
Objects map[plumbing.Hash]plumbing.EncodedObject
|
||||
|
Reference in New Issue
Block a user