github.com/rakutentech/cli@v6.12.5-0.20151006231303-24468b65536e+incompatible/cf/net/progress_reader.go (about)

     1  package net
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"time"
     7  
     8  	"github.com/cloudfoundry/cli/cf/formatters"
     9  	"github.com/cloudfoundry/cli/cf/terminal"
    10  )
    11  
    12  type ProgressReader struct {
    13  	ioReadSeeker   io.ReadSeeker
    14  	bytesRead      int64
    15  	total          int64
    16  	quit           chan bool
    17  	ui             terminal.UI
    18  	outputInterval time.Duration
    19  }
    20  
    21  func NewProgressReader(readSeeker io.ReadSeeker, ui terminal.UI, outputInterval time.Duration) *ProgressReader {
    22  	return &ProgressReader{
    23  		ioReadSeeker:   readSeeker,
    24  		ui:             ui,
    25  		outputInterval: outputInterval,
    26  	}
    27  }
    28  
    29  func (progressReader *ProgressReader) Read(p []byte) (int, error) {
    30  	if progressReader.ioReadSeeker == nil {
    31  		return 0, os.ErrInvalid
    32  	}
    33  
    34  	n, err := progressReader.ioReadSeeker.Read(p)
    35  
    36  	if progressReader.total > int64(0) {
    37  		if n > 0 {
    38  			if progressReader.quit == nil {
    39  				progressReader.quit = make(chan bool)
    40  				go progressReader.printProgress(progressReader.quit)
    41  			}
    42  
    43  			progressReader.bytesRead += int64(n)
    44  
    45  			if progressReader.total == progressReader.bytesRead {
    46  				progressReader.quit <- true
    47  				return n, err
    48  			}
    49  		}
    50  	}
    51  
    52  	return n, err
    53  }
    54  
    55  func (progressReader *ProgressReader) Seek(offset int64, whence int) (int64, error) {
    56  	return progressReader.ioReadSeeker.Seek(offset, whence)
    57  }
    58  
    59  func (progressReader *ProgressReader) printProgress(quit chan bool) {
    60  	timer := time.NewTicker(progressReader.outputInterval)
    61  
    62  	for {
    63  		select {
    64  		case <-quit:
    65  			//The spaces are there to ensure we overwrite the entire line
    66  			//before using the terminal printer to output Done Uploading
    67  			progressReader.ui.PrintCapturingNoOutput("\r                             ")
    68  			progressReader.ui.Say("\rDone uploading")
    69  			return
    70  		case <-timer.C:
    71  			progressReader.ui.PrintCapturingNoOutput("\r%s uploaded...", formatters.ByteSize(progressReader.bytesRead))
    72  		}
    73  	}
    74  }
    75  
    76  func (progressReader *ProgressReader) SetTotalSize(size int64) {
    77  	progressReader.total = size
    78  }