2015-03-19 19:30:55 +00:00
|
|
|
package lfs
|
2014-08-06 22:04:34 +00:00
|
|
|
|
|
|
|
import (
|
2014-08-07 16:44:42 +00:00
|
|
|
"fmt"
|
2014-08-06 22:04:34 +00:00
|
|
|
"io"
|
2014-08-07 16:44:42 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2014-08-06 22:04:34 +00:00
|
|
|
)
|
|
|
|
|
2014-08-07 17:27:06 +00:00
|
|
|
type CallbackReader struct {
|
|
|
|
C CopyCallback
|
|
|
|
TotalSize int64
|
|
|
|
ReadSize int64
|
|
|
|
io.Reader
|
2014-08-06 22:04:34 +00:00
|
|
|
}
|
|
|
|
|
2015-04-24 15:43:38 +00:00
|
|
|
type CopyCallback func(int64, int64, int) error
|
2014-08-07 14:53:13 +00:00
|
|
|
|
2014-08-07 17:27:06 +00:00
|
|
|
func (w *CallbackReader) Read(p []byte) (int, error) {
|
|
|
|
n, err := w.Reader.Read(p)
|
2014-08-06 22:04:34 +00:00
|
|
|
|
|
|
|
if n > 0 {
|
2014-08-07 17:27:06 +00:00
|
|
|
w.ReadSize += int64(n)
|
2014-08-06 22:04:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err == nil && w.C != nil {
|
2015-04-24 15:43:38 +00:00
|
|
|
err = w.C(w.TotalSize, w.ReadSize, n)
|
2014-08-06 22:04:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return n, err
|
|
|
|
}
|
|
|
|
|
2014-08-07 14:53:13 +00:00
|
|
|
func CopyWithCallback(writer io.Writer, reader io.Reader, totalSize int64, cb CopyCallback) (int64, error) {
|
|
|
|
if cb == nil {
|
|
|
|
return io.Copy(writer, reader)
|
|
|
|
}
|
|
|
|
|
2014-08-07 17:27:06 +00:00
|
|
|
cbReader := &CallbackReader{
|
2014-08-06 22:04:34 +00:00
|
|
|
C: cb,
|
|
|
|
TotalSize: totalSize,
|
2014-08-07 17:27:06 +00:00
|
|
|
Reader: reader,
|
2014-08-06 22:04:34 +00:00
|
|
|
}
|
2014-08-07 17:27:06 +00:00
|
|
|
return io.Copy(writer, cbReader)
|
2014-08-06 22:04:34 +00:00
|
|
|
}
|
2014-08-07 16:44:42 +00:00
|
|
|
|
2014-08-07 17:40:08 +00:00
|
|
|
func CopyCallbackFile(event, filename string, index, totalFiles int) (CopyCallback, *os.File, error) {
|
2015-03-19 19:30:55 +00:00
|
|
|
logPath := os.Getenv("GIT_LFS_PROGRESS")
|
2014-10-06 15:40:34 +00:00
|
|
|
if len(logPath) == 0 || len(filename) == 0 || len(event) == 0 {
|
2014-08-14 16:38:25 +00:00
|
|
|
return nil, nil, nil
|
|
|
|
}
|
|
|
|
|
2014-10-06 15:40:34 +00:00
|
|
|
if !filepath.IsAbs(logPath) {
|
2015-03-19 19:30:55 +00:00
|
|
|
return nil, nil, fmt.Errorf("GIT_LFS_PROGRESS must be an absolute path")
|
2014-08-07 16:44:42 +00:00
|
|
|
}
|
|
|
|
|
2014-10-06 15:40:34 +00:00
|
|
|
cbDir := filepath.Dir(logPath)
|
2014-08-07 16:44:42 +00:00
|
|
|
if err := os.MkdirAll(cbDir, 0755); err != nil {
|
2014-10-06 15:40:34 +00:00
|
|
|
return nil, nil, wrapProgressError(err, event, logPath)
|
2014-08-07 16:44:42 +00:00
|
|
|
}
|
|
|
|
|
2014-10-06 15:40:34 +00:00
|
|
|
file, err := os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
2014-08-07 16:44:42 +00:00
|
|
|
if err != nil {
|
2014-10-06 15:40:34 +00:00
|
|
|
return nil, file, wrapProgressError(err, event, logPath)
|
2014-08-07 16:44:42 +00:00
|
|
|
}
|
|
|
|
|
2014-08-14 15:25:55 +00:00
|
|
|
var prevWritten int64
|
2014-08-07 16:44:42 +00:00
|
|
|
|
2015-04-24 15:43:38 +00:00
|
|
|
cb := CopyCallback(func(total int64, written int64, current int) error {
|
2014-08-14 15:25:55 +00:00
|
|
|
if written != prevWritten {
|
|
|
|
_, err := file.Write([]byte(fmt.Sprintf("%s %d/%d %d/%d %s\n", event, index, totalFiles, written, total, filename)))
|
2014-08-12 16:46:10 +00:00
|
|
|
file.Sync()
|
2014-08-14 15:25:55 +00:00
|
|
|
prevWritten = written
|
2014-10-06 15:40:34 +00:00
|
|
|
return wrapProgressError(err, event, logPath)
|
2014-08-07 16:44:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
return cb, file, nil
|
|
|
|
}
|
|
|
|
|
2014-08-07 17:37:04 +00:00
|
|
|
func wrapProgressError(err error, event, filename string) error {
|
2014-08-07 16:44:42 +00:00
|
|
|
if err == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-03-22 19:02:33 +00:00
|
|
|
return fmt.Errorf("Error writing Git LFS %s progress to %s: %s", event, filename, err.Error())
|
2014-08-07 16:44:42 +00:00
|
|
|
}
|