github.com/q2/git-lfs@v0.5.1-0.20150410234700-03a0d4cec40e/lfs/util.go (about)

     1  package lfs
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  )
     9  
    10  type CallbackReader struct {
    11  	C         CopyCallback
    12  	TotalSize int64
    13  	ReadSize  int64
    14  	io.Reader
    15  }
    16  
    17  type CopyCallback func(int64, int64) error
    18  
    19  func (w *CallbackReader) Read(p []byte) (int, error) {
    20  	n, err := w.Reader.Read(p)
    21  
    22  	if n > 0 {
    23  		w.ReadSize += int64(n)
    24  	}
    25  
    26  	if err == nil && w.C != nil {
    27  		err = w.C(w.TotalSize, w.ReadSize)
    28  	}
    29  
    30  	return n, err
    31  }
    32  
    33  func CopyWithCallback(writer io.Writer, reader io.Reader, totalSize int64, cb CopyCallback) (int64, error) {
    34  	if cb == nil {
    35  		return io.Copy(writer, reader)
    36  	}
    37  
    38  	cbReader := &CallbackReader{
    39  		C:         cb,
    40  		TotalSize: totalSize,
    41  		Reader:    reader,
    42  	}
    43  	return io.Copy(writer, cbReader)
    44  }
    45  
    46  func CopyCallbackFile(event, filename string, index, totalFiles int) (CopyCallback, *os.File, error) {
    47  	logPath := os.Getenv("GIT_LFS_PROGRESS")
    48  	if len(logPath) == 0 || len(filename) == 0 || len(event) == 0 {
    49  		return nil, nil, nil
    50  	}
    51  
    52  	if !filepath.IsAbs(logPath) {
    53  		return nil, nil, fmt.Errorf("GIT_LFS_PROGRESS must be an absolute path")
    54  	}
    55  
    56  	cbDir := filepath.Dir(logPath)
    57  	if err := os.MkdirAll(cbDir, 0755); err != nil {
    58  		return nil, nil, wrapProgressError(err, event, logPath)
    59  	}
    60  
    61  	file, err := os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
    62  	if err != nil {
    63  		return nil, file, wrapProgressError(err, event, logPath)
    64  	}
    65  
    66  	var prevWritten int64
    67  
    68  	cb := CopyCallback(func(total int64, written int64) error {
    69  		if written != prevWritten {
    70  			_, err := file.Write([]byte(fmt.Sprintf("%s %d/%d %d/%d %s\n", event, index, totalFiles, written, total, filename)))
    71  			file.Sync()
    72  			prevWritten = written
    73  			return wrapProgressError(err, event, logPath)
    74  		}
    75  
    76  		return nil
    77  	})
    78  
    79  	return cb, file, nil
    80  }
    81  
    82  func wrapProgressError(err error, event, filename string) error {
    83  	if err == nil {
    84  		return nil
    85  	}
    86  
    87  	return fmt.Errorf("Error writing Git LFS %s progress to %s: %s", event, filename, err.Error())
    88  }