github.com/psexton/git-lfs@v2.1.1-0.20170517224304-289a18b2bc53+incompatible/lfs/pointer_clean.go (about) 1 package lfs 2 3 import ( 4 "bytes" 5 "crypto/sha256" 6 "encoding/hex" 7 "io" 8 "os" 9 10 "github.com/git-lfs/git-lfs/config" 11 "github.com/git-lfs/git-lfs/errors" 12 "github.com/git-lfs/git-lfs/progress" 13 "github.com/git-lfs/git-lfs/tools" 14 ) 15 16 type cleanedAsset struct { 17 Filename string 18 *Pointer 19 } 20 21 func PointerClean(reader io.Reader, fileName string, fileSize int64, cb progress.CopyCallback) (*cleanedAsset, error) { 22 extensions, err := config.Config.SortedExtensions() 23 if err != nil { 24 return nil, err 25 } 26 27 var oid string 28 var size int64 29 var tmp *os.File 30 var exts []*PointerExtension 31 if len(extensions) > 0 { 32 request := &pipeRequest{"clean", reader, fileName, extensions} 33 34 var response pipeResponse 35 if response, err = pipeExtensions(request); err != nil { 36 return nil, err 37 } 38 39 oid = response.results[len(response.results)-1].oidOut 40 tmp = response.file 41 var stat os.FileInfo 42 if stat, err = os.Stat(tmp.Name()); err != nil { 43 return nil, err 44 } 45 size = stat.Size() 46 47 for _, result := range response.results { 48 if result.oidIn != result.oidOut { 49 ext := NewPointerExtension(result.name, len(exts), result.oidIn) 50 exts = append(exts, ext) 51 } 52 } 53 } else { 54 oid, size, tmp, err = copyToTemp(reader, fileSize, cb) 55 if err != nil { 56 return nil, err 57 } 58 } 59 60 pointer := NewPointer(oid, size, exts) 61 return &cleanedAsset{tmp.Name(), pointer}, err 62 } 63 64 func copyToTemp(reader io.Reader, fileSize int64, cb progress.CopyCallback) (oid string, size int64, tmp *os.File, err error) { 65 tmp, err = TempFile("") 66 if err != nil { 67 return 68 } 69 70 defer tmp.Close() 71 72 oidHash := sha256.New() 73 writer := io.MultiWriter(oidHash, tmp) 74 75 if fileSize == 0 { 76 cb = nil 77 } 78 79 ptr, buf, err := DecodeFrom(reader) 80 81 by := make([]byte, blobSizeCutoff) 82 n, rerr := buf.Read(by) 83 by = by[:n] 84 85 if rerr != nil || (err == nil && len(by) < 512) { 86 err = errors.NewCleanPointerError(ptr, by) 87 return 88 } 89 90 var from io.Reader = bytes.NewReader(by) 91 if int64(len(by)) < fileSize { 92 // If there is still more data to be read from the file, tack on 93 // the original reader and continue the read from there. 94 from = io.MultiReader(from, reader) 95 } 96 97 size, err = tools.CopyWithCallback(writer, from, fileSize, cb) 98 99 if err != nil { 100 return 101 } 102 103 oid = hex.EncodeToString(oidHash.Sum(nil)) 104 return 105 } 106 107 func (a *cleanedAsset) Teardown() error { 108 return os.Remove(a.Filename) 109 }