1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
package lfs
import (
"github.com/git-lfs/git-lfs/v3/config"
"github.com/git-lfs/git-lfs/v3/git"
"github.com/git-lfs/git-lfs/v3/tools"
)
const (
// blobSizeCutoff is used to determine which files to scan for Git LFS
// pointers. Any file with a size below this cutoff will be scanned.
blobSizeCutoff = 1024
// stdoutBufSize is the size of the buffers given to a sub-process stdout
stdoutBufSize = 16384
// chanBufSize is the size of the channels used to pass data from one
// sub-process to another.
chanBufSize = 100
)
// WrappedPointer wraps a pointer.Pointer and provides the git sha1
// and the file name associated with the object, taken from the
// rev-list output.
type WrappedPointer struct {
Sha1 string
Name string
SrcName string
Status string
*Pointer
}
// catFileBatchCheck uses git cat-file --batch-check to get the type
// and size of a git object. Any object that isn't of type blob and
// under the blobSizeCutoff will be ignored. revs is a channel over
// which strings containing git sha1s will be sent. It returns a channel
// from which sha1 strings can be read.
func catFileBatchCheck(revs *StringChannelWrapper, lockableSet *lockableNameSet) (*StringChannelWrapper, chan string, error) {
smallRevCh := make(chan string, chanBufSize)
lockableCh := make(chan string, chanBufSize)
errCh := make(chan error, 2) // up to 2 errors, one from each goroutine
if err := runCatFileBatchCheck(smallRevCh, lockableCh, lockableSet, revs, errCh); err != nil {
return nil, nil, err
}
return NewStringChannelWrapper(smallRevCh, errCh), lockableCh, nil
}
// catFileBatch() uses an ObjectDatabase from the
// github.com/git-lfs/gitobj/v2 package to get the contents of Git
// blob objects, given their SHA1s, similar to the behaviour of
// 'git cat-file --batch'.
// Input Git blob SHA1s should be sent over the revs channel.
// The blob contents will be decoded as Git LFS pointers and any valid
// pointers will be returned as pointer.Pointer structs in a new channel.
func catFileBatch(revs *StringChannelWrapper, lockableSet *lockableNameSet, gitEnv, osEnv config.Environment) (*PointerChannelWrapper, chan string, error) {
pointerCh := make(chan *WrappedPointer, chanBufSize)
lockableCh := make(chan string, chanBufSize)
errCh := make(chan error, 5) // shared by 2 goroutines & may add more detail errors?
if err := runCatFileBatch(pointerCh, lockableCh, lockableSet, revs, errCh, gitEnv, osEnv); err != nil {
return nil, nil, err
}
return NewPointerChannelWrapper(pointerCh, errCh), lockableCh, nil
}
// ChannelWrapper for pointer Scan* functions to more easily return async error data via Wait()
// See NewPointerChannelWrapper for construction / use
type PointerChannelWrapper struct {
*tools.BaseChannelWrapper
Results <-chan *WrappedPointer
}
// Construct a new channel wrapper for WrappedPointer
// Caller can use s.Results directly for normal processing then call Wait() to finish & check for errors
// Scan function is required to create error channel large enough not to block (usually 1 is ok)
func NewPointerChannelWrapper(pointerChan <-chan *WrappedPointer, errorChan <-chan error) *PointerChannelWrapper {
return &PointerChannelWrapper{tools.NewBaseChannelWrapper(errorChan), pointerChan}
}
// ChannelWrapper for string channel functions to more easily return async error data via Wait()
// Caller can use s.Results directly for normal processing then call Wait() to finish & check for errors
// See NewStringChannelWrapper for construction / use
type StringChannelWrapper struct {
*tools.BaseChannelWrapper
Results <-chan string
}
// Construct a new channel wrapper for string
// Caller can use s.Results directly for normal processing then call Wait() to finish & check for errors
func NewStringChannelWrapper(stringChan <-chan string, errorChan <-chan error) *StringChannelWrapper {
return &StringChannelWrapper{tools.NewBaseChannelWrapper(errorChan), stringChan}
}
// ChannelWrapper for TreeBlob channel functions to more easily return async error data via Wait()
// See NewTreeBlobChannelWrapper for construction / use
type TreeBlobChannelWrapper struct {
*tools.BaseChannelWrapper
Results <-chan git.TreeBlob
}
// Construct a new channel wrapper for TreeBlob
// Caller can use s.Results directly for normal processing then call Wait() to finish & check for errors
func NewTreeBlobChannelWrapper(treeBlobChan <-chan git.TreeBlob, errorChan <-chan error) *TreeBlobChannelWrapper {
return &TreeBlobChannelWrapper{tools.NewBaseChannelWrapper(errorChan), treeBlobChan}
}
|